update to latest 2.2
[sdk/tools/web-simulator.git] / web / ripple.js
1 /*! 
2   Ripple Mobile Environment Emulator v0.9.8 :: Built On Mon Jul 15 2013 16:17:21 GMT+0800 (CST)
3
4                                 Apache License
5                            Version 2.0, January 2004
6                         http://www.apache.org/licenses/
7
8    TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
9
10    1. Definitions.
11
12       "License" shall mean the terms and conditions for use, reproduction,
13       and distribution as defined by Sections 1 through 9 of this document.
14
15       "Licensor" shall mean the copyright owner or entity authorized by
16       the copyright owner that is granting the License.
17
18       "Legal Entity" shall mean the union of the acting entity and all
19       other entities that control, are controlled by, or are under common
20       control with that entity. For the purposes of this definition,
21       "control" means (i) the power, direct or indirect, to cause the
22       direction or management of such entity, whether by contract or
23       otherwise, or (ii) ownership of fifty percent (50%) or more of the
24       outstanding shares, or (iii) beneficial ownership of such entity.
25
26       "You" (or "Your") shall mean an individual or Legal Entity
27       exercising permissions granted by this License.
28
29       "Source" form shall mean the preferred form for making modifications,
30       including but not limited to software source code, documentation
31       source, and configuration files.
32
33       "Object" form shall mean any form resulting from mechanical
34       transformation or translation of a Source form, including but
35       not limited to compiled object code, generated documentation,
36       and conversions to other media types.
37
38       "Work" shall mean the work of authorship, whether in Source or
39       Object form, made available under the License, as indicated by a
40       copyright notice that is included in or attached to the work
41       (an example is provided in the Appendix below).
42
43       "Derivative Works" shall mean any work, whether in Source or Object
44       form, that is based on (or derived from) the Work and for which the
45       editorial revisions, annotations, elaborations, or other modifications
46       represent, as a whole, an original work of authorship. For the purposes
47       of this License, Derivative Works shall not include works that remain
48       separable from, or merely link (or bind by name) to the interfaces of,
49       the Work and Derivative Works thereof.
50
51       "Contribution" shall mean any work of authorship, including
52       the original version of the Work and any modifications or additions
53       to that Work or Derivative Works thereof, that is intentionally
54       submitted to Licensor for inclusion in the Work by the copyright owner
55       or by an individual or Legal Entity authorized to submit on behalf of
56       the copyright owner. For the purposes of this definition, "submitted"
57       means any form of electronic, verbal, or written communication sent
58       to the Licensor or its representatives, including but not limited to
59       communication on electronic mailing lists, source code control systems,
60       and issue tracking systems that are managed by, or on behalf of, the
61       Licensor for the purpose of discussing and improving the Work, but
62       excluding communication that is conspicuously marked or otherwise
63       designated in writing by the copyright owner as "Not a Contribution."
64
65       "Contributor" shall mean Licensor and any individual or Legal Entity
66       on behalf of whom a Contribution has been received by Licensor and
67       subsequently incorporated within the Work.
68
69    2. Grant of Copyright License. Subject to the terms and conditions of
70       this License, each Contributor hereby grants to You a perpetual,
71       worldwide, non-exclusive, no-charge, royalty-free, irrevocable
72       copyright license to reproduce, prepare Derivative Works of,
73       publicly display, publicly perform, sublicense, and distribute the
74       Work and such Derivative Works in Source or Object form.
75
76    3. Grant of Patent License. Subject to the terms and conditions of
77       this License, each Contributor hereby grants to You a perpetual,
78       worldwide, non-exclusive, no-charge, royalty-free, irrevocable
79       (except as stated in this section) patent license to make, have made,
80       use, offer to sell, sell, import, and otherwise transfer the Work,
81       where such license applies only to those patent claims licensable
82       by such Contributor that are necessarily infringed by their
83       Contribution(s) alone or by combination of their Contribution(s)
84       with the Work to which such Contribution(s) was submitted. If You
85       institute patent litigation against any entity (including a
86       cross-claim or counterclaim in a lawsuit) alleging that the Work
87       or a Contribution incorporated within the Work constitutes direct
88       or contributory patent infringement, then any patent licenses
89       granted to You under this License for that Work shall terminate
90       as of the date such litigation is filed.
91
92    4. Redistribution. You may reproduce and distribute copies of the
93       Work or Derivative Works thereof in any medium, with or without
94       modifications, and in Source or Object form, provided that You
95       meet the following conditions:
96
97       (a) You must give any other recipients of the Work or
98           Derivative Works a copy of this License; and
99
100       (b) You must cause any modified files to carry prominent notices
101           stating that You changed the files; and
102
103       (c) You must retain, in the Source form of any Derivative Works
104           that You distribute, all copyright, patent, trademark, and
105           attribution notices from the Source form of the Work,
106           excluding those notices that do not pertain to any part of
107           the Derivative Works; and
108
109       (d) If the Work includes a "NOTICE" text file as part of its
110           distribution, then any Derivative Works that You distribute must
111           include a readable copy of the attribution notices contained
112           within such NOTICE file, excluding those notices that do not
113           pertain to any part of the Derivative Works, in at least one
114           of the following places: within a NOTICE text file distributed
115           as part of the Derivative Works; within the Source form or
116           documentation, if provided along with the Derivative Works; or,
117           within a display generated by the Derivative Works, if and
118           wherever such third-party notices normally appear. The contents
119           of the NOTICE file are for informational purposes only and
120           do not modify the License. You may add Your own attribution
121           notices within Derivative Works that You distribute, alongside
122           or as an addendum to the NOTICE text from the Work, provided
123           that such additional attribution notices cannot be construed
124           as modifying the License.
125
126       You may add Your own copyright statement to Your modifications and
127       may provide additional or different license terms and conditions
128       for use, reproduction, or distribution of Your modifications, or
129       for any such Derivative Works as a whole, provided Your use,
130       reproduction, and distribution of the Work otherwise complies with
131       the conditions stated in this License.
132
133    5. Submission of Contributions. Unless You explicitly state otherwise,
134       any Contribution intentionally submitted for inclusion in the Work
135       by You to the Licensor shall be under the terms and conditions of
136       this License, without any additional terms or conditions.
137       Notwithstanding the above, nothing herein shall supersede or modify
138       the terms of any separate license agreement you may have executed
139       with Licensor regarding such Contributions.
140
141    6. Trademarks. This License does not grant permission to use the trade
142       names, trademarks, service marks, or product names of the Licensor,
143       except as required for reasonable and customary use in describing the
144       origin of the Work and reproducing the content of the NOTICE file.
145
146    7. Disclaimer of Warranty. Unless required by applicable law or
147       agreed to in writing, Licensor provides the Work (and each
148       Contributor provides its Contributions) on an "AS IS" BASIS,
149       WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
150       implied, including, without limitation, any warranties or conditions
151       of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
152       PARTICULAR PURPOSE. You are solely responsible for determining the
153       appropriateness of using or redistributing the Work and assume any
154       risks associated with Your exercise of permissions under this License.
155
156    8. Limitation of Liability. In no event and under no legal theory,
157       whether in tort (including negligence), contract, or otherwise,
158       unless required by applicable law (such as deliberate and grossly
159       negligent acts) or agreed to in writing, shall any Contributor be
160       liable to You for damages, including any direct, indirect, special,
161       incidental, or consequential damages of any character arising as a
162       result of this License or out of the use or inability to use the
163       Work (including but not limited to damages for loss of goodwill,
164       work stoppage, computer failure or malfunction, or any and all
165       other commercial damages or losses), even if such Contributor
166       has been advised of the possibility of such damages.
167
168    9. Accepting Warranty or Additional Liability. While redistributing
169       the Work or Derivative Works thereof, You may choose to offer,
170       and charge a fee for, acceptance of support, warranty, indemnity,
171       or other liability obligations and/or rights consistent with this
172       License. However, in accepting such obligations, You may act only
173       on Your own behalf and on Your sole responsibility, not on behalf
174       of any other Contributor, and only if You agree to indemnify,
175       defend, and hold each Contributor harmless for any liability
176       incurred by, or claims asserted against, such Contributor by reason
177       of your accepting any such warranty or additional liability.
178
179    END OF TERMS AND CONDITIONS
180
181    APPENDIX: How to apply the Apache License to your work.
182
183       To apply the Apache License to your work, attach the following
184       boilerplate notice, with the fields enclosed by brackets "[]"
185       replaced with your own identifying information. (Don't include
186       the brackets!)  The text should be enclosed in the appropriate
187       comment syntax for the file format. We also recommend that a
188       file or class name and description of purpose be included on the
189       same "printed page" as the copyright notice for easier
190       identification within third-party archives.
191
192    Copyright [yyyy] [name of copyright owner]
193
194    Licensed under the Apache License, Version 2.0 (the "License");
195    you may not use this file except in compliance with the License.
196    You may obtain a copy of the License at
197
198        http://www.apache.org/licenses/LICENSE-2.0
199
200    Unless required by applicable law or agreed to in writing, software
201    distributed under the License is distributed on an "AS IS" BASIS,
202    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
203    See the License for the specific language governing permissions and
204    limitations under the License.
205
206 -------------------------------------------------------
207 Copyright 2011 Research In Motion Limited.
208
209 Contributors:
210         Brent Lintner (blintner@rim.com)
211         Dan Silivestru (dsilivestru@rim.com)
212         Gord Tanner (gtanner@rim.com)
213         Nino D'Aversa (ndaversa@rim.com)
214         Nukul Bhasin (nbhasin@rim.com)
215
216 -------------------------------------------------------
217 --> Kudos to third party awesomeness:
218
219 * browser-require *
220
221 https://github.com/rsms/browser-require
222
223 The MIT License
224 http://www.opensource.org/licenses/mit-license.php
225 Copyright (c) 2010 Rasmus Andersson http://hunch.se/
226
227 -------------------------------------------------------
228 * jWorkflow *
229
230 http://github.com/tinyhippos/jWorkflow/
231
232 The MIT License
233 http://www.opensource.org/licenses/mit-license.php
234 Copyright (c) 2010 all contributors:
235 Gord Tanner
236
237 -------------------------------------------------------
238 * jXHR.js (JSON-P XHR) *
239  v0.1 (c) Kyle Simpson 
240  MIT License
241
242 -------------------------------------------------------
243 * UI.Acceleromter Control (panel plugin) *
244
245 Licensed under the MIT license:
246   Copyright Train Hack 2010
247   Contributors: Wolfram Kriesing, Dan Silivestru, Brent Lintner
248   http://www.opensource.org/licenses/mit-license.php
249
250 -------------------------------------------------------
251 * jQuery JavaScript Library *
252
253 http://jquery.com/
254
255 Copyright 2010, John Resig
256 Licensed under MIT
257 http://jquery.org/license
258
259 Includes Sizzle.js
260 http://sizzlejs.com/
261 Copyright 2010, The Dojo Foundation
262 Released under the MIT, BSD, and GPL Licenses.
263
264 -------------------------------------------------------
265 * jQuery UI *
266
267 Copyright (c) 2010 AUTHORS.txt (http://jqueryui.com/about)
268 licensed under the MIT (MIT-LICENSE.txt)
269
270 http://docs.jquery.com/UI
271
272 -------------------------------------------------------
273 * jQuery Tooltip plugin *
274
275 http://bassistance.de/jquery-plugins/jquery-plugin-tooltip/
276 http://docs.jquery.com/Plugins/Tooltip
277
278 Copyright (c) 2006 - 2008 Jörn Zaefferer
279
280 Dual licensed under the MIT and GPL licenses:
281   http://www.opensource.org/licenses/mit-license.php
282   http://www.gnu.org/licenses/gpl.html
283
284 -------------------------------------------------------
285 * Math.uuid.js (v1.4) *
286
287 http://www.broofa.com
288 mailto:robert@broofa.com
289
290 Copyright (c) 2010 Robert Kieffer
291 Dual licensed under the MIT and GPL licenses.
292
293 -------------------------------------------------------
294 * Wii Opera SDK - 3D Math Class v2.7.22 2008-12-14 *
295 (c) 2007-2008 Daniel Gump. All Rights Reserved.                          
296  http://wiioperasdk.com, http://hullbreachonline.com                      
297  hullbreach@hullbreachonline.com                                          
298                                                                           
299 * Wii Opera SDK - Drawing Class v2.6.16 2008-12-14 * 
300 (c) 2007-2008 Daniel Gump. All Rights Reserved
301 http://wiioperasdk.com, http://hullbreachonline.com
302 hullbreach@hullbreachonline.com
303
304   Wii is a trademark of Nintendo Co., Ltd.                                
305   Opera is a trademark of Opera, ASA.                                     
306   This software package is not associated with either company             
307   but was created to support users of both.  Its alternative name         
308   when supporting other products is the HULLBREACH SDK.                   
309                                                                           
310   Redistribution and use in source and binary forms, with or without      
311   modification, are permitted provided that the following conditions      
312   are met:                                                                
313     * Redistributions of source code must retain the above copyright      
314       notice, this list of conditions and the following disclaimer.       
315     * Redistributions in binary form must reproduce the above copyright   
316       notice, this list of conditions and the following disclaimer in     
317       the documentation and/or other materials provided with the          
318       distribution.                                                       
319     * Neither the names HULLBREACH ONLINE nor WII OPERA SDK nor the names 
320       of its contributors may be used to endorse or promote products      
321       derived from this software without specific prior written           
322       permission.                                                         
323     * If the explicit purpose of the software is not to support the       
324       Nintendo Wii or the Opera Web browser, then the names of such must  
325       not be used in any derived product. The name shall be the           
326       HULLBREACH SDK with a reference link to http://hullbreachonline.    
327                                                                           
328   THIS SOFTWARE IS PROVIDED BY Daniel Gump ''AS IS'' AND ANY EXPRESS OR   
329   IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED          
330   WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE  
331   DISCLAIMED. IN NO EVENT SHALL Daniel Gump BE LIABLE FOR ANY DIRECT,     
332   INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES      
333   (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR      
334   SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)      
335   HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,     
336   STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING   
337   IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE      
338   POSSIBILITY OF SUCH DAMAGE.                                             
339
340 -------------------------------------------------------
341   OpenLayers.js -- OpenLayers Map Viewer Library
342
343   Copyright 2005-2010 OpenLayers Contributors, released under the Clear BSD
344   license. Full license text below taken from http://svn.openlayers.org/trunk/openlayers/license.txt
345
346         Copyright 2005-2011 OpenLayers Contributors. All rights reserved. See
347         authors.txt for full list.
348          
349         Redistribution and use in source and binary forms, with or without modification,
350         are permitted provided that the following conditions are met:
351          
352         1. Redistributions of source code must retain the above copyright notice, this
353         list of conditions and the following disclaimer.
354          
355         2. Redistributions in binary form must reproduce the above copyright notice,
356         this list of conditions and the following disclaimer in the documentation and/or
357         other materials provided with the distribution.
358          
359         THIS SOFTWARE IS PROVIDED BY OPENLAYERS CONTRIBUTORS ``AS IS'' AND ANY EXPRESS
360         OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
361         MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
362         SHALL COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
363         INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
364         LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
365         PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
366         LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
367         OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
368         ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
369          
370         The views and conclusions contained in the software and documentation are those
371         of the authors and should not be interpreted as representing official policies,
372         either expressed or implied, of OpenLayers Contributors.
373
374   Includes compressed code under the following licenses:
375
376   (For uncompressed versions of the code used please see the
377   OpenLayers SVN repository: <http://openlayers.org/>)
378
379 -------------------------------------------------------
380   Contains portions of Rico <http://openrico.org/>
381  
382   Copyright 2005 Sabre Airline Solutions  
383   
384   Licensed under the Apache License, Version 2.0 (the "License"); you
385   may not use this file except in compliance with the License. You
386   may obtain a copy of the License at the top of this file or a the following
387   link:
388   
389          http://www.apache.org/licenses/LICENSE-2.0  
390   
391   Unless required by applicable law or agreed to in writing, software
392   distributed under the License is distributed on an "AS IS" BASIS,
393   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
394   implied. See the License for the specific language governing
395   permissions and limitations under the License. 
396
397 -------------------------------------------------------
398   Contains XMLHttpRequest.js <http://code.google.com/p/xmlhttprequest/>
399   Copyright 2007 Sergey Ilinsky (http://www.ilinsky.com)
400  
401   Licensed under the Apache License, Version 2.0 (the "License");
402   you may not use this file except in compliance with the License.
403   You may obtain a copy of the License at
404   http://www.apache.org/licenses/LICENSE-2.0
405
406 -------------------------------------------------------
407   Contains portions of Gears <http://code.google.com/apis/gears/>
408
409   Copyright 2007, Google Inc.
410
411   Redistribution and use in source and binary forms, with or without
412   modification, are permitted provided that the following conditions are met:
413
414    1. Redistributions of source code must retain the above copyright notice,
415       this list of conditions and the following disclaimer.
416    2. Redistributions in binary form must reproduce the above copyright notice,
417       this list of conditions and the following disclaimer in the documentation
418       and/or other materials provided with the distribution.
419    3. Neither the name of Google Inc. nor the names of its contributors may be
420       used to endorse or promote products derived from this software without
421       specific prior written permission.
422  
423   THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
424   WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
425   MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
426   EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
427   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
428   PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
429   OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
430   WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
431   OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
432   ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
433  
434   Sets up google.gears.*, which is *the only* supported way to access Gears.
435
436   Circumvent this file at your own risk!
437  
438   In the future, Gears may automatically define google.gears.* without this
439   file. Gears may use these objects to transparently fix bugs and compatibility
440   issues. Applications that use the code below will continue to work seamlessly
441   when that happens.
442 */
443 window.require = null;window.define = null;/**
444  * almond 0.0.3 Copyright (c) 2011, The Dojo Foundation All Rights Reserved.
445  * Available via the MIT or new BSD license.
446  * see: http://github.com/jrburke/almond for details
447  */
448 /*jslint strict: false, plusplus: false */
449 /*global setTimeout: false */
450
451 var requirejs, require, define;
452 (function (undef) {
453
454     var defined = {},
455         waiting = {},
456         aps = [].slice,
457         main, req;
458
459     if (typeof define === "function") {
460         //If a define is already in play via another AMD loader,
461         //do not overwrite.
462         return;
463     }
464
465     /**
466      * Given a relative module name, like ./something, normalize it to
467      * a real name that can be mapped to a path.
468      * @param {String} name the relative name
469      * @param {String} baseName a real name that the name arg is relative
470      * to.
471      * @returns {String} normalized name
472      */
473     function normalize(name, baseName) {
474         //Adjust any relative paths.
475         if (name && name.charAt(0) === ".") {
476             //If have a base name, try to normalize against it,
477             //otherwise, assume it is a top-level require that will
478             //be relative to baseUrl in the end.
479             if (baseName) {
480                 //Convert baseName to array, and lop off the last part,
481                 //so that . matches that "directory" and not name of the baseName's
482                 //module. For instance, baseName of "one/two/three", maps to
483                 //"one/two/three.js", but we want the directory, "one/two" for
484                 //this normalization.
485                 baseName = baseName.split("/");
486                 baseName = baseName.slice(0, baseName.length - 1);
487
488                 name = baseName.concat(name.split("/"));
489
490                 //start trimDots
491                 var i, part;
492                 for (i = 0; (part = name[i]); i++) {
493                     if (part === ".") {
494                         name.splice(i, 1);
495                         i -= 1;
496                     } else if (part === "..") {
497                         if (i === 1 && (name[2] === '..' || name[0] === '..')) {
498                             //End of the line. Keep at least one non-dot
499                             //path segment at the front so it can be mapped
500                             //correctly to disk. Otherwise, there is likely
501                             //no path mapping for a path starting with '..'.
502                             //This can still fail, but catches the most reasonable
503                             //uses of ..
504                             break;
505                         } else if (i > 0) {
506                             name.splice(i - 1, 2);
507                             i -= 2;
508                         }
509                     }
510                 }
511                 //end trimDots
512
513                 name = name.join("/");
514             }
515         }
516         return name;
517     }
518
519     function makeRequire(relName, forceSync) {
520         return function () {
521             //A version of a require function that passes a moduleName
522             //value for items that may need to
523             //look up paths relative to the moduleName
524             return req.apply(undef, aps.call(arguments, 0).concat([relName, forceSync]));
525         };
526     }
527
528     function makeNormalize(relName) {
529         return function (name) {
530             return normalize(name, relName);
531         };
532     }
533
534     function makeLoad(depName) {
535         return function (value) {
536             defined[depName] = value;
537         };
538     }
539
540     function callDep(name) {
541         if (waiting.hasOwnProperty(name)) {
542             var args = waiting[name];
543             delete waiting[name];
544             main.apply(undef, args);
545         }
546         return defined[name];
547     }
548
549     /**
550      * Makes a name map, normalizing the name, and using a plugin
551      * for normalization if necessary. Grabs a ref to plugin
552      * too, as an optimization.
553      */
554     function makeMap(name, relName) {
555         var prefix, plugin,
556             index = name.indexOf('!');
557
558         if (index !== -1) {
559             prefix = normalize(name.slice(0, index), relName);
560             name = name.slice(index + 1);
561             plugin = callDep(prefix);
562
563             //Normalize according
564             if (plugin && plugin.normalize) {
565                 name = plugin.normalize(name, makeNormalize(relName));
566             } else {
567                 name = normalize(name, relName);
568             }
569         } else {
570             name = normalize(name, relName);
571         }
572
573         //Using ridiculous property names for space reasons
574         return {
575             f: prefix ? prefix + '!' + name : name, //fullName
576             n: name,
577             p: plugin
578         };
579     }
580
581     main = function (name, deps, callback, relName) {
582         var args = [],
583             usingExports,
584             cjsModule, depName, i, ret, map;
585
586         //Use name if no relName
587         if (!relName) {
588             relName = name;
589         }
590
591         //Call the callback to define the module, if necessary.
592         if (typeof callback === 'function') {
593
594             //Default to require, exports, module if no deps if
595             //the factory arg has any arguments specified.
596             if (!deps.length && callback.length) {
597                 deps = ['require', 'exports', 'module'];
598             }
599
600             //Pull out the defined dependencies and pass the ordered
601             //values to the callback.
602             for (i = 0; i < deps.length; i++) {
603                 map = makeMap(deps[i], relName);
604                 depName = map.f;
605
606                 //Fast path CommonJS standard dependencies.
607                 if (depName === "require") {
608                     args[i] = makeRequire(name);
609                 } else if (depName === "exports") {
610                     //CommonJS module spec 1.1
611                     args[i] = defined[name] = {};
612                     usingExports = true;
613                 } else if (depName === "module") {
614                     //CommonJS module spec 1.1
615                     cjsModule = args[i] = {
616                         id: name,
617                         uri: '',
618                         exports: defined[name]
619                     };
620                 } else if (defined.hasOwnProperty(depName) || waiting.hasOwnProperty(depName)) {
621                     args[i] = callDep(depName);
622                 } else if (map.p) {
623                     map.p.load(map.n, makeRequire(relName, true), makeLoad(depName), {});
624                     args[i] = defined[depName];
625                 } else {
626                     throw name + ' missing ' + depName;
627                 }
628             }
629
630             ret = callback.apply(defined[name], args);
631
632             if (name) {
633                 //If setting exports via "module" is in play,
634                 //favor that over return value and exports. After that,
635                 //favor a non-undefined return value over exports use.
636                 if (cjsModule && cjsModule.exports !== undef) {
637                     defined[name] = cjsModule.exports;
638                 } else if (!usingExports) {
639                     //Use the return value from the function.
640                     defined[name] = ret;
641                 }
642             }
643         } else if (name) {
644             //May just be an object definition for the module. Only
645             //worry about defining if have a module name.
646             defined[name] = callback;
647         }
648     };
649
650     requirejs = req = function (deps, callback, relName, forceSync) {
651         if (typeof deps === "string") {
652
653             //Just return the module wanted. In this scenario, the
654             //deps arg is the module name, and second arg (if passed)
655             //is just the relName.
656             //Normalize module name, if it contains . or ..
657             return callDep(makeMap(deps, callback).f);
658         } else if (!deps.splice) {
659             //deps is a config object, not an array.
660             //Drop the config stuff on the ground.
661             if (callback.splice) {
662                 //callback is an array, which means it is a dependency list.
663                 //Adjust args if there are dependencies
664                 deps = callback;
665                 callback = arguments[2];
666             } else {
667                 deps = [];
668             }
669         }
670
671         //Simulate async callback;
672         if (forceSync) {
673             main(undef, deps, callback, relName);
674         } else {
675             setTimeout(function () {
676                 main(undef, deps, callback, relName);
677             }, 15);
678         }
679
680         return req;
681     };
682
683     /**
684      * Just drops the config on the floor, but returns req in case
685      * the config return value is used.
686      */
687     req.config = function () {
688         return req;
689     };
690
691     /**
692      * Export require as a global, but only if it does not already exist.
693      */
694     if (!require) {
695         require = req;
696     }
697
698     define = function (name, deps, callback) {
699
700         //This module may not have dependencies
701         if (!deps.splice) {
702             //deps is not an array, so probably means
703             //an object literal or factory function for
704             //the value. Adjust args.
705             callback = deps;
706             deps = [];
707         }
708
709         if (define.unordered) {
710             waiting[name] = [name, deps, callback];
711         } else {
712             main(name, deps, callback);
713         }
714     };
715
716     define.amd = {
717         jQuery: true
718     };
719 }());
720 /*!
721  * jQuery JavaScript Library v1.6
722  * http://jquery.com/
723  *
724  * Copyright 2011, John Resig
725  * licensed under the MIT 
726  * http://jquery.org/license
727  *
728  * Includes Sizzle.js
729  * http://sizzlejs.com/
730  * Copyright 2011, The Dojo Foundation
731  * Released under the MIT, BSD, and GPL Licenses.
732  *
733  * Date: Mon May 2 13:50:00 2011 -0400
734  */
735 (function( window, undefined ) {
736
737 // Use the correct document accordingly with window argument (sandbox)
738 var document = window.document,
739         navigator = window.navigator,
740         location = window.location;
741 var jQuery = (function() {
742
743 // Define a local copy of jQuery
744 var jQuery = function( selector, context ) {
745                 // The jQuery object is actually just the init constructor 'enhanced'
746                 return new jQuery.fn.init( selector, context, rootjQuery );
747         },
748
749         // Map over jQuery in case of overwrite
750         _jQuery = window.jQuery,
751
752         // Map over the $ in case of overwrite
753         _$ = window.$,
754
755         // A central reference to the root jQuery(document)
756         rootjQuery,
757
758         // A simple way to check for HTML strings or ID strings
759         // (both of which we optimize for)
760         quickExpr = /^(?:[^<]*(<[\w\W]+>)[^>]*$|#([\w\-]*)$)/,
761
762         // Check if a string has a non-whitespace character in it
763         rnotwhite = /\S/,
764
765         // Used for trimming whitespace
766         trimLeft = /^\s+/,
767         trimRight = /\s+$/,
768
769         // Check for digits
770         rdigit = /\d/,
771
772         // Match a standalone tag
773         rsingleTag = /^<(\w+)\s*\/?>(?:<\/\1>)?$/,
774
775         // JSON RegExp
776         rvalidchars = /^[\],:{}\s]*$/,
777         rvalidescape = /\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,
778         rvalidtokens = /"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,
779         rvalidbraces = /(?:^|:|,)(?:\s*\[)+/g,
780
781         // Useragent RegExp
782         rwebkit = /(webkit)[ \/]([\w.]+)/,
783         ropera = /(opera)(?:.*version)?[ \/]([\w.]+)/,
784         rmsie = /(msie) ([\w.]+)/,
785         rmozilla = /(mozilla)(?:.*? rv:([\w.]+))?/,
786
787         // Keep a UserAgent string for use with jQuery.browser
788         userAgent = navigator.userAgent,
789
790         // For matching the engine and version of the browser
791         browserMatch,
792
793         // The deferred used on DOM ready
794         readyList,
795
796         // The ready event handler
797         DOMContentLoaded,
798
799         // Save a reference to some core methods
800         toString = Object.prototype.toString,
801         hasOwn = Object.prototype.hasOwnProperty,
802         push = Array.prototype.push,
803         slice = Array.prototype.slice,
804         trim = String.prototype.trim,
805         indexOf = Array.prototype.indexOf,
806
807         // [[Class]] -> type pairs
808         class2type = {};
809
810 jQuery.fn = jQuery.prototype = {
811         constructor: jQuery,
812         init: function( selector, context, rootjQuery ) {
813                 var match, elem, ret, doc;
814
815                 // Handle $(""), $(null), or $(undefined)
816                 if ( !selector ) {
817                         return this;
818                 }
819
820                 // Handle $(DOMElement)
821                 if ( selector.nodeType ) {
822                         this.context = this[0] = selector;
823                         this.length = 1;
824                         return this;
825                 }
826
827                 // The body element only exists once, optimize finding it
828                 if ( selector === "body" && !context && document.body ) {
829                         this.context = document;
830                         this[0] = document.body;
831                         this.selector = selector;
832                         this.length = 1;
833                         return this;
834                 }
835
836                 // Handle HTML strings
837                 if ( typeof selector === "string" ) {
838                         // Are we dealing with HTML string or an ID?
839                         if ( selector.charAt(0) === "<" && selector.charAt( selector.length - 1 ) === ">" && selector.length >= 3 ) {
840                                 // Assume that strings that start and end with <> are HTML and skip the regex check
841                                 match = [ null, selector, null ];
842
843                         } else {
844                                 match = quickExpr.exec( selector );
845                         }
846
847                         // Verify a match, and that no context was specified for #id
848                         if ( match && (match[1] || !context) ) {
849
850                                 // HANDLE: $(html) -> $(array)
851                                 if ( match[1] ) {
852                                         context = context instanceof jQuery ? context[0] : context;
853                                         doc = (context ? context.ownerDocument || context : document);
854
855                                         // If a single string is passed in and it's a single tag
856                                         // just do a createElement and skip the rest
857                                         ret = rsingleTag.exec( selector );
858
859                                         if ( ret ) {
860                                                 if ( jQuery.isPlainObject( context ) ) {
861                                                         selector = [ document.createElement( ret[1] ) ];
862                                                         jQuery.fn.attr.call( selector, context, true );
863
864                                                 } else {
865                                                         selector = [ doc.createElement( ret[1] ) ];
866                                                 }
867
868                                         } else {
869                                                 ret = jQuery.buildFragment( [ match[1] ], [ doc ] );
870                                                 selector = (ret.cacheable ? jQuery.clone(ret.fragment) : ret.fragment).childNodes;
871                                         }
872
873                                         return jQuery.merge( this, selector );
874
875                                 // HANDLE: $("#id")
876                                 } else {
877                                         elem = document.getElementById( match[2] );
878
879                                         // Check parentNode to catch when Blackberry 4.6 returns
880                                         // nodes that are no longer in the document #6963
881                                         if ( elem && elem.parentNode ) {
882                                                 // Handle the case where IE and Opera return items
883                                                 // by name instead of ID
884                                                 if ( elem.id !== match[2] ) {
885                                                         return rootjQuery.find( selector );
886                                                 }
887
888                                                 // Otherwise, we inject the element directly into the jQuery object
889                                                 this.length = 1;
890                                                 this[0] = elem;
891                                         }
892
893                                         this.context = document;
894                                         this.selector = selector;
895                                         return this;
896                                 }
897
898                         // HANDLE: $(expr, $(...))
899                         } else if ( !context || context.jquery ) {
900                                 return (context || rootjQuery).find( selector );
901
902                         // HANDLE: $(expr, context)
903                         // (which is just equivalent to: $(context).find(expr)
904                         } else {
905                                 return this.constructor( context ).find( selector );
906                         }
907
908                 // HANDLE: $(function)
909                 // Shortcut for document ready
910                 } else if ( jQuery.isFunction( selector ) ) {
911                         return rootjQuery.ready( selector );
912                 }
913
914                 if (selector.selector !== undefined) {
915                         this.selector = selector.selector;
916                         this.context = selector.context;
917                 }
918
919                 return jQuery.makeArray( selector, this );
920         },
921
922         // Start with an empty selector
923         selector: "",
924
925         // The current version of jQuery being used
926         jquery: "1.6",
927
928         // The default length of a jQuery object is 0
929         length: 0,
930
931         // The number of elements contained in the matched element set
932         size: function() {
933                 return this.length;
934         },
935
936         toArray: function() {
937                 return slice.call( this, 0 );
938         },
939
940         // Get the Nth element in the matched element set OR
941         // Get the whole matched element set as a clean array
942         get: function( num ) {
943                 return num == null ?
944
945                         // Return a 'clean' array
946                         this.toArray() :
947
948                         // Return just the object
949                         ( num < 0 ? this[ this.length + num ] : this[ num ] );
950         },
951
952         // Take an array of elements and push it onto the stack
953         // (returning the new matched element set)
954         pushStack: function( elems, name, selector ) {
955                 // Build a new jQuery matched element set
956                 var ret = this.constructor();
957
958                 if ( jQuery.isArray( elems ) ) {
959                         push.apply( ret, elems );
960
961                 } else {
962                         jQuery.merge( ret, elems );
963                 }
964
965                 // Add the old object onto the stack (as a reference)
966                 ret.prevObject = this;
967
968                 ret.context = this.context;
969
970                 if ( name === "find" ) {
971                         ret.selector = this.selector + (this.selector ? " " : "") + selector;
972                 } else if ( name ) {
973                         ret.selector = this.selector + "." + name + "(" + selector + ")";
974                 }
975
976                 // Return the newly-formed element set
977                 return ret;
978         },
979
980         // Execute a callback for every element in the matched set.
981         // (You can seed the arguments with an array of args, but this is
982         // only used internally.)
983         each: function( callback, args ) {
984                 return jQuery.each( this, callback, args );
985         },
986
987         ready: function( fn ) {
988                 // Attach the listeners
989                 jQuery.bindReady();
990
991                 // Add the callback
992                 readyList.done( fn );
993
994                 return this;
995         },
996
997         eq: function( i ) {
998                 return i === -1 ?
999                         this.slice( i ) :
1000                         this.slice( i, +i + 1 );
1001         },
1002
1003         first: function() {
1004                 return this.eq( 0 );
1005         },
1006
1007         last: function() {
1008                 return this.eq( -1 );
1009         },
1010
1011         slice: function() {
1012                 return this.pushStack( slice.apply( this, arguments ),
1013                         "slice", slice.call(arguments).join(",") );
1014         },
1015
1016         map: function( callback ) {
1017                 return this.pushStack( jQuery.map(this, function( elem, i ) {
1018                         return callback.call( elem, i, elem );
1019                 }));
1020         },
1021
1022         end: function() {
1023                 return this.prevObject || this.constructor(null);
1024         },
1025
1026         // For internal use only.
1027         // Behaves like an Array's method, not like a jQuery method.
1028         push: push,
1029         sort: [].sort,
1030         splice: [].splice
1031 };
1032
1033 // Give the init function the jQuery prototype for later instantiation
1034 jQuery.fn.init.prototype = jQuery.fn;
1035
1036 jQuery.extend = jQuery.fn.extend = function() {
1037         var options, name, src, copy, copyIsArray, clone,
1038                 target = arguments[0] || {},
1039                 i = 1,
1040                 length = arguments.length,
1041                 deep = false;
1042
1043         // Handle a deep copy situation
1044         if ( typeof target === "boolean" ) {
1045                 deep = target;
1046                 target = arguments[1] || {};
1047                 // skip the boolean and the target
1048                 i = 2;
1049         }
1050
1051         // Handle case when target is a string or something (possible in deep copy)
1052         if ( typeof target !== "object" && !jQuery.isFunction(target) ) {
1053                 target = {};
1054         }
1055
1056         // extend jQuery itself if only one argument is passed
1057         if ( length === i ) {
1058                 target = this;
1059                 --i;
1060         }
1061
1062         for ( ; i < length; i++ ) {
1063                 // Only deal with non-null/undefined values
1064                 if ( (options = arguments[ i ]) != null ) {
1065                         // Extend the base object
1066                         for ( name in options ) {
1067                                 src = target[ name ];
1068                                 copy = options[ name ];
1069
1070                                 // Prevent never-ending loop
1071                                 if ( target === copy ) {
1072                                         continue;
1073                                 }
1074
1075                                 // Recurse if we're merging plain objects or arrays
1076                                 if ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) {
1077                                         if ( copyIsArray ) {
1078                                                 copyIsArray = false;
1079                                                 clone = src && jQuery.isArray(src) ? src : [];
1080
1081                                         } else {
1082                                                 clone = src && jQuery.isPlainObject(src) ? src : {};
1083                                         }
1084
1085                                         // Never move original objects, clone them
1086                                         target[ name ] = jQuery.extend( deep, clone, copy );
1087
1088                                 // Don't bring in undefined values
1089                                 } else if ( copy !== undefined ) {
1090                                         target[ name ] = copy;
1091                                 }
1092                         }
1093                 }
1094         }
1095
1096         // Return the modified object
1097         return target;
1098 };
1099
1100 jQuery.extend({
1101         noConflict: function( deep ) {
1102                 if ( window.$ === jQuery ) {
1103                         window.$ = _$;
1104                 }
1105
1106                 if ( deep && window.jQuery === jQuery ) {
1107                         window.jQuery = _jQuery;
1108                 }
1109
1110                 return jQuery;
1111         },
1112
1113         // Is the DOM ready to be used? Set to true once it occurs.
1114         isReady: false,
1115
1116         // A counter to track how many items to wait for before
1117         // the ready event fires. See #6781
1118         readyWait: 1,
1119
1120         // Hold (or release) the ready event
1121         holdReady: function( hold ) {
1122                 if ( hold ) {
1123                         jQuery.readyWait++;
1124                 } else {
1125                         jQuery.ready( true );
1126                 }
1127         },
1128
1129         // Handle when the DOM is ready
1130         ready: function( wait ) {
1131                 // Either a released hold or an DOMready/load event and not yet ready
1132                 if ( (wait === true && !--jQuery.readyWait) || (wait !== true && !jQuery.isReady) ) {
1133                         // Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443).
1134                         if ( !document.body ) {
1135                                 return setTimeout( jQuery.ready, 1 );
1136                         }
1137
1138                         // Remember that the DOM is ready
1139                         jQuery.isReady = true;
1140
1141                         // If a normal DOM Ready event fired, decrement, and wait if need be
1142                         if ( wait !== true && --jQuery.readyWait > 0 ) {
1143                                 return;
1144                         }
1145
1146                         // If there are functions bound, to execute
1147                         readyList.resolveWith( document, [ jQuery ] );
1148
1149                         // Trigger any bound ready events
1150                         if ( jQuery.fn.trigger ) {
1151                                 jQuery( document ).trigger( "ready" ).unbind( "ready" );
1152                         }
1153                 }
1154         },
1155
1156         bindReady: function() {
1157                 if ( readyList ) {
1158                         return;
1159                 }
1160
1161                 readyList = jQuery._Deferred();
1162
1163                 // Catch cases where $(document).ready() is called after the
1164                 // browser event has already occurred.
1165                 if ( document.readyState === "complete" ) {
1166                         // Handle it asynchronously to allow scripts the opportunity to delay ready
1167                         return setTimeout( jQuery.ready, 1 );
1168                 }
1169
1170                 // Mozilla, Opera and webkit nightlies currently support this event
1171                 if ( document.addEventListener ) {
1172                         // Use the handy event callback
1173                         document.addEventListener( "DOMContentLoaded", DOMContentLoaded, false );
1174
1175                         // A fallback to window.onload, that will always work
1176                         window.addEventListener( "load", jQuery.ready, false );
1177
1178                 // If IE event model is used
1179                 } else if ( document.attachEvent ) {
1180                         // ensure firing before onload,
1181                         // maybe late but safe also for iframes
1182                         document.attachEvent( "onreadystatechange", DOMContentLoaded );
1183
1184                         // A fallback to window.onload, that will always work
1185                         window.attachEvent( "onload", jQuery.ready );
1186
1187                         // If IE and not a frame
1188                         // continually check to see if the document is ready
1189                         var toplevel = false;
1190
1191                         try {
1192                                 toplevel = window.frameElement == null;
1193                         } catch(e) {}
1194
1195                         if ( document.documentElement.doScroll && toplevel ) {
1196                                 doScrollCheck();
1197                         }
1198                 }
1199         },
1200
1201         // See test/unit/core.js for details concerning isFunction.
1202         // Since version 1.3, DOM methods and functions like alert
1203         // aren't supported. They return false on IE (#2968).
1204         isFunction: function( obj ) {
1205                 return jQuery.type(obj) === "function";
1206         },
1207
1208         isArray: Array.isArray || function( obj ) {
1209                 return jQuery.type(obj) === "array";
1210         },
1211
1212         // A crude way of determining if an object is a window
1213         isWindow: function( obj ) {
1214                 return obj && typeof obj === "object" && "setInterval" in obj;
1215         },
1216
1217         isNaN: function( obj ) {
1218                 return obj == null || !rdigit.test( obj ) || isNaN( obj );
1219         },
1220
1221         type: function( obj ) {
1222                 return obj == null ?
1223                         String( obj ) :
1224                         class2type[ toString.call(obj) ] || "object";
1225         },
1226
1227         isPlainObject: function( obj ) {
1228                 // Must be an Object.
1229                 // Because of IE, we also have to check the presence of the constructor property.
1230                 // Make sure that DOM nodes and window objects don't pass through, as well
1231                 if ( !obj || jQuery.type(obj) !== "object" || obj.nodeType || jQuery.isWindow( obj ) ) {
1232                         return false;
1233                 }
1234
1235                 // Not own constructor property must be Object
1236                 if ( obj.constructor &&
1237                         !hasOwn.call(obj, "constructor") &&
1238                         !hasOwn.call(obj.constructor.prototype, "isPrototypeOf") ) {
1239                         return false;
1240                 }
1241
1242                 // Own properties are enumerated firstly, so to speed up,
1243                 // if last one is own, then all properties are own.
1244
1245                 var key;
1246                 for ( key in obj ) {}
1247
1248                 return key === undefined || hasOwn.call( obj, key );
1249         },
1250
1251         isEmptyObject: function( obj ) {
1252                 for ( var name in obj ) {
1253                         return false;
1254                 }
1255                 return true;
1256         },
1257
1258         error: function( msg ) {
1259                 throw msg;
1260         },
1261
1262         parseJSON: function( data ) {
1263                 if ( typeof data !== "string" || !data ) {
1264                         return null;
1265                 }
1266
1267                 // Make sure leading/trailing whitespace is removed (IE can't handle it)
1268                 data = jQuery.trim( data );
1269
1270                 // Attempt to parse using the native JSON parser first
1271                 if ( window.JSON && window.JSON.parse ) {
1272                         return window.JSON.parse( data );
1273                 }
1274
1275                 // Make sure the incoming data is actual JSON
1276                 // Logic borrowed from http://json.org/json2.js
1277                 if ( rvalidchars.test( data.replace( rvalidescape, "@" )
1278                         .replace( rvalidtokens, "]" )
1279                         .replace( rvalidbraces, "")) ) {
1280
1281                         return (new Function( "return " + data ))();
1282
1283                 }
1284                 jQuery.error( "Invalid JSON: " + data );
1285         },
1286
1287         // Cross-browser xml parsing
1288         // (xml & tmp used internally)
1289         parseXML: function( data , xml , tmp ) {
1290
1291                 if ( window.DOMParser ) { // Standard
1292                         tmp = new DOMParser();
1293                         xml = tmp.parseFromString( data , "text/xml" );
1294                 } else { // IE
1295                         xml = new ActiveXObject( "Microsoft.XMLDOM" );
1296                         xml.async = "false";
1297                         xml.loadXML( data );
1298                 }
1299
1300                 tmp = xml.documentElement;
1301
1302                 if ( ! tmp || ! tmp.nodeName || tmp.nodeName === "parsererror" ) {
1303                         jQuery.error( "Invalid XML: " + data );
1304                 }
1305
1306                 return xml;
1307         },
1308
1309         noop: function() {},
1310
1311         // Evaluates a script in a global context
1312         // Workarounds based on findings by Jim Driscoll
1313         // http://weblogs.java.net/blog/driscoll/archive/2009/09/08/eval-javascript-global-context
1314         globalEval: function( data ) {
1315                 if ( data && rnotwhite.test( data ) ) {
1316                         // We use execScript on Internet Explorer
1317                         // We use an anonymous function so that context is window
1318                         // rather than jQuery in Firefox
1319                         ( window.execScript || function( data ) {
1320                                 window[ "eval" ].call( window, data );
1321                         } )( data );
1322                 }
1323         },
1324
1325         nodeName: function( elem, name ) {
1326                 return elem.nodeName && elem.nodeName.toUpperCase() === name.toUpperCase();
1327         },
1328
1329         // args is for internal usage only
1330         each: function( object, callback, args ) {
1331                 var name, i = 0,
1332                         length = object.length,
1333                         isObj = length === undefined || jQuery.isFunction( object );
1334
1335                 if ( args ) {
1336                         if ( isObj ) {
1337                                 for ( name in object ) {
1338                                         if ( callback.apply( object[ name ], args ) === false ) {
1339                                                 break;
1340                                         }
1341                                 }
1342                         } else {
1343                                 for ( ; i < length; ) {
1344                                         if ( callback.apply( object[ i++ ], args ) === false ) {
1345                                                 break;
1346                                         }
1347                                 }
1348                         }
1349
1350                 // A special, fast, case for the most common use of each
1351                 } else {
1352                         if ( isObj ) {
1353                                 for ( name in object ) {
1354                                         if ( callback.call( object[ name ], name, object[ name ] ) === false ) {
1355                                                 break;
1356                                         }
1357                                 }
1358                         } else {
1359                                 for ( ; i < length; ) {
1360                                         if ( callback.call( object[ i ], i, object[ i++ ] ) === false ) {
1361                                                 break;
1362                                         }
1363                                 }
1364                         }
1365                 }
1366
1367                 return object;
1368         },
1369
1370         // Use native String.trim function wherever possible
1371         trim: trim ?
1372                 function( text ) {
1373                         return text == null ?
1374                                 "" :
1375                                 trim.call( text );
1376                 } :
1377
1378                 // Otherwise use our own trimming functionality
1379                 function( text ) {
1380                         return text == null ?
1381                                 "" :
1382                                 text.toString().replace( trimLeft, "" ).replace( trimRight, "" );
1383                 },
1384
1385         // results is for internal usage only
1386         makeArray: function( array, results ) {
1387                 var ret = results || [];
1388
1389                 if ( array != null ) {
1390                         // The window, strings (and functions) also have 'length'
1391                         // The extra typeof function check is to prevent crashes
1392                         // in Safari 2 (See: #3039)
1393                         // Tweaked logic slightly to handle Blackberry 4.7 RegExp issues #6930
1394                         var type = jQuery.type( array );
1395
1396                         if ( array.length == null || type === "string" || type === "function" || type === "regexp" || jQuery.isWindow( array ) ) {
1397                                 push.call( ret, array );
1398                         } else {
1399                                 jQuery.merge( ret, array );
1400                         }
1401                 }
1402
1403                 return ret;
1404         },
1405
1406         inArray: function( elem, array ) {
1407
1408                 if ( indexOf ) {
1409                         return indexOf.call( array, elem );
1410                 }
1411
1412                 for ( var i = 0, length = array.length; i < length; i++ ) {
1413                         if ( array[ i ] === elem ) {
1414                                 return i;
1415                         }
1416                 }
1417
1418                 return -1;
1419         },
1420
1421         merge: function( first, second ) {
1422                 var i = first.length,
1423                         j = 0;
1424
1425                 if ( typeof second.length === "number" ) {
1426                         for ( var l = second.length; j < l; j++ ) {
1427                                 first[ i++ ] = second[ j ];
1428                         }
1429
1430                 } else {
1431                         while ( second[j] !== undefined ) {
1432                                 first[ i++ ] = second[ j++ ];
1433                         }
1434                 }
1435
1436                 first.length = i;
1437
1438                 return first;
1439         },
1440
1441         grep: function( elems, callback, inv ) {
1442                 var ret = [], retVal;
1443                 inv = !!inv;
1444
1445                 // Go through the array, only saving the items
1446                 // that pass the validator function
1447                 for ( var i = 0, length = elems.length; i < length; i++ ) {
1448                         retVal = !!callback( elems[ i ], i );
1449                         if ( inv !== retVal ) {
1450                                 ret.push( elems[ i ] );
1451                         }
1452                 }
1453
1454                 return ret;
1455         },
1456
1457         // arg is for internal usage only
1458         map: function( elems, callback, arg ) {
1459                 var value, key, ret = [],
1460                         i = 0,
1461                         length = elems.length,
1462                         // jquery objects are treated as arrays
1463                         isArray = elems instanceof jQuery || length !== undefined && typeof length === "number" && ( ( length > 0 && elems[ 0 ] && elems[ length -1 ] ) || length === 0 || jQuery.isArray( elems ) ) ;
1464
1465                 // Go through the array, translating each of the items to their
1466                 if ( isArray ) {
1467                         for ( ; i < length; i++ ) {
1468                                 value = callback( elems[ i ], i, arg );
1469
1470                                 if ( value != null ) {
1471                                         ret[ ret.length ] = value;
1472                                 }
1473                         }
1474
1475                 // Go through every key on the object,
1476                 } else {
1477                         for ( key in elems ) {
1478                                 value = callback( elems[ key ], key, arg );
1479
1480                                 if ( value != null ) {
1481                                         ret[ ret.length ] = value;
1482                                 }
1483                         }
1484                 }
1485
1486                 // Flatten any nested arrays
1487                 return ret.concat.apply( [], ret );
1488         },
1489
1490         // A global GUID counter for objects
1491         guid: 1,
1492
1493         // Bind a function to a context, optionally partially applying any
1494         // arguments.
1495         proxy: function( fn, context ) {
1496                 if ( typeof context === "string" ) {
1497                         var tmp = fn[ context ];
1498                         context = fn;
1499                         fn = tmp;
1500                 }
1501
1502                 // Quick check to determine if target is callable, in the spec
1503                 // this throws a TypeError, but we will just return undefined.
1504                 if ( !jQuery.isFunction( fn ) ) {
1505                         return undefined;
1506                 }
1507
1508                 // Simulated bind
1509                 var args = slice.call( arguments, 2 ),
1510                         proxy = function() {
1511                                 return fn.apply( context, args.concat( slice.call( arguments ) ) );
1512                         };
1513
1514                 // Set the guid of unique handler to the same of original handler, so it can be removed
1515                 proxy.guid = fn.guid = fn.guid || proxy.guid || jQuery.guid++;
1516
1517                 return proxy;
1518         },
1519
1520         // Mutifunctional method to get and set values to a collection
1521         // The value/s can be optionally by executed if its a function
1522         access: function( elems, key, value, exec, fn, pass ) {
1523                 var length = elems.length;
1524
1525                 // Setting many attributes
1526                 if ( typeof key === "object" ) {
1527                         for ( var k in key ) {
1528                                 jQuery.access( elems, k, key[k], exec, fn, value );
1529                         }
1530                         return elems;
1531                 }
1532
1533                 // Setting one attribute
1534                 if ( value !== undefined ) {
1535                         // Optionally, function values get executed if exec is true
1536                         exec = !pass && exec && jQuery.isFunction(value);
1537
1538                         for ( var i = 0; i < length; i++ ) {
1539                                 fn( elems[i], key, exec ? value.call( elems[i], i, fn( elems[i], key ) ) : value, pass );
1540                         }
1541
1542                         return elems;
1543                 }
1544
1545                 // Getting an attribute
1546                 return length ? fn( elems[0], key ) : undefined;
1547         },
1548
1549         now: function() {
1550                 return (new Date()).getTime();
1551         },
1552
1553         // Use of jQuery.browser is frowned upon.
1554         // More details: http://docs.jquery.com/Utilities/jQuery.browser
1555         uaMatch: function( ua ) {
1556                 ua = ua.toLowerCase();
1557
1558                 var match = rwebkit.exec( ua ) ||
1559                         ropera.exec( ua ) ||
1560                         rmsie.exec( ua ) ||
1561                         ua.indexOf("compatible") < 0 && rmozilla.exec( ua ) ||
1562                         [];
1563
1564                 return { browser: match[1] || "", version: match[2] || "0" };
1565         },
1566
1567         sub: function() {
1568                 function jQuerySub( selector, context ) {
1569                         return new jQuerySub.fn.init( selector, context );
1570                 }
1571                 jQuery.extend( true, jQuerySub, this );
1572                 jQuerySub.superclass = this;
1573                 jQuerySub.fn = jQuerySub.prototype = this();
1574                 jQuerySub.fn.constructor = jQuerySub;
1575                 jQuerySub.sub = this.sub;
1576                 jQuerySub.fn.init = function init( selector, context ) {
1577                         if ( context && context instanceof jQuery && !(context instanceof jQuerySub) ) {
1578                                 context = jQuerySub( context );
1579                         }
1580
1581                         return jQuery.fn.init.call( this, selector, context, rootjQuerySub );
1582                 };
1583                 jQuerySub.fn.init.prototype = jQuerySub.fn;
1584                 var rootjQuerySub = jQuerySub(document);
1585                 return jQuerySub;
1586         },
1587
1588         browser: {}
1589 });
1590
1591 // Populate the class2type map
1592 jQuery.each("Boolean Number String Function Array Date RegExp Object".split(" "), function(i, name) {
1593         class2type[ "[object " + name + "]" ] = name.toLowerCase();
1594 });
1595
1596 browserMatch = jQuery.uaMatch( userAgent );
1597 if ( browserMatch.browser ) {
1598         jQuery.browser[ browserMatch.browser ] = true;
1599         jQuery.browser.version = browserMatch.version;
1600 }
1601
1602 // Deprecated, use jQuery.browser.webkit instead
1603 if ( jQuery.browser.webkit ) {
1604         jQuery.browser.safari = true;
1605 }
1606
1607 // IE doesn't match non-breaking spaces with \s
1608 if ( rnotwhite.test( "\xA0" ) ) {
1609         trimLeft = /^[\s\xA0]+/;
1610         trimRight = /[\s\xA0]+$/;
1611 }
1612
1613 // All jQuery objects should point back to these
1614 rootjQuery = jQuery(document);
1615
1616 // Cleanup functions for the document ready method
1617 if ( document.addEventListener ) {
1618         DOMContentLoaded = function() {
1619                 document.removeEventListener( "DOMContentLoaded", DOMContentLoaded, false );
1620                 jQuery.ready();
1621         };
1622
1623 } else if ( document.attachEvent ) {
1624         DOMContentLoaded = function() {
1625                 // Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443).
1626                 if ( document.readyState === "complete" ) {
1627                         document.detachEvent( "onreadystatechange", DOMContentLoaded );
1628                         jQuery.ready();
1629                 }
1630         };
1631 }
1632
1633 // The DOM ready check for Internet Explorer
1634 function doScrollCheck() {
1635         if ( jQuery.isReady ) {
1636                 return;
1637         }
1638
1639         try {
1640                 // If IE is used, use the trick by Diego Perini
1641                 // http://javascript.nwbox.com/IEContentLoaded/
1642                 document.documentElement.doScroll("left");
1643         } catch(e) {
1644                 setTimeout( doScrollCheck, 1 );
1645                 return;
1646         }
1647
1648         // and execute any waiting functions
1649         jQuery.ready();
1650 }
1651
1652 // Expose jQuery to the global object
1653 return jQuery;
1654
1655 })();
1656
1657
1658 var // Promise methods
1659         promiseMethods = "done fail isResolved isRejected promise then always pipe".split( " " ),
1660         // Static reference to slice
1661         sliceDeferred = [].slice;
1662
1663 jQuery.extend({
1664         // Create a simple deferred (one callbacks list)
1665         _Deferred: function() {
1666                 var // callbacks list
1667                         callbacks = [],
1668                         // stored [ context , args ]
1669                         fired,
1670                         // to avoid firing when already doing so
1671                         firing,
1672                         // flag to know if the deferred has been cancelled
1673                         cancelled,
1674                         // the deferred itself
1675                         deferred  = {
1676
1677                                 // done( f1, f2, ...)
1678                                 done: function() {
1679                                         if ( !cancelled ) {
1680                                                 var args = arguments,
1681                                                         i,
1682                                                         length,
1683                                                         elem,
1684                                                         type,
1685                                                         _fired;
1686                                                 if ( fired ) {
1687                                                         _fired = fired;
1688                                                         fired = 0;
1689                                                 }
1690                                                 for ( i = 0, length = args.length; i < length; i++ ) {
1691                                                         elem = args[ i ];
1692                                                         type = jQuery.type( elem );
1693                                                         if ( type === "array" ) {
1694                                                                 deferred.done.apply( deferred, elem );
1695                                                         } else if ( type === "function" ) {
1696                                                                 callbacks.push( elem );
1697                                                         }
1698                                                 }
1699                                                 if ( _fired ) {
1700                                                         deferred.resolveWith( _fired[ 0 ], _fired[ 1 ] );
1701                                                 }
1702                                         }
1703                                         return this;
1704                                 },
1705
1706                                 // resolve with given context and args
1707                                 resolveWith: function( context, args ) {
1708                                         if ( !cancelled && !fired && !firing ) {
1709                                                 // make sure args are available (#8421)
1710                                                 args = args || [];
1711                                                 firing = 1;
1712                                                 try {
1713                                                         while( callbacks[ 0 ] ) {
1714                                                                 callbacks.shift().apply( context, args );
1715                                                         }
1716                                                 }
1717                                                 finally {
1718                                                         fired = [ context, args ];
1719                                                         firing = 0;
1720                                                 }
1721                                         }
1722                                         return this;
1723                                 },
1724
1725                                 // resolve with this as context and given arguments
1726                                 resolve: function() {
1727                                         deferred.resolveWith( this, arguments );
1728                                         return this;
1729                                 },
1730
1731                                 // Has this deferred been resolved?
1732                                 isResolved: function() {
1733                                         return !!( firing || fired );
1734                                 },
1735
1736                                 // Cancel
1737                                 cancel: function() {
1738                                         cancelled = 1;
1739                                         callbacks = [];
1740                                         return this;
1741                                 }
1742                         };
1743
1744                 return deferred;
1745         },
1746
1747         // Full fledged deferred (two callbacks list)
1748         Deferred: function( func ) {
1749                 var deferred = jQuery._Deferred(),
1750                         failDeferred = jQuery._Deferred(),
1751                         promise;
1752                 // Add errorDeferred methods, then and promise
1753                 jQuery.extend( deferred, {
1754                         then: function( doneCallbacks, failCallbacks ) {
1755                                 deferred.done( doneCallbacks ).fail( failCallbacks );
1756                                 return this;
1757                         },
1758                         always: function() {
1759                                 return deferred.done.apply( deferred, arguments ).fail.apply( this, arguments );
1760                         },
1761                         fail: failDeferred.done,
1762                         rejectWith: failDeferred.resolveWith,
1763                         reject: failDeferred.resolve,
1764                         isRejected: failDeferred.isResolved,
1765                         pipe: function( fnDone, fnFail ) {
1766                                 return jQuery.Deferred(function( newDefer ) {
1767                                         jQuery.each( {
1768                                                 done: [ fnDone, "resolve" ],
1769                                                 fail: [ fnFail, "reject" ]
1770                                         }, function( handler, data ) {
1771                                                 var fn = data[ 0 ],
1772                                                         action = data[ 1 ],
1773                                                         returned;
1774                                                 if ( jQuery.isFunction( fn ) ) {
1775                                                         deferred[ handler ](function() {
1776                                                                 returned = fn.apply( this, arguments );
1777                                                                 if ( jQuery.isFunction( returned.promise ) ) {
1778                                                                         returned.promise().then( newDefer.resolve, newDefer.reject );
1779                                                                 } else {
1780                                                                         newDefer[ action ]( returned );
1781                                                                 }
1782                                                         });
1783                                                 } else {
1784                                                         deferred[ handler ]( newDefer[ action ] );
1785                                                 }
1786                                         });
1787                                 }).promise();
1788                         },
1789                         // Get a promise for this deferred
1790                         // If obj is provided, the promise aspect is added to the object
1791                         promise: function( obj ) {
1792                                 if ( obj == null ) {
1793                                         if ( promise ) {
1794                                                 return promise;
1795                                         }
1796                                         promise = obj = {};
1797                                 }
1798                                 var i = promiseMethods.length;
1799                                 while( i-- ) {
1800                                         obj[ promiseMethods[i] ] = deferred[ promiseMethods[i] ];
1801                                 }
1802                                 return obj;
1803                         }
1804                 });
1805                 // Make sure only one callback list will be used
1806                 deferred.done( failDeferred.cancel ).fail( deferred.cancel );
1807                 // Unexpose cancel
1808                 delete deferred.cancel;
1809                 // Call given func if any
1810                 if ( func ) {
1811                         func.call( deferred, deferred );
1812                 }
1813                 return deferred;
1814         },
1815
1816         // Deferred helper
1817         when: function( firstParam ) {
1818                 var args = arguments,
1819                         i = 0,
1820                         length = args.length,
1821                         count = length,
1822                         deferred = length <= 1 && firstParam && jQuery.isFunction( firstParam.promise ) ?
1823                                 firstParam :
1824                                 jQuery.Deferred();
1825                 function resolveFunc( i ) {
1826                         return function( value ) {
1827                                 args[ i ] = arguments.length > 1 ? sliceDeferred.call( arguments, 0 ) : value;
1828                                 if ( !( --count ) ) {
1829                                         // Strange bug in FF4:
1830                                         // Values changed onto the arguments object sometimes end up as undefined values
1831                                         // outside the $.when method. Cloning the object into a fresh array solves the issue
1832                                         deferred.resolveWith( deferred, sliceDeferred.call( args, 0 ) );
1833                                 }
1834                         };
1835                 }
1836                 if ( length > 1 ) {
1837                         for( ; i < length; i++ ) {
1838                                 if ( args[ i ] && jQuery.isFunction( args[ i ].promise ) ) {
1839                                         args[ i ].promise().then( resolveFunc(i), deferred.reject );
1840                                 } else {
1841                                         --count;
1842                                 }
1843                         }
1844                         if ( !count ) {
1845                                 deferred.resolveWith( deferred, args );
1846                         }
1847                 } else if ( deferred !== firstParam ) {
1848                         deferred.resolveWith( deferred, length ? [ firstParam ] : [] );
1849                 }
1850                 return deferred.promise();
1851         }
1852 });
1853
1854
1855
1856 jQuery.support = (function() {
1857
1858         var div = document.createElement( "div" ),
1859                 all,
1860                 a,
1861                 select,
1862                 opt,
1863                 input,
1864                 marginDiv,
1865                 support,
1866                 fragment,
1867                 body,
1868                 bodyStyle,
1869                 tds,
1870                 events,
1871                 eventName,
1872                 i,
1873                 isSupported;
1874
1875         // Preliminary tests
1876         div.setAttribute("className", "t");
1877         div.innerHTML = "   <link/><table></table><a href='/a' style='top:1px;float:left;opacity:.55;'>a</a><input type='checkbox'/>";
1878
1879         all = div.getElementsByTagName( "*" );
1880         a = div.getElementsByTagName( "a" )[ 0 ];
1881
1882         // Can't get basic test support
1883         if ( !all || !all.length || !a ) {
1884                 return {};
1885         }
1886
1887         // First batch of supports tests
1888         select = document.createElement( "select" );
1889         opt = select.appendChild( document.createElement("option") );
1890         input = div.getElementsByTagName( "input" )[ 0 ];
1891
1892         support = {
1893                 // IE strips leading whitespace when .innerHTML is used
1894                 leadingWhitespace: ( div.firstChild.nodeType === 3 ),
1895
1896                 // Make sure that tbody elements aren't automatically inserted
1897                 // IE will insert them into empty tables
1898                 tbody: !div.getElementsByTagName( "tbody" ).length,
1899
1900                 // Make sure that link elements get serialized correctly by innerHTML
1901                 // This requires a wrapper element in IE
1902                 htmlSerialize: !!div.getElementsByTagName( "link" ).length,
1903
1904                 // Get the style information from getAttribute
1905                 // (IE uses .cssText instead)
1906                 style: /top/.test( a.getAttribute("style") ),
1907
1908                 // Make sure that URLs aren't manipulated
1909                 // (IE normalizes it by default)
1910                 hrefNormalized: ( a.getAttribute( "href" ) === "/a" ),
1911
1912                 // Make sure that element opacity exists
1913                 // (IE uses filter instead)
1914                 // Use a regex to work around a WebKit issue. See #5145
1915                 opacity: /^0.55$/.test( a.style.opacity ),
1916
1917                 // Verify style float existence
1918                 // (IE uses styleFloat instead of cssFloat)
1919                 cssFloat: !!a.style.cssFloat,
1920
1921                 // Make sure that if no value is specified for a checkbox
1922                 // that it defaults to "on".
1923                 // (WebKit defaults to "" instead)
1924                 checkOn: ( input.value === "on" ),
1925
1926                 // Make sure that a selected-by-default option has a working selected property.
1927                 // (WebKit defaults to false instead of true, IE too, if it's in an optgroup)
1928                 optSelected: opt.selected,
1929
1930                 // Test setAttribute on camelCase class. If it works, we need attrFixes when doing get/setAttribute (ie6/7)
1931                 getSetAttribute: div.className !== "t",
1932
1933                 // Will be defined later
1934                 submitBubbles: true,
1935                 changeBubbles: true,
1936                 focusinBubbles: false,
1937                 deleteExpando: true,
1938                 noCloneEvent: true,
1939                 inlineBlockNeedsLayout: false,
1940                 shrinkWrapBlocks: false,
1941                 reliableMarginRight: true
1942         };
1943
1944         // Make sure checked status is properly cloned
1945         input.checked = true;
1946         support.noCloneChecked = input.cloneNode( true ).checked;
1947
1948         // Make sure that the options inside disabled selects aren't marked as disabled
1949         // (WebKit marks them as disabled)
1950         select.disabled = true;
1951         support.optDisabled = !opt.disabled;
1952
1953         // Test to see if it's possible to delete an expando from an element
1954         // Fails in Internet Explorer
1955         try {
1956                 delete div.test;
1957         } catch( e ) {
1958                 support.deleteExpando = false;
1959         }
1960
1961         if ( !div.addEventListener && div.attachEvent && div.fireEvent ) {
1962                 div.attachEvent( "onclick", function click() {
1963                         // Cloning a node shouldn't copy over any
1964                         // bound event handlers (IE does this)
1965                         support.noCloneEvent = false;
1966                         div.detachEvent( "onclick", click );
1967                 });
1968                 div.cloneNode( true ).fireEvent( "onclick" );
1969         }
1970
1971         // Check if a radio maintains it's value
1972         // after being appended to the DOM
1973         input = document.createElement("input");
1974         input.value = "t";
1975         input.setAttribute("type", "radio");
1976         support.radioValue = input.value === "t";
1977
1978         input.setAttribute("checked", "checked");
1979         div.appendChild( input );
1980         fragment = document.createDocumentFragment();
1981         fragment.appendChild( div.firstChild );
1982
1983         // WebKit doesn't clone checked state correctly in fragments
1984         support.checkClone = fragment.cloneNode( true ).cloneNode( true ).lastChild.checked;
1985
1986         div.innerHTML = "";
1987
1988         // Figure out if the W3C box model works as expected
1989         div.style.width = div.style.paddingLeft = "1px";
1990
1991         // We use our own, invisible, body
1992         body = document.createElement( "body" );
1993         bodyStyle = {
1994                 visibility: "hidden",
1995                 width: 0,
1996                 height: 0,
1997                 border: 0,
1998                 margin: 0,
1999                 // Set background to avoid IE crashes when removing (#9028)
2000                 background: "none"
2001         };
2002         for ( i in bodyStyle ) {
2003                 body.style[ i ] = bodyStyle[ i ];
2004         }
2005         body.appendChild( div );
2006         document.documentElement.appendChild( body );
2007
2008         // Check if a disconnected checkbox will retain its checked
2009         // value of true after appended to the DOM (IE6/7)
2010         support.appendChecked = input.checked;
2011
2012         support.boxModel = div.offsetWidth === 2;
2013
2014         if ( "zoom" in div.style ) {
2015                 // Check if natively block-level elements act like inline-block
2016                 // elements when setting their display to 'inline' and giving
2017                 // them layout
2018                 // (IE < 8 does this)
2019                 div.style.display = "inline";
2020                 div.style.zoom = 1;
2021                 support.inlineBlockNeedsLayout = ( div.offsetWidth === 2 );
2022
2023                 // Check if elements with layout shrink-wrap their children
2024                 // (IE 6 does this)
2025                 div.style.display = "";
2026                 div.innerHTML = "<div style='width:4px;'></div>";
2027                 support.shrinkWrapBlocks = ( div.offsetWidth !== 2 );
2028         }
2029
2030         div.innerHTML = "<table><tr><td style='padding:0;border:0;display:none'></td><td>t</td></tr></table>";
2031         tds = div.getElementsByTagName( "td" );
2032
2033         // Check if table cells still have offsetWidth/Height when they are set
2034         // to display:none and there are still other visible table cells in a
2035         // table row; if so, offsetWidth/Height are not reliable for use when
2036         // determining if an element has been hidden directly using
2037         // display:none (it is still safe to use offsets if a parent element is
2038         // hidden; don safety goggles and see bug #4512 for more information).
2039         // (only IE 8 fails this test)
2040         isSupported = ( tds[ 0 ].offsetHeight === 0 );
2041
2042         tds[ 0 ].style.display = "";
2043         tds[ 1 ].style.display = "none";
2044
2045         // Check if empty table cells still have offsetWidth/Height
2046         // (IE < 8 fail this test)
2047         support.reliableHiddenOffsets = isSupported && ( tds[ 0 ].offsetHeight === 0 );
2048         div.innerHTML = "";
2049
2050         // Check if div with explicit width and no margin-right incorrectly
2051         // gets computed margin-right based on width of container. For more
2052         // info see bug #3333
2053         // Fails in WebKit before Feb 2011 nightlies
2054         // WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right
2055         if ( document.defaultView && document.defaultView.getComputedStyle ) {
2056                 marginDiv = document.createElement( "div" );
2057                 marginDiv.style.width = "0";
2058                 marginDiv.style.marginRight = "0";
2059                 div.appendChild( marginDiv );
2060                 support.reliableMarginRight =
2061                         ( parseInt( document.defaultView.getComputedStyle( marginDiv, null ).marginRight, 10 ) || 0 ) === 0;
2062         }
2063
2064         // Remove the body element we added
2065         body.innerHTML = "";
2066         document.documentElement.removeChild( body );
2067
2068         // Technique from Juriy Zaytsev
2069         // http://thinkweb2.com/projects/prototype/detecting-event-support-without-browser-sniffing/
2070         // We only care about the case where non-standard event systems
2071         // are used, namely in IE. Short-circuiting here helps us to
2072         // avoid an eval call (in setAttribute) which can cause CSP
2073         // to go haywire. See: https://developer.mozilla.org/en/Security/CSP
2074         if ( div.attachEvent ) {
2075                 for( i in {
2076                         submit: 1,
2077                         change: 1,
2078                         focusin: 1
2079                 } ) {
2080                         eventName = "on" + i;
2081                         isSupported = ( eventName in div );
2082                         if ( !isSupported ) {
2083                                 div.setAttribute( eventName, "return;" );
2084                                 isSupported = ( typeof div[ eventName ] === "function" );
2085                         }
2086                         support[ i + "Bubbles" ] = isSupported;
2087                 }
2088         }
2089
2090         return support;
2091 })();
2092
2093 // Keep track of boxModel
2094 jQuery.boxModel = jQuery.support.boxModel;
2095
2096
2097
2098
2099 var rbrace = /^(?:\{.*\}|\[.*\])$/,
2100         rmultiDash = /([a-z])([A-Z])/g;
2101
2102 jQuery.extend({
2103         cache: {},
2104
2105         // Please use with caution
2106         uuid: 0,
2107
2108         // Unique for each copy of jQuery on the page
2109         // Non-digits removed to match rinlinejQuery
2110         expando: "jQuery" + ( jQuery.fn.jquery + Math.random() ).replace( /\D/g, "" ),
2111
2112         // The following elements throw uncatchable exceptions if you
2113         // attempt to add expando properties to them.
2114         noData: {
2115                 "embed": true,
2116                 // Ban all objects except for Flash (which handle expandos)
2117                 "object": "clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",
2118                 "applet": true
2119         },
2120
2121         hasData: function( elem ) {
2122                 elem = elem.nodeType ? jQuery.cache[ elem[jQuery.expando] ] : elem[ jQuery.expando ];
2123
2124                 return !!elem && !isEmptyDataObject( elem );
2125         },
2126
2127         data: function( elem, name, data, pvt /* Internal Use Only */ ) {
2128                 if ( !jQuery.acceptData( elem ) ) {
2129                         return;
2130                 }
2131
2132                 var internalKey = jQuery.expando, getByName = typeof name === "string", thisCache,
2133
2134                         // We have to handle DOM nodes and JS objects differently because IE6-7
2135                         // can't GC object references properly across the DOM-JS boundary
2136                         isNode = elem.nodeType,
2137
2138                         // Only DOM nodes need the global jQuery cache; JS object data is
2139                         // attached directly to the object so GC can occur automatically
2140                         cache = isNode ? jQuery.cache : elem,
2141
2142                         // Only defining an ID for JS objects if its cache already exists allows
2143                         // the code to shortcut on the same path as a DOM node with no cache
2144                         id = isNode ? elem[ jQuery.expando ] : elem[ jQuery.expando ] && jQuery.expando;
2145
2146                 // Avoid doing any more work than we need to when trying to get data on an
2147                 // object that has no data at all
2148                 if ( (!id || (pvt && id && !cache[ id ][ internalKey ])) && getByName && data === undefined ) {
2149                         return;
2150                 }
2151
2152                 if ( !id ) {
2153                         // Only DOM nodes need a new unique ID for each element since their data
2154                         // ends up in the global cache
2155                         if ( isNode ) {
2156                                 elem[ jQuery.expando ] = id = ++jQuery.uuid;
2157                         } else {
2158                                 id = jQuery.expando;
2159                         }
2160                 }
2161
2162                 if ( !cache[ id ] ) {
2163                         cache[ id ] = {};
2164
2165                         // TODO: This is a hack for 1.5 ONLY. Avoids exposing jQuery
2166                         // metadata on plain JS objects when the object is serialized using
2167                         // JSON.stringify
2168                         if ( !isNode ) {
2169                                 cache[ id ].toJSON = jQuery.noop;
2170                         }
2171                 }
2172
2173                 // An object can be passed to jQuery.data instead of a key/value pair; this gets
2174                 // shallow copied over onto the existing cache
2175                 if ( typeof name === "object" || typeof name === "function" ) {
2176                         if ( pvt ) {
2177                                 cache[ id ][ internalKey ] = jQuery.extend(cache[ id ][ internalKey ], name);
2178                         } else {
2179                                 cache[ id ] = jQuery.extend(cache[ id ], name);
2180                         }
2181                 }
2182
2183                 thisCache = cache[ id ];
2184
2185                 // Internal jQuery data is stored in a separate object inside the object's data
2186                 // cache in order to avoid key collisions between internal data and user-defined
2187                 // data
2188                 if ( pvt ) {
2189                         if ( !thisCache[ internalKey ] ) {
2190                                 thisCache[ internalKey ] = {};
2191                         }
2192
2193                         thisCache = thisCache[ internalKey ];
2194                 }
2195
2196                 if ( data !== undefined ) {
2197                         thisCache[ name ] = data;
2198                 }
2199
2200                 // TODO: This is a hack for 1.5 ONLY. It will be removed in 1.6. Users should
2201                 // not attempt to inspect the internal events object using jQuery.data, as this
2202                 // internal data object is undocumented and subject to change.
2203                 if ( name === "events" && !thisCache[name] ) {
2204                         return thisCache[ internalKey ] && thisCache[ internalKey ].events;
2205                 }
2206
2207                 return getByName ? thisCache[ name ] : thisCache;
2208         },
2209
2210         removeData: function( elem, name, pvt /* Internal Use Only */ ) {
2211                 if ( !jQuery.acceptData( elem ) ) {
2212                         return;
2213                 }
2214
2215                 var internalKey = jQuery.expando, isNode = elem.nodeType,
2216
2217                         // See jQuery.data for more information
2218                         cache = isNode ? jQuery.cache : elem,
2219
2220                         // See jQuery.data for more information
2221                         id = isNode ? elem[ jQuery.expando ] : jQuery.expando;
2222
2223                 // If there is already no cache entry for this object, there is no
2224                 // purpose in continuing
2225                 if ( !cache[ id ] ) {
2226                         return;
2227                 }
2228
2229                 if ( name ) {
2230                         var thisCache = pvt ? cache[ id ][ internalKey ] : cache[ id ];
2231
2232                         if ( thisCache ) {
2233                                 delete thisCache[ name ];
2234
2235                                 // If there is no data left in the cache, we want to continue
2236                                 // and let the cache object itself get destroyed
2237                                 if ( !isEmptyDataObject(thisCache) ) {
2238                                         return;
2239                                 }
2240                         }
2241                 }
2242
2243                 // See jQuery.data for more information
2244                 if ( pvt ) {
2245                         delete cache[ id ][ internalKey ];
2246
2247                         // Don't destroy the parent cache unless the internal data object
2248                         // had been the only thing left in it
2249                         if ( !isEmptyDataObject(cache[ id ]) ) {
2250                                 return;
2251                         }
2252                 }
2253
2254                 var internalCache = cache[ id ][ internalKey ];
2255
2256                 // Browsers that fail expando deletion also refuse to delete expandos on
2257                 // the window, but it will allow it on all other JS objects; other browsers
2258                 // don't care
2259                 if ( jQuery.support.deleteExpando || cache != window ) {
2260                         delete cache[ id ];
2261                 } else {
2262                         cache[ id ] = null;
2263                 }
2264
2265                 // We destroyed the entire user cache at once because it's faster than
2266                 // iterating through each key, but we need to continue to persist internal
2267                 // data if it existed
2268                 if ( internalCache ) {
2269                         cache[ id ] = {};
2270                         // TODO: This is a hack for 1.5 ONLY. Avoids exposing jQuery
2271                         // metadata on plain JS objects when the object is serialized using
2272                         // JSON.stringify
2273                         if ( !isNode ) {
2274                                 cache[ id ].toJSON = jQuery.noop;
2275                         }
2276
2277                         cache[ id ][ internalKey ] = internalCache;
2278
2279                 // Otherwise, we need to eliminate the expando on the node to avoid
2280                 // false lookups in the cache for entries that no longer exist
2281                 } else if ( isNode ) {
2282                         // IE does not allow us to delete expando properties from nodes,
2283                         // nor does it have a removeAttribute function on Document nodes;
2284                         // we must handle all of these cases
2285                         if ( jQuery.support.deleteExpando ) {
2286                                 delete elem[ jQuery.expando ];
2287                         } else if ( elem.removeAttribute ) {
2288                                 elem.removeAttribute( jQuery.expando );
2289                         } else {
2290                                 elem[ jQuery.expando ] = null;
2291                         }
2292                 }
2293         },
2294
2295         // For internal use only.
2296         _data: function( elem, name, data ) {
2297                 return jQuery.data( elem, name, data, true );
2298         },
2299
2300         // A method for determining if a DOM node can handle the data expando
2301         acceptData: function( elem ) {
2302                 if ( elem.nodeName ) {
2303                         var match = jQuery.noData[ elem.nodeName.toLowerCase() ];
2304
2305                         if ( match ) {
2306                                 return !(match === true || elem.getAttribute("classid") !== match);
2307                         }
2308                 }
2309
2310                 return true;
2311         }
2312 });
2313
2314 jQuery.fn.extend({
2315         data: function( key, value ) {
2316                 var data = null;
2317
2318                 if ( typeof key === "undefined" ) {
2319                         if ( this.length ) {
2320                                 data = jQuery.data( this[0] );
2321
2322                                 if ( this[0].nodeType === 1 ) {
2323                             var attr = this[0].attributes, name;
2324                                         for ( var i = 0, l = attr.length; i < l; i++ ) {
2325                                                 name = attr[i].name;
2326
2327                                                 if ( name.indexOf( "data-" ) === 0 ) {
2328                                                         name = jQuery.camelCase( name.substring(5) );
2329
2330                                                         dataAttr( this[0], name, data[ name ] );
2331                                                 }
2332                                         }
2333                                 }
2334                         }
2335
2336                         return data;
2337
2338                 } else if ( typeof key === "object" ) {
2339                         return this.each(function() {
2340                                 jQuery.data( this, key );
2341                         });
2342                 }
2343
2344                 var parts = key.split(".");
2345                 parts[1] = parts[1] ? "." + parts[1] : "";
2346
2347                 if ( value === undefined ) {
2348                         data = this.triggerHandler("getData" + parts[1] + "!", [parts[0]]);
2349
2350                         // Try to fetch any internally stored data first
2351                         if ( data === undefined && this.length ) {
2352                                 data = jQuery.data( this[0], key );
2353                                 data = dataAttr( this[0], key, data );
2354                         }
2355
2356                         return data === undefined && parts[1] ?
2357                                 this.data( parts[0] ) :
2358                                 data;
2359
2360                 } else {
2361                         return this.each(function() {
2362                                 var $this = jQuery( this ),
2363                                         args = [ parts[0], value ];
2364
2365                                 $this.triggerHandler( "setData" + parts[1] + "!", args );
2366                                 jQuery.data( this, key, value );
2367                                 $this.triggerHandler( "changeData" + parts[1] + "!", args );
2368                         });
2369                 }
2370         },
2371
2372         removeData: function( key ) {
2373                 return this.each(function() {
2374                         jQuery.removeData( this, key );
2375                 });
2376         }
2377 });
2378
2379 function dataAttr( elem, key, data ) {
2380         // If nothing was found internally, try to fetch any
2381         // data from the HTML5 data-* attribute
2382         if ( data === undefined && elem.nodeType === 1 ) {
2383                 name = "data-" + key.replace( rmultiDash, "$1-$2" ).toLowerCase();
2384
2385                 data = elem.getAttribute( name );
2386
2387                 if ( typeof data === "string" ) {
2388                         try {
2389                                 data = data === "true" ? true :
2390                                 data === "false" ? false :
2391                                 data === "null" ? null :
2392                                 !jQuery.isNaN( data ) ? parseFloat( data ) :
2393                                         rbrace.test( data ) ? jQuery.parseJSON( data ) :
2394                                         data;
2395                         } catch( e ) {}
2396
2397                         // Make sure we set the data so it isn't changed later
2398                         jQuery.data( elem, key, data );
2399
2400                 } else {
2401                         data = undefined;
2402                 }
2403         }
2404
2405         return data;
2406 }
2407
2408 // TODO: This is a hack for 1.5 ONLY to allow objects with a single toJSON
2409 // property to be considered empty objects; this property always exists in
2410 // order to make sure JSON.stringify does not expose internal metadata
2411 function isEmptyDataObject( obj ) {
2412         for ( var name in obj ) {
2413                 if ( name !== "toJSON" ) {
2414                         return false;
2415                 }
2416         }
2417
2418         return true;
2419 }
2420
2421
2422
2423
2424 function handleQueueMarkDefer( elem, type, src ) {
2425         var deferDataKey = type + "defer",
2426                 queueDataKey = type + "queue",
2427                 markDataKey = type + "mark",
2428                 defer = jQuery.data( elem, deferDataKey, undefined, true );
2429         if ( defer &&
2430                 ( src === "queue" || !jQuery.data( elem, queueDataKey, undefined, true ) ) &&
2431                 ( src === "mark" || !jQuery.data( elem, markDataKey, undefined, true ) ) ) {
2432                 // Give room for hard-coded callbacks to fire first
2433                 // and eventually mark/queue something else on the element
2434                 setTimeout( function() {
2435                         if ( !jQuery.data( elem, queueDataKey, undefined, true ) &&
2436                                 !jQuery.data( elem, markDataKey, undefined, true ) ) {
2437                                 jQuery.removeData( elem, deferDataKey, true );
2438                                 defer.resolve();
2439                         }
2440                 }, 0 );
2441         }
2442 }
2443
2444 jQuery.extend({
2445
2446         _mark: function( elem, type ) {
2447                 if ( elem ) {
2448                         type = (type || "fx") + "mark";
2449                         jQuery.data( elem, type, (jQuery.data(elem,type,undefined,true) || 0) + 1, true );
2450                 }
2451         },
2452
2453         _unmark: function( force, elem, type ) {
2454                 if ( force !== true ) {
2455                         type = elem;
2456                         elem = force;
2457                         force = false;
2458                 }
2459                 if ( elem ) {
2460                         type = type || "fx";
2461                         var key = type + "mark",
2462                                 count = force ? 0 : ( (jQuery.data( elem, key, undefined, true) || 1 ) - 1 );
2463                         if ( count ) {
2464                                 jQuery.data( elem, key, count, true );
2465                         } else {
2466                                 jQuery.removeData( elem, key, true );
2467                                 handleQueueMarkDefer( elem, type, "mark" );
2468                         }
2469                 }
2470         },
2471
2472         queue: function( elem, type, data ) {
2473                 if ( elem ) {
2474                         type = (type || "fx") + "queue";
2475                         var q = jQuery.data( elem, type, undefined, true );
2476                         // Speed up dequeue by getting out quickly if this is just a lookup
2477                         if ( data ) {
2478                                 if ( !q || jQuery.isArray(data) ) {
2479                                         q = jQuery.data( elem, type, jQuery.makeArray(data), true );
2480                                 } else {
2481                                         q.push( data );
2482                                 }
2483                         }
2484                         return q || [];
2485                 }
2486         },
2487
2488         dequeue: function( elem, type ) {
2489                 type = type || "fx";
2490
2491                 var queue = jQuery.queue( elem, type ),
2492                         fn = queue.shift(),
2493                         defer;
2494
2495                 // If the fx queue is dequeued, always remove the progress sentinel
2496                 if ( fn === "inprogress" ) {
2497                         fn = queue.shift();
2498                 }
2499
2500                 if ( fn ) {
2501                         // Add a progress sentinel to prevent the fx queue from being
2502                         // automatically dequeued
2503                         if ( type === "fx" ) {
2504                                 queue.unshift("inprogress");
2505                         }
2506
2507                         fn.call(elem, function() {
2508                                 jQuery.dequeue(elem, type);
2509                         });
2510                 }
2511
2512                 if ( !queue.length ) {
2513                         jQuery.removeData( elem, type + "queue", true );
2514                         handleQueueMarkDefer( elem, type, "queue" );
2515                 }
2516         }
2517 });
2518
2519 jQuery.fn.extend({
2520         queue: function( type, data ) {
2521                 if ( typeof type !== "string" ) {
2522                         data = type;
2523                         type = "fx";
2524                 }
2525
2526                 if ( data === undefined ) {
2527                         return jQuery.queue( this[0], type );
2528                 }
2529                 return this.each(function() {
2530                         var queue = jQuery.queue( this, type, data );
2531
2532                         if ( type === "fx" && queue[0] !== "inprogress" ) {
2533                                 jQuery.dequeue( this, type );
2534                         }
2535                 });
2536         },
2537         dequeue: function( type ) {
2538                 return this.each(function() {
2539                         jQuery.dequeue( this, type );
2540                 });
2541         },
2542         // Based off of the plugin by Clint Helfers, with permission.
2543         // http://blindsignals.com/index.php/2009/07/jquery-delay/
2544         delay: function( time, type ) {
2545                 time = jQuery.fx ? jQuery.fx.speeds[time] || time : time;
2546                 type = type || "fx";
2547
2548                 return this.queue( type, function() {
2549                         var elem = this;
2550                         setTimeout(function() {
2551                                 jQuery.dequeue( elem, type );
2552                         }, time );
2553                 });
2554         },
2555         clearQueue: function( type ) {
2556                 return this.queue( type || "fx", [] );
2557         },
2558         // Get a promise resolved when queues of a certain type
2559         // are emptied (fx is the type by default)
2560         promise: function( type, object ) {
2561                 if ( typeof type !== "string" ) {
2562                         object = type;
2563                         type = undefined;
2564                 }
2565                 type = type || "fx";
2566                 var defer = jQuery.Deferred(),
2567                         elements = this,
2568                         i = elements.length,
2569                         count = 1,
2570                         deferDataKey = type + "defer",
2571                         queueDataKey = type + "queue",
2572                         markDataKey = type + "mark";
2573                 function resolve() {
2574                         if ( !( --count ) ) {
2575                                 defer.resolveWith( elements, [ elements ] );
2576                         }
2577                 }
2578                 while( i-- ) {
2579                         if (( tmp = jQuery.data( elements[ i ], deferDataKey, undefined, true ) ||
2580                                         ( jQuery.data( elements[ i ], queueDataKey, undefined, true ) ||
2581                                                 jQuery.data( elements[ i ], markDataKey, undefined, true ) ) &&
2582                                         jQuery.data( elements[ i ], deferDataKey, jQuery._Deferred(), true ) )) {
2583                                 count++;
2584                                 tmp.done( resolve );
2585                         }
2586                 }
2587                 resolve();
2588                 return defer.promise();
2589         }
2590 });
2591
2592
2593
2594
2595 var rclass = /[\n\t\r]/g,
2596         rspace = /\s+/,
2597         rreturn = /\r/g,
2598         rtype = /^(?:button|input)$/i,
2599         rfocusable = /^(?:button|input|object|select|textarea)$/i,
2600         rclickable = /^a(?:rea)?$/i,
2601         rspecial = /^(?:data-|aria-)/,
2602         rinvalidChar = /\:/,
2603         formHook;
2604
2605 jQuery.fn.extend({
2606         attr: function( name, value ) {
2607                 return jQuery.access( this, name, value, true, jQuery.attr );
2608         },
2609
2610         removeAttr: function( name ) {
2611                 return this.each(function() {
2612                         jQuery.removeAttr( this, name );
2613                 });
2614         },
2615         
2616         prop: function( name, value ) {
2617                 return jQuery.access( this, name, value, true, jQuery.prop );
2618         },
2619         
2620         removeProp: function( name ) {
2621                 return this.each(function() {
2622                         // try/catch handles cases where IE balks (such as removing a property on window)
2623                         try {
2624                                 this[ name ] = undefined;
2625                                 delete this[ name ];
2626                         } catch( e ) {}
2627                 });
2628         },
2629
2630         addClass: function( value ) {
2631                 if ( jQuery.isFunction( value ) ) {
2632                         return this.each(function(i) {
2633                                 var self = jQuery(this);
2634                                 self.addClass( value.call(this, i, self.attr("class") || "") );
2635                         });
2636                 }
2637
2638                 if ( value && typeof value === "string" ) {
2639                         var classNames = (value || "").split( rspace );
2640
2641                         for ( var i = 0, l = this.length; i < l; i++ ) {
2642                                 var elem = this[i];
2643
2644                                 if ( elem.nodeType === 1 ) {
2645                                         if ( !elem.className ) {
2646                                                 elem.className = value;
2647
2648                                         } else {
2649                                                 var className = " " + elem.className + " ",
2650                                                         setClass = elem.className;
2651
2652                                                 for ( var c = 0, cl = classNames.length; c < cl; c++ ) {
2653                                                         if ( className.indexOf( " " + classNames[c] + " " ) < 0 ) {
2654                                                                 setClass += " " + classNames[c];
2655                                                         }
2656                                                 }
2657                                                 elem.className = jQuery.trim( setClass );
2658                                         }
2659                                 }
2660                         }
2661                 }
2662
2663                 return this;
2664         },
2665
2666         removeClass: function( value ) {
2667                 if ( jQuery.isFunction(value) ) {
2668                         return this.each(function(i) {
2669                                 var self = jQuery(this);
2670                                 self.removeClass( value.call(this, i, self.attr("class")) );
2671                         });
2672                 }
2673
2674                 if ( (value && typeof value === "string") || value === undefined ) {
2675                         var classNames = (value || "").split( rspace );
2676
2677                         for ( var i = 0, l = this.length; i < l; i++ ) {
2678                                 var elem = this[i];
2679
2680                                 if ( elem.nodeType === 1 && elem.className ) {
2681                                         if ( value ) {
2682                                                 var className = (" " + elem.className + " ").replace(rclass, " ");
2683                                                 for ( var c = 0, cl = classNames.length; c < cl; c++ ) {
2684                                                         className = className.replace(" " + classNames[c] + " ", " ");
2685                                                 }
2686                                                 elem.className = jQuery.trim( className );
2687
2688                                         } else {
2689                                                 elem.className = "";
2690                                         }
2691                                 }
2692                         }
2693                 }
2694
2695                 return this;
2696         },
2697
2698         toggleClass: function( value, stateVal ) {
2699                 var type = typeof value,
2700                         isBool = typeof stateVal === "boolean";
2701
2702                 if ( jQuery.isFunction( value ) ) {
2703                         return this.each(function(i) {
2704                                 var self = jQuery(this);
2705                                 self.toggleClass( value.call(this, i, self.attr("class"), stateVal), stateVal );
2706                         });
2707                 }
2708
2709                 return this.each(function() {
2710                         if ( type === "string" ) {
2711                                 // toggle individual class names
2712                                 var className,
2713                                         i = 0,
2714                                         self = jQuery( this ),
2715                                         state = stateVal,
2716                                         classNames = value.split( rspace );
2717
2718                                 while ( (className = classNames[ i++ ]) ) {
2719                                         // check each className given, space seperated list
2720                                         state = isBool ? state : !self.hasClass( className );
2721                                         self[ state ? "addClass" : "removeClass" ]( className );
2722                                 }
2723
2724                         } else if ( type === "undefined" || type === "boolean" ) {
2725                                 if ( this.className ) {
2726                                         // store className if set
2727                                         jQuery._data( this, "__className__", this.className );
2728                                 }
2729
2730                                 // toggle whole className
2731                                 this.className = this.className || value === false ? "" : jQuery._data( this, "__className__" ) || "";
2732                         }
2733                 });
2734         },
2735
2736         hasClass: function( selector ) {
2737                 var className = " " + selector + " ";
2738                 for ( var i = 0, l = this.length; i < l; i++ ) {
2739                         if ( (" " + this[i].className + " ").replace(rclass, " ").indexOf( className ) > -1 ) {
2740                                 return true;
2741                         }
2742                 }
2743
2744                 return false;
2745         },
2746
2747         val: function( value ) {
2748                 var hooks, ret,
2749                         elem = this[0];
2750                 
2751                 if ( !arguments.length ) {
2752                         if ( elem ) {
2753                                 hooks = jQuery.valHooks[ elem.nodeName.toLowerCase() ] || jQuery.valHooks[ elem.type ];
2754
2755                                 if ( hooks && "get" in hooks && (ret = hooks.get( elem, "value" )) !== undefined ) {
2756                                         return ret;
2757                                 }
2758
2759                                 return (elem.value || "").replace(rreturn, "");
2760                         }
2761
2762                         return undefined;
2763                 }
2764
2765                 var isFunction = jQuery.isFunction( value );
2766
2767                 return this.each(function( i ) {
2768                         var self = jQuery(this), val;
2769
2770                         if ( this.nodeType !== 1 ) {
2771                                 return;
2772                         }
2773
2774                         if ( isFunction ) {
2775                                 val = value.call( this, i, self.val() );
2776                         } else {
2777                                 val = value;
2778                         }
2779
2780                         // Treat null/undefined as ""; convert numbers to string
2781                         if ( val == null ) {
2782                                 val = "";
2783                         } else if ( typeof val === "number" ) {
2784                                 val += "";
2785                         } else if ( jQuery.isArray( val ) ) {
2786                                 val = jQuery.map(val, function ( value ) {
2787                                         return value == null ? "" : value + "";
2788                                 });
2789                         }
2790
2791                         hooks = jQuery.valHooks[ this.nodeName.toLowerCase() ] || jQuery.valHooks[ this.type ];
2792
2793                         // If set returns undefined, fall back to normal setting
2794                         if ( !hooks || ("set" in hooks && hooks.set( this, val, "value" ) === undefined) ) {
2795                                 this.value = val;
2796                         }
2797                 });
2798         }
2799 });
2800
2801 jQuery.extend({
2802         valHooks: {
2803                 option: {
2804                         get: function( elem ) {
2805                                 // attributes.value is undefined in Blackberry 4.7 but
2806                                 // uses .value. See #6932
2807                                 var val = elem.attributes.value;
2808                                 return !val || val.specified ? elem.value : elem.text;
2809                         }
2810                 },
2811                 select: {
2812                         get: function( elem ) {
2813                                 var index = elem.selectedIndex,
2814                                         values = [],
2815                                         options = elem.options,
2816                                         one = elem.type === "select-one";
2817
2818                                 // Nothing was selected
2819                                 if ( index < 0 ) {
2820                                         return null;
2821                                 }
2822
2823                                 // Loop through all the selected options
2824                                 for ( var i = one ? index : 0, max = one ? index + 1 : options.length; i < max; i++ ) {
2825                                         var option = options[ i ];
2826
2827                                         // Don't return options that are disabled or in a disabled optgroup
2828                                         if ( option.selected && (jQuery.support.optDisabled ? !option.disabled : option.getAttribute("disabled") === null) &&
2829                                                         (!option.parentNode.disabled || !jQuery.nodeName( option.parentNode, "optgroup" )) ) {
2830
2831                                                 // Get the specific value for the option
2832                                                 value = jQuery( option ).val();
2833
2834                                                 // We don't need an array for one selects
2835                                                 if ( one ) {
2836                                                         return value;
2837                                                 }
2838
2839                                                 // Multi-Selects return an array
2840                                                 values.push( value );
2841                                         }
2842                                 }
2843
2844                                 // Fixes Bug #2551 -- select.val() broken in IE after form.reset()
2845                                 if ( one && !values.length && options.length ) {
2846                                         return jQuery( options[ index ] ).val();
2847                                 }
2848
2849                                 return values;
2850                         },
2851
2852                         set: function( elem, value ) {
2853                                 var values = jQuery.makeArray( value );
2854
2855                                 jQuery(elem).find("option").each(function() {
2856                                         this.selected = jQuery.inArray( jQuery(this).val(), values ) >= 0;
2857                                 });
2858
2859                                 if ( !values.length ) {
2860                                         elem.selectedIndex = -1;
2861                                 }
2862                                 return values;
2863                         }
2864                 }
2865         },
2866
2867         attrFn: {
2868                 val: true,
2869                 css: true,
2870                 html: true,
2871                 text: true,
2872                 data: true,
2873                 width: true,
2874                 height: true,
2875                 offset: true
2876         },
2877         
2878         attrFix: {
2879                 // Always normalize to ensure hook usage
2880                 tabindex: "tabIndex",
2881                 readonly: "readOnly"
2882         },
2883         
2884         attr: function( elem, name, value, pass ) {
2885                 var nType = elem.nodeType;
2886                 
2887                 // don't get/set attributes on text, comment and attribute nodes
2888                 if ( !elem || nType === 3 || nType === 8 || nType === 2 ) {
2889                         return undefined;
2890                 }
2891
2892                 if ( pass && name in jQuery.attrFn ) {
2893                         return jQuery( elem )[ name ]( value );
2894                 }
2895                 
2896                 var ret, hooks,
2897                         notxml = nType !== 1 || !jQuery.isXMLDoc( elem );
2898                 
2899                 // Normalize the name if needed
2900                 name = notxml && jQuery.attrFix[ name ] || name;
2901
2902                 // Get the appropriate hook, or the formHook
2903                 // if getSetAttribute is not supported and we have form objects in IE6/7
2904                 hooks = jQuery.attrHooks[ name ] ||
2905                         ( formHook && (jQuery.nodeName( elem, "form" ) || rinvalidChar.test( name )) ?
2906                                 formHook :
2907                                 undefined );
2908
2909                 if ( value !== undefined ) {
2910
2911                         if ( value === null || (value === false && !rspecial.test( name )) ) {
2912                                 jQuery.removeAttr( elem, name );
2913                                 return undefined;
2914
2915                         } else if ( hooks && "set" in hooks && notxml && (ret = hooks.set( elem, value, name )) !== undefined ) {
2916                                 return ret;
2917
2918                         } else {
2919
2920                                 // Set boolean attributes to the same name
2921                                 if ( value === true && !rspecial.test( name ) ) {
2922                                         value = name;
2923                                 }
2924
2925                                 elem.setAttribute( name, "" + value );
2926                                 return value;
2927                         }
2928
2929                 } else {
2930
2931                         if ( hooks && "get" in hooks && notxml ) {
2932                                 return hooks.get( elem, name );
2933
2934                         } else {
2935
2936                                 ret = elem.getAttribute( name );
2937
2938                                 // Non-existent attributes return null, we normalize to undefined
2939                                 return ret === null ?
2940                                         undefined :
2941                                         ret;
2942                         }
2943                 }
2944         },
2945         
2946         removeAttr: function( elem, name ) {
2947                 if ( elem.nodeType === 1 ) {
2948                         name = jQuery.attrFix[ name ] || name;
2949                 
2950                         if ( jQuery.support.getSetAttribute ) {
2951                                 // Use removeAttribute in browsers that support it
2952                                 elem.removeAttribute( name );
2953                         } else {
2954                                 jQuery.attr( elem, name, "" );
2955                                 elem.removeAttributeNode( elem.getAttributeNode( name ) );
2956                         }
2957                 }
2958         },
2959
2960         attrHooks: {
2961                 type: {
2962                         set: function( elem, value ) {
2963                                 // We can't allow the type property to be changed (since it causes problems in IE)
2964                                 if ( rtype.test( elem.nodeName ) && elem.parentNode ) {
2965                                         jQuery.error( "type property can't be changed" );
2966                                 } else if ( !jQuery.support.radioValue && value === "radio" && jQuery.nodeName(elem, "input") ) {
2967                                         // Setting the type on a radio button after the value resets the value in IE6-9
2968                                         // Reset value to it's default in case type is set after value
2969                                         // This is for element creation
2970                                         var val = elem.getAttribute("value");
2971                                         elem.setAttribute( "type", value );
2972                                         if ( val ) {
2973                                                 elem.value = val;
2974                                         }
2975                                         return value;
2976                                 }
2977                         }
2978                 },
2979                 tabIndex: {
2980                         get: function( elem ) {
2981                                 // elem.tabIndex doesn't always return the correct value when it hasn't been explicitly set
2982                                 // http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/
2983                                 var attributeNode = elem.getAttributeNode("tabIndex");
2984
2985                                 return attributeNode && attributeNode.specified ?
2986                                         parseInt( attributeNode.value, 10 ) :
2987                                         rfocusable.test( elem.nodeName ) || rclickable.test( elem.nodeName ) && elem.href ?
2988                                                 0 :
2989                                                 undefined;
2990                         }
2991                 }
2992         },
2993         
2994         propFix: {},
2995         
2996         prop: function( elem, name, value ) {
2997                 var nType = elem.nodeType;
2998                 
2999                 // don't get/set properties on text, comment and attribute nodes
3000                 if ( !elem || nType === 3 || nType === 8 || nType === 2 ) {
3001                         return undefined;
3002                 }
3003                 
3004                 var ret, hooks,
3005                         notxml = nType !== 1 || !jQuery.isXMLDoc( elem );
3006                 
3007                 // Try to normalize/fix the name
3008                 name = notxml && jQuery.propFix[ name ] || name;
3009                 
3010                 hooks = jQuery.propHooks[ name ];
3011                 
3012                 if ( value !== undefined ) {
3013                         if ( hooks && "set" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ) {
3014                                 return ret;
3015                         
3016                         } else {
3017                                 return (elem[ name ] = value);
3018                         }
3019                 
3020                 } else {
3021                         if ( hooks && "get" in hooks && (ret = hooks.get( elem, name )) !== undefined ) {
3022                                 return ret;
3023                                 
3024                         } else {
3025                                 return elem[ name ];
3026                         }
3027                 }
3028         },
3029         
3030         propHooks: {}
3031 });
3032
3033 // IE6/7 do not support getting/setting some attributes with get/setAttribute
3034 if ( !jQuery.support.getSetAttribute ) {
3035         jQuery.attrFix = jQuery.extend( jQuery.attrFix, {
3036                 "for": "htmlFor",
3037                 "class": "className",
3038                 maxlength: "maxLength",
3039                 cellspacing: "cellSpacing",
3040                 cellpadding: "cellPadding",
3041                 rowspan: "rowSpan",
3042                 colspan: "colSpan",
3043                 usemap: "useMap",
3044                 frameborder: "frameBorder"
3045         });
3046         
3047         // Use this for any attribute on a form in IE6/7
3048         formHook = jQuery.attrHooks.name = jQuery.attrHooks.value = jQuery.valHooks.button = {
3049                 get: function( elem, name ) {
3050                         var ret;
3051                         if ( name === "value" && !jQuery.nodeName( elem, "button" ) ) {
3052                                 return elem.getAttribute( name );
3053                         }
3054                         ret = elem.getAttributeNode( name );
3055                         // Return undefined if not specified instead of empty string
3056                         return ret && ret.specified ?
3057                                 ret.nodeValue :
3058                                 undefined;
3059                 },
3060                 set: function( elem, value, name ) {
3061                         // Check form objects in IE (multiple bugs related)
3062                         // Only use nodeValue if the attribute node exists on the form
3063                         var ret = elem.getAttributeNode( name );
3064                         if ( ret ) {
3065                                 ret.nodeValue = value;
3066                                 return value;
3067                         }
3068                 }
3069         };
3070
3071         // Set width and height to auto instead of 0 on empty string( Bug #8150 )
3072         // This is for removals
3073         jQuery.each([ "width", "height" ], function( i, name ) {
3074                 jQuery.attrHooks[ name ] = jQuery.extend( jQuery.attrHooks[ name ], {
3075                         set: function( elem, value ) {
3076                                 if ( value === "" ) {
3077                                         elem.setAttribute( name, "auto" );
3078                                         return value;
3079                                 }
3080                         }
3081                 });
3082         });
3083 }
3084
3085
3086 // Some attributes require a special call on IE
3087 if ( !jQuery.support.hrefNormalized ) {
3088         jQuery.each([ "href", "src", "width", "height" ], function( i, name ) {
3089                 jQuery.attrHooks[ name ] = jQuery.extend( jQuery.attrHooks[ name ], {
3090                         get: function( elem ) {
3091                                 var ret = elem.getAttribute( name, 2 );
3092                                 return ret === null ? undefined : ret;
3093                         }
3094                 });
3095         });
3096 }
3097
3098 if ( !jQuery.support.style ) {
3099         jQuery.attrHooks.style = {
3100                 get: function( elem ) {
3101                         // Return undefined in the case of empty string
3102                         // Normalize to lowercase since IE uppercases css property names
3103                         return elem.style.cssText.toLowerCase() || undefined;
3104                 },
3105                 set: function( elem, value ) {
3106                         return (elem.style.cssText = "" + value);
3107                 }
3108         };
3109 }
3110
3111 // Safari mis-reports the default selected property of an option
3112 // Accessing the parent's selectedIndex property fixes it
3113 if ( !jQuery.support.optSelected ) {
3114         jQuery.propHooks.selected = jQuery.extend( jQuery.propHooks.selected, {
3115                 get: function( elem ) {
3116                         var parent = elem.parentNode;
3117
3118                         if ( parent ) {
3119                                 parent.selectedIndex;
3120
3121                                 // Make sure that it also works with optgroups, see #5701
3122                                 if ( parent.parentNode ) {
3123                                         parent.parentNode.selectedIndex;
3124                                 }
3125                         }
3126                 }
3127         });
3128 }
3129
3130 // Radios and checkboxes getter/setter
3131 if ( !jQuery.support.checkOn ) {
3132         jQuery.each([ "radio", "checkbox" ], function() {
3133                 jQuery.valHooks[ this ] = {
3134                         get: function( elem ) {
3135                                 // Handle the case where in Webkit "" is returned instead of "on" if a value isn't specified
3136                                 return elem.getAttribute("value") === null ? "on" : elem.value;
3137                         }
3138                 };
3139         });
3140 }
3141 jQuery.each([ "radio", "checkbox" ], function() {
3142         jQuery.valHooks[ this ] = jQuery.extend( jQuery.valHooks[ this ], {
3143                 set: function( elem, value ) {
3144                         if ( jQuery.isArray( value ) ) {
3145                                 return (elem.checked = jQuery.inArray( jQuery(elem).val(), value ) >= 0);
3146                         }
3147                 }
3148         });
3149 });
3150
3151
3152
3153
3154 var hasOwn = Object.prototype.hasOwnProperty,
3155         rnamespaces = /\.(.*)$/,
3156         rformElems = /^(?:textarea|input|select)$/i,
3157         rperiod = /\./g,
3158         rspaces = / /g,
3159         rescape = /[^\w\s.|`]/g,
3160         fcleanup = function( nm ) {
3161                 return nm.replace(rescape, "\\$&");
3162         };
3163
3164 /*
3165  * A number of helper functions used for managing events.
3166  * Many of the ideas behind this code originated from
3167  * Dean Edwards' addEvent library.
3168  */
3169 jQuery.event = {
3170
3171         // Bind an event to an element
3172         // Original by Dean Edwards
3173         add: function( elem, types, handler, data ) {
3174                 if ( elem.nodeType === 3 || elem.nodeType === 8 ) {
3175                         return;
3176                 }
3177
3178                 if ( handler === false ) {
3179                         handler = returnFalse;
3180                 } else if ( !handler ) {
3181                         // Fixes bug #7229. Fix recommended by jdalton
3182                         return;
3183                 }
3184
3185                 var handleObjIn, handleObj;
3186
3187                 if ( handler.handler ) {
3188                         handleObjIn = handler;
3189                         handler = handleObjIn.handler;
3190                 }
3191
3192                 // Make sure that the function being executed has a unique ID
3193                 if ( !handler.guid ) {
3194                         handler.guid = jQuery.guid++;
3195                 }
3196
3197                 // Init the element's event structure
3198                 var elemData = jQuery._data( elem );
3199
3200                 // If no elemData is found then we must be trying to bind to one of the
3201                 // banned noData elements
3202                 if ( !elemData ) {
3203                         return;
3204                 }
3205
3206                 var events = elemData.events,
3207                         eventHandle = elemData.handle;
3208
3209                 if ( !events ) {
3210                         elemData.events = events = {};
3211                 }
3212
3213                 if ( !eventHandle ) {
3214                         elemData.handle = eventHandle = function( e ) {
3215                                 // Discard the second event of a jQuery.event.trigger() and
3216                                 // when an event is called after a page has unloaded
3217                                 return typeof jQuery !== "undefined" && (!e || jQuery.event.triggered !== e.type) ?
3218                                         jQuery.event.handle.apply( eventHandle.elem, arguments ) :
3219                                         undefined;
3220                         };
3221                 }
3222
3223                 // Add elem as a property of the handle function
3224                 // This is to prevent a memory leak with non-native events in IE.
3225                 eventHandle.elem = elem;
3226
3227                 // Handle multiple events separated by a space
3228                 // jQuery(...).bind("mouseover mouseout", fn);
3229                 types = types.split(" ");
3230
3231                 var type, i = 0, namespaces;
3232
3233                 while ( (type = types[ i++ ]) ) {
3234                         handleObj = handleObjIn ?
3235                                 jQuery.extend({}, handleObjIn) :
3236                                 { handler: handler, data: data };
3237
3238                         // Namespaced event handlers
3239                         if ( type.indexOf(".") > -1 ) {
3240                                 namespaces = type.split(".");
3241                                 type = namespaces.shift();
3242                                 handleObj.namespace = namespaces.slice(0).sort().join(".");
3243
3244                         } else {
3245                                 namespaces = [];
3246                                 handleObj.namespace = "";
3247                         }
3248
3249                         handleObj.type = type;
3250                         if ( !handleObj.guid ) {
3251                                 handleObj.guid = handler.guid;
3252                         }
3253
3254                         // Get the current list of functions bound to this event
3255                         var handlers = events[ type ],
3256                                 special = jQuery.event.special[ type ] || {};
3257
3258                         // Init the event handler queue
3259                         if ( !handlers ) {
3260                                 handlers = events[ type ] = [];
3261
3262                                 // Check for a special event handler
3263                                 // Only use addEventListener/attachEvent if the special
3264                                 // events handler returns false
3265                                 if ( !special.setup || special.setup.call( elem, data, namespaces, eventHandle ) === false ) {
3266                                         // Bind the global event handler to the element
3267                                         if ( elem.addEventListener ) {
3268                                                 elem.addEventListener( type, eventHandle, false );
3269
3270                                         } else if ( elem.attachEvent ) {
3271                                                 elem.attachEvent( "on" + type, eventHandle );
3272                                         }
3273                                 }
3274                         }
3275
3276                         if ( special.add ) {
3277                                 special.add.call( elem, handleObj );
3278
3279                                 if ( !handleObj.handler.guid ) {
3280                                         handleObj.handler.guid = handler.guid;
3281                                 }
3282                         }
3283
3284                         // Add the function to the element's handler list
3285                         handlers.push( handleObj );
3286
3287                         // Keep track of which events have been used, for event optimization
3288                         jQuery.event.global[ type ] = true;
3289                 }
3290
3291                 // Nullify elem to prevent memory leaks in IE
3292                 elem = null;
3293         },
3294
3295         global: {},
3296
3297         // Detach an event or set of events from an element
3298         remove: function( elem, types, handler, pos ) {
3299                 // don't do events on text and comment nodes
3300                 if ( elem.nodeType === 3 || elem.nodeType === 8 ) {
3301                         return;
3302                 }
3303
3304                 if ( handler === false ) {
3305                         handler = returnFalse;
3306                 }
3307
3308                 var ret, type, fn, j, i = 0, all, namespaces, namespace, special, eventType, handleObj, origType,
3309                         elemData = jQuery.hasData( elem ) && jQuery._data( elem ),
3310                         events = elemData && elemData.events;
3311
3312                 if ( !elemData || !events ) {
3313                         return;
3314                 }
3315
3316                 // types is actually an event object here
3317                 if ( types && types.type ) {
3318                         handler = types.handler;
3319                         types = types.type;
3320                 }
3321
3322                 // Unbind all events for the element
3323                 if ( !types || typeof types === "string" && types.charAt(0) === "." ) {
3324                         types = types || "";
3325
3326                         for ( type in events ) {
3327                                 jQuery.event.remove( elem, type + types );
3328                         }
3329
3330                         return;
3331                 }
3332
3333                 // Handle multiple events separated by a space
3334                 // jQuery(...).unbind("mouseover mouseout", fn);
3335                 types = types.split(" ");
3336
3337                 while ( (type = types[ i++ ]) ) {
3338                         origType = type;
3339                         handleObj = null;
3340                         all = type.indexOf(".") < 0;
3341                         namespaces = [];
3342
3343                         if ( !all ) {
3344                                 // Namespaced event handlers
3345                                 namespaces = type.split(".");
3346                                 type = namespaces.shift();
3347
3348                                 namespace = new RegExp("(^|\\.)" +
3349                                         jQuery.map( namespaces.slice(0).sort(), fcleanup ).join("\\.(?:.*\\.)?") + "(\\.|$)");
3350                         }
3351
3352                         eventType = events[ type ];
3353
3354                         if ( !eventType ) {
3355                                 continue;
3356                         }
3357
3358                         if ( !handler ) {
3359                                 for ( j = 0; j < eventType.length; j++ ) {
3360                                         handleObj = eventType[ j ];
3361
3362                                         if ( all || namespace.test( handleObj.namespace ) ) {
3363                                                 jQuery.event.remove( elem, origType, handleObj.handler, j );
3364                                                 eventType.splice( j--, 1 );
3365                                         }
3366                                 }
3367
3368                                 continue;
3369                         }
3370
3371                         special = jQuery.event.special[ type ] || {};
3372
3373                         for ( j = pos || 0; j < eventType.length; j++ ) {
3374                                 handleObj = eventType[ j ];
3375
3376                                 if ( handler.guid === handleObj.guid ) {
3377                                         // remove the given handler for the given type
3378                                         if ( all || namespace.test( handleObj.namespace ) ) {
3379                                                 if ( pos == null ) {
3380                                                         eventType.splice( j--, 1 );
3381                                                 }
3382
3383                                                 if ( special.remove ) {
3384                                                         special.remove.call( elem, handleObj );
3385                                                 }
3386                                         }
3387
3388                                         if ( pos != null ) {
3389                                                 break;
3390                                         }
3391                                 }
3392                         }
3393
3394                         // remove generic event handler if no more handlers exist
3395                         if ( eventType.length === 0 || pos != null && eventType.length === 1 ) {
3396                                 if ( !special.teardown || special.teardown.call( elem, namespaces ) === false ) {
3397                                         jQuery.removeEvent( elem, type, elemData.handle );
3398                                 }
3399
3400                                 ret = null;
3401                                 delete events[ type ];
3402                         }
3403                 }
3404
3405                 // Remove the expando if it's no longer used
3406                 if ( jQuery.isEmptyObject( events ) ) {
3407                         var handle = elemData.handle;
3408                         if ( handle ) {
3409                                 handle.elem = null;
3410                         }
3411
3412                         delete elemData.events;
3413                         delete elemData.handle;
3414
3415                         if ( jQuery.isEmptyObject( elemData ) ) {
3416                                 jQuery.removeData( elem, undefined, true );
3417                         }
3418                 }
3419         },
3420         
3421         // Events that are safe to short-circuit if no handlers are attached.
3422         // Native DOM events should not be added, they may have inline handlers.
3423         customEvent: {
3424                 "getData": true,
3425                 "setData": true,
3426                 "changeData": true
3427         },
3428
3429         trigger: function( event, data, elem, onlyHandlers ) {
3430                 // Event object or event type
3431                 var type = event.type || event,
3432                         namespaces = [],
3433                         exclusive;
3434
3435                 if ( type.indexOf("!") >= 0 ) {
3436                         // Exclusive events trigger only for the exact event (no namespaces)
3437                         type = type.slice(0, -1);
3438                         exclusive = true;
3439                 }
3440
3441                 if ( type.indexOf(".") >= 0 ) {
3442                         // Namespaced trigger; create a regexp to match event type in handle()
3443                         namespaces = type.split(".");
3444                         type = namespaces.shift();
3445                         namespaces.sort();
3446                 }
3447
3448                 if ( (!elem || jQuery.event.customEvent[ type ]) && !jQuery.event.global[ type ] ) {
3449                         // No jQuery handlers for this event type, and it can't have inline handlers
3450                         return;
3451                 }
3452
3453                 // Caller can pass in an Event, Object, or just an event type string
3454                 event = typeof event === "object" ?
3455                         // jQuery.Event object
3456                         event[ jQuery.expando ] ? event :
3457                         // Object literal
3458                         new jQuery.Event( type, event ) :
3459                         // Just the event type (string)
3460                         new jQuery.Event( type );
3461
3462                 event.type = type;
3463                 event.exclusive = exclusive;
3464                 event.namespace = namespaces.join(".");
3465                 event.namespace_re = new RegExp("(^|\\.)" + namespaces.join("\\.(?:.*\\.)?") + "(\\.|$)");
3466                 
3467                 // triggerHandler() and global events don't bubble or run the default action
3468                 if ( onlyHandlers || !elem ) {
3469                         event.preventDefault();
3470                         event.stopPropagation();
3471                 }
3472
3473                 // Handle a global trigger
3474                 if ( !elem ) {
3475                         // TODO: Stop taunting the data cache; remove global events and always attach to document
3476                         jQuery.each( jQuery.cache, function() {
3477                                 // internalKey variable is just used to make it easier to find
3478                                 // and potentially change this stuff later; currently it just
3479                                 // points to jQuery.expando
3480                                 var internalKey = jQuery.expando,
3481                                         internalCache = this[ internalKey ];
3482                                 if ( internalCache && internalCache.events && internalCache.events[ type ] ) {
3483                                         jQuery.event.trigger( event, data, internalCache.handle.elem );
3484                                 }
3485                         });
3486                         return;
3487                 }
3488
3489                 // Don't do events on text and comment nodes
3490                 if ( elem.nodeType === 3 || elem.nodeType === 8 ) {
3491                         return;
3492                 }
3493
3494                 // Clean up the event in case it is being reused
3495                 event.result = undefined;
3496                 event.target = elem;
3497
3498                 // Clone any incoming data and prepend the event, creating the handler arg list
3499                 data = data ? jQuery.makeArray( data ) : [];
3500                 data.unshift( event );
3501
3502                 var cur = elem,
3503                         // IE doesn't like method names with a colon (#3533, #8272)
3504                         ontype = type.indexOf(":") < 0 ? "on" + type : "";
3505
3506                 // Fire event on the current element, then bubble up the DOM tree
3507                 do {
3508                         var handle = jQuery._data( cur, "handle" );
3509
3510                         event.currentTarget = cur;
3511                         if ( handle ) {
3512                                 handle.apply( cur, data );
3513                         }
3514
3515                         // Trigger an inline bound script
3516                         if ( ontype && jQuery.acceptData( cur ) && cur[ ontype ] && cur[ ontype ].apply( cur, data ) === false ) {
3517                                 event.result = false;
3518                                 event.preventDefault();
3519                         }
3520
3521                         // Bubble up to document, then to window
3522                         cur = cur.parentNode || cur.ownerDocument || cur === event.target.ownerDocument && window;
3523                 } while ( cur && !event.isPropagationStopped() );
3524
3525                 // If nobody prevented the default action, do it now
3526                 if ( !event.isDefaultPrevented() ) {
3527                         var old,
3528                                 special = jQuery.event.special[ type ] || {};
3529
3530                         if ( (!special._default || special._default.call( elem.ownerDocument, event ) === false) &&
3531                                 !(type === "click" && jQuery.nodeName( elem, "a" )) && jQuery.acceptData( elem ) ) {
3532
3533                                 // Call a native DOM method on the target with the same name name as the event.
3534                                 // Can't use an .isFunction)() check here because IE6/7 fails that test.
3535                                 // IE<9 dies on focus to hidden element (#1486), may want to revisit a try/catch.
3536                                 try {
3537                                         if ( ontype && elem[ type ] ) {
3538                                                 // Don't re-trigger an onFOO event when we call its FOO() method
3539                                                 old = elem[ ontype ];
3540
3541                                                 if ( old ) {
3542                                                         elem[ ontype ] = null;
3543                                                 }
3544
3545                                                 jQuery.event.triggered = type;
3546                                                 elem[ type ]();
3547                                         }
3548                                 } catch ( ieError ) {}
3549
3550                                 if ( old ) {
3551                                         elem[ ontype ] = old;
3552                                 }
3553
3554                                 jQuery.event.triggered = undefined;
3555                         }
3556                 }
3557                 
3558                 return event.result;
3559         },
3560
3561         handle: function( event ) {
3562                 event = jQuery.event.fix( event || window.event );
3563                 // Snapshot the handlers list since a called handler may add/remove events.
3564                 var handlers = ((jQuery._data( this, "events" ) || {})[ event.type ] || []).slice(0),
3565                         run_all = !event.exclusive && !event.namespace,
3566                         args = Array.prototype.slice.call( arguments, 0 );
3567
3568                 // Use the fix-ed Event rather than the (read-only) native event
3569                 args[0] = event;
3570                 event.currentTarget = this;
3571
3572                 for ( var j = 0, l = handlers.length; j < l; j++ ) {
3573                         var handleObj = handlers[ j ];
3574
3575                         // Triggered event must 1) be non-exclusive and have no namespace, or
3576                         // 2) have namespace(s) a subset or equal to those in the bound event.
3577                         if ( run_all || event.namespace_re.test( handleObj.namespace ) ) {
3578                                 // Pass in a reference to the handler function itself
3579                                 // So that we can later remove it
3580                                 event.handler = handleObj.handler;
3581                                 event.data = handleObj.data;
3582                                 event.handleObj = handleObj;
3583
3584                                 var ret = handleObj.handler.apply( this, args );
3585
3586                                 if ( ret !== undefined ) {
3587                                         event.result = ret;
3588                                         if ( ret === false ) {
3589                                                 event.preventDefault();
3590                                                 event.stopPropagation();
3591                                         }
3592                                 }
3593
3594                                 if ( event.isImmediatePropagationStopped() ) {
3595                                         break;
3596                                 }
3597                         }
3598                 }
3599                 return event.result;
3600         },
3601
3602         props: "altKey attrChange attrName bubbles button cancelable charCode clientX clientY ctrlKey currentTarget data detail eventPhase fromElement handler keyCode layerX layerY metaKey newValue offsetX offsetY pageX pageY prevValue relatedNode relatedTarget screenX screenY shiftKey srcElement target toElement view wheelDelta which".split(" "),
3603
3604         fix: function( event ) {
3605                 if ( event[ jQuery.expando ] ) {
3606                         return event;
3607                 }
3608
3609                 // store a copy of the original event object
3610                 // and "clone" to set read-only properties
3611                 var originalEvent = event;
3612                 event = jQuery.Event( originalEvent );
3613
3614                 for ( var i = this.props.length, prop; i; ) {
3615                         prop = this.props[ --i ];
3616                         event[ prop ] = originalEvent[ prop ];
3617                 }
3618
3619                 // Fix target property, if necessary
3620                 if ( !event.target ) {
3621                         // Fixes #1925 where srcElement might not be defined either
3622                         event.target = event.srcElement || document;
3623                 }
3624
3625                 // check if target is a textnode (safari)
3626                 if ( event.target.nodeType === 3 ) {
3627                         event.target = event.target.parentNode;
3628                 }
3629
3630                 // Add relatedTarget, if necessary
3631                 if ( !event.relatedTarget && event.fromElement ) {
3632                         event.relatedTarget = event.fromElement === event.target ? event.toElement : event.fromElement;
3633                 }
3634
3635                 // Calculate pageX/Y if missing and clientX/Y available
3636                 if ( event.pageX == null && event.clientX != null ) {
3637                         var eventDocument = event.target.ownerDocument || document,
3638                                 doc = eventDocument.documentElement,
3639                                 body = eventDocument.body;
3640
3641                         event.pageX = event.clientX + (doc && doc.scrollLeft || body && body.scrollLeft || 0) - (doc && doc.clientLeft || body && body.clientLeft || 0);
3642                         event.pageY = event.clientY + (doc && doc.scrollTop  || body && body.scrollTop  || 0) - (doc && doc.clientTop  || body && body.clientTop  || 0);
3643                 }
3644
3645                 // Add which for key events
3646                 if ( event.which == null && (event.charCode != null || event.keyCode != null) ) {
3647                         event.which = event.charCode != null ? event.charCode : event.keyCode;
3648                 }
3649
3650                 // Add metaKey to non-Mac browsers (use ctrl for PC's and Meta for Macs)
3651                 if ( !event.metaKey && event.ctrlKey ) {
3652                         event.metaKey = event.ctrlKey;
3653                 }
3654
3655                 // Add which for click: 1 === left; 2 === middle; 3 === right
3656                 // Note: button is not normalized, so don't use it
3657                 if ( !event.which && event.button !== undefined ) {
3658                         event.which = (event.button & 1 ? 1 : ( event.button & 2 ? 3 : ( event.button & 4 ? 2 : 0 ) ));
3659                 }
3660
3661                 return event;
3662         },
3663
3664         // Deprecated, use jQuery.guid instead
3665         guid: 1E8,
3666
3667         // Deprecated, use jQuery.proxy instead
3668         proxy: jQuery.proxy,
3669
3670         special: {
3671                 ready: {
3672                         // Make sure the ready event is setup
3673                         setup: jQuery.bindReady,
3674                         teardown: jQuery.noop
3675                 },
3676
3677                 live: {
3678                         add: function( handleObj ) {
3679                                 jQuery.event.add( this,
3680                                         liveConvert( handleObj.origType, handleObj.selector ),
3681                                         jQuery.extend({}, handleObj, {handler: liveHandler, guid: handleObj.handler.guid}) );
3682                         },
3683
3684                         remove: function( handleObj ) {
3685                                 jQuery.event.remove( this, liveConvert( handleObj.origType, handleObj.selector ), handleObj );
3686                         }
3687                 },
3688
3689                 beforeunload: {
3690                         setup: function( data, namespaces, eventHandle ) {
3691                                 // We only want to do this special case on windows
3692                                 if ( jQuery.isWindow( this ) ) {
3693                                         this.onbeforeunload = eventHandle;
3694                                 }
3695                         },
3696
3697                         teardown: function( namespaces, eventHandle ) {
3698                                 if ( this.onbeforeunload === eventHandle ) {
3699                                         this.onbeforeunload = null;
3700                                 }
3701                         }
3702                 }
3703         }
3704 };
3705
3706 jQuery.removeEvent = document.removeEventListener ?
3707         function( elem, type, handle ) {
3708                 if ( elem.removeEventListener ) {
3709                         elem.removeEventListener( type, handle, false );
3710                 }
3711         } :
3712         function( elem, type, handle ) {
3713                 if ( elem.detachEvent ) {
3714                         elem.detachEvent( "on" + type, handle );
3715                 }
3716         };
3717
3718 jQuery.Event = function( src, props ) {
3719         // Allow instantiation without the 'new' keyword
3720         if ( !this.preventDefault ) {
3721                 return new jQuery.Event( src, props );
3722         }
3723
3724         // Event object
3725         if ( src && src.type ) {
3726                 this.originalEvent = src;
3727                 this.type = src.type;
3728
3729                 // Events bubbling up the document may have been marked as prevented
3730                 // by a handler lower down the tree; reflect the correct value.
3731                 this.isDefaultPrevented = (src.defaultPrevented || src.returnValue === false ||
3732                         src.getPreventDefault && src.getPreventDefault()) ? returnTrue : returnFalse;
3733
3734         // Event type
3735         } else {
3736                 this.type = src;
3737         }
3738
3739         // Put explicitly provided properties onto the event object
3740         if ( props ) {
3741                 jQuery.extend( this, props );
3742         }
3743
3744         // timeStamp is buggy for some events on Firefox(#3843)
3745         // So we won't rely on the native value
3746         this.timeStamp = jQuery.now();
3747
3748         // Mark it as fixed
3749         this[ jQuery.expando ] = true;
3750 };
3751
3752 function returnFalse() {
3753         return false;
3754 }
3755 function returnTrue() {
3756         return true;
3757 }
3758
3759 // jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding
3760 // http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html
3761 jQuery.Event.prototype = {
3762         preventDefault: function() {
3763                 this.isDefaultPrevented = returnTrue;
3764
3765                 var e = this.originalEvent;
3766                 if ( !e ) {
3767                         return;
3768                 }
3769
3770                 // if preventDefault exists run it on the original event
3771                 if ( e.preventDefault ) {
3772                         e.preventDefault();
3773
3774                 // otherwise set the returnValue property of the original event to false (IE)
3775                 } else {
3776                         e.returnValue = false;
3777                 }
3778         },
3779         stopPropagation: function() {
3780                 this.isPropagationStopped = returnTrue;
3781
3782                 var e = this.originalEvent;
3783                 if ( !e ) {
3784                         return;
3785                 }
3786                 // if stopPropagation exists run it on the original event
3787                 if ( e.stopPropagation ) {
3788                         e.stopPropagation();
3789                 }
3790                 // otherwise set the cancelBubble property of the original event to true (IE)
3791                 e.cancelBubble = true;
3792         },
3793         stopImmediatePropagation: function() {
3794                 this.isImmediatePropagationStopped = returnTrue;
3795                 this.stopPropagation();
3796         },
3797         isDefaultPrevented: returnFalse,
3798         isPropagationStopped: returnFalse,
3799         isImmediatePropagationStopped: returnFalse
3800 };
3801
3802 // Checks if an event happened on an element within another element
3803 // Used in jQuery.event.special.mouseenter and mouseleave handlers
3804 var withinElement = function( event ) {
3805         // Check if mouse(over|out) are still within the same parent element
3806         var parent = event.relatedTarget;
3807
3808         // Firefox sometimes assigns relatedTarget a XUL element
3809         // which we cannot access the parentNode property of
3810         try {
3811
3812                 // Chrome does something similar, the parentNode property
3813                 // can be accessed but is null.
3814                 if ( parent && parent !== document && !parent.parentNode ) {
3815                         return;
3816                 }
3817                 // Traverse up the tree
3818                 while ( parent && parent !== this ) {
3819                         parent = parent.parentNode;
3820                 }
3821
3822                 if ( parent !== this ) {
3823                         // set the correct event type
3824                         event.type = event.data;
3825
3826                         // handle event if we actually just moused on to a non sub-element
3827                         jQuery.event.handle.apply( this, arguments );
3828                 }
3829
3830         // assuming we've left the element since we most likely mousedover a xul element
3831         } catch(e) { }
3832 },
3833
3834 // In case of event delegation, we only need to rename the event.type,
3835 // liveHandler will take care of the rest.
3836 delegate = function( event ) {
3837         event.type = event.data;
3838         jQuery.event.handle.apply( this, arguments );
3839 };
3840
3841 // Create mouseenter and mouseleave events
3842 jQuery.each({
3843         mouseenter: "mouseover",
3844         mouseleave: "mouseout"
3845 }, function( orig, fix ) {
3846         jQuery.event.special[ orig ] = {
3847                 setup: function( data ) {
3848                         jQuery.event.add( this, fix, data && data.selector ? delegate : withinElement, orig );
3849                 },
3850                 teardown: function( data ) {
3851                         jQuery.event.remove( this, fix, data && data.selector ? delegate : withinElement );
3852                 }
3853         };
3854 });
3855
3856 // submit delegation
3857 if ( !jQuery.support.submitBubbles ) {
3858
3859         jQuery.event.special.submit = {
3860                 setup: function( data, namespaces ) {
3861                         if ( !jQuery.nodeName( this, "form" ) ) {
3862                                 jQuery.event.add(this, "click.specialSubmit", function( e ) {
3863                                         var elem = e.target,
3864                                                 type = elem.type;
3865
3866                                         if ( (type === "submit" || type === "image") && jQuery( elem ).closest("form").length ) {
3867                                                 trigger( "submit", this, arguments );
3868                                         }
3869                                 });
3870
3871                                 jQuery.event.add(this, "keypress.specialSubmit", function( e ) {
3872                                         var elem = e.target,
3873                                                 type = elem.type;
3874
3875                                         if ( (type === "text" || type === "password") && jQuery( elem ).closest("form").length && e.keyCode === 13 ) {
3876                                                 trigger( "submit", this, arguments );
3877                                         }
3878                                 });
3879
3880                         } else {
3881                                 return false;
3882                         }
3883                 },
3884
3885                 teardown: function( namespaces ) {
3886                         jQuery.event.remove( this, ".specialSubmit" );
3887                 }
3888         };
3889
3890 }
3891
3892 // change delegation, happens here so we have bind.
3893 if ( !jQuery.support.changeBubbles ) {
3894
3895         var changeFilters,
3896
3897         getVal = function( elem ) {
3898                 var type = elem.type, val = elem.value;
3899
3900                 if ( type === "radio" || type === "checkbox" ) {
3901                         val = elem.checked;
3902
3903                 } else if ( type === "select-multiple" ) {
3904                         val = elem.selectedIndex > -1 ?
3905                                 jQuery.map( elem.options, function( elem ) {
3906                                         return elem.selected;
3907                                 }).join("-") :
3908                                 "";
3909
3910                 } else if ( jQuery.nodeName( elem, "select" ) ) {
3911                         val = elem.selectedIndex;
3912                 }
3913
3914                 return val;
3915         },
3916
3917         testChange = function testChange( e ) {
3918                 var elem = e.target, data, val;
3919
3920                 if ( !rformElems.test( elem.nodeName ) || elem.readOnly ) {
3921                         return;
3922                 }
3923
3924                 data = jQuery._data( elem, "_change_data" );
3925                 val = getVal(elem);
3926
3927                 // the current data will be also retrieved by beforeactivate
3928                 if ( e.type !== "focusout" || elem.type !== "radio" ) {
3929                         jQuery._data( elem, "_change_data", val );
3930                 }
3931
3932                 if ( data === undefined || val === data ) {
3933                         return;
3934                 }
3935
3936                 if ( data != null || val ) {
3937                         e.type = "change";
3938                         e.liveFired = undefined;
3939                         jQuery.event.trigger( e, arguments[1], elem );
3940                 }
3941         };
3942
3943         jQuery.event.special.change = {
3944                 filters: {
3945                         focusout: testChange,
3946
3947                         beforedeactivate: testChange,
3948
3949                         click: function( e ) {
3950                                 var elem = e.target, type = jQuery.nodeName( elem, "input" ) ? elem.type : "";
3951
3952                                 if ( type === "radio" || type === "checkbox" || jQuery.nodeName( elem, "select" ) ) {
3953                                         testChange.call( this, e );
3954                                 }
3955                         },
3956
3957                         // Change has to be called before submit
3958                         // Keydown will be called before keypress, which is used in submit-event delegation
3959                         keydown: function( e ) {
3960                                 var elem = e.target, type = jQuery.nodeName( elem, "input" ) ? elem.type : "";
3961
3962                                 if ( (e.keyCode === 13 && !jQuery.nodeName( elem, "textarea" ) ) ||
3963                                         (e.keyCode === 32 && (type === "checkbox" || type === "radio")) ||
3964                                         type === "select-multiple" ) {
3965                                         testChange.call( this, e );
3966                                 }
3967                         },
3968
3969                         // Beforeactivate happens also before the previous element is blurred
3970                         // with this event you can't trigger a change event, but you can store
3971                         // information
3972                         beforeactivate: function( e ) {
3973                                 var elem = e.target;
3974                                 jQuery._data( elem, "_change_data", getVal(elem) );
3975                         }
3976                 },
3977
3978                 setup: function( data, namespaces ) {
3979                         if ( this.type === "file" ) {
3980                                 return false;
3981                         }
3982
3983                         for ( var type in changeFilters ) {
3984                                 jQuery.event.add( this, type + ".specialChange", changeFilters[type] );
3985                         }
3986
3987                         return rformElems.test( this.nodeName );
3988                 },
3989
3990                 teardown: function( namespaces ) {
3991                         jQuery.event.remove( this, ".specialChange" );
3992
3993                         return rformElems.test( this.nodeName );
3994                 }
3995         };
3996
3997         changeFilters = jQuery.event.special.change.filters;
3998
3999         // Handle when the input is .focus()'d
4000         changeFilters.focus = changeFilters.beforeactivate;
4001 }
4002
4003 function trigger( type, elem, args ) {
4004         // Piggyback on a donor event to simulate a different one.
4005         // Fake originalEvent to avoid donor's stopPropagation, but if the
4006         // simulated event prevents default then we do the same on the donor.
4007         // Don't pass args or remember liveFired; they apply to the donor event.
4008         var event = jQuery.extend( {}, args[ 0 ] );
4009         event.type = type;
4010         event.originalEvent = {};
4011         event.liveFired = undefined;
4012         jQuery.event.handle.call( elem, event );
4013         if ( event.isDefaultPrevented() ) {
4014                 args[ 0 ].preventDefault();
4015         }
4016 }
4017
4018 // Create "bubbling" focus and blur events
4019 if ( !jQuery.support.focusinBubbles ) {
4020         jQuery.each({ focus: "focusin", blur: "focusout" }, function( orig, fix ) {
4021
4022                 // Attach a single capturing handler while someone wants focusin/focusout
4023                 var attaches = 0;
4024
4025                 jQuery.event.special[ fix ] = {
4026                         setup: function() {
4027                                 if ( attaches++ === 0 ) {
4028                                         document.addEventListener( orig, handler, true );
4029                                 }
4030                         },
4031                         teardown: function() {
4032                                 if ( --attaches === 0 ) {
4033                                         document.removeEventListener( orig, handler, true );
4034                                 }
4035                         }
4036                 };
4037
4038                 function handler( donor ) {
4039                         // Donor event is always a native one; fix it and switch its type.
4040                         // Let focusin/out handler cancel the donor focus/blur event.
4041                         var e = jQuery.event.fix( donor );
4042                         e.type = fix;
4043                         e.originalEvent = {};
4044                         jQuery.event.trigger( e, null, e.target );
4045                         if ( e.isDefaultPrevented() ) {
4046                                 donor.preventDefault();
4047                         }
4048                 }
4049         });
4050 }
4051
4052 jQuery.each(["bind", "one"], function( i, name ) {
4053         jQuery.fn[ name ] = function( type, data, fn ) {
4054                 var handler;
4055
4056                 // Handle object literals
4057                 if ( typeof type === "object" ) {
4058                         for ( var key in type ) {
4059                                 this[ name ](key, data, type[key], fn);
4060                         }
4061                         return this;
4062                 }
4063
4064                 if ( arguments.length === 2 || data === false ) {
4065                         fn = data;
4066                         data = undefined;
4067                 }
4068
4069                 if ( name === "one" ) {
4070                         handler = function( event ) {
4071                                 jQuery( this ).unbind( event, handler );
4072                                 return fn.apply( this, arguments );
4073                         };
4074                         handler.guid = fn.guid || jQuery.guid++;
4075                 } else {
4076                         handler = fn;
4077                 }
4078
4079                 if ( type === "unload" && name !== "one" ) {
4080                         this.one( type, data, fn );
4081
4082                 } else {
4083                         for ( var i = 0, l = this.length; i < l; i++ ) {
4084                                 jQuery.event.add( this[i], type, handler, data );
4085                         }
4086                 }
4087
4088                 return this;
4089         };
4090 });
4091
4092 jQuery.fn.extend({
4093         unbind: function( type, fn ) {
4094                 // Handle object literals
4095                 if ( typeof type === "object" && !type.preventDefault ) {
4096                         for ( var key in type ) {
4097                                 this.unbind(key, type[key]);
4098                         }
4099
4100                 } else {
4101                         for ( var i = 0, l = this.length; i < l; i++ ) {
4102                                 jQuery.event.remove( this[i], type, fn );
4103                         }
4104                 }
4105
4106                 return this;
4107         },
4108
4109         delegate: function( selector, types, data, fn ) {
4110                 return this.live( types, data, fn, selector );
4111         },
4112
4113         undelegate: function( selector, types, fn ) {
4114                 if ( arguments.length === 0 ) {
4115                         return this.unbind( "live" );
4116
4117                 } else {
4118                         return this.die( types, null, fn, selector );
4119                 }
4120         },
4121
4122         trigger: function( type, data ) {
4123                 return this.each(function() {
4124                         jQuery.event.trigger( type, data, this );
4125                 });
4126         },
4127
4128         triggerHandler: function( type, data ) {
4129                 if ( this[0] ) {
4130                         return jQuery.event.trigger( type, data, this[0], true );
4131                 }
4132         },
4133
4134         toggle: function( fn ) {
4135                 // Save reference to arguments for access in closure
4136                 var args = arguments,
4137                         guid = fn.guid || jQuery.guid++,
4138                         i = 0,
4139                         toggler = function( event ) {
4140                                 // Figure out which function to execute
4141                                 var lastToggle = ( jQuery.data( this, "lastToggle" + fn.guid ) || 0 ) % i;
4142                                 jQuery.data( this, "lastToggle" + fn.guid, lastToggle + 1 );
4143
4144                                 // Make sure that clicks stop
4145                                 event.preventDefault();
4146
4147                                 // and execute the function
4148                                 return args[ lastToggle ].apply( this, arguments ) || false;
4149                         };
4150
4151                 // link all the functions, so any of them can unbind this click handler
4152                 toggler.guid = guid;
4153                 while ( i < args.length ) {
4154                         args[ i++ ].guid = guid;
4155                 }
4156
4157                 return this.click( toggler );
4158         },
4159
4160         hover: function( fnOver, fnOut ) {
4161                 return this.mouseenter( fnOver ).mouseleave( fnOut || fnOver );
4162         }
4163 });
4164
4165 var liveMap = {
4166         focus: "focusin",
4167         blur: "focusout",
4168         mouseenter: "mouseover",
4169         mouseleave: "mouseout"
4170 };
4171
4172 jQuery.each(["live", "die"], function( i, name ) {
4173         jQuery.fn[ name ] = function( types, data, fn, origSelector /* Internal Use Only */ ) {
4174                 var type, i = 0, match, namespaces, preType,
4175                         selector = origSelector || this.selector,
4176                         context = origSelector ? this : jQuery( this.context );
4177
4178                 if ( typeof types === "object" && !types.preventDefault ) {
4179                         for ( var key in types ) {
4180                                 context[ name ]( key, data, types[key], selector );
4181                         }
4182
4183                         return this;
4184                 }
4185
4186                 if ( name === "die" && !types &&
4187                                         origSelector && origSelector.charAt(0) === "." ) {
4188
4189                         context.unbind( origSelector );
4190
4191                         return this;
4192                 }
4193
4194                 if ( data === false || jQuery.isFunction( data ) ) {
4195                         fn = data || returnFalse;
4196                         data = undefined;
4197                 }
4198
4199                 types = (types || "").split(" ");
4200
4201                 while ( (type = types[ i++ ]) != null ) {
4202                         match = rnamespaces.exec( type );
4203                         namespaces = "";
4204
4205                         if ( match )  {
4206                                 namespaces = match[0];
4207                                 type = type.replace( rnamespaces, "" );
4208                         }
4209
4210                         if ( type === "hover" ) {
4211                                 types.push( "mouseenter" + namespaces, "mouseleave" + namespaces );
4212                                 continue;
4213                         }
4214
4215                         preType = type;
4216
4217                         if ( liveMap[ type ] ) {
4218                                 types.push( liveMap[ type ] + namespaces );
4219                                 type = type + namespaces;
4220
4221                         } else {
4222                                 type = (liveMap[ type ] || type) + namespaces;
4223                         }
4224
4225                         if ( name === "live" ) {
4226                                 // bind live handler
4227                                 for ( var j = 0, l = context.length; j < l; j++ ) {
4228                                         jQuery.event.add( context[j], "live." + liveConvert( type, selector ),
4229                                                 { data: data, selector: selector, handler: fn, origType: type, origHandler: fn, preType: preType } );
4230                                 }
4231
4232                         } else {
4233                                 // unbind live handler
4234                                 context.unbind( "live." + liveConvert( type, selector ), fn );
4235                         }
4236                 }
4237
4238                 return this;
4239         };
4240 });
4241
4242 function liveHandler( event ) {
4243         var stop, maxLevel, related, match, handleObj, elem, j, i, l, data, close, namespace, ret,
4244                 elems = [],
4245                 selectors = [],
4246                 events = jQuery._data( this, "events" );
4247
4248         // Make sure we avoid non-left-click bubbling in Firefox (#3861) and disabled elements in IE (#6911)
4249         if ( event.liveFired === this || !events || !events.live || event.target.disabled || event.button && event.type === "click" ) {
4250                 return;
4251         }
4252
4253         if ( event.namespace ) {
4254                 namespace = new RegExp("(^|\\.)" + event.namespace.split(".").join("\\.(?:.*\\.)?") + "(\\.|$)");
4255         }
4256
4257         event.liveFired = this;
4258
4259         var live = events.live.slice(0);
4260
4261         for ( j = 0; j < live.length; j++ ) {
4262                 handleObj = live[j];
4263
4264                 if ( handleObj.origType.replace( rnamespaces, "" ) === event.type ) {
4265                         selectors.push( handleObj.selector );
4266
4267                 } else {
4268                         live.splice( j--, 1 );
4269                 }
4270         }
4271
4272         match = jQuery( event.target ).closest( selectors, event.currentTarget );
4273
4274         for ( i = 0, l = match.length; i < l; i++ ) {
4275                 close = match[i];
4276
4277                 for ( j = 0; j < live.length; j++ ) {
4278                         handleObj = live[j];
4279
4280                         if ( close.selector === handleObj.selector && (!namespace || namespace.test( handleObj.namespace )) && !close.elem.disabled ) {
4281                                 elem = close.elem;
4282                                 related = null;
4283
4284                                 // Those two events require additional checking
4285                                 if ( handleObj.preType === "mouseenter" || handleObj.preType === "mouseleave" ) {
4286                                         event.type = handleObj.preType;
4287                                         related = jQuery( event.relatedTarget ).closest( handleObj.selector )[0];
4288
4289                                         // Make sure not to accidentally match a child element with the same selector
4290                                         if ( related && jQuery.contains( elem, related ) ) {
4291                                                 related = elem;
4292                                         }
4293                                 }
4294
4295                                 if ( !related || related !== elem ) {
4296                                         elems.push({ elem: elem, handleObj: handleObj, level: close.level });
4297                                 }
4298                         }
4299                 }
4300         }
4301
4302         for ( i = 0, l = elems.length; i < l; i++ ) {
4303                 match = elems[i];
4304
4305                 if ( maxLevel && match.level > maxLevel ) {
4306                         break;
4307                 }
4308
4309                 event.currentTarget = match.elem;
4310                 event.data = match.handleObj.data;
4311                 event.handleObj = match.handleObj;
4312
4313                 ret = match.handleObj.origHandler.apply( match.elem, arguments );
4314
4315                 if ( ret === false || event.isPropagationStopped() ) {
4316                         maxLevel = match.level;
4317
4318                         if ( ret === false ) {
4319                                 stop = false;
4320                         }
4321                         if ( event.isImmediatePropagationStopped() ) {
4322                                 break;
4323                         }
4324                 }
4325         }
4326
4327         return stop;
4328 }
4329
4330 function liveConvert( type, selector ) {
4331         return (type && type !== "*" ? type + "." : "") + selector.replace(rperiod, "`").replace(rspaces, "&");
4332 }
4333
4334 jQuery.each( ("blur focus focusin focusout load resize scroll unload click dblclick " +
4335         "mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave " +
4336         "change select submit keydown keypress keyup error").split(" "), function( i, name ) {
4337
4338         // Handle event binding
4339         jQuery.fn[ name ] = function( data, fn ) {
4340                 if ( fn == null ) {
4341                         fn = data;
4342                         data = null;
4343                 }
4344
4345                 return arguments.length > 0 ?
4346                         this.bind( name, data, fn ) :
4347                         this.trigger( name );
4348         };
4349
4350         if ( jQuery.attrFn ) {
4351                 jQuery.attrFn[ name ] = true;
4352         }
4353 });
4354
4355
4356
4357 /*!
4358  * Sizzle CSS Selector Engine
4359  *  Copyright 2011, The Dojo Foundation
4360  *  Released under the MIT, BSD, and GPL Licenses.
4361  *  More information: http://sizzlejs.com/
4362  */
4363 (function(){
4364
4365 var chunker = /((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^\[\]]*\]|['"][^'"]*['"]|[^\[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g,
4366         done = 0,
4367         toString = Object.prototype.toString,
4368         hasDuplicate = false,
4369         baseHasDuplicate = true,
4370         rBackslash = /\\/g,
4371         rNonWord = /\W/;
4372
4373 // Here we check if the JavaScript engine is using some sort of
4374 // optimization where it does not always call our comparision
4375 // function. If that is the case, discard the hasDuplicate value.
4376 //   Thus far that includes Google Chrome.
4377 [0, 0].sort(function() {
4378         baseHasDuplicate = false;
4379         return 0;
4380 });
4381
4382 var Sizzle = function( selector, context, results, seed ) {
4383         results = results || [];
4384         context = context || document;
4385
4386         var origContext = context;
4387
4388         if ( context.nodeType !== 1 && context.nodeType !== 9 ) {
4389                 return [];
4390         }
4391         
4392         if ( !selector || typeof selector !== "string" ) {
4393                 return results;
4394         }
4395
4396         var m, set, checkSet, extra, ret, cur, pop, i,
4397                 prune = true,
4398                 contextXML = Sizzle.isXML( context ),
4399                 parts = [],
4400                 soFar = selector;
4401         
4402         // Reset the position of the chunker regexp (start from head)
4403         do {
4404                 chunker.exec( "" );
4405                 m = chunker.exec( soFar );
4406
4407                 if ( m ) {
4408                         soFar = m[3];
4409                 
4410                         parts.push( m[1] );
4411                 
4412                         if ( m[2] ) {
4413                                 extra = m[3];
4414                                 break;
4415                         }
4416                 }
4417         } while ( m );
4418
4419         if ( parts.length > 1 && origPOS.exec( selector ) ) {
4420
4421                 if ( parts.length === 2 && Expr.relative[ parts[0] ] ) {
4422                         set = posProcess( parts[0] + parts[1], context );
4423
4424                 } else {
4425                         set = Expr.relative[ parts[0] ] ?
4426                                 [ context ] :
4427                                 Sizzle( parts.shift(), context );
4428
4429                         while ( parts.length ) {
4430                                 selector = parts.shift();
4431
4432                                 if ( Expr.relative[ selector ] ) {
4433                                         selector += parts.shift();
4434                                 }
4435                                 
4436                                 set = posProcess( selector, set );
4437                         }
4438                 }
4439
4440         } else {
4441                 // Take a shortcut and set the context if the root selector is an ID
4442                 // (but not if it'll be faster if the inner selector is an ID)
4443                 if ( !seed && parts.length > 1 && context.nodeType === 9 && !contextXML &&
4444                                 Expr.match.ID.test(parts[0]) && !Expr.match.ID.test(parts[parts.length - 1]) ) {
4445
4446                         ret = Sizzle.find( parts.shift(), context, contextXML );
4447                         context = ret.expr ?
4448                                 Sizzle.filter( ret.expr, ret.set )[0] :
4449                                 ret.set[0];
4450                 }
4451
4452                 if ( context ) {
4453                         ret = seed ?
4454                                 { expr: parts.pop(), set: makeArray(seed) } :
4455                                 Sizzle.find( parts.pop(), parts.length === 1 && (parts[0] === "~" || parts[0] === "+") && context.parentNode ? context.parentNode : context, contextXML );
4456
4457                         set = ret.expr ?
4458                                 Sizzle.filter( ret.expr, ret.set ) :
4459                                 ret.set;
4460
4461                         if ( parts.length > 0 ) {
4462                                 checkSet = makeArray( set );
4463
4464                         } else {
4465                                 prune = false;
4466                         }
4467
4468                         while ( parts.length ) {
4469                                 cur = parts.pop();
4470                                 pop = cur;
4471
4472                                 if ( !Expr.relative[ cur ] ) {
4473                                         cur = "";
4474                                 } else {
4475                                         pop = parts.pop();
4476                                 }
4477
4478                                 if ( pop == null ) {
4479                                         pop = context;
4480                                 }
4481
4482                                 Expr.relative[ cur ]( checkSet, pop, contextXML );
4483                         }
4484
4485                 } else {
4486                         checkSet = parts = [];
4487                 }
4488         }
4489
4490         if ( !checkSet ) {
4491                 checkSet = set;
4492         }
4493
4494         if ( !checkSet ) {
4495                 Sizzle.error( cur || selector );
4496         }
4497
4498         if ( toString.call(checkSet) === "[object Array]" ) {
4499                 if ( !prune ) {
4500                         results.push.apply( results, checkSet );
4501
4502                 } else if ( context && context.nodeType === 1 ) {
4503                         for ( i = 0; checkSet[i] != null; i++ ) {
4504                                 if ( checkSet[i] && (checkSet[i] === true || checkSet[i].nodeType === 1 && Sizzle.contains(context, checkSet[i])) ) {
4505                                         results.push( set[i] );
4506                                 }
4507                         }
4508
4509                 } else {
4510                         for ( i = 0; checkSet[i] != null; i++ ) {
4511                                 if ( checkSet[i] && checkSet[i].nodeType === 1 ) {
4512                                         results.push( set[i] );
4513                                 }
4514                         }
4515                 }
4516
4517         } else {
4518                 makeArray( checkSet, results );
4519         }
4520
4521         if ( extra ) {
4522                 Sizzle( extra, origContext, results, seed );
4523                 Sizzle.uniqueSort( results );
4524         }
4525
4526         return results;
4527 };
4528
4529 Sizzle.uniqueSort = function( results ) {
4530         if ( sortOrder ) {
4531                 hasDuplicate = baseHasDuplicate;
4532                 results.sort( sortOrder );
4533
4534                 if ( hasDuplicate ) {
4535                         for ( var i = 1; i < results.length; i++ ) {
4536                                 if ( results[i] === results[ i - 1 ] ) {
4537                                         results.splice( i--, 1 );
4538                                 }
4539                         }
4540                 }
4541         }
4542
4543         return results;
4544 };
4545
4546 Sizzle.matches = function( expr, set ) {
4547         return Sizzle( expr, null, null, set );
4548 };
4549
4550 Sizzle.matchesSelector = function( node, expr ) {
4551         return Sizzle( expr, null, null, [node] ).length > 0;
4552 };
4553
4554 Sizzle.find = function( expr, context, isXML ) {
4555         var set;
4556
4557         if ( !expr ) {
4558                 return [];
4559         }
4560
4561         for ( var i = 0, l = Expr.order.length; i < l; i++ ) {
4562                 var match,
4563                         type = Expr.order[i];
4564                 
4565                 if ( (match = Expr.leftMatch[ type ].exec( expr )) ) {
4566                         var left = match[1];
4567                         match.splice( 1, 1 );
4568
4569                         if ( left.substr( left.length - 1 ) !== "\\" ) {
4570                                 match[1] = (match[1] || "").replace( rBackslash, "" );
4571                                 set = Expr.find[ type ]( match, context, isXML );
4572
4573                                 if ( set != null ) {
4574                                         expr = expr.replace( Expr.match[ type ], "" );
4575                                         break;
4576                                 }
4577                         }
4578                 }
4579         }
4580
4581         if ( !set ) {
4582                 set = typeof context.getElementsByTagName !== "undefined" ?
4583                         context.getElementsByTagName( "*" ) :
4584                         [];
4585         }
4586
4587         return { set: set, expr: expr };
4588 };
4589
4590 Sizzle.filter = function( expr, set, inplace, not ) {
4591         var match, anyFound,
4592                 old = expr,
4593                 result = [],
4594                 curLoop = set,
4595                 isXMLFilter = set && set[0] && Sizzle.isXML( set[0] );
4596
4597         while ( expr && set.length ) {
4598                 for ( var type in Expr.filter ) {
4599                         if ( (match = Expr.leftMatch[ type ].exec( expr )) != null && match[2] ) {
4600                                 var found, item,
4601                                         filter = Expr.filter[ type ],
4602                                         left = match[1];
4603
4604                                 anyFound = false;
4605
4606                                 match.splice(1,1);
4607
4608                                 if ( left.substr( left.length - 1 ) === "\\" ) {
4609                                         continue;
4610                                 }
4611
4612                                 if ( curLoop === result ) {
4613                                         result = [];
4614                                 }
4615
4616                                 if ( Expr.preFilter[ type ] ) {
4617                                         match = Expr.preFilter[ type ]( match, curLoop, inplace, result, not, isXMLFilter );
4618
4619                                         if ( !match ) {
4620                                                 anyFound = found = true;
4621
4622                                         } else if ( match === true ) {
4623                                                 continue;
4624                                         }
4625                                 }
4626
4627                                 if ( match ) {
4628                                         for ( var i = 0; (item = curLoop[i]) != null; i++ ) {
4629                                                 if ( item ) {
4630                                                         found = filter( item, match, i, curLoop );
4631                                                         var pass = not ^ !!found;
4632
4633                                                         if ( inplace && found != null ) {
4634                                                                 if ( pass ) {
4635                                                                         anyFound = true;
4636
4637                                                                 } else {
4638                                                                         curLoop[i] = false;
4639                                                                 }
4640
4641                                                         } else if ( pass ) {
4642                                                                 result.push( item );
4643                                                                 anyFound = true;
4644                                                         }
4645                                                 }
4646                                         }
4647                                 }
4648
4649                                 if ( found !== undefined ) {
4650                                         if ( !inplace ) {
4651                                                 curLoop = result;
4652                                         }
4653
4654                                         expr = expr.replace( Expr.match[ type ], "" );
4655
4656                                         if ( !anyFound ) {
4657                                                 return [];
4658                                         }
4659
4660                                         break;
4661                                 }
4662                         }
4663                 }
4664
4665                 // Improper expression
4666                 if ( expr === old ) {
4667                         if ( anyFound == null ) {
4668                                 Sizzle.error( expr );
4669
4670                         } else {
4671                                 break;
4672                         }
4673                 }
4674
4675                 old = expr;
4676         }
4677
4678         return curLoop;
4679 };
4680
4681 Sizzle.error = function( msg ) {
4682         throw "Syntax error, unrecognized expression: " + msg;
4683 };
4684
4685 var Expr = Sizzle.selectors = {
4686         order: [ "ID", "NAME", "TAG" ],
4687
4688         match: {
4689                 ID: /#((?:[\w\u00c0-\uFFFF\-]|\\.)+)/,
4690                 CLASS: /\.((?:[\w\u00c0-\uFFFF\-]|\\.)+)/,
4691                 NAME: /\[name=['"]*((?:[\w\u00c0-\uFFFF\-]|\\.)+)['"]*\]/,
4692                 ATTR: /\[\s*((?:[\w\u00c0-\uFFFF\-]|\\.)+)\s*(?:(\S?=)\s*(?:(['"])(.*?)\3|(#?(?:[\w\u00c0-\uFFFF\-]|\\.)*)|)|)\s*\]/,
4693                 TAG: /^((?:[\w\u00c0-\uFFFF\*\-]|\\.)+)/,
4694                 CHILD: /:(only|nth|last|first)-child(?:\(\s*(even|odd|(?:[+\-]?\d+|(?:[+\-]?\d*)?n\s*(?:[+\-]\s*\d+)?))\s*\))?/,
4695                 POS: /:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^\-]|$)/,
4696                 PSEUDO: /:((?:[\w\u00c0-\uFFFF\-]|\\.)+)(?:\((['"]?)((?:\([^\)]+\)|[^\(\)]*)+)\2\))?/
4697         },
4698
4699         leftMatch: {},
4700
4701         attrMap: {
4702                 "class": "className",
4703                 "for": "htmlFor"
4704         },
4705
4706         attrHandle: {
4707                 href: function( elem ) {
4708                         return elem.getAttribute( "href" );
4709                 },
4710                 type: function( elem ) {
4711                         return elem.getAttribute( "type" );
4712                 }
4713         },
4714
4715         relative: {
4716                 "+": function(checkSet, part){
4717                         var isPartStr = typeof part === "string",
4718                                 isTag = isPartStr && !rNonWord.test( part ),
4719                                 isPartStrNotTag = isPartStr && !isTag;
4720
4721                         if ( isTag ) {
4722                                 part = part.toLowerCase();
4723                         }
4724
4725                         for ( var i = 0, l = checkSet.length, elem; i < l; i++ ) {
4726                                 if ( (elem = checkSet[i]) ) {
4727                                         while ( (elem = elem.previousSibling) && elem.nodeType !== 1 ) {}
4728
4729                                         checkSet[i] = isPartStrNotTag || elem && elem.nodeName.toLowerCase() === part ?
4730                                                 elem || false :
4731                                                 elem === part;
4732                                 }
4733                         }
4734
4735                         if ( isPartStrNotTag ) {
4736                                 Sizzle.filter( part, checkSet, true );
4737                         }
4738                 },
4739
4740                 ">": function( checkSet, part ) {
4741                         var elem,
4742                                 isPartStr = typeof part === "string",
4743                                 i = 0,
4744                                 l = checkSet.length;
4745
4746                         if ( isPartStr && !rNonWord.test( part ) ) {
4747                                 part = part.toLowerCase();
4748
4749                                 for ( ; i < l; i++ ) {
4750                                         elem = checkSet[i];
4751
4752                                         if ( elem ) {
4753                                                 var parent = elem.parentNode;
4754                                                 checkSet[i] = parent.nodeName.toLowerCase() === part ? parent : false;
4755                                         }
4756                                 }
4757
4758                         } else {
4759                                 for ( ; i < l; i++ ) {
4760                                         elem = checkSet[i];
4761
4762                                         if ( elem ) {
4763                                                 checkSet[i] = isPartStr ?
4764                                                         elem.parentNode :
4765                                                         elem.parentNode === part;
4766                                         }
4767                                 }
4768
4769                                 if ( isPartStr ) {
4770                                         Sizzle.filter( part, checkSet, true );
4771                                 }
4772                         }
4773                 },
4774
4775                 "": function(checkSet, part, isXML){
4776                         var nodeCheck,
4777                                 doneName = done++,
4778                                 checkFn = dirCheck;
4779
4780                         if ( typeof part === "string" && !rNonWord.test( part ) ) {
4781                                 part = part.toLowerCase();
4782                                 nodeCheck = part;
4783                                 checkFn = dirNodeCheck;
4784                         }
4785
4786                         checkFn( "parentNode", part, doneName, checkSet, nodeCheck, isXML );
4787                 },
4788
4789                 "~": function( checkSet, part, isXML ) {
4790                         var nodeCheck,
4791                                 doneName = done++,
4792                                 checkFn = dirCheck;
4793
4794                         if ( typeof part === "string" && !rNonWord.test( part ) ) {
4795                                 part = part.toLowerCase();
4796                                 nodeCheck = part;
4797                                 checkFn = dirNodeCheck;
4798                         }
4799
4800                         checkFn( "previousSibling", part, doneName, checkSet, nodeCheck, isXML );
4801                 }
4802         },
4803
4804         find: {
4805                 ID: function( match, context, isXML ) {
4806                         if ( typeof context.getElementById !== "undefined" && !isXML ) {
4807                                 var m = context.getElementById(match[1]);
4808                                 // Check parentNode to catch when Blackberry 4.6 returns
4809                                 // nodes that are no longer in the document #6963
4810                                 return m && m.parentNode ? [m] : [];
4811                         }
4812                 },
4813
4814                 NAME: function( match, context ) {
4815                         if ( typeof context.getElementsByName !== "undefined" ) {
4816                                 var ret = [],
4817                                         results = context.getElementsByName( match[1] );
4818
4819                                 for ( var i = 0, l = results.length; i < l; i++ ) {
4820                                         if ( results[i].getAttribute("name") === match[1] ) {
4821                                                 ret.push( results[i] );
4822                                         }
4823                                 }
4824
4825                                 return ret.length === 0 ? null : ret;
4826                         }
4827                 },
4828
4829                 TAG: function( match, context ) {
4830                         if ( typeof context.getElementsByTagName !== "undefined" ) {
4831                                 return context.getElementsByTagName( match[1] );
4832                         }
4833                 }
4834         },
4835         preFilter: {
4836                 CLASS: function( match, curLoop, inplace, result, not, isXML ) {
4837                         match = " " + match[1].replace( rBackslash, "" ) + " ";
4838
4839                         if ( isXML ) {
4840                                 return match;
4841                         }
4842
4843                         for ( var i = 0, elem; (elem = curLoop[i]) != null; i++ ) {
4844                                 if ( elem ) {
4845                                         if ( not ^ (elem.className && (" " + elem.className + " ").replace(/[\t\n\r]/g, " ").indexOf(match) >= 0) ) {
4846                                                 if ( !inplace ) {
4847                                                         result.push( elem );
4848                                                 }
4849
4850                                         } else if ( inplace ) {
4851                                                 curLoop[i] = false;
4852                                         }
4853                                 }
4854                         }
4855
4856                         return false;
4857                 },
4858
4859                 ID: function( match ) {
4860                         return match[1].replace( rBackslash, "" );
4861                 },
4862
4863                 TAG: function( match, curLoop ) {
4864                         return match[1].replace( rBackslash, "" ).toLowerCase();
4865                 },
4866
4867                 CHILD: function( match ) {
4868                         if ( match[1] === "nth" ) {
4869                                 if ( !match[2] ) {
4870                                         Sizzle.error( match[0] );
4871                                 }
4872
4873                                 match[2] = match[2].replace(/^\+|\s*/g, '');
4874
4875                                 // parse equations like 'even', 'odd', '5', '2n', '3n+2', '4n-1', '-n+6'
4876                                 var test = /(-?)(\d*)(?:n([+\-]?\d*))?/.exec(
4877                                         match[2] === "even" && "2n" || match[2] === "odd" && "2n+1" ||
4878                                         !/\D/.test( match[2] ) && "0n+" + match[2] || match[2]);
4879
4880                                 // calculate the numbers (first)n+(last) including if they are negative
4881                                 match[2] = (test[1] + (test[2] || 1)) - 0;
4882                                 match[3] = test[3] - 0;
4883                         }
4884                         else if ( match[2] ) {
4885                                 Sizzle.error( match[0] );
4886                         }
4887
4888                         // TODO: Move to normal caching system
4889                         match[0] = done++;
4890
4891                         return match;
4892                 },
4893
4894                 ATTR: function( match, curLoop, inplace, result, not, isXML ) {
4895                         var name = match[1] = match[1].replace( rBackslash, "" );
4896                         
4897                         if ( !isXML && Expr.attrMap[name] ) {
4898                                 match[1] = Expr.attrMap[name];
4899                         }
4900
4901                         // Handle if an un-quoted value was used
4902                         match[4] = ( match[4] || match[5] || "" ).replace( rBackslash, "" );
4903
4904                         if ( match[2] === "~=" ) {
4905                                 match[4] = " " + match[4] + " ";
4906                         }
4907
4908                         return match;
4909                 },
4910
4911                 PSEUDO: function( match, curLoop, inplace, result, not ) {
4912                         if ( match[1] === "not" ) {
4913                                 // If we're dealing with a complex expression, or a simple one
4914                                 if ( ( chunker.exec(match[3]) || "" ).length > 1 || /^\w/.test(match[3]) ) {
4915                                         match[3] = Sizzle(match[3], null, null, curLoop);
4916
4917                                 } else {
4918                                         var ret = Sizzle.filter(match[3], curLoop, inplace, true ^ not);
4919
4920                                         if ( !inplace ) {
4921                                                 result.push.apply( result, ret );
4922                                         }
4923
4924                                         return false;
4925                                 }
4926
4927                         } else if ( Expr.match.POS.test( match[0] ) || Expr.match.CHILD.test( match[0] ) ) {
4928                                 return true;
4929                         }
4930                         
4931                         return match;
4932                 },
4933
4934                 POS: function( match ) {
4935                         match.unshift( true );
4936
4937                         return match;
4938                 }
4939         },
4940         
4941         filters: {
4942                 enabled: function( elem ) {
4943                         return elem.disabled === false && elem.type !== "hidden";
4944                 },
4945
4946                 disabled: function( elem ) {
4947                         return elem.disabled === true;
4948                 },
4949
4950                 checked: function( elem ) {
4951                         return elem.checked === true;
4952                 },
4953                 
4954                 selected: function( elem ) {
4955                         // Accessing this property makes selected-by-default
4956                         // options in Safari work properly
4957                         if ( elem.parentNode ) {
4958                                 elem.parentNode.selectedIndex;
4959                         }
4960                         
4961                         return elem.selected === true;
4962                 },
4963
4964                 parent: function( elem ) {
4965                         return !!elem.firstChild;
4966                 },
4967
4968                 empty: function( elem ) {
4969                         return !elem.firstChild;
4970                 },
4971
4972                 has: function( elem, i, match ) {
4973                         return !!Sizzle( match[3], elem ).length;
4974                 },
4975
4976                 header: function( elem ) {
4977                         return (/h\d/i).test( elem.nodeName );
4978                 },
4979
4980                 text: function( elem ) {
4981                         var attr = elem.getAttribute( "type" ), type = elem.type;
4982                         // IE6 and 7 will map elem.type to 'text' for new HTML5 types (search, etc) 
4983                         // use getAttribute instead to test this case
4984                         return elem.nodeName.toLowerCase() === "input" && "text" === type && ( attr === type || attr === null );
4985                 },
4986
4987                 radio: function( elem ) {
4988                         return elem.nodeName.toLowerCase() === "input" && "radio" === elem.type;
4989                 },
4990
4991                 checkbox: function( elem ) {
4992                         return elem.nodeName.toLowerCase() === "input" && "checkbox" === elem.type;
4993                 },
4994
4995                 file: function( elem ) {
4996                         return elem.nodeName.toLowerCase() === "input" && "file" === elem.type;
4997                 },
4998
4999                 password: function( elem ) {
5000                         return elem.nodeName.toLowerCase() === "input" && "password" === elem.type;
5001                 },
5002
5003                 submit: function( elem ) {
5004                         var name = elem.nodeName.toLowerCase();
5005                         return (name === "input" || name === "button") && "submit" === elem.type;
5006                 },
5007
5008                 image: function( elem ) {
5009                         return elem.nodeName.toLowerCase() === "input" && "image" === elem.type;
5010                 },
5011
5012                 reset: function( elem ) {
5013                         return elem.nodeName.toLowerCase() === "input" && "reset" === elem.type;
5014                 },
5015
5016                 button: function( elem ) {
5017                         var name = elem.nodeName.toLowerCase();
5018                         return name === "input" && "button" === elem.type || name === "button";
5019                 },
5020
5021                 input: function( elem ) {
5022                         return (/input|select|textarea|button/i).test( elem.nodeName );
5023                 },
5024
5025                 focus: function( elem ) {
5026                         return elem === elem.ownerDocument.activeElement;
5027                 }
5028         },
5029         setFilters: {
5030                 first: function( elem, i ) {
5031                         return i === 0;
5032                 },
5033
5034                 last: function( elem, i, match, array ) {
5035                         return i === array.length - 1;
5036                 },
5037
5038                 even: function( elem, i ) {
5039                         return i % 2 === 0;
5040                 },
5041
5042                 odd: function( elem, i ) {
5043                         return i % 2 === 1;
5044                 },
5045
5046                 lt: function( elem, i, match ) {
5047                         return i < match[3] - 0;
5048                 },
5049
5050                 gt: function( elem, i, match ) {
5051                         return i > match[3] - 0;
5052                 },
5053
5054                 nth: function( elem, i, match ) {
5055                         return match[3] - 0 === i;
5056                 },
5057
5058                 eq: function( elem, i, match ) {
5059                         return match[3] - 0 === i;
5060                 }
5061         },
5062         filter: {
5063                 PSEUDO: function( elem, match, i, array ) {
5064                         var name = match[1],
5065                                 filter = Expr.filters[ name ];
5066
5067                         if ( filter ) {
5068                                 return filter( elem, i, match, array );
5069
5070                         } else if ( name === "contains" ) {
5071                                 return (elem.textContent || elem.innerText || Sizzle.getText([ elem ]) || "").indexOf(match[3]) >= 0;
5072
5073                         } else if ( name === "not" ) {
5074                                 var not = match[3];
5075
5076                                 for ( var j = 0, l = not.length; j < l; j++ ) {
5077                                         if ( not[j] === elem ) {
5078                                                 return false;
5079                                         }
5080                                 }
5081
5082                                 return true;
5083
5084                         } else {
5085                                 Sizzle.error( name );
5086                         }
5087                 },
5088
5089                 CHILD: function( elem, match ) {
5090                         var type = match[1],
5091                                 node = elem;
5092
5093                         switch ( type ) {
5094                                 case "only":
5095                                 case "first":
5096                                         while ( (node = node.previousSibling) )  {
5097                                                 if ( node.nodeType === 1 ) { 
5098                                                         return false; 
5099                                                 }
5100                                         }
5101
5102                                         if ( type === "first" ) { 
5103                                                 return true; 
5104                                         }
5105
5106                                         node = elem;
5107
5108                                 case "last":
5109                                         while ( (node = node.nextSibling) )      {
5110                                                 if ( node.nodeType === 1 ) { 
5111                                                         return false; 
5112                                                 }
5113                                         }
5114
5115                                         return true;
5116
5117                                 case "nth":
5118                                         var first = match[2],
5119                                                 last = match[3];
5120
5121                                         if ( first === 1 && last === 0 ) {
5122                                                 return true;
5123                                         }
5124                                         
5125                                         var doneName = match[0],
5126                                                 parent = elem.parentNode;
5127         
5128                                         if ( parent && (parent.sizcache !== doneName || !elem.nodeIndex) ) {
5129                                                 var count = 0;
5130                                                 
5131                                                 for ( node = parent.firstChild; node; node = node.nextSibling ) {
5132                                                         if ( node.nodeType === 1 ) {
5133                                                                 node.nodeIndex = ++count;
5134                                                         }
5135                                                 } 
5136
5137                                                 parent.sizcache = doneName;
5138                                         }
5139                                         
5140                                         var diff = elem.nodeIndex - last;
5141
5142                                         if ( first === 0 ) {
5143                                                 return diff === 0;
5144
5145                                         } else {
5146                                                 return ( diff % first === 0 && diff / first >= 0 );
5147                                         }
5148                         }
5149                 },
5150
5151                 ID: function( elem, match ) {
5152                         return elem.nodeType === 1 && elem.getAttribute("id") === match;
5153                 },
5154
5155                 TAG: function( elem, match ) {
5156                         return (match === "*" && elem.nodeType === 1) || elem.nodeName.toLowerCase() === match;
5157                 },
5158                 
5159                 CLASS: function( elem, match ) {
5160                         return (" " + (elem.className || elem.getAttribute("class")) + " ")
5161                                 .indexOf( match ) > -1;
5162                 },
5163
5164                 ATTR: function( elem, match ) {
5165                         var name = match[1],
5166                                 result = Expr.attrHandle[ name ] ?
5167                                         Expr.attrHandle[ name ]( elem ) :
5168                                         elem[ name ] != null ?
5169                                                 elem[ name ] :
5170                                                 elem.getAttribute( name ),
5171                                 value = result + "",
5172                                 type = match[2],
5173                                 check = match[4];
5174
5175                         return result == null ?
5176                                 type === "!=" :
5177                                 type === "=" ?
5178                                 value === check :
5179                                 type === "*=" ?
5180                                 value.indexOf(check) >= 0 :
5181                                 type === "~=" ?
5182                                 (" " + value + " ").indexOf(check) >= 0 :
5183                                 !check ?
5184                                 value && result !== false :
5185                                 type === "!=" ?
5186                                 value !== check :
5187                                 type === "^=" ?
5188                                 value.indexOf(check) === 0 :
5189                                 type === "$=" ?
5190                                 value.substr(value.length - check.length) === check :
5191                                 type === "|=" ?
5192                                 value === check || value.substr(0, check.length + 1) === check + "-" :
5193                                 false;
5194                 },
5195
5196                 POS: function( elem, match, i, array ) {
5197                         var name = match[2],
5198                                 filter = Expr.setFilters[ name ];
5199
5200                         if ( filter ) {
5201                                 return filter( elem, i, match, array );
5202                         }
5203                 }
5204         }
5205 };
5206
5207 var origPOS = Expr.match.POS,
5208         fescape = function(all, num){
5209                 return "\\" + (num - 0 + 1);
5210         };
5211
5212 for ( var type in Expr.match ) {
5213         Expr.match[ type ] = new RegExp( Expr.match[ type ].source + (/(?![^\[]*\])(?![^\(]*\))/.source) );
5214         Expr.leftMatch[ type ] = new RegExp( /(^(?:.|\r|\n)*?)/.source + Expr.match[ type ].source.replace(/\\(\d+)/g, fescape) );
5215 }
5216
5217 var makeArray = function( array, results ) {
5218         array = Array.prototype.slice.call( array, 0 );
5219
5220         if ( results ) {
5221                 results.push.apply( results, array );
5222                 return results;
5223         }
5224         
5225         return array;
5226 };
5227
5228 // Perform a simple check to determine if the browser is capable of
5229 // converting a NodeList to an array using builtin methods.
5230 // Also verifies that the returned array holds DOM nodes
5231 // (which is not the case in the Blackberry browser)
5232 try {
5233         Array.prototype.slice.call( document.documentElement.childNodes, 0 )[0].nodeType;
5234
5235 // Provide a fallback method if it does not work
5236 } catch( e ) {
5237         makeArray = function( array, results ) {
5238                 var i = 0,
5239                         ret = results || [];
5240
5241                 if ( toString.call(array) === "[object Array]" ) {
5242                         Array.prototype.push.apply( ret, array );
5243
5244                 } else {
5245                         if ( typeof array.length === "number" ) {
5246                                 for ( var l = array.length; i < l; i++ ) {
5247                                         ret.push( array[i] );
5248                                 }
5249
5250                         } else {
5251                                 for ( ; array[i]; i++ ) {
5252                                         ret.push( array[i] );
5253                                 }
5254                         }
5255                 }
5256
5257                 return ret;
5258         };
5259 }
5260
5261 var sortOrder, siblingCheck;
5262
5263 if ( document.documentElement.compareDocumentPosition ) {
5264         sortOrder = function( a, b ) {
5265                 if ( a === b ) {
5266                         hasDuplicate = true;
5267                         return 0;
5268                 }
5269
5270                 if ( !a.compareDocumentPosition || !b.compareDocumentPosition ) {
5271                         return a.compareDocumentPosition ? -1 : 1;
5272                 }
5273
5274                 return a.compareDocumentPosition(b) & 4 ? -1 : 1;
5275         };
5276
5277 } else {
5278         sortOrder = function( a, b ) {
5279                 var al, bl,
5280                         ap = [],
5281                         bp = [],
5282                         aup = a.parentNode,
5283                         bup = b.parentNode,
5284                         cur = aup;
5285
5286                 // The nodes are identical, we can exit early
5287                 if ( a === b ) {
5288                         hasDuplicate = true;
5289                         return 0;
5290
5291                 // If the nodes are siblings (or identical) we can do a quick check
5292                 } else if ( aup === bup ) {
5293                         return siblingCheck( a, b );
5294
5295                 // If no parents were found then the nodes are disconnected
5296                 } else if ( !aup ) {
5297                         return -1;
5298
5299                 } else if ( !bup ) {
5300                         return 1;
5301                 }
5302
5303                 // Otherwise they're somewhere else in the tree so we need
5304                 // to build up a full list of the parentNodes for comparison
5305                 while ( cur ) {
5306                         ap.unshift( cur );
5307                         cur = cur.parentNode;
5308                 }
5309
5310                 cur = bup;
5311
5312                 while ( cur ) {
5313                         bp.unshift( cur );
5314                         cur = cur.parentNode;
5315                 }
5316
5317                 al = ap.length;
5318                 bl = bp.length;
5319
5320                 // Start walking down the tree looking for a discrepancy
5321                 for ( var i = 0; i < al && i < bl; i++ ) {
5322                         if ( ap[i] !== bp[i] ) {
5323                                 return siblingCheck( ap[i], bp[i] );
5324                         }
5325                 }
5326
5327                 // We ended someplace up the tree so do a sibling check
5328                 return i === al ?
5329                         siblingCheck( a, bp[i], -1 ) :
5330                         siblingCheck( ap[i], b, 1 );
5331         };
5332
5333         siblingCheck = function( a, b, ret ) {
5334                 if ( a === b ) {
5335                         return ret;
5336                 }
5337
5338                 var cur = a.nextSibling;
5339
5340                 while ( cur ) {
5341                         if ( cur === b ) {
5342                                 return -1;
5343                         }
5344
5345                         cur = cur.nextSibling;
5346                 }
5347
5348                 return 1;
5349         };
5350 }
5351
5352 // Utility function for retreiving the text value of an array of DOM nodes
5353 Sizzle.getText = function( elems ) {
5354         var ret = "", elem;
5355
5356         for ( var i = 0; elems[i]; i++ ) {
5357                 elem = elems[i];
5358
5359                 // Get the text from text nodes and CDATA nodes
5360                 if ( elem.nodeType === 3 || elem.nodeType === 4 ) {
5361                         ret += elem.nodeValue;
5362
5363                 // Traverse everything else, except comment nodes
5364                 } else if ( elem.nodeType !== 8 ) {
5365                         ret += Sizzle.getText( elem.childNodes );
5366                 }
5367         }
5368
5369         return ret;
5370 };
5371
5372 // Check to see if the browser returns elements by name when
5373 // querying by getElementById (and provide a workaround)
5374 (function(){
5375         // We're going to inject a fake input element with a specified name
5376         var form = document.createElement("div"),
5377                 id = "script" + (new Date()).getTime(),
5378                 root = document.documentElement;
5379
5380         form.innerHTML = "<a name='" + id + "'/>";
5381
5382         // Inject it into the root element, check its status, and remove it quickly
5383         root.insertBefore( form, root.firstChild );
5384
5385         // The workaround has to do additional checks after a getElementById
5386         // Which slows things down for other browsers (hence the branching)
5387         if ( document.getElementById( id ) ) {
5388                 Expr.find.ID = function( match, context, isXML ) {
5389                         if ( typeof context.getElementById !== "undefined" && !isXML ) {
5390                                 var m = context.getElementById(match[1]);
5391
5392                                 return m ?
5393                                         m.id === match[1] || typeof m.getAttributeNode !== "undefined" && m.getAttributeNode("id").nodeValue === match[1] ?
5394                                                 [m] :
5395                                                 undefined :
5396                                         [];
5397                         }
5398                 };
5399
5400                 Expr.filter.ID = function( elem, match ) {
5401                         var node = typeof elem.getAttributeNode !== "undefined" && elem.getAttributeNode("id");
5402
5403                         return elem.nodeType === 1 && node && node.nodeValue === match;
5404                 };
5405         }
5406
5407         root.removeChild( form );
5408
5409         // release memory in IE
5410         root = form = null;
5411 })();
5412
5413 (function(){
5414         // Check to see if the browser returns only elements
5415         // when doing getElementsByTagName("*")
5416
5417         // Create a fake element
5418         var div = document.createElement("div");
5419         div.appendChild( document.createComment("") );
5420
5421         // Make sure no comments are found
5422         if ( div.getElementsByTagName("*").length > 0 ) {
5423                 Expr.find.TAG = function( match, context ) {
5424                         var results = context.getElementsByTagName( match[1] );
5425
5426                         // Filter out possible comments
5427                         if ( match[1] === "*" ) {
5428                                 var tmp = [];
5429
5430                                 for ( var i = 0; results[i]; i++ ) {
5431                                         if ( results[i].nodeType === 1 ) {
5432                                                 tmp.push( results[i] );
5433                                         }
5434                                 }
5435
5436                                 results = tmp;
5437                         }
5438
5439                         return results;
5440                 };
5441         }
5442
5443         // Check to see if an attribute returns normalized href attributes
5444         div.innerHTML = "<a href='#'></a>";
5445
5446         if ( div.firstChild && typeof div.firstChild.getAttribute !== "undefined" &&
5447                         div.firstChild.getAttribute("href") !== "#" ) {
5448
5449                 Expr.attrHandle.href = function( elem ) {
5450                         return elem.getAttribute( "href", 2 );
5451                 };
5452         }
5453
5454         // release memory in IE
5455         div = null;
5456 })();
5457
5458 if ( document.querySelectorAll ) {
5459         (function(){
5460                 var oldSizzle = Sizzle,
5461                         div = document.createElement("div"),
5462                         id = "__sizzle__";
5463
5464                 div.innerHTML = "<p class='TEST'></p>";
5465
5466                 // Safari can't handle uppercase or unicode characters when
5467                 // in quirks mode.
5468                 if ( div.querySelectorAll && div.querySelectorAll(".TEST").length === 0 ) {
5469                         return;
5470                 }
5471         
5472                 Sizzle = function( query, context, extra, seed ) {
5473                         context = context || document;
5474
5475                         // Only use querySelectorAll on non-XML documents
5476                         // (ID selectors don't work in non-HTML documents)
5477                         if ( !seed && !Sizzle.isXML(context) ) {
5478                                 // See if we find a selector to speed up
5479                                 var match = /^(\w+$)|^\.([\w\-]+$)|^#([\w\-]+$)/.exec( query );
5480                                 
5481                                 if ( match && (context.nodeType === 1 || context.nodeType === 9) ) {
5482                                         // Speed-up: Sizzle("TAG")
5483                                         if ( match[1] ) {
5484                                                 return makeArray( context.getElementsByTagName( query ), extra );
5485                                         
5486                                         // Speed-up: Sizzle(".CLASS")
5487                                         } else if ( match[2] && Expr.find.CLASS && context.getElementsByClassName ) {
5488                                                 return makeArray( context.getElementsByClassName( match[2] ), extra );
5489                                         }
5490                                 }
5491                                 
5492                                 if ( context.nodeType === 9 ) {
5493                                         // Speed-up: Sizzle("body")
5494                                         // The body element only exists once, optimize finding it
5495                                         if ( query === "body" && context.body ) {
5496                                                 return makeArray( [ context.body ], extra );
5497                                                 
5498                                         // Speed-up: Sizzle("#ID")
5499                                         } else if ( match && match[3] ) {
5500                                                 var elem = context.getElementById( match[3] );
5501
5502                                                 // Check parentNode to catch when Blackberry 4.6 returns
5503                                                 // nodes that are no longer in the document #6963
5504                                                 if ( elem && elem.parentNode ) {
5505                                                         // Handle the case where IE and Opera return items
5506                                                         // by name instead of ID
5507                                                         if ( elem.id === match[3] ) {
5508                                                                 return makeArray( [ elem ], extra );
5509                                                         }
5510                                                         
5511                                                 } else {
5512                                                         return makeArray( [], extra );
5513                                                 }
5514                                         }
5515                                         
5516                                         try {
5517                                                 return makeArray( context.querySelectorAll(query), extra );
5518                                         } catch(qsaError) {}
5519
5520                                 // qSA works strangely on Element-rooted queries
5521                                 // We can work around this by specifying an extra ID on the root
5522                                 // and working up from there (Thanks to Andrew Dupont for the technique)
5523                                 // IE 8 doesn't work on object elements
5524                                 } else if ( context.nodeType === 1 && context.nodeName.toLowerCase() !== "object" ) {
5525                                         var oldContext = context,
5526                                                 old = context.getAttribute( "id" ),
5527                                                 nid = old || id,
5528                                                 hasParent = context.parentNode,
5529                                                 relativeHierarchySelector = /^\s*[+~]/.test( query );
5530
5531                                         if ( !old ) {
5532                                                 context.setAttribute( "id", nid );
5533                                         } else {
5534                                                 nid = nid.replace( /'/g, "\\$&" );
5535                                         }
5536                                         if ( relativeHierarchySelector && hasParent ) {
5537                                                 context = context.parentNode;
5538                                         }
5539
5540                                         try {
5541                                                 if ( !relativeHierarchySelector || hasParent ) {
5542                                                         return makeArray( context.querySelectorAll( "[id='" + nid + "'] " + query ), extra );
5543                                                 }
5544
5545                                         } catch(pseudoError) {
5546                                         } finally {
5547                                                 if ( !old ) {
5548                                                         oldContext.removeAttribute( "id" );
5549                                                 }
5550                                         }
5551                                 }
5552                         }
5553                 
5554                         return oldSizzle(query, context, extra, seed);
5555                 };
5556
5557                 for ( var prop in oldSizzle ) {
5558                         Sizzle[ prop ] = oldSizzle[ prop ];
5559                 }
5560
5561                 // release memory in IE
5562                 div = null;
5563         })();
5564 }
5565
5566 (function(){
5567         var html = document.documentElement,
5568                 matches = html.matchesSelector || html.mozMatchesSelector || html.webkitMatchesSelector || html.msMatchesSelector;
5569
5570         if ( matches ) {
5571                 // Check to see if it's possible to do matchesSelector
5572                 // on a disconnected node (IE 9 fails this)
5573                 var disconnectedMatch = !matches.call( document.createElement( "div" ), "div" ),
5574                         pseudoWorks = false;
5575
5576                 try {
5577                         // This should fail with an exception
5578                         // Gecko does not error, returns false instead
5579                         matches.call( document.documentElement, "[test!='']:sizzle" );
5580         
5581                 } catch( pseudoError ) {
5582                         pseudoWorks = true;
5583                 }
5584
5585                 Sizzle.matchesSelector = function( node, expr ) {
5586                         // Make sure that attribute selectors are quoted
5587                         expr = expr.replace(/\=\s*([^'"\]]*)\s*\]/g, "='$1']");
5588
5589                         if ( !Sizzle.isXML( node ) ) {
5590                                 try { 
5591                                         if ( pseudoWorks || !Expr.match.PSEUDO.test( expr ) && !/!=/.test( expr ) ) {
5592                                                 var ret = matches.call( node, expr );
5593
5594                                                 // IE 9's matchesSelector returns false on disconnected nodes
5595                                                 if ( ret || !disconnectedMatch ||
5596                                                                 // As well, disconnected nodes are said to be in a document
5597                                                                 // fragment in IE 9, so check for that
5598                                                                 node.document && node.document.nodeType !== 11 ) {
5599                                                         return ret;
5600                                                 }
5601                                         }
5602                                 } catch(e) {}
5603                         }
5604
5605                         return Sizzle(expr, null, null, [node]).length > 0;
5606                 };
5607         }
5608 })();
5609
5610 (function(){
5611         var div = document.createElement("div");
5612
5613         div.innerHTML = "<div class='test e'></div><div class='test'></div>";
5614
5615         // Opera can't find a second classname (in 9.6)
5616         // Also, make sure that getElementsByClassName actually exists
5617         if ( !div.getElementsByClassName || div.getElementsByClassName("e").length === 0 ) {
5618                 return;
5619         }
5620
5621         // Safari caches class attributes, doesn't catch changes (in 3.2)
5622         div.lastChild.className = "e";
5623
5624         if ( div.getElementsByClassName("e").length === 1 ) {
5625                 return;
5626         }
5627         
5628         Expr.order.splice(1, 0, "CLASS");
5629         Expr.find.CLASS = function( match, context, isXML ) {
5630                 if ( typeof context.getElementsByClassName !== "undefined" && !isXML ) {
5631                         return context.getElementsByClassName(match[1]);
5632                 }
5633         };
5634
5635         // release memory in IE
5636         div = null;
5637 })();
5638
5639 function dirNodeCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) {
5640         for ( var i = 0, l = checkSet.length; i < l; i++ ) {
5641                 var elem = checkSet[i];
5642
5643                 if ( elem ) {
5644                         var match = false;
5645
5646                         elem = elem[dir];
5647
5648                         while ( elem ) {
5649                                 if ( elem.sizcache === doneName ) {
5650                                         match = checkSet[elem.sizset];
5651                                         break;
5652                                 }
5653
5654                                 if ( elem.nodeType === 1 && !isXML ){
5655                                         elem.sizcache = doneName;
5656                                         elem.sizset = i;
5657                                 }
5658
5659                                 if ( elem.nodeName.toLowerCase() === cur ) {
5660                                         match = elem;
5661                                         break;
5662                                 }
5663
5664                                 elem = elem[dir];
5665                         }
5666
5667                         checkSet[i] = match;
5668                 }
5669         }
5670 }
5671
5672 function dirCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) {
5673         for ( var i = 0, l = checkSet.length; i < l; i++ ) {
5674                 var elem = checkSet[i];
5675
5676                 if ( elem ) {
5677                         var match = false;
5678                         
5679                         elem = elem[dir];
5680
5681                         while ( elem ) {
5682                                 if ( elem.sizcache === doneName ) {
5683                                         match = checkSet[elem.sizset];
5684                                         break;
5685                                 }
5686
5687                                 if ( elem.nodeType === 1 ) {
5688                                         if ( !isXML ) {
5689                                                 elem.sizcache = doneName;
5690                                                 elem.sizset = i;
5691                                         }
5692
5693                                         if ( typeof cur !== "string" ) {
5694                                                 if ( elem === cur ) {
5695                                                         match = true;
5696                                                         break;
5697                                                 }
5698
5699                                         } else if ( Sizzle.filter( cur, [elem] ).length > 0 ) {
5700                                                 match = elem;
5701                                                 break;
5702                                         }
5703                                 }
5704
5705                                 elem = elem[dir];
5706                         }
5707
5708                         checkSet[i] = match;
5709                 }
5710         }
5711 }
5712
5713 if ( document.documentElement.contains ) {
5714         Sizzle.contains = function( a, b ) {
5715                 return a !== b && (a.contains ? a.contains(b) : true);
5716         };
5717
5718 } else if ( document.documentElement.compareDocumentPosition ) {
5719         Sizzle.contains = function( a, b ) {
5720                 return !!(a.compareDocumentPosition(b) & 16);
5721         };
5722
5723 } else {
5724         Sizzle.contains = function() {
5725                 return false;
5726         };
5727 }
5728
5729 Sizzle.isXML = function( elem ) {
5730         // documentElement is verified for cases where it doesn't yet exist
5731         // (such as loading iframes in IE - #4833) 
5732         var documentElement = (elem ? elem.ownerDocument || elem : 0).documentElement;
5733
5734         return documentElement ? documentElement.nodeName !== "HTML" : false;
5735 };
5736
5737 var posProcess = function( selector, context ) {
5738         var match,
5739                 tmpSet = [],
5740                 later = "",
5741                 root = context.nodeType ? [context] : context;
5742
5743         // Position selectors must be done after the filter
5744         // And so must :not(positional) so we move all PSEUDOs to the end
5745         while ( (match = Expr.match.PSEUDO.exec( selector )) ) {
5746                 later += match[0];
5747                 selector = selector.replace( Expr.match.PSEUDO, "" );
5748         }
5749
5750         selector = Expr.relative[selector] ? selector + "*" : selector;
5751
5752         for ( var i = 0, l = root.length; i < l; i++ ) {
5753                 Sizzle( selector, root[i], tmpSet );
5754         }
5755
5756         return Sizzle.filter( later, tmpSet );
5757 };
5758
5759 // EXPOSE
5760 jQuery.find = Sizzle;
5761 jQuery.expr = Sizzle.selectors;
5762 jQuery.expr[":"] = jQuery.expr.filters;
5763 jQuery.unique = Sizzle.uniqueSort;
5764 jQuery.text = Sizzle.getText;
5765 jQuery.isXMLDoc = Sizzle.isXML;
5766 jQuery.contains = Sizzle.contains;
5767
5768
5769 })();
5770
5771
5772 var runtil = /Until$/,
5773         rparentsprev = /^(?:parents|prevUntil|prevAll)/,
5774         // Note: This RegExp should be improved, or likely pulled from Sizzle
5775         rmultiselector = /,/,
5776         isSimple = /^.[^:#\[\.,]*$/,
5777         slice = Array.prototype.slice,
5778         POS = jQuery.expr.match.POS,
5779         // methods guaranteed to produce a unique set when starting from a unique set
5780         guaranteedUnique = {
5781                 children: true,
5782                 contents: true,
5783                 next: true,
5784                 prev: true
5785         };
5786
5787 jQuery.fn.extend({
5788         find: function( selector ) {
5789                 var self = this,
5790                         i, l;
5791
5792                 if ( typeof selector !== "string" ) {
5793                         return jQuery( selector ).filter(function() {
5794                                 for ( i = 0, l = self.length; i < l; i++ ) {
5795                                         if ( jQuery.contains( self[ i ], this ) ) {
5796                                                 return true;
5797                                         }
5798                                 }
5799                         });
5800                 }
5801
5802                 var ret = this.pushStack( "", "find", selector ),
5803                         length, n, r;
5804
5805                 for ( i = 0, l = this.length; i < l; i++ ) {
5806                         length = ret.length;
5807                         jQuery.find( selector, this[i], ret );
5808
5809                         if ( i > 0 ) {
5810                                 // Make sure that the results are unique
5811                                 for ( n = length; n < ret.length; n++ ) {
5812                                         for ( r = 0; r < length; r++ ) {
5813                                                 if ( ret[r] === ret[n] ) {
5814                                                         ret.splice(n--, 1);
5815                                                         break;
5816                                                 }
5817                                         }
5818                                 }
5819                         }
5820                 }
5821
5822                 return ret;
5823         },
5824
5825         has: function( target ) {
5826                 var targets = jQuery( target );
5827                 return this.filter(function() {
5828                         for ( var i = 0, l = targets.length; i < l; i++ ) {
5829                                 if ( jQuery.contains( this, targets[i] ) ) {
5830                                         return true;
5831                                 }
5832                         }
5833                 });
5834         },
5835
5836         not: function( selector ) {
5837                 return this.pushStack( winnow(this, selector, false), "not", selector);
5838         },
5839
5840         filter: function( selector ) {
5841                 return this.pushStack( winnow(this, selector, true), "filter", selector );
5842         },
5843
5844         is: function( selector ) {
5845                 return !!selector && ( typeof selector === "string" ?
5846                         jQuery.filter( selector, this ).length > 0 :
5847                         this.filter( selector ).length > 0 );
5848         },
5849
5850         closest: function( selectors, context ) {
5851                 var ret = [], i, l, cur = this[0];
5852                 
5853                 // Array
5854                 if ( jQuery.isArray( selectors ) ) {
5855                         var match, selector,
5856                                 matches = {},
5857                                 level = 1;
5858
5859                         if ( cur && selectors.length ) {
5860                                 for ( i = 0, l = selectors.length; i < l; i++ ) {
5861                                         selector = selectors[i];
5862
5863                                         if ( !matches[ selector ] ) {
5864                                                 matches[ selector ] = POS.test( selector ) ?
5865                                                         jQuery( selector, context || this.context ) :
5866                                                         selector;
5867                                         }
5868                                 }
5869
5870                                 while ( cur && cur.ownerDocument && cur !== context ) {
5871                                         for ( selector in matches ) {
5872                                                 match = matches[ selector ];
5873
5874                                                 if ( match.jquery ? match.index( cur ) > -1 : jQuery( cur ).is( match ) ) {
5875                                                         ret.push({ selector: selector, elem: cur, level: level });
5876                                                 }
5877                                         }
5878
5879                                         cur = cur.parentNode;
5880                                         level++;
5881                                 }
5882                         }
5883
5884                         return ret;
5885                 }
5886
5887                 // String
5888                 var pos = POS.test( selectors ) || typeof selectors !== "string" ?
5889                                 jQuery( selectors, context || this.context ) :
5890                                 0;
5891
5892                 for ( i = 0, l = this.length; i < l; i++ ) {
5893                         cur = this[i];
5894
5895                         while ( cur ) {
5896                                 if ( pos ? pos.index(cur) > -1 : jQuery.find.matchesSelector(cur, selectors) ) {
5897                                         ret.push( cur );
5898                                         break;
5899
5900                                 } else {
5901                                         cur = cur.parentNode;
5902                                         if ( !cur || !cur.ownerDocument || cur === context || cur.nodeType === 11 ) {
5903                                                 break;
5904                                         }
5905                                 }
5906                         }
5907                 }
5908
5909                 ret = ret.length > 1 ? jQuery.unique( ret ) : ret;
5910
5911                 return this.pushStack( ret, "closest", selectors );
5912         },
5913
5914         // Determine the position of an element within
5915         // the matched set of elements
5916         index: function( elem ) {
5917                 if ( !elem || typeof elem === "string" ) {
5918                         return jQuery.inArray( this[0],
5919                                 // If it receives a string, the selector is used
5920                                 // If it receives nothing, the siblings are used
5921                                 elem ? jQuery( elem ) : this.parent().children() );
5922                 }
5923                 // Locate the position of the desired element
5924                 return jQuery.inArray(
5925                         // If it receives a jQuery object, the first element is used
5926                         elem.jquery ? elem[0] : elem, this );
5927         },
5928
5929         add: function( selector, context ) {
5930                 var set = typeof selector === "string" ?
5931                                 jQuery( selector, context ) :
5932                                 jQuery.makeArray( selector && selector.nodeType ? [ selector ] : selector ),
5933                         all = jQuery.merge( this.get(), set );
5934
5935                 return this.pushStack( isDisconnected( set[0] ) || isDisconnected( all[0] ) ?
5936                         all :
5937                         jQuery.unique( all ) );
5938         },
5939
5940         andSelf: function() {
5941                 return this.add( this.prevObject );
5942         }
5943 });
5944
5945 // A painfully simple check to see if an element is disconnected
5946 // from a document (should be improved, where feasible).
5947 function isDisconnected( node ) {
5948         return !node || !node.parentNode || node.parentNode.nodeType === 11;
5949 }
5950
5951 jQuery.each({
5952         parent: function( elem ) {
5953                 var parent = elem.parentNode;
5954                 return parent && parent.nodeType !== 11 ? parent : null;
5955         },
5956         parents: function( elem ) {
5957                 return jQuery.dir( elem, "parentNode" );
5958         },
5959         parentsUntil: function( elem, i, until ) {
5960                 return jQuery.dir( elem, "parentNode", until );
5961         },
5962         next: function( elem ) {
5963                 return jQuery.nth( elem, 2, "nextSibling" );
5964         },
5965         prev: function( elem ) {
5966                 return jQuery.nth( elem, 2, "previousSibling" );
5967         },
5968         nextAll: function( elem ) {
5969                 return jQuery.dir( elem, "nextSibling" );
5970         },
5971         prevAll: function( elem ) {
5972                 return jQuery.dir( elem, "previousSibling" );
5973         },
5974         nextUntil: function( elem, i, until ) {
5975                 return jQuery.dir( elem, "nextSibling", until );
5976         },
5977         prevUntil: function( elem, i, until ) {
5978                 return jQuery.dir( elem, "previousSibling", until );
5979         },
5980         siblings: function( elem ) {
5981                 return jQuery.sibling( elem.parentNode.firstChild, elem );
5982         },
5983         children: function( elem ) {
5984                 return jQuery.sibling( elem.firstChild );
5985         },
5986         contents: function( elem ) {
5987                 return jQuery.nodeName( elem, "iframe" ) ?
5988                         elem.contentDocument || elem.contentWindow.document :
5989                         jQuery.makeArray( elem.childNodes );
5990         }
5991 }, function( name, fn ) {
5992         jQuery.fn[ name ] = function( until, selector ) {
5993                 var ret = jQuery.map( this, fn, until ),
5994                         // The variable 'args' was introduced in
5995                         // https://github.com/jquery/jquery/commit/52a0238
5996                         // to work around a bug in Chrome 10 (Dev) and should be removed when the bug is fixed.
5997                         // http://code.google.com/p/v8/issues/detail?id=1050
5998                         args = slice.call(arguments);
5999
6000                 if ( !runtil.test( name ) ) {
6001                         selector = until;
6002                 }
6003
6004                 if ( selector && typeof selector === "string" ) {
6005                         ret = jQuery.filter( selector, ret );
6006                 }
6007
6008                 ret = this.length > 1 && !guaranteedUnique[ name ] ? jQuery.unique( ret ) : ret;
6009
6010                 if ( (this.length > 1 || rmultiselector.test( selector )) && rparentsprev.test( name ) ) {
6011                         ret = ret.reverse();
6012                 }
6013
6014                 return this.pushStack( ret, name, args.join(",") );
6015         };
6016 });
6017
6018 jQuery.extend({
6019         filter: function( expr, elems, not ) {
6020                 if ( not ) {
6021                         expr = ":not(" + expr + ")";
6022                 }
6023
6024                 return elems.length === 1 ?
6025                         jQuery.find.matchesSelector(elems[0], expr) ? [ elems[0] ] : [] :
6026                         jQuery.find.matches(expr, elems);
6027         },
6028
6029         dir: function( elem, dir, until ) {
6030                 var matched = [],
6031                         cur = elem[ dir ];
6032
6033                 while ( cur && cur.nodeType !== 9 && (until === undefined || cur.nodeType !== 1 || !jQuery( cur ).is( until )) ) {
6034                         if ( cur.nodeType === 1 ) {
6035                                 matched.push( cur );
6036                         }
6037                         cur = cur[dir];
6038                 }
6039                 return matched;
6040         },
6041
6042         nth: function( cur, result, dir, elem ) {
6043                 result = result || 1;
6044                 var num = 0;
6045
6046                 for ( ; cur; cur = cur[dir] ) {
6047                         if ( cur.nodeType === 1 && ++num === result ) {
6048                                 break;
6049                         }
6050                 }
6051
6052                 return cur;
6053         },
6054
6055         sibling: function( n, elem ) {
6056                 var r = [];
6057
6058                 for ( ; n; n = n.nextSibling ) {
6059                         if ( n.nodeType === 1 && n !== elem ) {
6060                                 r.push( n );
6061                         }
6062                 }
6063
6064                 return r;
6065         }
6066 });
6067
6068 // Implement the identical functionality for filter and not
6069 function winnow( elements, qualifier, keep ) {
6070
6071         // Can't pass null or undefined to indexOf in Firefox 4
6072         // Set to 0 to skip string check
6073         qualifier = qualifier || 0;
6074
6075         if ( jQuery.isFunction( qualifier ) ) {
6076                 return jQuery.grep(elements, function( elem, i ) {
6077                         var retVal = !!qualifier.call( elem, i, elem );
6078                         return retVal === keep;
6079                 });
6080
6081         } else if ( qualifier.nodeType ) {
6082                 return jQuery.grep(elements, function( elem, i ) {
6083                         return (elem === qualifier) === keep;
6084                 });
6085
6086         } else if ( typeof qualifier === "string" ) {
6087                 var filtered = jQuery.grep(elements, function( elem ) {
6088                         return elem.nodeType === 1;
6089                 });
6090
6091                 if ( isSimple.test( qualifier ) ) {
6092                         return jQuery.filter(qualifier, filtered, !keep);
6093                 } else {
6094                         qualifier = jQuery.filter( qualifier, filtered );
6095                 }
6096         }
6097
6098         return jQuery.grep(elements, function( elem, i ) {
6099                 return (jQuery.inArray( elem, qualifier ) >= 0) === keep;
6100         });
6101 }
6102
6103
6104
6105
6106 var rinlinejQuery = / jQuery\d+="(?:\d+|null)"/g,
6107         rleadingWhitespace = /^\s+/,
6108         rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/ig,
6109         rtagName = /<([\w:]+)/,
6110         rtbody = /<tbody/i,
6111         rhtml = /<|&#?\w+;/,
6112         rnocache = /<(?:script|object|embed|option|style)/i,
6113         // checked="checked" or checked
6114         rchecked = /checked\s*(?:[^=]|=\s*.checked.)/i,
6115         rscriptType = /\/(java|ecma)script/i,
6116         wrapMap = {
6117                 option: [ 1, "<select multiple='multiple'>", "</select>" ],
6118                 legend: [ 1, "<fieldset>", "</fieldset>" ],
6119                 thead: [ 1, "<table>", "</table>" ],
6120                 tr: [ 2, "<table><tbody>", "</tbody></table>" ],
6121                 td: [ 3, "<table><tbody><tr>", "</tr></tbody></table>" ],
6122                 col: [ 2, "<table><tbody></tbody><colgroup>", "</colgroup></table>" ],
6123                 area: [ 1, "<map>", "</map>" ],
6124                 _default: [ 0, "", "" ]
6125         };
6126
6127 wrapMap.optgroup = wrapMap.option;
6128 wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead;
6129 wrapMap.th = wrapMap.td;
6130
6131 // IE can't serialize <link> and <script> tags normally
6132 if ( !jQuery.support.htmlSerialize ) {
6133         wrapMap._default = [ 1, "div<div>", "</div>" ];
6134 }
6135
6136 jQuery.fn.extend({
6137         text: function( text ) {
6138                 if ( jQuery.isFunction(text) ) {
6139                         return this.each(function(i) {
6140                                 var self = jQuery( this );
6141
6142                                 self.text( text.call(this, i, self.text()) );
6143                         });
6144                 }
6145
6146                 if ( typeof text !== "object" && text !== undefined ) {
6147                         return this.empty().append( (this[0] && this[0].ownerDocument || document).createTextNode( text ) );
6148                 }
6149
6150                 return jQuery.text( this );
6151         },
6152
6153         wrapAll: function( html ) {
6154                 if ( jQuery.isFunction( html ) ) {
6155                         return this.each(function(i) {
6156                                 jQuery(this).wrapAll( html.call(this, i) );
6157                         });
6158                 }
6159
6160                 if ( this[0] ) {
6161                         // The elements to wrap the target around
6162                         var wrap = jQuery( html, this[0].ownerDocument ).eq(0).clone(true);
6163
6164                         if ( this[0].parentNode ) {
6165                                 wrap.insertBefore( this[0] );
6166                         }
6167
6168                         wrap.map(function() {
6169                                 var elem = this;
6170
6171                                 while ( elem.firstChild && elem.firstChild.nodeType === 1 ) {
6172                                         elem = elem.firstChild;
6173                                 }
6174
6175                                 return elem;
6176                         }).append( this );
6177                 }
6178
6179                 return this;
6180         },
6181
6182         wrapInner: function( html ) {
6183                 if ( jQuery.isFunction( html ) ) {
6184                         return this.each(function(i) {
6185                                 jQuery(this).wrapInner( html.call(this, i) );
6186                         });
6187                 }
6188
6189                 return this.each(function() {
6190                         var self = jQuery( this ),
6191                                 contents = self.contents();
6192
6193                         if ( contents.length ) {
6194                                 contents.wrapAll( html );
6195
6196                         } else {
6197                                 self.append( html );
6198                         }
6199                 });
6200         },
6201
6202         wrap: function( html ) {
6203                 return this.each(function() {
6204                         jQuery( this ).wrapAll( html );
6205                 });
6206         },
6207
6208         unwrap: function() {
6209                 return this.parent().each(function() {
6210                         if ( !jQuery.nodeName( this, "body" ) ) {
6211                                 jQuery( this ).replaceWith( this.childNodes );
6212                         }
6213                 }).end();
6214         },
6215
6216         append: function() {
6217                 return this.domManip(arguments, true, function( elem ) {
6218                         if ( this.nodeType === 1 ) {
6219                                 this.appendChild( elem );
6220                         }
6221                 });
6222         },
6223
6224         prepend: function() {
6225                 return this.domManip(arguments, true, function( elem ) {
6226                         if ( this.nodeType === 1 ) {
6227                                 this.insertBefore( elem, this.firstChild );
6228                         }
6229                 });
6230         },
6231
6232         before: function() {
6233                 if ( this[0] && this[0].parentNode ) {
6234                         return this.domManip(arguments, false, function( elem ) {
6235                                 this.parentNode.insertBefore( elem, this );
6236                         });
6237                 } else if ( arguments.length ) {
6238                         var set = jQuery(arguments[0]);
6239                         set.push.apply( set, this.toArray() );
6240                         return this.pushStack( set, "before", arguments );
6241                 }
6242         },
6243
6244         after: function() {
6245                 if ( this[0] && this[0].parentNode ) {
6246                         return this.domManip(arguments, false, function( elem ) {
6247                                 this.parentNode.insertBefore( elem, this.nextSibling );
6248                         });
6249                 } else if ( arguments.length ) {
6250                         var set = this.pushStack( this, "after", arguments );
6251                         set.push.apply( set, jQuery(arguments[0]).toArray() );
6252                         return set;
6253                 }
6254         },
6255
6256         // keepData is for internal use only--do not document
6257         remove: function( selector, keepData ) {
6258                 for ( var i = 0, elem; (elem = this[i]) != null; i++ ) {
6259                         if ( !selector || jQuery.filter( selector, [ elem ] ).length ) {
6260                                 if ( !keepData && elem.nodeType === 1 ) {
6261                                         jQuery.cleanData( elem.getElementsByTagName("*") );
6262                                         jQuery.cleanData( [ elem ] );
6263                                 }
6264
6265                                 if ( elem.parentNode ) {
6266                                         elem.parentNode.removeChild( elem );
6267                                 }
6268                         }
6269                 }
6270
6271                 return this;
6272         },
6273
6274         empty: function() {
6275                 for ( var i = 0, elem; (elem = this[i]) != null; i++ ) {
6276                         // Remove element nodes and prevent memory leaks
6277                         if ( elem.nodeType === 1 ) {
6278                                 jQuery.cleanData( elem.getElementsByTagName("*") );
6279                         }
6280
6281                         // Remove any remaining nodes
6282                         while ( elem.firstChild ) {
6283                                 elem.removeChild( elem.firstChild );
6284                         }
6285                 }
6286
6287                 return this;
6288         },
6289
6290         clone: function( dataAndEvents, deepDataAndEvents ) {
6291                 dataAndEvents = dataAndEvents == null ? false : dataAndEvents;
6292                 deepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents;
6293
6294                 return this.map( function () {
6295                         return jQuery.clone( this, dataAndEvents, deepDataAndEvents );
6296                 });
6297         },
6298
6299         html: function( value ) {
6300                 if ( value === undefined ) {
6301                         return this[0] && this[0].nodeType === 1 ?
6302                                 this[0].innerHTML.replace(rinlinejQuery, "") :
6303                                 null;
6304
6305                 // See if we can take a shortcut and just use innerHTML
6306                 } else if ( typeof value === "string" && !rnocache.test( value ) &&
6307                         (jQuery.support.leadingWhitespace || !rleadingWhitespace.test( value )) &&
6308                         !wrapMap[ (rtagName.exec( value ) || ["", ""])[1].toLowerCase() ] ) {
6309
6310                         value = value.replace(rxhtmlTag, "<$1></$2>");
6311
6312                         try {
6313                                 for ( var i = 0, l = this.length; i < l; i++ ) {
6314                                         // Remove element nodes and prevent memory leaks
6315                                         if ( this[i].nodeType === 1 ) {
6316                                                 jQuery.cleanData( this[i].getElementsByTagName("*") );
6317                                                 this[i].innerHTML = value;
6318                                         }
6319                                 }
6320
6321                         // If using innerHTML throws an exception, use the fallback method
6322                         } catch(e) {
6323                                 this.empty().append( value );
6324                         }
6325
6326                 } else if ( jQuery.isFunction( value ) ) {
6327                         this.each(function(i){
6328                                 var self = jQuery( this );
6329
6330                                 self.html( value.call(this, i, self.html()) );
6331                         });
6332
6333                 } else {
6334                         this.empty().append( value );
6335                 }
6336
6337                 return this;
6338         },
6339
6340         replaceWith: function( value ) {
6341                 if ( this[0] && this[0].parentNode ) {
6342                         // Make sure that the elements are removed from the DOM before they are inserted
6343                         // this can help fix replacing a parent with child elements
6344                         if ( jQuery.isFunction( value ) ) {
6345                                 return this.each(function(i) {
6346                                         var self = jQuery(this), old = self.html();
6347                                         self.replaceWith( value.call( this, i, old ) );
6348                                 });
6349                         }
6350
6351                         if ( typeof value !== "string" ) {
6352                                 value = jQuery( value ).detach();
6353                         }
6354
6355                         return this.each(function() {
6356                                 var next = this.nextSibling,
6357                                         parent = this.parentNode;
6358
6359                                 jQuery( this ).remove();
6360
6361                                 if ( next ) {
6362                                         jQuery(next).before( value );
6363                                 } else {
6364                                         jQuery(parent).append( value );
6365                                 }
6366                         });
6367                 } else {
6368                         return this.length ?
6369                                 this.pushStack( jQuery(jQuery.isFunction(value) ? value() : value), "replaceWith", value ) :
6370                                 this;
6371                 }
6372         },
6373
6374         detach: function( selector ) {
6375                 return this.remove( selector, true );
6376         },
6377
6378         domManip: function( args, table, callback ) {
6379                 var results, first, fragment, parent,
6380                         value = args[0],
6381                         scripts = [];
6382
6383                 // We can't cloneNode fragments that contain checked, in WebKit
6384                 if ( !jQuery.support.checkClone && arguments.length === 3 && typeof value === "string" && rchecked.test( value ) ) {
6385                         return this.each(function() {
6386                                 jQuery(this).domManip( args, table, callback, true );
6387                         });
6388                 }
6389
6390                 if ( jQuery.isFunction(value) ) {
6391                         return this.each(function(i) {
6392                                 var self = jQuery(this);
6393                                 args[0] = value.call(this, i, table ? self.html() : undefined);
6394                                 self.domManip( args, table, callback );
6395                         });
6396                 }
6397
6398                 if ( this[0] ) {
6399                         parent = value && value.parentNode;
6400
6401                         // If we're in a fragment, just use that instead of building a new one
6402                         if ( jQuery.support.parentNode && parent && parent.nodeType === 11 && parent.childNodes.length === this.length ) {
6403                                 results = { fragment: parent };
6404
6405                         } else {
6406                                 results = jQuery.buildFragment( args, this, scripts );
6407                         }
6408
6409                         fragment = results.fragment;
6410
6411                         if ( fragment.childNodes.length === 1 ) {
6412                                 first = fragment = fragment.firstChild;
6413                         } else {
6414                                 first = fragment.firstChild;
6415                         }
6416
6417                         if ( first ) {
6418                                 table = table && jQuery.nodeName( first, "tr" );
6419
6420                                 for ( var i = 0, l = this.length, lastIndex = l - 1; i < l; i++ ) {
6421                                         callback.call(
6422                                                 table ?
6423                                                         root(this[i], first) :
6424                                                         this[i],
6425                                                 // Make sure that we do not leak memory by inadvertently discarding
6426                                                 // the original fragment (which might have attached data) instead of
6427                                                 // using it; in addition, use the original fragment object for the last
6428                                                 // item instead of first because it can end up being emptied incorrectly
6429                                                 // in certain situations (Bug #8070).
6430                                                 // Fragments from the fragment cache must always be cloned and never used
6431                                                 // in place.
6432                                                 results.cacheable || (l > 1 && i < lastIndex) ?
6433                                                         jQuery.clone( fragment, true, true ) :
6434                                                         fragment
6435                                         );
6436                                 }
6437                         }
6438
6439                         if ( scripts.length ) {
6440                                 jQuery.each( scripts, evalScript );
6441                         }
6442                 }
6443
6444                 return this;
6445         }
6446 });
6447
6448 function root( elem, cur ) {
6449         return jQuery.nodeName(elem, "table") ?
6450                 (elem.getElementsByTagName("tbody")[0] ||
6451                 elem.appendChild(elem.ownerDocument.createElement("tbody"))) :
6452                 elem;
6453 }
6454
6455 function cloneCopyEvent( src, dest ) {
6456
6457         if ( dest.nodeType !== 1 || !jQuery.hasData( src ) ) {
6458                 return;
6459         }
6460
6461         var internalKey = jQuery.expando,
6462                 oldData = jQuery.data( src ),
6463                 curData = jQuery.data( dest, oldData );
6464
6465         // Switch to use the internal data object, if it exists, for the next
6466         // stage of data copying
6467         if ( (oldData = oldData[ internalKey ]) ) {
6468                 var events = oldData.events;
6469                                 curData = curData[ internalKey ] = jQuery.extend({}, oldData);
6470
6471                 if ( events ) {
6472                         delete curData.handle;
6473                         curData.events = {};
6474
6475                         for ( var type in events ) {
6476                                 for ( var i = 0, l = events[ type ].length; i < l; i++ ) {
6477                                         jQuery.event.add( dest, type + ( events[ type ][ i ].namespace ? "." : "" ) + events[ type ][ i ].namespace, events[ type ][ i ], events[ type ][ i ].data );
6478                                 }
6479                         }
6480                 }
6481         }
6482 }
6483
6484 function cloneFixAttributes( src, dest ) {
6485         var nodeName;
6486
6487         // We do not need to do anything for non-Elements
6488         if ( dest.nodeType !== 1 ) {
6489                 return;
6490         }
6491
6492         // clearAttributes removes the attributes, which we don't want,
6493         // but also removes the attachEvent events, which we *do* want
6494         if ( dest.clearAttributes ) {
6495                 dest.clearAttributes();
6496         }
6497
6498         // mergeAttributes, in contrast, only merges back on the
6499         // original attributes, not the events
6500         if ( dest.mergeAttributes ) {
6501                 dest.mergeAttributes( src );
6502         }
6503
6504         nodeName = dest.nodeName.toLowerCase();
6505
6506         // IE6-8 fail to clone children inside object elements that use
6507         // the proprietary classid attribute value (rather than the type
6508         // attribute) to identify the type of content to display
6509         if ( nodeName === "object" ) {
6510                 dest.outerHTML = src.outerHTML;
6511
6512         } else if ( nodeName === "input" && (src.type === "checkbox" || src.type === "radio") ) {
6513                 // IE6-8 fails to persist the checked state of a cloned checkbox
6514                 // or radio button. Worse, IE6-7 fail to give the cloned element
6515                 // a checked appearance if the defaultChecked value isn't also set
6516                 if ( src.checked ) {
6517                         dest.defaultChecked = dest.checked = src.checked;
6518                 }
6519
6520                 // IE6-7 get confused and end up setting the value of a cloned
6521                 // checkbox/radio button to an empty string instead of "on"
6522                 if ( dest.value !== src.value ) {
6523                         dest.value = src.value;
6524                 }
6525
6526         // IE6-8 fails to return the selected option to the default selected
6527         // state when cloning options
6528         } else if ( nodeName === "option" ) {
6529                 dest.selected = src.defaultSelected;
6530
6531         // IE6-8 fails to set the defaultValue to the correct value when
6532         // cloning other types of input fields
6533         } else if ( nodeName === "input" || nodeName === "textarea" ) {
6534                 dest.defaultValue = src.defaultValue;
6535         }
6536
6537         // Event data gets referenced instead of copied if the expando
6538         // gets copied too
6539         dest.removeAttribute( jQuery.expando );
6540 }
6541
6542 jQuery.buildFragment = function( args, nodes, scripts ) {
6543         var fragment, cacheable, cacheresults,
6544                 doc = (nodes && nodes[0] ? nodes[0].ownerDocument || nodes[0] : document);
6545
6546         // Only cache "small" (1/2 KB) HTML strings that are associated with the main document
6547         // Cloning options loses the selected state, so don't cache them
6548         // IE 6 doesn't like it when you put <object> or <embed> elements in a fragment
6549         // Also, WebKit does not clone 'checked' attributes on cloneNode, so don't cache
6550         if ( args.length === 1 && typeof args[0] === "string" && args[0].length < 512 && doc === document &&
6551                 args[0].charAt(0) === "<" && !rnocache.test( args[0] ) && (jQuery.support.checkClone || !rchecked.test( args[0] )) ) {
6552
6553                 cacheable = true;
6554
6555                 cacheresults = jQuery.fragments[ args[0] ];
6556                 if ( cacheresults && cacheresults !== 1 ) {
6557                         fragment = cacheresults;
6558                 }
6559         }
6560
6561         if ( !fragment ) {
6562                 fragment = doc.createDocumentFragment();
6563                 jQuery.clean( args, doc, fragment, scripts );
6564         }
6565
6566         if ( cacheable ) {
6567                 jQuery.fragments[ args[0] ] = cacheresults ? fragment : 1;
6568         }
6569
6570         return { fragment: fragment, cacheable: cacheable };
6571 };
6572
6573 jQuery.fragments = {};
6574
6575 jQuery.each({
6576         appendTo: "append",
6577         prependTo: "prepend",
6578         insertBefore: "before",
6579         insertAfter: "after",
6580         replaceAll: "replaceWith"
6581 }, function( name, original ) {
6582         jQuery.fn[ name ] = function( selector ) {
6583                 var ret = [],
6584                         insert = jQuery( selector ),
6585                         parent = this.length === 1 && this[0].parentNode;
6586
6587                 if ( parent && parent.nodeType === 11 && parent.childNodes.length === 1 && insert.length === 1 ) {
6588                         insert[ original ]( this[0] );
6589                         return this;
6590
6591                 } else {
6592                         for ( var i = 0, l = insert.length; i < l; i++ ) {
6593                                 var elems = (i > 0 ? this.clone(true) : this).get();
6594                                 jQuery( insert[i] )[ original ]( elems );
6595                                 ret = ret.concat( elems );
6596                         }
6597
6598                         return this.pushStack( ret, name, insert.selector );
6599                 }
6600         };
6601 });
6602
6603 function getAll( elem ) {
6604         if ( "getElementsByTagName" in elem ) {
6605                 return elem.getElementsByTagName( "*" );
6606         
6607         } else if ( "querySelectorAll" in elem ) {
6608                 return elem.querySelectorAll( "*" );
6609
6610         } else {
6611                 return [];
6612         }
6613 }
6614
6615 // Used in clean, fixes the defaultChecked property
6616 function fixDefaultChecked( elem ) {
6617         if ( elem.type === "checkbox" || elem.type === "radio" ) {
6618                 elem.defaultChecked = elem.checked;
6619         }
6620 }
6621 // Finds all inputs and passes them to fixDefaultChecked
6622 function findInputs( elem ) {
6623         if ( jQuery.nodeName( elem, "input" ) ) {
6624                 fixDefaultChecked( elem );
6625         } else if ( elem.getElementsByTagName ) {
6626                 jQuery.grep( elem.getElementsByTagName("input"), fixDefaultChecked );
6627         }
6628 }
6629
6630 jQuery.extend({
6631         clone: function( elem, dataAndEvents, deepDataAndEvents ) {
6632                 var clone = elem.cloneNode(true),
6633                                 srcElements,
6634                                 destElements,
6635                                 i;
6636
6637                 if ( (!jQuery.support.noCloneEvent || !jQuery.support.noCloneChecked) &&
6638                                 (elem.nodeType === 1 || elem.nodeType === 11) && !jQuery.isXMLDoc(elem) ) {
6639                         // IE copies events bound via attachEvent when using cloneNode.
6640                         // Calling detachEvent on the clone will also remove the events
6641                         // from the original. In order to get around this, we use some
6642                         // proprietary methods to clear the events. Thanks to MooTools
6643                         // guys for this hotness.
6644
6645                         cloneFixAttributes( elem, clone );
6646
6647                         // Using Sizzle here is crazy slow, so we use getElementsByTagName
6648                         // instead
6649                         srcElements = getAll( elem );
6650                         destElements = getAll( clone );
6651
6652                         // Weird iteration because IE will replace the length property
6653                         // with an element if you are cloning the body and one of the
6654                         // elements on the page has a name or id of "length"
6655                         for ( i = 0; srcElements[i]; ++i ) {
6656                                 cloneFixAttributes( srcElements[i], destElements[i] );
6657                         }
6658                 }
6659
6660                 // Copy the events from the original to the clone
6661                 if ( dataAndEvents ) {
6662                         cloneCopyEvent( elem, clone );
6663
6664                         if ( deepDataAndEvents ) {
6665                                 srcElements = getAll( elem );
6666                                 destElements = getAll( clone );
6667
6668                                 for ( i = 0; srcElements[i]; ++i ) {
6669                                         cloneCopyEvent( srcElements[i], destElements[i] );
6670                                 }
6671                         }
6672                 }
6673
6674                 // Return the cloned set
6675                 return clone;
6676         },
6677
6678         clean: function( elems, context, fragment, scripts ) {
6679                 var checkScriptType;
6680
6681                 context = context || document;
6682
6683                 // !context.createElement fails in IE with an error but returns typeof 'object'
6684                 if ( typeof context.createElement === "undefined" ) {
6685                         context = context.ownerDocument || context[0] && context[0].ownerDocument || document;
6686                 }
6687
6688                 var ret = [];
6689
6690                 for ( var i = 0, elem; (elem = elems[i]) != null; i++ ) {
6691                         if ( typeof elem === "number" ) {
6692                                 elem += "";
6693                         }
6694
6695                         if ( !elem ) {
6696                                 continue;
6697                         }
6698
6699                         // Convert html string into DOM nodes
6700                         if ( typeof elem === "string" ) {
6701                                 if ( !rhtml.test( elem ) ) {
6702                                         elem = context.createTextNode( elem );
6703                                 } else {
6704                                         // Fix "XHTML"-style tags in all browsers
6705                                         elem = elem.replace(rxhtmlTag, "<$1></$2>");
6706
6707                                         // Trim whitespace, otherwise indexOf won't work as expected
6708                                         var tag = (rtagName.exec( elem ) || ["", ""])[1].toLowerCase(),
6709                                                 wrap = wrapMap[ tag ] || wrapMap._default,
6710                                                 depth = wrap[0],
6711                                                 div = context.createElement("div");
6712
6713                                         // Go to html and back, then peel off extra wrappers
6714                                         div.innerHTML = wrap[1] + elem + wrap[2];
6715
6716                                         // Move to the right depth
6717                                         while ( depth-- ) {
6718                                                 div = div.lastChild;
6719                                         }
6720
6721                                         // Remove IE's autoinserted <tbody> from table fragments
6722                                         if ( !jQuery.support.tbody ) {
6723
6724                                                 // String was a <table>, *may* have spurious <tbody>
6725                                                 var hasBody = rtbody.test(elem),
6726                                                         tbody = tag === "table" && !hasBody ?
6727                                                                 div.firstChild && div.firstChild.childNodes :
6728
6729                                                                 // String was a bare <thead> or <tfoot>
6730                                                                 wrap[1] === "<table>" && !hasBody ?
6731                                                                         div.childNodes :
6732                                                                         [];
6733
6734                                                 for ( var j = tbody.length - 1; j >= 0 ; --j ) {
6735                                                         if ( jQuery.nodeName( tbody[ j ], "tbody" ) && !tbody[ j ].childNodes.length ) {
6736                                                                 tbody[ j ].parentNode.removeChild( tbody[ j ] );
6737                                                         }
6738                                                 }
6739                                         }
6740
6741                                         // IE completely kills leading whitespace when innerHTML is used
6742                                         if ( !jQuery.support.leadingWhitespace && rleadingWhitespace.test( elem ) ) {
6743                                                 div.insertBefore( context.createTextNode( rleadingWhitespace.exec(elem)[0] ), div.firstChild );
6744                                         }
6745
6746                                         elem = div.childNodes;
6747                                 }
6748                         }
6749
6750                         // Resets defaultChecked for any radios and checkboxes
6751                         // about to be appended to the DOM in IE 6/7 (#8060)
6752                         var len;
6753                         if ( !jQuery.support.appendChecked ) {
6754                                 if ( elem[0] && typeof (len = elem.length) === "number" ) {
6755                                         for ( i = 0; i < len; i++ ) {
6756                                                 findInputs( elem[i] );
6757                                         }
6758                                 } else {
6759                                         findInputs( elem );
6760                                 }
6761                         }
6762
6763                         if ( elem.nodeType ) {
6764                                 ret.push( elem );
6765                         } else {
6766                                 ret = jQuery.merge( ret, elem );
6767                         }
6768                 }
6769
6770                 if ( fragment ) {
6771                         checkScriptType = function( elem ) {
6772                                 return !elem.type || rscriptType.test( elem.type );
6773                         };
6774                         for ( i = 0; ret[i]; i++ ) {
6775                                 if ( scripts && jQuery.nodeName( ret[i], "script" ) && (!ret[i].type || ret[i].type.toLowerCase() === "text/javascript") ) {
6776                                         scripts.push( ret[i].parentNode ? ret[i].parentNode.removeChild( ret[i] ) : ret[i] );
6777
6778                                 } else {
6779                                         if ( ret[i].nodeType === 1 ) {
6780                                                 var jsTags = jQuery.grep( ret[i].getElementsByTagName( "script" ), checkScriptType );
6781
6782                                                 ret.splice.apply( ret, [i + 1, 0].concat( jsTags ) );
6783                                         }
6784                                         fragment.appendChild( ret[i] );
6785                                 }
6786                         }
6787                 }
6788
6789                 return ret;
6790         },
6791
6792         cleanData: function( elems ) {
6793                 var data, id, cache = jQuery.cache, internalKey = jQuery.expando, special = jQuery.event.special,
6794                         deleteExpando = jQuery.support.deleteExpando;
6795
6796                 for ( var i = 0, elem; (elem = elems[i]) != null; i++ ) {
6797                         if ( elem.nodeName && jQuery.noData[elem.nodeName.toLowerCase()] ) {
6798                                 continue;
6799                         }
6800
6801                         id = elem[ jQuery.expando ];
6802
6803                         if ( id ) {
6804                                 data = cache[ id ] && cache[ id ][ internalKey ];
6805
6806                                 if ( data && data.events ) {
6807                                         for ( var type in data.events ) {
6808                                                 if ( special[ type ] ) {
6809                                                         jQuery.event.remove( elem, type );
6810
6811                                                 // This is a shortcut to avoid jQuery.event.remove's overhead
6812                                                 } else {
6813                                                         jQuery.removeEvent( elem, type, data.handle );
6814                                                 }
6815                                         }
6816
6817                                         // Null the DOM reference to avoid IE6/7/8 leak (#7054)
6818                                         if ( data.handle ) {
6819                                                 data.handle.elem = null;
6820                                         }
6821                                 }
6822
6823                                 if ( deleteExpando ) {
6824                                         delete elem[ jQuery.expando ];
6825
6826                                 } else if ( elem.removeAttribute ) {
6827                                         elem.removeAttribute( jQuery.expando );
6828                                 }
6829
6830                                 delete cache[ id ];
6831                         }
6832                 }
6833         }
6834 });
6835
6836 function evalScript( i, elem ) {
6837         if ( elem.src ) {
6838                 jQuery.ajax({
6839                         url: elem.src,
6840                         async: false,
6841                         dataType: "script"
6842                 });
6843         } else {
6844                 jQuery.globalEval( elem.text || elem.textContent || elem.innerHTML || "" );
6845         }
6846
6847         if ( elem.parentNode ) {
6848                 elem.parentNode.removeChild( elem );
6849         }
6850 }
6851
6852
6853
6854
6855 var ralpha = /alpha\([^)]*\)/i,
6856         ropacity = /opacity=([^)]*)/,
6857         rdashAlpha = /-([a-z])/ig,
6858         // fixed for IE9, see #8346
6859         rupper = /([A-Z]|^ms)/g,
6860         rnumpx = /^-?\d+(?:px)?$/i,
6861         rnum = /^-?\d/,
6862         rrelNum = /^[+\-]=/,
6863         rrelNumFilter = /[^+\-\.\de]+/g,
6864
6865         cssShow = { position: "absolute", visibility: "hidden", display: "block" },
6866         cssWidth = [ "Left", "Right" ],
6867         cssHeight = [ "Top", "Bottom" ],
6868         curCSS,
6869
6870         getComputedStyle,
6871         currentStyle,
6872
6873         fcamelCase = function( all, letter ) {
6874                 return letter.toUpperCase();
6875         };
6876
6877 jQuery.fn.css = function( name, value ) {
6878         // Setting 'undefined' is a no-op
6879         if ( arguments.length === 2 && value === undefined ) {
6880                 return this;
6881         }
6882
6883         return jQuery.access( this, name, value, true, function( elem, name, value ) {
6884                 return value !== undefined ?
6885                         jQuery.style( elem, name, value ) :
6886                         jQuery.css( elem, name );
6887         });
6888 };
6889
6890 jQuery.extend({
6891         // Add in style property hooks for overriding the default
6892         // behavior of getting and setting a style property
6893         cssHooks: {
6894                 opacity: {
6895                         get: function( elem, computed ) {
6896                                 if ( computed ) {
6897                                         // We should always get a number back from opacity
6898                                         var ret = curCSS( elem, "opacity", "opacity" );
6899                                         return ret === "" ? "1" : ret;
6900
6901                                 } else {
6902                                         return elem.style.opacity;
6903                                 }
6904                         }
6905                 }
6906         },
6907
6908         // Exclude the following css properties to add px
6909         cssNumber: {
6910                 "zIndex": true,
6911                 "fontWeight": true,
6912                 "opacity": true,
6913                 "zoom": true,
6914                 "lineHeight": true,
6915                 "widows": true,
6916                 "orphans": true
6917         },
6918
6919         // Add in properties whose names you wish to fix before
6920         // setting or getting the value
6921         cssProps: {
6922                 // normalize float css property
6923                 "float": jQuery.support.cssFloat ? "cssFloat" : "styleFloat"
6924         },
6925
6926         // Get and set the style property on a DOM Node
6927         style: function( elem, name, value, extra ) {
6928                 // Don't set styles on text and comment nodes
6929                 if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 || !elem.style ) {
6930                         return;
6931                 }
6932
6933                 // Make sure that we're working with the right name
6934                 var ret, type, origName = jQuery.camelCase( name ),
6935                         style = elem.style, hooks = jQuery.cssHooks[ origName ];
6936
6937                 name = jQuery.cssProps[ origName ] || origName;
6938
6939                 // Check if we're setting a value
6940                 if ( value !== undefined ) {
6941                         type = typeof value;
6942
6943                         // Make sure that NaN and null values aren't set. See: #7116
6944                         if ( type === "number" && isNaN( value ) || value == null ) {
6945                                 return;
6946                         }
6947
6948                         // convert relative number strings (+= or -=) to relative numbers. #7345
6949                         if ( type === "string" && rrelNum.test( value ) ) {
6950                                 value = +value.replace( rrelNumFilter, "" ) + parseFloat( jQuery.css( elem, name ) );
6951                         }
6952
6953                         // If a number was passed in, add 'px' to the (except for certain CSS properties)
6954                         if ( type === "number" && !jQuery.cssNumber[ origName ] ) {
6955                                 value += "px";
6956                         }
6957
6958                         // If a hook was provided, use that value, otherwise just set the specified value
6959                         if ( !hooks || !("set" in hooks) || (value = hooks.set( elem, value )) !== undefined ) {
6960                                 // Wrapped to prevent IE from throwing errors when 'invalid' values are provided
6961                                 // Fixes bug #5509
6962                                 try {
6963                                         style[ name ] = value;
6964                                 } catch(e) {}
6965                         }
6966
6967                 } else {
6968                         // If a hook was provided get the non-computed value from there
6969                         if ( hooks && "get" in hooks && (ret = hooks.get( elem, false, extra )) !== undefined ) {
6970                                 return ret;
6971                         }
6972
6973                         // Otherwise just get the value from the style object
6974                         return style[ name ];
6975                 }
6976         },
6977
6978         css: function( elem, name, extra ) {
6979                 var ret, hooks;
6980
6981                 // Make sure that we're working with the right name
6982                 name = jQuery.camelCase( name );
6983                 hooks = jQuery.cssHooks[ name ];
6984                 name = jQuery.cssProps[ name ] || name;
6985
6986                 // cssFloat needs a special treatment
6987                 if ( name === "cssFloat" ) {
6988                         name = "float";
6989                 }
6990
6991                 // If a hook was provided get the computed value from there
6992                 if ( hooks && "get" in hooks && (ret = hooks.get( elem, true, extra )) !== undefined ) {
6993                         return ret;
6994
6995                 // Otherwise, if a way to get the computed value exists, use that
6996                 } else if ( curCSS ) {
6997                         return curCSS( elem, name );
6998                 }
6999         },
7000
7001         // A method for quickly swapping in/out CSS properties to get correct calculations
7002         swap: function( elem, options, callback ) {
7003                 var old = {};
7004
7005                 // Remember the old values, and insert the new ones
7006                 for ( var name in options ) {
7007                         old[ name ] = elem.style[ name ];
7008                         elem.style[ name ] = options[ name ];
7009                 }
7010
7011                 callback.call( elem );
7012
7013                 // Revert the old values
7014                 for ( name in options ) {
7015                         elem.style[ name ] = old[ name ];
7016                 }
7017         },
7018
7019         camelCase: function( string ) {
7020                 return string.replace( rdashAlpha, fcamelCase );
7021         }
7022 });
7023
7024 // DEPRECATED, Use jQuery.css() instead
7025 jQuery.curCSS = jQuery.css;
7026
7027 jQuery.each(["height", "width"], function( i, name ) {
7028         jQuery.cssHooks[ name ] = {
7029                 get: function( elem, computed, extra ) {
7030                         var val;
7031
7032                         if ( computed ) {
7033                                 if ( elem.offsetWidth !== 0 ) {
7034                                         val = getWH( elem, name, extra );
7035
7036                                 } else {
7037                                         jQuery.swap( elem, cssShow, function() {
7038                                                 val = getWH( elem, name, extra );
7039                                         });
7040                                 }
7041
7042                                 if ( val <= 0 ) {
7043                                         val = curCSS( elem, name, name );
7044
7045                                         if ( val === "0px" && currentStyle ) {
7046                                                 val = currentStyle( elem, name, name );
7047                                         }
7048
7049                                         if ( val != null ) {
7050                                                 // Should return "auto" instead of 0, use 0 for
7051                                                 // temporary backwards-compat
7052                                                 return val === "" || val === "auto" ? "0px" : val;
7053                                         }
7054                                 }
7055
7056                                 if ( val < 0 || val == null ) {
7057                                         val = elem.style[ name ];
7058
7059                                         // Should return "auto" instead of 0, use 0 for
7060                                         // temporary backwards-compat
7061                                         return val === "" || val === "auto" ? "0px" : val;
7062                                 }
7063
7064                                 return typeof val === "string" ? val : val + "px";
7065                         }
7066                 },
7067
7068                 set: function( elem, value ) {
7069                         if ( rnumpx.test( value ) ) {
7070                                 // ignore negative width and height values #1599
7071                                 value = parseFloat(value);
7072
7073                                 if ( value >= 0 ) {
7074                                         return value + "px";
7075                                 }
7076
7077                         } else {
7078                                 return value;
7079                         }
7080                 }
7081         };
7082 });
7083
7084 if ( !jQuery.support.opacity ) {
7085         jQuery.cssHooks.opacity = {
7086                 get: function( elem, computed ) {
7087                         // IE uses filters for opacity
7088                         return ropacity.test( (computed && elem.currentStyle ? elem.currentStyle.filter : elem.style.filter) || "" ) ?
7089                                 ( parseFloat( RegExp.$1 ) / 100 ) + "" :
7090                                 computed ? "1" : "";
7091                 },
7092
7093                 set: function( elem, value ) {
7094                         var style = elem.style,
7095                                 currentStyle = elem.currentStyle;
7096
7097                         // IE has trouble with opacity if it does not have layout
7098                         // Force it by setting the zoom level
7099                         style.zoom = 1;
7100
7101                         // Set the alpha filter to set the opacity
7102                         var opacity = jQuery.isNaN( value ) ?
7103                                 "" :
7104                                 "alpha(opacity=" + value * 100 + ")",
7105                                 filter = currentStyle && currentStyle.filter || style.filter || "";
7106
7107                         style.filter = ralpha.test( filter ) ?
7108                                 filter.replace( ralpha, opacity ) :
7109                                 filter + " " + opacity;
7110                 }
7111         };
7112 }
7113
7114 jQuery(function() {
7115         // This hook cannot be added until DOM ready because the support test
7116         // for it is not run until after DOM ready
7117         if ( !jQuery.support.reliableMarginRight ) {
7118                 jQuery.cssHooks.marginRight = {
7119                         get: function( elem, computed ) {
7120                                 // WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right
7121                                 // Work around by temporarily setting element display to inline-block
7122                                 var ret;
7123                                 jQuery.swap( elem, { "display": "inline-block" }, function() {
7124                                         if ( computed ) {
7125                                                 ret = curCSS( elem, "margin-right", "marginRight" );
7126                                         } else {
7127                                                 ret = elem.style.marginRight;
7128                                         }
7129                                 });
7130                                 return ret;
7131                         }
7132                 };
7133         }
7134 });
7135
7136 if ( document.defaultView && document.defaultView.getComputedStyle ) {
7137         getComputedStyle = function( elem, name ) {
7138                 var ret, defaultView, computedStyle;
7139
7140                 name = name.replace( rupper, "-$1" ).toLowerCase();
7141
7142                 if ( !(defaultView = elem.ownerDocument.defaultView) ) {
7143                         return undefined;
7144                 }
7145
7146                 if ( (computedStyle = defaultView.getComputedStyle( elem, null )) ) {
7147                         ret = computedStyle.getPropertyValue( name );
7148                         if ( ret === "" && !jQuery.contains( elem.ownerDocument.documentElement, elem ) ) {
7149                                 ret = jQuery.style( elem, name );
7150                         }
7151                 }
7152
7153                 return ret;
7154         };
7155 }
7156
7157 if ( document.documentElement.currentStyle ) {
7158         currentStyle = function( elem, name ) {
7159                 var left,
7160                         ret = elem.currentStyle && elem.currentStyle[ name ],
7161                         rsLeft = elem.runtimeStyle && elem.runtimeStyle[ name ],
7162                         style = elem.style;
7163
7164                 // From the awesome hack by Dean Edwards
7165                 // http://erik.eae.net/archives/2007/07/27/18.54.15/#comment-102291
7166
7167                 // If we're not dealing with a regular pixel number
7168                 // but a number that has a weird ending, we need to convert it to pixels
7169                 if ( !rnumpx.test( ret ) && rnum.test( ret ) ) {
7170                         // Remember the original values
7171                         left = style.left;
7172
7173                         // Put in the new values to get a computed value out
7174                         if ( rsLeft ) {
7175                                 elem.runtimeStyle.left = elem.currentStyle.left;
7176                         }
7177                         style.left = name === "fontSize" ? "1em" : (ret || 0);
7178                         ret = style.pixelLeft + "px";
7179
7180                         // Revert the changed values
7181                         style.left = left;
7182                         if ( rsLeft ) {
7183                                 elem.runtimeStyle.left = rsLeft;
7184                         }
7185                 }
7186
7187                 return ret === "" ? "auto" : ret;
7188         };
7189 }
7190
7191 curCSS = getComputedStyle || currentStyle;
7192
7193 function getWH( elem, name, extra ) {
7194         var which = name === "width" ? cssWidth : cssHeight,
7195                 val = name === "width" ? elem.offsetWidth : elem.offsetHeight;
7196
7197         if ( extra === "border" ) {
7198                 return val;
7199         }
7200
7201         jQuery.each( which, function() {
7202                 if ( !extra ) {
7203                         val -= parseFloat(jQuery.css( elem, "padding" + this )) || 0;
7204                 }
7205
7206                 if ( extra === "margin" ) {
7207                         val += parseFloat(jQuery.css( elem, "margin" + this )) || 0;
7208
7209                 } else {
7210                         val -= parseFloat(jQuery.css( elem, "border" + this + "Width" )) || 0;
7211                 }
7212         });
7213
7214         return val;
7215 }
7216
7217 if ( jQuery.expr && jQuery.expr.filters ) {
7218         jQuery.expr.filters.hidden = function( elem ) {
7219                 var width = elem.offsetWidth,
7220                         height = elem.offsetHeight;
7221
7222                 return (width === 0 && height === 0) || (!jQuery.support.reliableHiddenOffsets && (elem.style.display || jQuery.css( elem, "display" )) === "none");
7223         };
7224
7225         jQuery.expr.filters.visible = function( elem ) {
7226                 return !jQuery.expr.filters.hidden( elem );
7227         };
7228 }
7229
7230
7231
7232
7233 var r20 = /%20/g,
7234         rbracket = /\[\]$/,
7235         rCRLF = /\r?\n/g,
7236         rhash = /#.*$/,
7237         rheaders = /^(.*?):[ \t]*([^\r\n]*)\r?$/mg, // IE leaves an \r character at EOL
7238         rinput = /^(?:color|date|datetime|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i,
7239         // #7653, #8125, #8152: local protocol detection
7240         rlocalProtocol = /^(?:about|app|app\-storage|.+\-extension|file|widget):$/,
7241         rnoContent = /^(?:GET|HEAD)$/,
7242         rprotocol = /^\/\//,
7243         rquery = /\?/,
7244         rscript = /<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi,
7245         rselectTextarea = /^(?:select|textarea)/i,
7246         rspacesAjax = /\s+/,
7247         rts = /([?&])_=[^&]*/,
7248         rurl = /^([\w\+\.\-]+:)(?:\/\/([^\/?#:]*)(?::(\d+))?)?/,
7249
7250         // Keep a copy of the old load method
7251         _load = jQuery.fn.load,
7252
7253         /* Prefilters
7254          * 1) They are useful to introduce custom dataTypes (see ajax/jsonp.js for an example)
7255          * 2) These are called:
7256          *    - BEFORE asking for a transport
7257          *    - AFTER param serialization (s.data is a string if s.processData is true)
7258          * 3) key is the dataType
7259          * 4) the catchall symbol "*" can be used
7260          * 5) execution will start with transport dataType and THEN continue down to "*" if needed
7261          */
7262         prefilters = {},
7263
7264         /* Transports bindings
7265          * 1) key is the dataType
7266          * 2) the catchall symbol "*" can be used
7267          * 3) selection will start with transport dataType and THEN go to "*" if needed
7268          */
7269         transports = {},
7270
7271         // Document location
7272         ajaxLocation,
7273
7274         // Document location segments
7275         ajaxLocParts;
7276
7277 // #8138, IE may throw an exception when accessing
7278 // a field from window.location if document.domain has been set
7279 try {
7280         ajaxLocation = location.href;
7281 } catch( e ) {
7282         // Use the href attribute of an A element
7283         // since IE will modify it given document.location
7284         ajaxLocation = document.createElement( "a" );
7285         ajaxLocation.href = "";
7286         ajaxLocation = ajaxLocation.href;
7287 }
7288
7289 // Segment location into parts
7290 ajaxLocParts = rurl.exec( ajaxLocation.toLowerCase() ) || [];
7291
7292 // Base "constructor" for jQuery.ajaxPrefilter and jQuery.ajaxTransport
7293 function addToPrefiltersOrTransports( structure ) {
7294
7295         // dataTypeExpression is optional and defaults to "*"
7296         return function( dataTypeExpression, func ) {
7297
7298                 if ( typeof dataTypeExpression !== "string" ) {
7299                         func = dataTypeExpression;
7300                         dataTypeExpression = "*";
7301                 }
7302
7303                 if ( jQuery.isFunction( func ) ) {
7304                         var dataTypes = dataTypeExpression.toLowerCase().split( rspacesAjax ),
7305                                 i = 0,
7306                                 length = dataTypes.length,
7307                                 dataType,
7308                                 list,
7309                                 placeBefore;
7310
7311                         // For each dataType in the dataTypeExpression
7312                         for(; i < length; i++ ) {
7313                                 dataType = dataTypes[ i ];
7314                                 // We control if we're asked to add before
7315                                 // any existing element
7316                                 placeBefore = /^\+/.test( dataType );
7317                                 if ( placeBefore ) {
7318                                         dataType = dataType.substr( 1 ) || "*";
7319                                 }
7320                                 list = structure[ dataType ] = structure[ dataType ] || [];
7321                                 // then we add to the structure accordingly
7322                                 list[ placeBefore ? "unshift" : "push" ]( func );
7323                         }
7324                 }
7325         };
7326 }
7327
7328 // Base inspection function for prefilters and transports
7329 function inspectPrefiltersOrTransports( structure, options, originalOptions, jqXHR,
7330                 dataType /* internal */, inspected /* internal */ ) {
7331
7332         dataType = dataType || options.dataTypes[ 0 ];
7333         inspected = inspected || {};
7334
7335         inspected[ dataType ] = true;
7336
7337         var list = structure[ dataType ],
7338                 i = 0,
7339                 length = list ? list.length : 0,
7340                 executeOnly = ( structure === prefilters ),
7341                 selection;
7342
7343         for(; i < length && ( executeOnly || !selection ); i++ ) {
7344                 selection = list[ i ]( options, originalOptions, jqXHR );
7345                 // If we got redirected to another dataType
7346                 // we try there if executing only and not done already
7347                 if ( typeof selection === "string" ) {
7348                         if ( !executeOnly || inspected[ selection ] ) {
7349                                 selection = undefined;
7350                         } else {
7351                                 options.dataTypes.unshift( selection );
7352                                 selection = inspectPrefiltersOrTransports(
7353                                                 structure, options, originalOptions, jqXHR, selection, inspected );
7354                         }
7355                 }
7356         }
7357         // If we're only executing or nothing was selected
7358         // we try the catchall dataType if not done already
7359         if ( ( executeOnly || !selection ) && !inspected[ "*" ] ) {
7360                 selection = inspectPrefiltersOrTransports(
7361                                 structure, options, originalOptions, jqXHR, "*", inspected );
7362         }
7363         // unnecessary when only executing (prefilters)
7364         // but it'll be ignored by the caller in that case
7365         return selection;
7366 }
7367
7368 jQuery.fn.extend({
7369         load: function( url, params, callback ) {
7370                 if ( typeof url !== "string" && _load ) {
7371                         return _load.apply( this, arguments );
7372
7373                 // Don't do a request if no elements are being requested
7374                 } else if ( !this.length ) {
7375                         return this;
7376                 }
7377
7378                 var off = url.indexOf( " " );
7379                 if ( off >= 0 ) {
7380                         var selector = url.slice( off, url.length );
7381                         url = url.slice( 0, off );
7382                 }
7383
7384                 // Default to a GET request
7385                 var type = "GET";
7386
7387                 // If the second parameter was provided
7388                 if ( params ) {
7389                         // If it's a function
7390                         if ( jQuery.isFunction( params ) ) {
7391                                 // We assume that it's the callback
7392                                 callback = params;
7393                                 params = undefined;
7394
7395                         // Otherwise, build a param string
7396                         } else if ( typeof params === "object" ) {
7397                                 params = jQuery.param( params, jQuery.ajaxSettings.traditional );
7398                                 type = "POST";
7399                         }
7400                 }
7401
7402                 var self = this;
7403
7404                 // Request the remote document
7405                 jQuery.ajax({
7406                         url: url,
7407                         type: type,
7408                         dataType: "html",
7409                         data: params,
7410                         // Complete callback (responseText is used internally)
7411                         complete: function( jqXHR, status, responseText ) {
7412                                 // Store the response as specified by the jqXHR object
7413                                 responseText = jqXHR.responseText;
7414                                 // If successful, inject the HTML into all the matched elements
7415                                 if ( jqXHR.isResolved() ) {
7416                                         // #4825: Get the actual response in case
7417                                         // a dataFilter is present in ajaxSettings
7418                                         jqXHR.done(function( r ) {
7419                                                 responseText = r;
7420                                         });
7421                                         // See if a selector was specified
7422                                         self.html( selector ?
7423                                                 // Create a dummy div to hold the results
7424                                                 jQuery("<div>")
7425                                                         // inject the contents of the document in, removing the scripts
7426                                                         // to avoid any 'Permission Denied' errors in IE
7427                                                         .append(responseText.replace(rscript, ""))
7428
7429                                                         // Locate the specified elements
7430                                                         .find(selector) :
7431
7432                                                 // If not, just inject the full result
7433                                                 responseText );
7434                                 }
7435
7436                                 if ( callback ) {
7437                                         self.each( callback, [ responseText, status, jqXHR ] );
7438                                 }
7439                         }
7440                 });
7441
7442                 return this;
7443         },
7444
7445         serialize: function() {
7446                 return jQuery.param( this.serializeArray() );
7447         },
7448
7449         serializeArray: function() {
7450                 return this.map(function(){
7451                         return this.elements ? jQuery.makeArray( this.elements ) : this;
7452                 })
7453                 .filter(function(){
7454                         return this.name && !this.disabled &&
7455                                 ( this.checked || rselectTextarea.test( this.nodeName ) ||
7456                                         rinput.test( this.type ) );
7457                 })
7458                 .map(function( i, elem ){
7459                         var val = jQuery( this ).val();
7460
7461                         return val == null ?
7462                                 null :
7463                                 jQuery.isArray( val ) ?
7464                                         jQuery.map( val, function( val, i ){
7465                                                 return { name: elem.name, value: val.replace( rCRLF, "\r\n" ) };
7466                                         }) :
7467                                         { name: elem.name, value: val.replace( rCRLF, "\r\n" ) };
7468                 }).get();
7469         }
7470 });
7471
7472 // Attach a bunch of functions for handling common AJAX events
7473 jQuery.each( "ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split( " " ), function( i, o ){
7474         jQuery.fn[ o ] = function( f ){
7475                 return this.bind( o, f );
7476         };
7477 });
7478
7479 jQuery.each( [ "get", "post" ], function( i, method ) {
7480         jQuery[ method ] = function( url, data, callback, type ) {
7481                 // shift arguments if data argument was omitted
7482                 if ( jQuery.isFunction( data ) ) {
7483                         type = type || callback;
7484                         callback = data;
7485                         data = undefined;
7486                 }
7487
7488                 return jQuery.ajax({
7489                         type: method,
7490                         url: url,
7491                         data: data,
7492                         success: callback,
7493                         dataType: type
7494                 });
7495         };
7496 });
7497
7498 jQuery.extend({
7499
7500         getScript: function( url, callback ) {
7501                 return jQuery.get( url, undefined, callback, "script" );
7502         },
7503
7504         getJSON: function( url, data, callback ) {
7505                 return jQuery.get( url, data, callback, "json" );
7506         },
7507
7508         // Creates a full fledged settings object into target
7509         // with both ajaxSettings and settings fields.
7510         // If target is omitted, writes into ajaxSettings.
7511         ajaxSetup: function ( target, settings ) {
7512                 if ( !settings ) {
7513                         // Only one parameter, we extend ajaxSettings
7514                         settings = target;
7515                         target = jQuery.extend( true, jQuery.ajaxSettings, settings );
7516                 } else {
7517                         // target was provided, we extend into it
7518                         jQuery.extend( true, target, jQuery.ajaxSettings, settings );
7519                 }
7520                 // Flatten fields we don't want deep extended
7521                 for( var field in { context: 1, url: 1 } ) {
7522                         if ( field in settings ) {
7523                                 target[ field ] = settings[ field ];
7524                         } else if( field in jQuery.ajaxSettings ) {
7525                                 target[ field ] = jQuery.ajaxSettings[ field ];
7526                         }
7527                 }
7528                 return target;
7529         },
7530
7531         ajaxSettings: {
7532                 url: ajaxLocation,
7533                 isLocal: rlocalProtocol.test( ajaxLocParts[ 1 ] ),
7534                 global: true,
7535                 type: "GET",
7536                 contentType: "application/x-www-form-urlencoded",
7537                 processData: true,
7538                 async: true,
7539                 /*
7540                 timeout: 0,
7541                 data: null,
7542                 dataType: null,
7543                 username: null,
7544                 password: null,
7545                 cache: null,
7546                 traditional: false,
7547                 headers: {},
7548                 */
7549
7550                 accepts: {
7551                         xml: "application/xml, text/xml",
7552                         html: "text/html",
7553                         text: "text/plain",
7554                         json: "application/json, text/javascript",
7555                         "*": "*/*"
7556                 },
7557
7558                 contents: {
7559                         xml: /xml/,
7560                         html: /html/,
7561                         json: /json/
7562                 },
7563
7564                 responseFields: {
7565                         xml: "responseXML",
7566                         text: "responseText"
7567                 },
7568
7569                 // List of data converters
7570                 // 1) key format is "source_type destination_type" (a single space in-between)
7571                 // 2) the catchall symbol "*" can be used for source_type
7572                 converters: {
7573
7574                         // Convert anything to text
7575                         "* text": window.String,
7576
7577                         // Text to html (true = no transformation)
7578                         "text html": true,
7579
7580                         // Evaluate text as a json expression
7581                         "text json": jQuery.parseJSON,
7582
7583                         // Parse text as xml
7584                         "text xml": jQuery.parseXML
7585                 }
7586         },
7587
7588         ajaxPrefilter: addToPrefiltersOrTransports( prefilters ),
7589         ajaxTransport: addToPrefiltersOrTransports( transports ),
7590
7591         // Main method
7592         ajax: function( url, options ) {
7593
7594                 // If url is an object, simulate pre-1.5 signature
7595                 if ( typeof url === "object" ) {
7596                         options = url;
7597                         url = undefined;
7598                 }
7599
7600                 // Force options to be an object
7601                 options = options || {};
7602
7603                 var // Create the final options object
7604                         s = jQuery.ajaxSetup( {}, options ),
7605                         // Callbacks context
7606                         callbackContext = s.context || s,
7607                         // Context for global events
7608                         // It's the callbackContext if one was provided in the options
7609                         // and if it's a DOM node or a jQuery collection
7610                         globalEventContext = callbackContext !== s &&
7611                                 ( callbackContext.nodeType || callbackContext instanceof jQuery ) ?
7612                                                 jQuery( callbackContext ) : jQuery.event,
7613                         // Deferreds
7614                         deferred = jQuery.Deferred(),
7615                         completeDeferred = jQuery._Deferred(),
7616                         // Status-dependent callbacks
7617                         statusCode = s.statusCode || {},
7618                         // ifModified key
7619                         ifModifiedKey,
7620                         // Headers (they are sent all at once)
7621                         requestHeaders = {},
7622                         requestHeadersNames = {},
7623                         // Response headers
7624                         responseHeadersString,
7625                         responseHeaders,
7626                         // transport
7627                         transport,
7628                         // timeout handle
7629                         timeoutTimer,
7630                         // Cross-domain detection vars
7631                         parts,
7632                         // The jqXHR state
7633                         state = 0,
7634                         // To know if global events are to be dispatched
7635                         fireGlobals,
7636                         // Loop variable
7637                         i,
7638                         // Fake xhr
7639                         jqXHR = {
7640
7641                                 readyState: 0,
7642
7643                                 // Caches the header
7644                                 setRequestHeader: function( name, value ) {
7645                                         if ( !state ) {
7646                                                 var lname = name.toLowerCase();
7647                                                 name = requestHeadersNames[ lname ] = requestHeadersNames[ lname ] || name;
7648                                                 requestHeaders[ name ] = value;
7649                                         }
7650                                         return this;
7651                                 },
7652
7653                                 // Raw string
7654                                 getAllResponseHeaders: function() {
7655                                         return state === 2 ? responseHeadersString : null;
7656                                 },
7657
7658                                 // Builds headers hashtable if needed
7659                                 getResponseHeader: function( key ) {
7660                                         var match;
7661                                         if ( state === 2 ) {
7662                                                 if ( !responseHeaders ) {
7663                                                         responseHeaders = {};
7664                                                         while( ( match = rheaders.exec( responseHeadersString ) ) ) {
7665                                                                 responseHeaders[ match[1].toLowerCase() ] = match[ 2 ];
7666                                                         }
7667                                                 }
7668                                                 match = responseHeaders[ key.toLowerCase() ];
7669                                         }
7670                                         return match === undefined ? null : match;
7671                                 },
7672
7673                                 // Overrides response content-type header
7674                                 overrideMimeType: function( type ) {
7675                                         if ( !state ) {
7676                                                 s.mimeType = type;
7677                                         }
7678                                         return this;
7679                                 },
7680
7681                                 // Cancel the request
7682                                 abort: function( statusText ) {
7683                                         statusText = statusText || "abort";
7684                                         if ( transport ) {
7685                                                 transport.abort( statusText );
7686                                         }
7687                                         done( 0, statusText );
7688                                         return this;
7689                                 }
7690                         };
7691
7692                 // Callback for when everything is done
7693                 // It is defined here because jslint complains if it is declared
7694                 // at the end of the function (which would be more logical and readable)
7695                 function done( status, statusText, responses, headers ) {
7696
7697                         // Called once
7698                         if ( state === 2 ) {
7699                                 return;
7700                         }
7701
7702                         // State is "done" now
7703                         state = 2;
7704
7705                         // Clear timeout if it exists
7706                         if ( timeoutTimer ) {
7707                                 clearTimeout( timeoutTimer );
7708                         }
7709
7710                         // Dereference transport for early garbage collection
7711                         // (no matter how long the jqXHR object will be used)
7712                         transport = undefined;
7713
7714                         // Cache response headers
7715                         responseHeadersString = headers || "";
7716
7717                         // Set readyState
7718                         jqXHR.readyState = status ? 4 : 0;
7719
7720                         var isSuccess,
7721                                 success,
7722                                 error,
7723                                 response = responses ? ajaxHandleResponses( s, jqXHR, responses ) : undefined,
7724                                 lastModified,
7725                                 etag;
7726
7727                         // If successful, handle type chaining
7728                         if ( status >= 200 && status < 300 || status === 304 ) {
7729
7730                                 // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.
7731                                 if ( s.ifModified ) {
7732
7733                                         if ( ( lastModified = jqXHR.getResponseHeader( "Last-Modified" ) ) ) {
7734                                                 jQuery.lastModified[ ifModifiedKey ] = lastModified;
7735                                         }
7736                                         if ( ( etag = jqXHR.getResponseHeader( "Etag" ) ) ) {
7737                                                 jQuery.etag[ ifModifiedKey ] = etag;
7738                                         }
7739                                 }
7740
7741                                 // If not modified
7742                                 if ( status === 304 ) {
7743
7744                                         statusText = "notmodified";
7745                                         isSuccess = true;
7746
7747                                 // If we have data
7748                                 } else {
7749
7750                                         try {
7751                                                 success = ajaxConvert( s, response );
7752                                                 statusText = "success";
7753                                                 isSuccess = true;
7754                                         } catch(e) {
7755                                                 // We have a parsererror
7756                                                 statusText = "parsererror";
7757                                                 error = e;
7758                                         }
7759                                 }
7760                         } else {
7761                                 // We extract error from statusText
7762                                 // then normalize statusText and status for non-aborts
7763                                 error = statusText;
7764                                 if( !statusText || status ) {
7765                                         statusText = "error";
7766                                         if ( status < 0 ) {
7767                                                 status = 0;
7768                                         }
7769                                 }
7770                         }
7771
7772                         // Set data for the fake xhr object
7773                         jqXHR.status = status;
7774                         jqXHR.statusText = statusText;
7775
7776                         // Success/Error
7777                         if ( isSuccess ) {
7778                                 deferred.resolveWith( callbackContext, [ success, statusText, jqXHR ] );
7779                         } else {
7780                                 deferred.rejectWith( callbackContext, [ jqXHR, statusText, error ] );
7781                         }
7782
7783                         // Status-dependent callbacks
7784                         jqXHR.statusCode( statusCode );
7785                         statusCode = undefined;
7786
7787                         if ( fireGlobals ) {
7788                                 globalEventContext.trigger( "ajax" + ( isSuccess ? "Success" : "Error" ),
7789                                                 [ jqXHR, s, isSuccess ? success : error ] );
7790                         }
7791
7792                         // Complete
7793                         completeDeferred.resolveWith( callbackContext, [ jqXHR, statusText ] );
7794
7795                         if ( fireGlobals ) {
7796                                 globalEventContext.trigger( "ajaxComplete", [ jqXHR, s] );
7797                                 // Handle the global AJAX counter
7798                                 if ( !( --jQuery.active ) ) {
7799                                         jQuery.event.trigger( "ajaxStop" );
7800                                 }
7801                         }
7802                 }
7803
7804                 // Attach deferreds
7805                 deferred.promise( jqXHR );
7806                 jqXHR.success = jqXHR.done;
7807                 jqXHR.error = jqXHR.fail;
7808                 jqXHR.complete = completeDeferred.done;
7809
7810                 // Status-dependent callbacks
7811                 jqXHR.statusCode = function( map ) {
7812                         if ( map ) {
7813                                 var tmp;
7814                                 if ( state < 2 ) {
7815                                         for( tmp in map ) {
7816                                                 statusCode[ tmp ] = [ statusCode[tmp], map[tmp] ];
7817                                         }
7818                                 } else {
7819                                         tmp = map[ jqXHR.status ];
7820                                         jqXHR.then( tmp, tmp );
7821                                 }
7822                         }
7823                         return this;
7824                 };
7825
7826                 // Remove hash character (#7531: and string promotion)
7827                 // Add protocol if not provided (#5866: IE7 issue with protocol-less urls)
7828                 // We also use the url parameter if available
7829                 s.url = ( ( url || s.url ) + "" ).replace( rhash, "" ).replace( rprotocol, ajaxLocParts[ 1 ] + "//" );
7830
7831                 // Extract dataTypes list
7832                 s.dataTypes = jQuery.trim( s.dataType || "*" ).toLowerCase().split( rspacesAjax );
7833
7834                 // Determine if a cross-domain request is in order
7835                 if ( s.crossDomain == null ) {
7836                         parts = rurl.exec( s.url.toLowerCase() );
7837                         s.crossDomain = !!( parts &&
7838                                 ( parts[ 1 ] != ajaxLocParts[ 1 ] || parts[ 2 ] != ajaxLocParts[ 2 ] ||
7839                                         ( parts[ 3 ] || ( parts[ 1 ] === "http:" ? 80 : 443 ) ) !=
7840                                                 ( ajaxLocParts[ 3 ] || ( ajaxLocParts[ 1 ] === "http:" ? 80 : 443 ) ) )
7841                         );
7842                 }
7843
7844                 // Convert data if not already a string
7845                 if ( s.data && s.processData && typeof s.data !== "string" ) {
7846                         s.data = jQuery.param( s.data, s.traditional );
7847                 }
7848
7849                 // Apply prefilters
7850                 inspectPrefiltersOrTransports( prefilters, s, options, jqXHR );
7851
7852                 // If request was aborted inside a prefiler, stop there
7853                 if ( state === 2 ) {
7854                         return false;
7855                 }
7856
7857                 // We can fire global events as of now if asked to
7858                 fireGlobals = s.global;
7859
7860                 // Uppercase the type
7861                 s.type = s.type.toUpperCase();
7862
7863                 // Determine if request has content
7864                 s.hasContent = !rnoContent.test( s.type );
7865
7866                 // Watch for a new set of requests
7867                 if ( fireGlobals && jQuery.active++ === 0 ) {
7868                         jQuery.event.trigger( "ajaxStart" );
7869                 }
7870
7871                 // More options handling for requests with no content
7872                 if ( !s.hasContent ) {
7873
7874                         // If data is available, append data to url
7875                         if ( s.data ) {
7876                                 s.url += ( rquery.test( s.url ) ? "&" : "?" ) + s.data;
7877                         }
7878
7879                         // Get ifModifiedKey before adding the anti-cache parameter
7880                         ifModifiedKey = s.url;
7881
7882                         // Add anti-cache in url if needed
7883                         if ( s.cache === false ) {
7884
7885                                 var ts = jQuery.now(),
7886                                         // try replacing _= if it is there
7887                                         ret = s.url.replace( rts, "$1_=" + ts );
7888
7889                                 // if nothing was replaced, add timestamp to the end
7890                                 s.url = ret + ( (ret === s.url ) ? ( rquery.test( s.url ) ? "&" : "?" ) + "_=" + ts : "" );
7891                         }
7892                 }
7893
7894                 // Set the correct header, if data is being sent
7895                 if ( s.data && s.hasContent && s.contentType !== false || options.contentType ) {
7896                         jqXHR.setRequestHeader( "Content-Type", s.contentType );
7897                 }
7898
7899                 // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.
7900                 if ( s.ifModified ) {
7901                         ifModifiedKey = ifModifiedKey || s.url;
7902                         if ( jQuery.lastModified[ ifModifiedKey ] ) {
7903                                 jqXHR.setRequestHeader( "If-Modified-Since", jQuery.lastModified[ ifModifiedKey ] );
7904                         }
7905                         if ( jQuery.etag[ ifModifiedKey ] ) {
7906                                 jqXHR.setRequestHeader( "If-None-Match", jQuery.etag[ ifModifiedKey ] );
7907                         }
7908                 }
7909
7910                 // Set the Accepts header for the server, depending on the dataType
7911                 jqXHR.setRequestHeader(
7912                         "Accept",
7913                         s.dataTypes[ 0 ] && s.accepts[ s.dataTypes[0] ] ?
7914                                 s.accepts[ s.dataTypes[0] ] + ( s.dataTypes[ 0 ] !== "*" ? ", */*; q=0.01" : "" ) :
7915                                 s.accepts[ "*" ]
7916                 );
7917
7918                 // Check for headers option
7919                 for ( i in s.headers ) {
7920                         jqXHR.setRequestHeader( i, s.headers[ i ] );
7921                 }
7922
7923                 // Allow custom headers/mimetypes and early abort
7924                 if ( s.beforeSend && ( s.beforeSend.call( callbackContext, jqXHR, s ) === false || state === 2 ) ) {
7925                                 // Abort if not done already
7926                                 jqXHR.abort();
7927                                 return false;
7928
7929                 }
7930
7931                 // Install callbacks on deferreds
7932                 for ( i in { success: 1, error: 1, complete: 1 } ) {
7933                         jqXHR[ i ]( s[ i ] );
7934                 }
7935
7936                 // Get transport
7937                 transport = inspectPrefiltersOrTransports( transports, s, options, jqXHR );
7938
7939                 // If no transport, we auto-abort
7940                 if ( !transport ) {
7941                         done( -1, "No Transport" );
7942                 } else {
7943                         jqXHR.readyState = 1;
7944                         // Send global event
7945                         if ( fireGlobals ) {
7946                                 globalEventContext.trigger( "ajaxSend", [ jqXHR, s ] );
7947                         }
7948                         // Timeout
7949                         if ( s.async && s.timeout > 0 ) {
7950                                 timeoutTimer = setTimeout( function(){
7951                                         jqXHR.abort( "timeout" );
7952                                 }, s.timeout );
7953                         }
7954
7955                         try {
7956                                 state = 1;
7957                                 transport.send( requestHeaders, done );
7958                         } catch (e) {
7959                                 // Propagate exception as error if not done
7960                                 if ( status < 2 ) {
7961                                         done( -1, e );
7962                                 // Simply rethrow otherwise
7963                                 } else {
7964                                         jQuery.error( e );
7965                                 }
7966                         }
7967                 }
7968
7969                 return jqXHR;
7970         },
7971
7972         // Serialize an array of form elements or a set of
7973         // key/values into a query string
7974         param: function( a, traditional ) {
7975                 var s = [],
7976                         add = function( key, value ) {
7977                                 // If value is a function, invoke it and return its value
7978                                 value = jQuery.isFunction( value ) ? value() : value;
7979                                 s[ s.length ] = encodeURIComponent( key ) + "=" + encodeURIComponent( value );
7980                         };
7981
7982                 // Set traditional to true for jQuery <= 1.3.2 behavior.
7983                 if ( traditional === undefined ) {
7984                         traditional = jQuery.ajaxSettings.traditional;
7985                 }
7986
7987                 // If an array was passed in, assume that it is an array of form elements.
7988                 if ( jQuery.isArray( a ) || ( a.jquery && !jQuery.isPlainObject( a ) ) ) {
7989                         // Serialize the form elements
7990                         jQuery.each( a, function() {
7991                                 add( this.name, this.value );
7992                         });
7993
7994                 } else {
7995                         // If traditional, encode the "old" way (the way 1.3.2 or older
7996                         // did it), otherwise encode params recursively.
7997                         for ( var prefix in a ) {
7998                                 buildParams( prefix, a[ prefix ], traditional, add );
7999                         }
8000                 }
8001
8002                 // Return the resulting serialization
8003                 return s.join( "&" ).replace( r20, "+" );
8004         }
8005 });
8006
8007 function buildParams( prefix, obj, traditional, add ) {
8008         if ( jQuery.isArray( obj ) ) {
8009                 // Serialize array item.
8010                 jQuery.each( obj, function( i, v ) {
8011                         if ( traditional || rbracket.test( prefix ) ) {
8012                                 // Treat each array item as a scalar.
8013                                 add( prefix, v );
8014
8015                         } else {
8016                                 // If array item is non-scalar (array or object), encode its
8017                                 // numeric index to resolve deserialization ambiguity issues.
8018                                 // Note that rack (as of 1.0.0) can't currently deserialize
8019                                 // nested arrays properly, and attempting to do so may cause
8020                                 // a server error. Possible fixes are to modify rack's
8021                                 // deserialization algorithm or to provide an option or flag
8022                                 // to force array serialization to be shallow.
8023                                 buildParams( prefix + "[" + ( typeof v === "object" || jQuery.isArray(v) ? i : "" ) + "]", v, traditional, add );
8024                         }
8025                 });
8026
8027         } else if ( !traditional && obj != null && typeof obj === "object" ) {
8028                 // Serialize object item.
8029                 for ( var name in obj ) {
8030                         buildParams( prefix + "[" + name + "]", obj[ name ], traditional, add );
8031                 }
8032
8033         } else {
8034                 // Serialize scalar item.
8035                 add( prefix, obj );
8036         }
8037 }
8038
8039 // This is still on the jQuery object... for now
8040 // Want to move this to jQuery.ajax some day
8041 jQuery.extend({
8042
8043         // Counter for holding the number of active queries
8044         active: 0,
8045
8046         // Last-Modified header cache for next request
8047         lastModified: {},
8048         etag: {}
8049
8050 });
8051
8052 /* Handles responses to an ajax request:
8053  * - sets all responseXXX fields accordingly
8054  * - finds the right dataType (mediates between content-type and expected dataType)
8055  * - returns the corresponding response
8056  */
8057 function ajaxHandleResponses( s, jqXHR, responses ) {
8058
8059         var contents = s.contents,
8060                 dataTypes = s.dataTypes,
8061                 responseFields = s.responseFields,
8062                 ct,
8063                 type,
8064                 finalDataType,
8065                 firstDataType;
8066
8067         // Fill responseXXX fields
8068         for( type in responseFields ) {
8069                 if ( type in responses ) {
8070                         jqXHR[ responseFields[type] ] = responses[ type ];
8071                 }
8072         }
8073
8074         // Remove auto dataType and get content-type in the process
8075         while( dataTypes[ 0 ] === "*" ) {
8076                 dataTypes.shift();
8077                 if ( ct === undefined ) {
8078                         ct = s.mimeType || jqXHR.getResponseHeader( "content-type" );
8079                 }
8080         }
8081
8082         // Check if we're dealing with a known content-type
8083         if ( ct ) {
8084                 for ( type in contents ) {
8085                         if ( contents[ type ] && contents[ type ].test( ct ) ) {
8086                                 dataTypes.unshift( type );
8087                                 break;
8088                         }
8089                 }
8090         }
8091
8092         // Check to see if we have a response for the expected dataType
8093         if ( dataTypes[ 0 ] in responses ) {
8094                 finalDataType = dataTypes[ 0 ];
8095         } else {
8096                 // Try convertible dataTypes
8097                 for ( type in responses ) {
8098                         if ( !dataTypes[ 0 ] || s.converters[ type + " " + dataTypes[0] ] ) {
8099                                 finalDataType = type;
8100                                 break;
8101                         }
8102                         if ( !firstDataType ) {
8103                                 firstDataType = type;
8104                         }
8105                 }
8106                 // Or just use first one
8107                 finalDataType = finalDataType || firstDataType;
8108         }
8109
8110         // If we found a dataType
8111         // We add the dataType to the list if needed
8112         // and return the corresponding response
8113         if ( finalDataType ) {
8114                 if ( finalDataType !== dataTypes[ 0 ] ) {
8115                         dataTypes.unshift( finalDataType );
8116                 }
8117                 return responses[ finalDataType ];
8118         }
8119 }
8120
8121 // Chain conversions given the request and the original response
8122 function ajaxConvert( s, response ) {
8123
8124         // Apply the dataFilter if provided
8125         if ( s.dataFilter ) {
8126                 response = s.dataFilter( response, s.dataType );
8127         }
8128
8129         var dataTypes = s.dataTypes,
8130                 converters = {},
8131                 i,
8132                 key,
8133                 length = dataTypes.length,
8134                 tmp,
8135                 // Current and previous dataTypes
8136                 current = dataTypes[ 0 ],
8137                 prev,
8138                 // Conversion expression
8139                 conversion,
8140                 // Conversion function
8141                 conv,
8142                 // Conversion functions (transitive conversion)
8143                 conv1,
8144                 conv2;
8145
8146         // For each dataType in the chain
8147         for( i = 1; i < length; i++ ) {
8148
8149                 // Create converters map
8150                 // with lowercased keys
8151                 if ( i === 1 ) {
8152                         for( key in s.converters ) {
8153                                 if( typeof key === "string" ) {
8154                                         converters[ key.toLowerCase() ] = s.converters[ key ];
8155                                 }
8156                         }
8157                 }
8158
8159                 // Get the dataTypes
8160                 prev = current;
8161                 current = dataTypes[ i ];
8162
8163                 // If current is auto dataType, update it to prev
8164                 if( current === "*" ) {
8165                         current = prev;
8166                 // If no auto and dataTypes are actually different
8167                 } else if ( prev !== "*" && prev !== current ) {
8168
8169                         // Get the converter
8170                         conversion = prev + " " + current;
8171                         conv = converters[ conversion ] || converters[ "* " + current ];
8172
8173                         // If there is no direct converter, search transitively
8174                         if ( !conv ) {
8175                                 conv2 = undefined;
8176                                 for( conv1 in converters ) {
8177                                         tmp = conv1.split( " " );
8178                                         if ( tmp[ 0 ] === prev || tmp[ 0 ] === "*" ) {
8179                                                 conv2 = converters[ tmp[1] + " " + current ];
8180                                                 if ( conv2 ) {
8181                                                         conv1 = converters[ conv1 ];
8182                                                         if ( conv1 === true ) {
8183                                                                 conv = conv2;
8184                                                         } else if ( conv2 === true ) {
8185                                                                 conv = conv1;
8186                                                         }
8187                                                         break;
8188                                                 }
8189                                         }
8190                                 }
8191                         }
8192                         // If we found no converter, dispatch an error
8193                         if ( !( conv || conv2 ) ) {
8194                                 jQuery.error( "No conversion from " + conversion.replace(" "," to ") );
8195                         }
8196                         // If found converter is not an equivalence
8197                         if ( conv !== true ) {
8198                                 // Convert with 1 or 2 converters accordingly
8199                                 response = conv ? conv( response ) : conv2( conv1(response) );
8200                         }
8201                 }
8202         }
8203         return response;
8204 }
8205
8206
8207
8208
8209 var jsc = jQuery.now(),
8210         jsre = /(\=)\?(&|$)|\?\?/i;
8211
8212 // Default jsonp settings
8213 jQuery.ajaxSetup({
8214         jsonp: "callback",
8215         jsonpCallback: function() {
8216                 return jQuery.expando + "_" + ( jsc++ );
8217         }
8218 });
8219
8220 // Detect, normalize options and install callbacks for jsonp requests
8221 jQuery.ajaxPrefilter( "json jsonp", function( s, originalSettings, jqXHR ) {
8222
8223         var inspectData = s.contentType === "application/x-www-form-urlencoded" &&
8224                 ( typeof s.data === "string" );
8225
8226         if ( s.dataTypes[ 0 ] === "jsonp" ||
8227                 s.jsonp !== false && ( jsre.test( s.url ) ||
8228                                 inspectData && jsre.test( s.data ) ) ) {
8229
8230                 var responseContainer,
8231                         jsonpCallback = s.jsonpCallback =
8232                                 jQuery.isFunction( s.jsonpCallback ) ? s.jsonpCallback() : s.jsonpCallback,
8233                         previous = window[ jsonpCallback ],
8234                         url = s.url,
8235                         data = s.data,
8236                         replace = "$1" + jsonpCallback + "$2";
8237
8238                 if ( s.jsonp !== false ) {
8239                         url = url.replace( jsre, replace );
8240                         if ( s.url === url ) {
8241                                 if ( inspectData ) {
8242                                         data = data.replace( jsre, replace );
8243                                 }
8244                                 if ( s.data === data ) {
8245                                         // Add callback manually
8246                                         url += (/\?/.test( url ) ? "&" : "?") + s.jsonp + "=" + jsonpCallback;
8247                                 }
8248                         }
8249                 }
8250
8251                 s.url = url;
8252                 s.data = data;
8253
8254                 // Install callback
8255                 window[ jsonpCallback ] = function( response ) {
8256                         responseContainer = [ response ];
8257                 };
8258
8259                 // Clean-up function
8260                 jqXHR.always(function() {
8261                         // Set callback back to previous value
8262                         window[ jsonpCallback ] = previous;
8263                         // Call if it was a function and we have a response
8264                         if ( responseContainer && jQuery.isFunction( previous ) ) {
8265                                 window[ jsonpCallback ]( responseContainer[ 0 ] );
8266                         }
8267                 });
8268
8269                 // Use data converter to retrieve json after script execution
8270                 s.converters["script json"] = function() {
8271                         if ( !responseContainer ) {
8272                                 jQuery.error( jsonpCallback + " was not called" );
8273                         }
8274                         return responseContainer[ 0 ];
8275                 };
8276
8277                 // force json dataType
8278                 s.dataTypes[ 0 ] = "json";
8279
8280                 // Delegate to script
8281                 return "script";
8282         }
8283 });
8284
8285
8286
8287
8288 // Install script dataType
8289 jQuery.ajaxSetup({
8290         accepts: {
8291                 script: "text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"
8292         },
8293         contents: {
8294                 script: /javascript|ecmascript/
8295         },
8296         converters: {
8297                 "text script": function( text ) {
8298                         jQuery.globalEval( text );
8299                         return text;
8300                 }
8301         }
8302 });
8303
8304 // Handle cache's special case and global
8305 jQuery.ajaxPrefilter( "script", function( s ) {
8306         if ( s.cache === undefined ) {
8307                 s.cache = false;
8308         }
8309         if ( s.crossDomain ) {
8310                 s.type = "GET";
8311                 s.global = false;
8312         }
8313 });
8314
8315 // Bind script tag hack transport
8316 jQuery.ajaxTransport( "script", function(s) {
8317
8318         // This transport only deals with cross domain requests
8319         if ( s.crossDomain ) {
8320
8321                 var script,
8322                         head = document.head || document.getElementsByTagName( "head" )[0] || document.documentElement;
8323
8324                 return {
8325
8326                         send: function( _, callback ) {
8327
8328                                 script = document.createElement( "script" );
8329
8330                                 script.async = "async";
8331
8332                                 if ( s.scriptCharset ) {
8333                                         script.charset = s.scriptCharset;
8334                                 }
8335
8336                                 script.src = s.url;
8337
8338                                 // Attach handlers for all browsers
8339                                 script.onload = script.onreadystatechange = function( _, isAbort ) {
8340
8341                                         if ( isAbort || !script.readyState || /loaded|complete/.test( script.readyState ) ) {
8342
8343                                                 // Handle memory leak in IE
8344                                                 script.onload = script.onreadystatechange = null;
8345
8346                                                 // Remove the script
8347                                                 if ( head && script.parentNode ) {
8348                                                         head.removeChild( script );
8349                                                 }
8350
8351                                                 // Dereference the script
8352                                                 script = undefined;
8353
8354                                                 // Callback if not abort
8355                                                 if ( !isAbort ) {
8356                                                         callback( 200, "success" );
8357                                                 }
8358                                         }
8359                                 };
8360                                 // Use insertBefore instead of appendChild  to circumvent an IE6 bug.
8361                                 // This arises when a base node is used (#2709 and #4378).
8362                                 head.insertBefore( script, head.firstChild );
8363                         },
8364
8365                         abort: function() {
8366                                 if ( script ) {
8367                                         script.onload( 0, 1 );
8368                                 }
8369                         }
8370                 };
8371         }
8372 });
8373
8374
8375
8376
8377 var // #5280: Internet Explorer will keep connections alive if we don't abort on unload
8378         xhrOnUnloadAbort = window.ActiveXObject ? function() {
8379                 // Abort all pending requests
8380                 for ( var key in xhrCallbacks ) {
8381                         xhrCallbacks[ key ]( 0, 1 );
8382                 }
8383         } : false,
8384         xhrId = 0,
8385         xhrCallbacks;
8386
8387 // Functions to create xhrs
8388 function createStandardXHR() {
8389         try {
8390                 return new window.XMLHttpRequest();
8391         } catch( e ) {}
8392 }
8393
8394 function createActiveXHR() {
8395         try {
8396                 return new window.ActiveXObject( "Microsoft.XMLHTTP" );
8397         } catch( e ) {}
8398 }
8399
8400 // Create the request object
8401 // (This is still attached to ajaxSettings for backward compatibility)
8402 jQuery.ajaxSettings.xhr = window.ActiveXObject ?
8403         /* Microsoft failed to properly
8404          * implement the XMLHttpRequest in IE7 (can't request local files),
8405          * so we use the ActiveXObject when it is available
8406          * Additionally XMLHttpRequest can be disabled in IE7/IE8 so
8407          * we need a fallback.
8408          */
8409         function() {
8410                 return !this.isLocal && createStandardXHR() || createActiveXHR();
8411         } :
8412         // For all other browsers, use the standard XMLHttpRequest object
8413         createStandardXHR;
8414
8415 // Determine support properties
8416 (function( xhr ) {
8417         jQuery.extend( jQuery.support, {
8418                 ajax: !!xhr,
8419                 cors: !!xhr && ( "withCredentials" in xhr )
8420         });
8421 })( jQuery.ajaxSettings.xhr() );
8422
8423 // Create transport if the browser can provide an xhr
8424 if ( jQuery.support.ajax ) {
8425
8426         jQuery.ajaxTransport(function( s ) {
8427                 // Cross domain only allowed if supported through XMLHttpRequest
8428                 if ( !s.crossDomain || jQuery.support.cors ) {
8429
8430                         var callback;
8431
8432                         return {
8433                                 send: function( headers, complete ) {
8434
8435                                         // Get a new xhr
8436                                         var xhr = s.xhr(),
8437                                                 handle,
8438                                                 i;
8439
8440                                         // Open the socket
8441                                         // Passing null username, generates a login popup on Opera (#2865)
8442                                         if ( s.username ) {
8443                                                 xhr.open( s.type, s.url, s.async, s.username, s.password );
8444                                         } else {
8445                                                 xhr.open( s.type, s.url, s.async );
8446                                         }
8447
8448                                         // Apply custom fields if provided
8449                                         if ( s.xhrFields ) {
8450                                                 for ( i in s.xhrFields ) {
8451                                                         xhr[ i ] = s.xhrFields[ i ];
8452                                                 }
8453                                         }
8454
8455                                         // Override mime type if needed
8456                                         if ( s.mimeType && xhr.overrideMimeType ) {
8457                                                 xhr.overrideMimeType( s.mimeType );
8458                                         }
8459
8460                                         // X-Requested-With header
8461                                         // For cross-domain requests, seeing as conditions for a preflight are
8462                                         // akin to a jigsaw puzzle, we simply never set it to be sure.
8463                                         // (it can always be set on a per-request basis or even using ajaxSetup)
8464                                         // For same-domain requests, won't change header if already provided.
8465                                         if ( !s.crossDomain && !headers["X-Requested-With"] ) {
8466                                                 headers[ "X-Requested-With" ] = "XMLHttpRequest";
8467                                         }
8468
8469                                         // Need an extra try/catch for cross domain requests in Firefox 3
8470                                         try {
8471                                                 for ( i in headers ) {
8472                                                         xhr.setRequestHeader( i, headers[ i ] );
8473                                                 }
8474                                         } catch( _ ) {}
8475
8476                                         // Do send the request
8477                                         // This may raise an exception which is actually
8478                                         // handled in jQuery.ajax (so no try/catch here)
8479                                         xhr.send( ( s.hasContent && s.data ) || null );
8480
8481                                         // Listener
8482                                         callback = function( _, isAbort ) {
8483
8484                                                 var status,
8485                                                         statusText,
8486                                                         responseHeaders,
8487                                                         responses,
8488                                                         xml;
8489
8490                                                 // Firefox throws exceptions when accessing properties
8491                                                 // of an xhr when a network error occured
8492                                                 // http://helpful.knobs-dials.com/index.php/Component_returned_failure_code:_0x80040111_(NS_ERROR_NOT_AVAILABLE)
8493                                                 try {
8494
8495                                                         // Was never called and is aborted or complete
8496                                                         if ( callback && ( isAbort || xhr.readyState === 4 ) ) {
8497
8498                                                                 // Only called once
8499                                                                 callback = undefined;
8500
8501                                                                 // Do not keep as active anymore
8502                                                                 if ( handle ) {
8503                                                                         xhr.onreadystatechange = jQuery.noop;
8504                                                                         if ( xhrOnUnloadAbort ) {
8505                                                                                 delete xhrCallbacks[ handle ];
8506                                                                         }
8507                                                                 }
8508
8509                                                                 // If it's an abort
8510                                                                 if ( isAbort ) {
8511                                                                         // Abort it manually if needed
8512                                                                         if ( xhr.readyState !== 4 ) {
8513                                                                                 xhr.abort();
8514                                                                         }
8515                                                                 } else {
8516                                                                         status = xhr.status;
8517                                                                         responseHeaders = xhr.getAllResponseHeaders();
8518                                                                         responses = {};
8519                                                                         xml = xhr.responseXML;
8520
8521                                                                         // Construct response list
8522                                                                         if ( xml && xml.documentElement /* #4958 */ ) {
8523                                                                                 responses.xml = xml;
8524                                                                         }
8525                                                                         responses.text = xhr.responseText;
8526
8527                                                                         // Firefox throws an exception when accessing
8528                                                                         // statusText for faulty cross-domain requests
8529                                                                         try {
8530                                                                                 statusText = xhr.statusText;
8531                                                                         } catch( e ) {
8532                                                                                 // We normalize with Webkit giving an empty statusText
8533                                                                                 statusText = "";
8534                                                                         }
8535
8536                                                                         // Filter status for non standard behaviors
8537
8538                                                                         // If the request is local and we have data: assume a success
8539                                                                         // (success with no data won't get notified, that's the best we
8540                                                                         // can do given current implementations)
8541                                                                         if ( !status && s.isLocal && !s.crossDomain ) {
8542                                                                                 status = responses.text ? 200 : 404;
8543                                                                         // IE - #1450: sometimes returns 1223 when it should be 204
8544                                                                         } else if ( status === 1223 ) {
8545                                                                                 status = 204;
8546                                                                         }
8547                                                                 }
8548                                                         }
8549                                                 } catch( firefoxAccessException ) {
8550                                                         if ( !isAbort ) {
8551                                                                 complete( -1, firefoxAccessException );
8552                                                         }
8553                                                 }
8554
8555                                                 // Call complete if needed
8556                                                 if ( responses ) {
8557                                                         complete( status, statusText, responses, responseHeaders );
8558                                                 }
8559                                         };
8560
8561                                         // if we're in sync mode or it's in cache
8562                                         // and has been retrieved directly (IE6 & IE7)
8563                                         // we need to manually fire the callback
8564                                         if ( !s.async || xhr.readyState === 4 ) {
8565                                                 callback();
8566                                         } else {
8567                                                 handle = ++xhrId;
8568                                                 if ( xhrOnUnloadAbort ) {
8569                                                         // Create the active xhrs callbacks list if needed
8570                                                         // and attach the unload handler
8571                                                         if ( !xhrCallbacks ) {
8572                                                                 xhrCallbacks = {};
8573                                                                 jQuery( window ).unload( xhrOnUnloadAbort );
8574                                                         }
8575                                                         // Add to list of active xhrs callbacks
8576                                                         xhrCallbacks[ handle ] = callback;
8577                                                 }
8578                                                 xhr.onreadystatechange = callback;
8579                                         }
8580                                 },
8581
8582                                 abort: function() {
8583                                         if ( callback ) {
8584                                                 callback(0,1);
8585                                         }
8586                                 }
8587                         };
8588                 }
8589         });
8590 }
8591
8592
8593
8594
8595 var elemdisplay = {},
8596         iframe, iframeDoc,
8597         rfxtypes = /^(?:toggle|show|hide)$/,
8598         rfxnum = /^([+\-]=)?([\d+.\-]+)([a-z%]*)$/i,
8599         timerId,
8600         fxAttrs = [
8601                 // height animations
8602                 [ "height", "marginTop", "marginBottom", "paddingTop", "paddingBottom" ],
8603                 // width animations
8604                 [ "width", "marginLeft", "marginRight", "paddingLeft", "paddingRight" ],
8605                 // opacity animations
8606                 [ "opacity" ]
8607         ],
8608         fxNow,
8609         requestAnimationFrame = window.webkitRequestAnimationFrame ||
8610             window.mozRequestAnimationFrame ||
8611             window.oRequestAnimationFrame;
8612
8613 jQuery.fn.extend({
8614         show: function( speed, easing, callback ) {
8615                 var elem, display;
8616
8617                 if ( speed || speed === 0 ) {
8618                         return this.animate( genFx("show", 3), speed, easing, callback);
8619
8620                 } else {
8621                         for ( var i = 0, j = this.length; i < j; i++ ) {
8622                                 elem = this[i];
8623
8624                                 if ( elem.style ) {
8625                                         display = elem.style.display;
8626
8627                                         // Reset the inline display of this element to learn if it is
8628                                         // being hidden by cascaded rules or not
8629                                         if ( !jQuery._data(elem, "olddisplay") && display === "none" ) {
8630                                                 display = elem.style.display = "";
8631                                         }
8632
8633                                         // Set elements which have been overridden with display: none
8634                                         // in a stylesheet to whatever the default browser style is
8635                                         // for such an element
8636                                         if ( display === "" && jQuery.css( elem, "display" ) === "none" ) {
8637                                                 jQuery._data(elem, "olddisplay", defaultDisplay(elem.nodeName));
8638                                         }
8639                                 }
8640                         }
8641
8642                         // Set the display of most of the elements in a second loop
8643                         // to avoid the constant reflow
8644                         for ( i = 0; i < j; i++ ) {
8645                                 elem = this[i];
8646
8647                                 if ( elem.style ) {
8648                                         display = elem.style.display;
8649
8650                                         if ( display === "" || display === "none" ) {
8651                                                 elem.style.display = jQuery._data(elem, "olddisplay") || "";
8652                                         }
8653                                 }
8654                         }
8655
8656                         return this;
8657                 }
8658         },
8659
8660         hide: function( speed, easing, callback ) {
8661                 if ( speed || speed === 0 ) {
8662                         return this.animate( genFx("hide", 3), speed, easing, callback);
8663
8664                 } else {
8665                         for ( var i = 0, j = this.length; i < j; i++ ) {
8666                                 if ( this[i].style ) {
8667                                         var display = jQuery.css( this[i], "display" );
8668
8669                                         if ( display !== "none" && !jQuery._data( this[i], "olddisplay" ) ) {
8670                                                 jQuery._data( this[i], "olddisplay", display );
8671                                         }
8672                                 }
8673                         }
8674
8675                         // Set the display of the elements in a second loop
8676                         // to avoid the constant reflow
8677                         for ( i = 0; i < j; i++ ) {
8678                                 if ( this[i].style ) {
8679                                         this[i].style.display = "none";
8680                                 }
8681                         }
8682
8683                         return this;
8684                 }
8685         },
8686
8687         // Save the old toggle function
8688         _toggle: jQuery.fn.toggle,
8689
8690         toggle: function( fn, fn2, callback ) {
8691                 var bool = typeof fn === "boolean";
8692
8693                 if ( jQuery.isFunction(fn) && jQuery.isFunction(fn2) ) {
8694                         this._toggle.apply( this, arguments );
8695
8696                 } else if ( fn == null || bool ) {
8697                         this.each(function() {
8698                                 var state = bool ? fn : jQuery(this).is(":hidden");
8699                                 jQuery(this)[ state ? "show" : "hide" ]();
8700                         });
8701
8702                 } else {
8703                         this.animate(genFx("toggle", 3), fn, fn2, callback);
8704                 }
8705
8706                 return this;
8707         },
8708
8709         fadeTo: function( speed, to, easing, callback ) {
8710                 return this.filter(":hidden").css("opacity", 0).show().end()
8711                                         .animate({opacity: to}, speed, easing, callback);
8712         },
8713
8714         animate: function( prop, speed, easing, callback ) {
8715                 var optall = jQuery.speed(speed, easing, callback);
8716
8717                 if ( jQuery.isEmptyObject( prop ) ) {
8718                         return this.each( optall.complete, [ false ] );
8719                 }
8720
8721                 return this[ optall.queue === false ? "each" : "queue" ](function() {
8722                         // XXX 'this' does not always have a nodeName when running the
8723                         // test suite
8724
8725                         if ( optall.queue === false ) {
8726                                 jQuery._mark( this );
8727                         }
8728
8729                         var opt = jQuery.extend({}, optall),
8730                                 isElement = this.nodeType === 1,
8731                                 hidden = isElement && jQuery(this).is(":hidden"),
8732                                 name, val, p,
8733                                 display, e,
8734                                 parts, start, end, unit;
8735
8736                         // will store per property easing and be used to determine when an animation is complete
8737                         opt.animatedProperties = {};
8738
8739                         for ( p in prop ) {
8740
8741                                 // property name normalization
8742                                 name = jQuery.camelCase( p );
8743                                 if ( p !== name ) {
8744                                         prop[ name ] = prop[ p ];
8745                                         delete prop[ p ];
8746                                 }
8747
8748                                 val = prop[name];
8749
8750                                 if ( val === "hide" && hidden || val === "show" && !hidden ) {
8751                                         return opt.complete.call(this);
8752                                 }
8753
8754                                 if ( isElement && ( name === "height" || name === "width" ) ) {
8755                                         // Make sure that nothing sneaks out
8756                                         // Record all 3 overflow attributes because IE does not
8757                                         // change the overflow attribute when overflowX and
8758                                         // overflowY are set to the same value
8759                                         opt.overflow = [ this.style.overflow, this.style.overflowX, this.style.overflowY ];
8760
8761                                         // Set display property to inline-block for height/width
8762                                         // animations on inline elements that are having width/height
8763                                         // animated
8764                                         if ( jQuery.css( this, "display" ) === "inline" &&
8765                                                         jQuery.css( this, "float" ) === "none" ) {
8766                                                 if ( !jQuery.support.inlineBlockNeedsLayout ) {
8767                                                         this.style.display = "inline-block";
8768
8769                                                 } else {
8770                                                         display = defaultDisplay(this.nodeName);
8771
8772                                                         // inline-level elements accept inline-block;
8773                                                         // block-level elements need to be inline with layout
8774                                                         if ( display === "inline" ) {
8775                                                                 this.style.display = "inline-block";
8776
8777                                                         } else {
8778                                                                 this.style.display = "inline";
8779                                                                 this.style.zoom = 1;
8780                                                         }
8781                                                 }
8782                                         }
8783                                 }
8784
8785                                 // easing resolution: per property > opt.specialEasing > opt.easing > 'swing' (default)
8786                                 opt.animatedProperties[name] = jQuery.isArray( val ) ?
8787                                         val[1]:
8788                                         opt.specialEasing && opt.specialEasing[name] || opt.easing || 'swing';
8789                         }
8790
8791                         if ( opt.overflow != null ) {
8792                                 this.style.overflow = "hidden";
8793                         }
8794
8795                         for ( p in prop ) {
8796                                 e = new jQuery.fx( this, opt, p );
8797
8798                                 val = prop[p];
8799
8800                                 if ( rfxtypes.test(val) ) {
8801                                         e[ val === "toggle" ? hidden ? "show" : "hide" : val ]();
8802
8803                                 } else {
8804                                         parts = rfxnum.exec(val);
8805                                         start = e.cur();
8806
8807                                         if ( parts ) {
8808                                                 end = parseFloat( parts[2] );
8809                                                 unit = parts[3] || ( jQuery.cssNumber[ name ] ? "" : "px" );
8810
8811                                                 // We need to compute starting value
8812                                                 if ( unit !== "px" ) {
8813                                                         jQuery.style( this, p, (end || 1) + unit);
8814                                                         start = ((end || 1) / e.cur()) * start;
8815                                                         jQuery.style( this, p, start + unit);
8816                                                 }
8817
8818                                                 // If a +=/-= token was provided, we're doing a relative animation
8819                                                 if ( parts[1] ) {
8820                                                         end = ((parts[1] === "-=" ? -1 : 1) * end) + start;
8821                                                 }
8822
8823                                                 e.custom( start, end, unit );
8824
8825                                         } else {
8826                                                 e.custom( start, val, "" );
8827                                         }
8828                                 }
8829                         }
8830
8831                         // For JS strict compliance
8832                         return true;
8833                 });
8834         },
8835
8836         stop: function( clearQueue, gotoEnd ) {
8837                 if ( clearQueue ) {
8838                         this.queue([]);
8839                 }
8840
8841                 this.each(function() {
8842                         var timers = jQuery.timers,
8843                                 i = timers.length;
8844                         // clear marker counters if we know they won't be
8845                         if ( !gotoEnd ) {
8846                                 jQuery._unmark( true, this );
8847                         }
8848                         // go in reverse order so anything added to the queue during the loop is ignored
8849                         while ( i-- ) {
8850                                 if ( timers[i].elem === this ) {
8851                                         if (gotoEnd) {
8852                                                 // force the next step to be the last
8853                                                 timers[i](true);
8854                                         }
8855
8856                                         timers.splice(i, 1);
8857                                 }
8858                         }
8859                 });
8860
8861                 // start the next in the queue if the last step wasn't forced
8862                 if ( !gotoEnd ) {
8863                         this.dequeue();
8864                 }
8865
8866                 return this;
8867         }
8868
8869 });
8870
8871 // Animations created synchronously will run synchronously
8872 function createFxNow() {
8873         setTimeout( clearFxNow, 0 );
8874         return ( fxNow = jQuery.now() );
8875 }
8876
8877 function clearFxNow() {
8878         fxNow = undefined;
8879 }
8880
8881 // Generate parameters to create a standard animation
8882 function genFx( type, num ) {
8883         var obj = {};
8884
8885         jQuery.each( fxAttrs.concat.apply([], fxAttrs.slice(0,num)), function() {
8886                 obj[ this ] = type;
8887         });
8888
8889         return obj;
8890 }
8891
8892 // Generate shortcuts for custom animations
8893 jQuery.each({
8894         slideDown: genFx("show", 1),
8895         slideUp: genFx("hide", 1),
8896         slideToggle: genFx("toggle", 1),
8897         fadeIn: { opacity: "show" },
8898         fadeOut: { opacity: "hide" },
8899         fadeToggle: { opacity: "toggle" }
8900 }, function( name, props ) {
8901         jQuery.fn[ name ] = function( speed, easing, callback ) {
8902                 return this.animate( props, speed, easing, callback );
8903         };
8904 });
8905
8906 jQuery.extend({
8907         speed: function( speed, easing, fn ) {
8908                 var opt = speed && typeof speed === "object" ? jQuery.extend({}, speed) : {
8909                         complete: fn || !fn && easing ||
8910                                 jQuery.isFunction( speed ) && speed,
8911                         duration: speed,
8912                         easing: fn && easing || easing && !jQuery.isFunction(easing) && easing
8913                 };
8914
8915                 opt.duration = jQuery.fx.off ? 0 : typeof opt.duration === "number" ? opt.duration :
8916                         opt.duration in jQuery.fx.speeds ? jQuery.fx.speeds[opt.duration] : jQuery.fx.speeds._default;
8917
8918                 // Queueing
8919                 opt.old = opt.complete;
8920                 opt.complete = function( noUnmark ) {
8921                         if ( opt.queue !== false ) {
8922                                 jQuery.dequeue( this );
8923                         } else if ( noUnmark !== false ) {
8924                                 jQuery._unmark( this );
8925                         }
8926
8927                         if ( jQuery.isFunction( opt.old ) ) {
8928                                 opt.old.call( this );
8929                         }
8930                 };
8931
8932                 return opt;
8933         },
8934
8935         easing: {
8936                 linear: function( p, n, firstNum, diff ) {
8937                         return firstNum + diff * p;
8938                 },
8939                 swing: function( p, n, firstNum, diff ) {
8940                         return ((-Math.cos(p*Math.PI)/2) + 0.5) * diff + firstNum;
8941                 }
8942         },
8943
8944         timers: [],
8945
8946         fx: function( elem, options, prop ) {
8947                 this.options = options;
8948                 this.elem = elem;
8949                 this.prop = prop;
8950
8951                 options.orig = options.orig || {};
8952         }
8953
8954 });
8955
8956 jQuery.fx.prototype = {
8957         // Simple function for setting a style value
8958         update: function() {
8959                 if ( this.options.step ) {
8960                         this.options.step.call( this.elem, this.now, this );
8961                 }
8962
8963                 (jQuery.fx.step[this.prop] || jQuery.fx.step._default)( this );
8964         },
8965
8966         // Get the current size
8967         cur: function() {
8968                 if ( this.elem[this.prop] != null && (!this.elem.style || this.elem.style[this.prop] == null) ) {
8969                         return this.elem[ this.prop ];
8970                 }
8971
8972                 var parsed,
8973                         r = jQuery.css( this.elem, this.prop );
8974                 // Empty strings, null, undefined and "auto" are converted to 0,
8975                 // complex values such as "rotate(1rad)" are returned as is,
8976                 // simple values such as "10px" are parsed to Float.
8977                 return isNaN( parsed = parseFloat( r ) ) ? !r || r === "auto" ? 0 : r : parsed;
8978         },
8979
8980         // Start an animation from one number to another
8981         custom: function( from, to, unit ) {
8982                 var self = this,
8983                         fx = jQuery.fx,
8984                         raf;
8985
8986                 this.startTime = fxNow || createFxNow();
8987                 this.start = from;
8988                 this.end = to;
8989                 this.unit = unit || this.unit || ( jQuery.cssNumber[ this.prop ] ? "" : "px" );
8990                 this.now = this.start;
8991                 this.pos = this.state = 0;
8992
8993                 function t( gotoEnd ) {
8994                         return self.step(gotoEnd);
8995                 }
8996
8997                 t.elem = this.elem;
8998
8999                 if ( t() && jQuery.timers.push(t) && !timerId ) {
9000                         // Use requestAnimationFrame instead of setInterval if available
9001                         if ( requestAnimationFrame ) {
9002                                 timerId = 1;
9003                                 raf = function() {
9004                                         // When timerId gets set to null at any point, this stops
9005                                         if ( timerId ) {
9006                                                 requestAnimationFrame( raf );
9007                                                 fx.tick();
9008                                         }
9009                                 };
9010                                 requestAnimationFrame( raf );
9011                         } else {
9012                                 timerId = setInterval( fx.tick, fx.interval );
9013                         }
9014                 }
9015         },
9016
9017         // Simple 'show' function
9018         show: function() {
9019                 // Remember where we started, so that we can go back to it later
9020                 this.options.orig[this.prop] = jQuery.style( this.elem, this.prop );
9021                 this.options.show = true;
9022
9023                 // Begin the animation
9024                 // Make sure that we start at a small width/height to avoid any
9025                 // flash of content
9026                 this.custom(this.prop === "width" || this.prop === "height" ? 1 : 0, this.cur());
9027
9028                 // Start by showing the element
9029                 jQuery( this.elem ).show();
9030         },
9031
9032         // Simple 'hide' function
9033         hide: function() {
9034                 // Remember where we started, so that we can go back to it later
9035                 this.options.orig[this.prop] = jQuery.style( this.elem, this.prop );
9036                 this.options.hide = true;
9037
9038                 // Begin the animation
9039                 this.custom(this.cur(), 0);
9040         },
9041
9042         // Each step of an animation
9043         step: function( gotoEnd ) {
9044                 var t = fxNow || createFxNow(),
9045                         done = true,
9046                         elem = this.elem,
9047                         options = this.options,
9048                         i, n;
9049
9050                 if ( gotoEnd || t >= options.duration + this.startTime ) {
9051                         this.now = this.end;
9052                         this.pos = this.state = 1;
9053                         this.update();
9054
9055                         options.animatedProperties[ this.prop ] = true;
9056
9057                         for ( i in options.animatedProperties ) {
9058                                 if ( options.animatedProperties[i] !== true ) {
9059                                         done = false;
9060                                 }
9061                         }
9062
9063                         if ( done ) {
9064                                 // Reset the overflow
9065                                 if ( options.overflow != null && !jQuery.support.shrinkWrapBlocks ) {
9066
9067                                         jQuery.each( [ "", "X", "Y" ], function (index, value) {
9068                                                 elem.style[ "overflow" + value ] = options.overflow[index];
9069                                         });
9070                                 }
9071
9072                                 // Hide the element if the "hide" operation was done
9073                                 if ( options.hide ) {
9074                                         jQuery(elem).hide();
9075                                 }
9076
9077                                 // Reset the properties, if the item has been hidden or shown
9078                                 if ( options.hide || options.show ) {
9079                                         for ( var p in options.animatedProperties ) {
9080                                                 jQuery.style( elem, p, options.orig[p] );
9081                                         }
9082                                 }
9083
9084                                 // Execute the complete function
9085                                 options.complete.call( elem );
9086                         }
9087
9088                         return false;
9089
9090                 } else {
9091                         // classical easing cannot be used with an Infinity duration
9092                         if ( options.duration == Infinity ) {
9093                                 this.now = t;
9094                         } else {
9095                                 n = t - this.startTime;
9096
9097                                 this.state = n / options.duration;
9098                                 // Perform the easing function, defaults to swing
9099                                 this.pos = jQuery.easing[options.animatedProperties[this.prop]](this.state, n, 0, 1, options.duration);
9100                                 this.now = this.start + ((this.end - this.start) * this.pos);
9101                         }
9102                         // Perform the next step of the animation
9103                         this.update();
9104                 }
9105
9106                 return true;
9107         }
9108 };
9109
9110 jQuery.extend( jQuery.fx, {
9111         tick: function() {
9112                 var timers = jQuery.timers,
9113                         i = timers.length;
9114                 while ( i-- ) {
9115                         if ( !timers[i]() ) {
9116                                 timers.splice(i, 1);
9117                         }
9118                 }
9119
9120                 if ( !timers.length ) {
9121                         jQuery.fx.stop();
9122                 }
9123         },
9124
9125         interval: 13,
9126
9127         stop: function() {
9128                 clearInterval( timerId );
9129                 timerId = null;
9130         },
9131
9132         speeds: {
9133                 slow: 600,
9134                 fast: 200,
9135                 // Default speed
9136                 _default: 400
9137         },
9138
9139         step: {
9140                 opacity: function( fx ) {
9141                         jQuery.style( fx.elem, "opacity", fx.now );
9142                 },
9143
9144                 _default: function( fx ) {
9145                         if ( fx.elem.style && fx.elem.style[ fx.prop ] != null ) {
9146                                 fx.elem.style[ fx.prop ] = (fx.prop === "width" || fx.prop === "height" ? Math.max(0, fx.now) : fx.now) + fx.unit;
9147                         } else {
9148                                 fx.elem[ fx.prop ] = fx.now;
9149                         }
9150                 }
9151         }
9152 });
9153
9154 if ( jQuery.expr && jQuery.expr.filters ) {
9155         jQuery.expr.filters.animated = function( elem ) {
9156                 return jQuery.grep(jQuery.timers, function( fn ) {
9157                         return elem === fn.elem;
9158                 }).length;
9159         };
9160 }
9161
9162 // Try to restore the default display value of an element
9163 function defaultDisplay( nodeName ) {
9164
9165         if ( !elemdisplay[ nodeName ] ) {
9166
9167                 var elem = jQuery( "<" + nodeName + ">" ).appendTo( "body" ),
9168                         display = elem.css( "display" );
9169
9170                 elem.remove();
9171
9172                 // If the simple way fails,
9173                 // get element's real default display by attaching it to a temp iframe
9174                 if ( display === "none" || display === "" ) {
9175                         // No iframe to use yet, so create it
9176                         if ( !iframe ) {
9177                                 iframe = document.createElement( "iframe" );
9178                                 iframe.frameBorder = iframe.width = iframe.height = 0;
9179                         }
9180
9181                         document.body.appendChild( iframe );
9182
9183                         // Create a cacheable copy of the iframe document on first call.
9184                         // IE and Opera will allow us to reuse the iframeDoc without re-writing the fake html
9185                         // document to it, Webkit & Firefox won't allow reusing the iframe document
9186                         if ( !iframeDoc || !iframe.createElement ) {
9187                                 iframeDoc = ( iframe.contentWindow || iframe.contentDocument ).document;
9188                                 iframeDoc.write( "<!doctype><html><body></body></html>" );
9189                         }
9190
9191                         elem = iframeDoc.createElement( nodeName );
9192
9193                         iframeDoc.body.appendChild( elem );
9194
9195                         display = jQuery.css( elem, "display" );
9196
9197                         document.body.removeChild( iframe );
9198                 }
9199
9200                 // Store the correct default display
9201                 elemdisplay[ nodeName ] = display;
9202         }
9203
9204         return elemdisplay[ nodeName ];
9205 }
9206
9207
9208
9209
9210 var rtable = /^t(?:able|d|h)$/i,
9211         rroot = /^(?:body|html)$/i;
9212
9213 if ( "getBoundingClientRect" in document.documentElement ) {
9214         jQuery.fn.offset = function( options ) {
9215                 var elem = this[0], box;
9216
9217                 if ( options ) {
9218                         return this.each(function( i ) {
9219                                 jQuery.offset.setOffset( this, options, i );
9220                         });
9221                 }
9222
9223                 if ( !elem || !elem.ownerDocument ) {
9224                         return null;
9225                 }
9226
9227                 if ( elem === elem.ownerDocument.body ) {
9228                         return jQuery.offset.bodyOffset( elem );
9229                 }
9230
9231                 try {
9232                         box = elem.getBoundingClientRect();
9233                 } catch(e) {}
9234
9235                 var doc = elem.ownerDocument,
9236                         docElem = doc.documentElement;
9237
9238                 // Make sure we're not dealing with a disconnected DOM node
9239                 if ( !box || !jQuery.contains( docElem, elem ) ) {
9240                         return box ? { top: box.top, left: box.left } : { top: 0, left: 0 };
9241                 }
9242
9243                 var body = doc.body,
9244                         win = getWindow(doc),
9245                         clientTop  = docElem.clientTop  || body.clientTop  || 0,
9246                         clientLeft = docElem.clientLeft || body.clientLeft || 0,
9247                         scrollTop  = win.pageYOffset || jQuery.support.boxModel && docElem.scrollTop  || body.scrollTop,
9248                         scrollLeft = win.pageXOffset || jQuery.support.boxModel && docElem.scrollLeft || body.scrollLeft,
9249                         top  = box.top  + scrollTop  - clientTop,
9250                         left = box.left + scrollLeft - clientLeft;
9251
9252                 return { top: top, left: left };
9253         };
9254
9255 } else {
9256         jQuery.fn.offset = function( options ) {
9257                 var elem = this[0];
9258
9259                 if ( options ) {
9260                         return this.each(function( i ) {
9261                                 jQuery.offset.setOffset( this, options, i );
9262                         });
9263                 }
9264
9265                 if ( !elem || !elem.ownerDocument ) {
9266                         return null;
9267                 }
9268
9269                 if ( elem === elem.ownerDocument.body ) {
9270                         return jQuery.offset.bodyOffset( elem );
9271                 }
9272
9273                 jQuery.offset.initialize();
9274
9275                 var computedStyle,
9276                         offsetParent = elem.offsetParent,
9277                         prevOffsetParent = elem,
9278                         doc = elem.ownerDocument,
9279                         docElem = doc.documentElement,
9280                         body = doc.body,
9281                         defaultView = doc.defaultView,
9282                         prevComputedStyle = defaultView ? defaultView.getComputedStyle( elem, null ) : elem.currentStyle,
9283                         top = elem.offsetTop,
9284                         left = elem.offsetLeft;
9285
9286                 while ( (elem = elem.parentNode) && elem !== body && elem !== docElem ) {
9287                         if ( jQuery.offset.supportsFixedPosition && prevComputedStyle.position === "fixed" ) {
9288                                 break;
9289                         }
9290
9291                         computedStyle = defaultView ? defaultView.getComputedStyle(elem, null) : elem.currentStyle;
9292                         top  -= elem.scrollTop;
9293                         left -= elem.scrollLeft;
9294
9295                         if ( elem === offsetParent ) {
9296                                 top  += elem.offsetTop;
9297                                 left += elem.offsetLeft;
9298
9299                                 if ( jQuery.offset.doesNotAddBorder && !(jQuery.offset.doesAddBorderForTableAndCells && rtable.test(elem.nodeName)) ) {
9300                                         top  += parseFloat( computedStyle.borderTopWidth  ) || 0;
9301                                         left += parseFloat( computedStyle.borderLeftWidth ) || 0;
9302                                 }
9303
9304                                 prevOffsetParent = offsetParent;
9305                                 offsetParent = elem.offsetParent;
9306                         }
9307
9308                         if ( jQuery.offset.subtractsBorderForOverflowNotVisible && computedStyle.overflow !== "visible" ) {
9309                                 top  += parseFloat( computedStyle.borderTopWidth  ) || 0;
9310                                 left += parseFloat( computedStyle.borderLeftWidth ) || 0;
9311                         }
9312
9313                         prevComputedStyle = computedStyle;
9314                 }
9315
9316                 if ( prevComputedStyle.position === "relative" || prevComputedStyle.position === "static" ) {
9317                         top  += body.offsetTop;
9318                         left += body.offsetLeft;
9319                 }
9320
9321                 if ( jQuery.offset.supportsFixedPosition && prevComputedStyle.position === "fixed" ) {
9322                         top  += Math.max( docElem.scrollTop, body.scrollTop );
9323                         left += Math.max( docElem.scrollLeft, body.scrollLeft );
9324                 }
9325
9326                 return { top: top, left: left };
9327         };
9328 }
9329
9330 jQuery.offset = {
9331         initialize: function() {
9332                 var body = document.body, container = document.createElement("div"), innerDiv, checkDiv, table, td, bodyMarginTop = parseFloat( jQuery.css(body, "marginTop") ) || 0,
9333                         html = "<div style='position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;width:1px;height:1px;'><div></div></div><table style='position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;width:1px;height:1px;' cellpadding='0' cellspacing='0'><tr><td></td></tr></table>";
9334
9335                 jQuery.extend( container.style, { position: "absolute", top: 0, left: 0, margin: 0, border: 0, width: "1px", height: "1px", visibility: "hidden" } );
9336
9337                 container.innerHTML = html;
9338                 body.insertBefore( container, body.firstChild );
9339                 innerDiv = container.firstChild;
9340                 checkDiv = innerDiv.firstChild;
9341                 td = innerDiv.nextSibling.firstChild.firstChild;
9342
9343                 this.doesNotAddBorder = (checkDiv.offsetTop !== 5);
9344                 this.doesAddBorderForTableAndCells = (td.offsetTop === 5);
9345
9346                 checkDiv.style.position = "fixed";
9347                 checkDiv.style.top = "20px";
9348
9349                 // safari subtracts parent border width here which is 5px
9350                 this.supportsFixedPosition = (checkDiv.offsetTop === 20 || checkDiv.offsetTop === 15);
9351                 checkDiv.style.position = checkDiv.style.top = "";
9352
9353                 innerDiv.style.overflow = "hidden";
9354                 innerDiv.style.position = "relative";
9355
9356                 this.subtractsBorderForOverflowNotVisible = (checkDiv.offsetTop === -5);
9357
9358                 this.doesNotIncludeMarginInBodyOffset = (body.offsetTop !== bodyMarginTop);
9359
9360                 body.removeChild( container );
9361                 jQuery.offset.initialize = jQuery.noop;
9362         },
9363
9364         bodyOffset: function( body ) {
9365                 var top = body.offsetTop,
9366                         left = body.offsetLeft;
9367
9368                 jQuery.offset.initialize();
9369
9370                 if ( jQuery.offset.doesNotIncludeMarginInBodyOffset ) {
9371                         top  += parseFloat( jQuery.css(body, "marginTop") ) || 0;
9372                         left += parseFloat( jQuery.css(body, "marginLeft") ) || 0;
9373                 }
9374
9375                 return { top: top, left: left };
9376         },
9377
9378         setOffset: function( elem, options, i ) {
9379                 var position = jQuery.css( elem, "position" );
9380
9381                 // set position first, in-case top/left are set even on static elem
9382                 if ( position === "static" ) {
9383                         elem.style.position = "relative";
9384                 }
9385
9386                 var curElem = jQuery( elem ),
9387                         curOffset = curElem.offset(),
9388                         curCSSTop = jQuery.css( elem, "top" ),
9389                         curCSSLeft = jQuery.css( elem, "left" ),
9390                         calculatePosition = (position === "absolute" || position === "fixed") && jQuery.inArray("auto", [curCSSTop, curCSSLeft]) > -1,
9391                         props = {}, curPosition = {}, curTop, curLeft;
9392
9393                 // need to be able to calculate position if either top or left is auto and position is either absolute or fixed
9394                 if ( calculatePosition ) {
9395                         curPosition = curElem.position();
9396                         curTop = curPosition.top;
9397                         curLeft = curPosition.left;
9398                 } else {
9399                         curTop = parseFloat( curCSSTop ) || 0;
9400                         curLeft = parseFloat( curCSSLeft ) || 0;
9401                 }
9402
9403                 if ( jQuery.isFunction( options ) ) {
9404                         options = options.call( elem, i, curOffset );
9405                 }
9406
9407                 if (options.top != null) {
9408                         props.top = (options.top - curOffset.top) + curTop;
9409                 }
9410                 if (options.left != null) {
9411                         props.left = (options.left - curOffset.left) + curLeft;
9412                 }
9413
9414                 if ( "using" in options ) {
9415                         options.using.call( elem, props );
9416                 } else {
9417                         curElem.css( props );
9418                 }
9419         }
9420 };
9421
9422
9423 jQuery.fn.extend({
9424         position: function() {
9425                 if ( !this[0] ) {
9426                         return null;
9427                 }
9428
9429                 var elem = this[0],
9430
9431                 // Get *real* offsetParent
9432                 offsetParent = this.offsetParent(),
9433
9434                 // Get correct offsets
9435                 offset       = this.offset(),
9436                 parentOffset = rroot.test(offsetParent[0].nodeName) ? { top: 0, left: 0 } : offsetParent.offset();
9437
9438                 // Subtract element margins
9439                 // note: when an element has margin: auto the offsetLeft and marginLeft
9440                 // are the same in Safari causing offset.left to incorrectly be 0
9441                 offset.top  -= parseFloat( jQuery.css(elem, "marginTop") ) || 0;
9442                 offset.left -= parseFloat( jQuery.css(elem, "marginLeft") ) || 0;
9443
9444                 // Add offsetParent borders
9445                 parentOffset.top  += parseFloat( jQuery.css(offsetParent[0], "borderTopWidth") ) || 0;
9446                 parentOffset.left += parseFloat( jQuery.css(offsetParent[0], "borderLeftWidth") ) || 0;
9447
9448                 // Subtract the two offsets
9449                 return {
9450                         top:  offset.top  - parentOffset.top,
9451                         left: offset.left - parentOffset.left
9452                 };
9453         },
9454
9455         offsetParent: function() {
9456                 return this.map(function() {
9457                         var offsetParent = this.offsetParent || document.body;
9458                         while ( offsetParent && (!rroot.test(offsetParent.nodeName) && jQuery.css(offsetParent, "position") === "static") ) {
9459                                 offsetParent = offsetParent.offsetParent;
9460                         }
9461                         return offsetParent;
9462                 });
9463         }
9464 });
9465
9466
9467 // Create scrollLeft and scrollTop methods
9468 jQuery.each( ["Left", "Top"], function( i, name ) {
9469         var method = "scroll" + name;
9470
9471         jQuery.fn[ method ] = function( val ) {
9472                 var elem, win;
9473
9474                 if ( val === undefined ) {
9475                         elem = this[ 0 ];
9476
9477                         if ( !elem ) {
9478                                 return null;
9479                         }
9480
9481                         win = getWindow( elem );
9482
9483                         // Return the scroll offset
9484                         return win ? ("pageXOffset" in win) ? win[ i ? "pageYOffset" : "pageXOffset" ] :
9485                                 jQuery.support.boxModel && win.document.documentElement[ method ] ||
9486                                         win.document.body[ method ] :
9487                                 elem[ method ];
9488                 }
9489
9490                 // Set the scroll offset
9491                 return this.each(function() {
9492                         win = getWindow( this );
9493
9494                         if ( win ) {
9495                                 win.scrollTo(
9496                                         !i ? val : jQuery( win ).scrollLeft(),
9497                                          i ? val : jQuery( win ).scrollTop()
9498                                 );
9499
9500                         } else {
9501                                 this[ method ] = val;
9502                         }
9503                 });
9504         };
9505 });
9506
9507 function getWindow( elem ) {
9508         return jQuery.isWindow( elem ) ?
9509                 elem :
9510                 elem.nodeType === 9 ?
9511                         elem.defaultView || elem.parentWindow :
9512                         false;
9513 }
9514
9515
9516
9517
9518 // Create innerHeight, innerWidth, outerHeight and outerWidth methods
9519 jQuery.each([ "Height", "Width" ], function( i, name ) {
9520
9521         var type = name.toLowerCase();
9522
9523         // innerHeight and innerWidth
9524         jQuery.fn["inner" + name] = function() {
9525                 return this[0] ?
9526                         parseFloat( jQuery.css( this[0], type, "padding" ) ) :
9527                         null;
9528         };
9529
9530         // outerHeight and outerWidth
9531         jQuery.fn["outer" + name] = function( margin ) {
9532                 return this[0] ?
9533                         parseFloat( jQuery.css( this[0], type, margin ? "margin" : "border" ) ) :
9534                         null;
9535         };
9536
9537         jQuery.fn[ type ] = function( size ) {
9538                 // Get window width or height
9539                 var elem = this[0];
9540                 if ( !elem ) {
9541                         return size == null ? null : this;
9542                 }
9543
9544                 if ( jQuery.isFunction( size ) ) {
9545                         return this.each(function( i ) {
9546                                 var self = jQuery( this );
9547                                 self[ type ]( size.call( this, i, self[ type ]() ) );
9548                         });
9549                 }
9550
9551                 if ( jQuery.isWindow( elem ) ) {
9552                         // Everyone else use document.documentElement or document.body depending on Quirks vs Standards mode
9553                         // 3rd condition allows Nokia support, as it supports the docElem prop but not CSS1Compat
9554                         var docElemProp = elem.document.documentElement[ "client" + name ];
9555                         return elem.document.compatMode === "CSS1Compat" && docElemProp ||
9556                                 elem.document.body[ "client" + name ] || docElemProp;
9557
9558                 // Get document width or height
9559                 } else if ( elem.nodeType === 9 ) {
9560                         // Either scroll[Width/Height] or offset[Width/Height], whichever is greater
9561                         return Math.max(
9562                                 elem.documentElement["client" + name],
9563                                 elem.body["scroll" + name], elem.documentElement["scroll" + name],
9564                                 elem.body["offset" + name], elem.documentElement["offset" + name]
9565                         );
9566
9567                 // Get or set width or height on the element
9568                 } else if ( size === undefined ) {
9569                         var orig = jQuery.css( elem, type ),
9570                                 ret = parseFloat( orig );
9571
9572                         return jQuery.isNaN( ret ) ? orig : ret;
9573
9574                 // Set the width or height on the element (default to pixels if value is unitless)
9575                 } else {
9576                         return this.css( type, typeof size === "string" ? size : size + "px" );
9577                 }
9578         };
9579
9580 });
9581
9582
9583 window.jQuery = window.$ = jQuery;
9584 })(window);
9585 /*!
9586  * jQuery UI 1.8.12
9587  *
9588  * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
9589  * licensed under MIT 
9590  * http://jquery.org/license
9591  *
9592  * http://docs.jquery.com/UI
9593  */
9594 (function( $, undefined ) {
9595
9596 // prevent duplicate loading
9597 // this is only a problem because we proxy existing functions
9598 // and we don't want to double proxy them
9599 $.ui = $.ui || {};
9600 if ( $.ui.version ) {
9601         return;
9602 }
9603
9604 $.extend( $.ui, {
9605         version: "1.8.12",
9606
9607         keyCode: {
9608                 ALT: 18,
9609                 BACKSPACE: 8,
9610                 CAPS_LOCK: 20,
9611                 COMMA: 188,
9612                 COMMAND: 91,
9613                 COMMAND_LEFT: 91, // COMMAND
9614                 COMMAND_RIGHT: 93,
9615                 CONTROL: 17,
9616                 DELETE: 46,
9617                 DOWN: 40,
9618                 END: 35,
9619                 ENTER: 13,
9620                 ESCAPE: 27,
9621                 HOME: 36,
9622                 INSERT: 45,
9623                 LEFT: 37,
9624                 MENU: 93, // COMMAND_RIGHT
9625                 NUMPAD_ADD: 107,
9626                 NUMPAD_DECIMAL: 110,
9627                 NUMPAD_DIVIDE: 111,
9628                 NUMPAD_ENTER: 108,
9629                 NUMPAD_MULTIPLY: 106,
9630                 NUMPAD_SUBTRACT: 109,
9631                 PAGE_DOWN: 34,
9632                 PAGE_UP: 33,
9633                 PERIOD: 190,
9634                 RIGHT: 39,
9635                 SHIFT: 16,
9636                 SPACE: 32,
9637                 TAB: 9,
9638                 UP: 38,
9639                 WINDOWS: 91 // COMMAND
9640         }
9641 });
9642
9643 // plugins
9644 $.fn.extend({
9645         _focus: $.fn.focus,
9646         focus: function( delay, fn ) {
9647                 return typeof delay === "number" ?
9648                         this.each(function() {
9649                                 var elem = this;
9650                                 setTimeout(function() {
9651                                         $( elem ).focus();
9652                                         if ( fn ) {
9653                                                 fn.call( elem );
9654                                         }
9655                                 }, delay );
9656                         }) :
9657                         this._focus.apply( this, arguments );
9658         },
9659
9660         scrollParent: function() {
9661                 var scrollParent;
9662                 if (($.browser.msie && (/(static|relative)/).test(this.css('position'))) || (/absolute/).test(this.css('position'))) {
9663                         scrollParent = this.parents().filter(function() {
9664                                 return (/(relative|absolute|fixed)/).test($.curCSS(this,'position',1)) && (/(auto|scroll)/).test($.curCSS(this,'overflow',1)+$.curCSS(this,'overflow-y',1)+$.curCSS(this,'overflow-x',1));
9665                         }).eq(0);
9666                 } else {
9667                         scrollParent = this.parents().filter(function() {
9668                                 return (/(auto|scroll)/).test($.curCSS(this,'overflow',1)+$.curCSS(this,'overflow-y',1)+$.curCSS(this,'overflow-x',1));
9669                         }).eq(0);
9670                 }
9671
9672                 return (/fixed/).test(this.css('position')) || !scrollParent.length ? $(document) : scrollParent;
9673         },
9674
9675         zIndex: function( zIndex ) {
9676                 if ( zIndex !== undefined ) {
9677                         return this.css( "zIndex", zIndex );
9678                 }
9679
9680                 if ( this.length ) {
9681                         var elem = $( this[ 0 ] ), position, value;
9682                         while ( elem.length && elem[ 0 ] !== document ) {
9683                                 // Ignore z-index if position is set to a value where z-index is ignored by the browser
9684                                 // This makes behavior of this function consistent across browsers
9685                                 // WebKit always returns auto if the element is positioned
9686                                 position = elem.css( "position" );
9687                                 if ( position === "absolute" || position === "relative" || position === "fixed" ) {
9688                                         // IE returns 0 when zIndex is not specified
9689                                         // other browsers return a string
9690                                         // we ignore the case of nested elements with an explicit value of 0
9691                                         // <div style="z-index: -10;"><div style="z-index: 0;"></div></div>
9692                                         value = parseInt( elem.css( "zIndex" ), 10 );
9693                                         if ( !isNaN( value ) && value !== 0 ) {
9694                                                 return value;
9695                                         }
9696                                 }
9697                                 elem = elem.parent();
9698                         }
9699                 }
9700
9701                 return 0;
9702         },
9703
9704         disableSelection: function() {
9705                 return this.bind( ( $.support.selectstart ? "selectstart" : "mousedown" ) +
9706                         ".ui-disableSelection", function( event ) {
9707                                 event.preventDefault();
9708                         });
9709         },
9710
9711         enableSelection: function() {
9712                 return this.unbind( ".ui-disableSelection" );
9713         }
9714 });
9715
9716 $.each( [ "Width", "Height" ], function( i, name ) {
9717         var side = name === "Width" ? [ "Left", "Right" ] : [ "Top", "Bottom" ],
9718                 type = name.toLowerCase(),
9719                 orig = {
9720                         innerWidth: $.fn.innerWidth,
9721                         innerHeight: $.fn.innerHeight,
9722                         outerWidth: $.fn.outerWidth,
9723                         outerHeight: $.fn.outerHeight
9724                 };
9725
9726         function reduce( elem, size, border, margin ) {
9727                 $.each( side, function() {
9728                         size -= parseFloat( $.curCSS( elem, "padding" + this, true) ) || 0;
9729                         if ( border ) {
9730                                 size -= parseFloat( $.curCSS( elem, "border" + this + "Width", true) ) || 0;
9731                         }
9732                         if ( margin ) {
9733                                 size -= parseFloat( $.curCSS( elem, "margin" + this, true) ) || 0;
9734                         }
9735                 });
9736                 return size;
9737         }
9738
9739         $.fn[ "inner" + name ] = function( size ) {
9740                 if ( size === undefined ) {
9741                         return orig[ "inner" + name ].call( this );
9742                 }
9743
9744                 return this.each(function() {
9745                         $( this ).css( type, reduce( this, size ) + "px" );
9746                 });
9747         };
9748
9749         $.fn[ "outer" + name] = function( size, margin ) {
9750                 if ( typeof size !== "number" ) {
9751                         return orig[ "outer" + name ].call( this, size );
9752                 }
9753
9754                 return this.each(function() {
9755                         $( this).css( type, reduce( this, size, true, margin ) + "px" );
9756                 });
9757         };
9758 });
9759
9760 // selectors
9761 function visible( element ) {
9762         return !$( element ).parents().andSelf().filter(function() {
9763                 return $.curCSS( this, "visibility" ) === "hidden" ||
9764                         $.expr.filters.hidden( this );
9765         }).length;
9766 }
9767
9768 $.extend( $.expr[ ":" ], {
9769         data: function( elem, i, match ) {
9770                 return !!$.data( elem, match[ 3 ] );
9771         },
9772
9773         focusable: function( element ) {
9774                 var nodeName = element.nodeName.toLowerCase(),
9775                         tabIndex = $.attr( element, "tabindex" );
9776                 if ( "area" === nodeName ) {
9777                         var map = element.parentNode,
9778                                 mapName = map.name,
9779                                 img;
9780                         if ( !element.href || !mapName || map.nodeName.toLowerCase() !== "map" ) {
9781                                 return false;
9782                         }
9783                         img = $( "img[usemap=#" + mapName + "]" )[0];
9784                         return !!img && visible( img );
9785                 }
9786                 return ( /input|select|textarea|button|object/.test( nodeName )
9787                         ? !element.disabled
9788                         : "a" == nodeName
9789                                 ? element.href || !isNaN( tabIndex )
9790                                 : !isNaN( tabIndex ))
9791                         // the element and all of its ancestors must be visible
9792                         && visible( element );
9793         },
9794
9795         tabbable: function( element ) {
9796                 var tabIndex = $.attr( element, "tabindex" );
9797                 return ( isNaN( tabIndex ) || tabIndex >= 0 ) && $( element ).is( ":focusable" );
9798         }
9799 });
9800
9801 // support
9802 $(function() {
9803         var body = document.body,
9804                 div = body.appendChild( div = document.createElement( "div" ) );
9805
9806         $.extend( div.style, {
9807                 minHeight: "100px",
9808                 height: "auto",
9809                 padding: 0,
9810                 borderWidth: 0
9811         });
9812
9813         $.support.minHeight = div.offsetHeight === 100;
9814         $.support.selectstart = "onselectstart" in div;
9815
9816         // set display to none to avoid a layout bug in IE
9817         // http://dev.jquery.com/ticket/4014
9818         body.removeChild( div ).style.display = "none";
9819 });
9820
9821
9822
9823
9824
9825 // deprecated
9826 $.extend( $.ui, {
9827         // $.ui.plugin is deprecated.  Use the proxy pattern instead.
9828         plugin: {
9829                 add: function( module, option, set ) {
9830                         var proto = $.ui[ module ].prototype;
9831                         for ( var i in set ) {
9832                                 proto.plugins[ i ] = proto.plugins[ i ] || [];
9833                                 proto.plugins[ i ].push( [ option, set[ i ] ] );
9834                         }
9835                 },
9836                 call: function( instance, name, args ) {
9837                         var set = instance.plugins[ name ];
9838                         if ( !set || !instance.element[ 0 ].parentNode ) {
9839                                 return;
9840                         }
9841         
9842                         for ( var i = 0; i < set.length; i++ ) {
9843                                 if ( instance.options[ set[ i ][ 0 ] ] ) {
9844                                         set[ i ][ 1 ].apply( instance.element, args );
9845                                 }
9846                         }
9847                 }
9848         },
9849         
9850         // will be deprecated when we switch to jQuery 1.4 - use jQuery.contains()
9851         contains: function( a, b ) {
9852                 return document.compareDocumentPosition ?
9853                         a.compareDocumentPosition( b ) & 16 :
9854                         a !== b && a.contains( b );
9855         },
9856         
9857         // only used by resizable
9858         hasScroll: function( el, a ) {
9859         
9860                 //If overflow is hidden, the element might have extra content, but the user wants to hide it
9861                 if ( $( el ).css( "overflow" ) === "hidden") {
9862                         return false;
9863                 }
9864         
9865                 var scroll = ( a && a === "left" ) ? "scrollLeft" : "scrollTop",
9866                         has = false;
9867         
9868                 if ( el[ scroll ] > 0 ) {
9869                         return true;
9870                 }
9871         
9872                 // TODO: determine which cases actually cause this to happen
9873                 // if the element doesn't have the scroll set, see if it's possible to
9874                 // set the scroll
9875                 el[ scroll ] = 1;
9876                 has = ( el[ scroll ] > 0 );
9877                 el[ scroll ] = 0;
9878                 return has;
9879         },
9880         
9881         // these are odd functions, fix the API or move into individual plugins
9882         isOverAxis: function( x, reference, size ) {
9883                 //Determines when x coordinate is over "b" element axis
9884                 return ( x > reference ) && ( x < ( reference + size ) );
9885         },
9886         isOver: function( y, x, top, left, height, width ) {
9887                 //Determines when x, y coordinates is over "b" element
9888                 return $.ui.isOverAxis( y, top, height ) && $.ui.isOverAxis( x, left, width );
9889         }
9890 });
9891
9892 })( jQuery );
9893 /*!
9894  * jQuery UI Widget 1.8.12
9895  *
9896  * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
9897  * Dual licensed under the MIT or GPL Version 2 licenses.
9898  * http://jquery.org/license
9899  *
9900  * http://docs.jquery.com/UI/Widget
9901  */
9902 (function( $, undefined ) {
9903
9904 // jQuery 1.4+
9905 if ( $.cleanData ) {
9906         var _cleanData = $.cleanData;
9907         $.cleanData = function( elems ) {
9908                 for ( var i = 0, elem; (elem = elems[i]) != null; i++ ) {
9909                         $( elem ).triggerHandler( "remove" );
9910                 }
9911                 _cleanData( elems );
9912         };
9913 } else {
9914         var _remove = $.fn.remove;
9915         $.fn.remove = function( selector, keepData ) {
9916                 return this.each(function() {
9917                         if ( !keepData ) {
9918                                 if ( !selector || $.filter( selector, [ this ] ).length ) {
9919                                         $( "*", this ).add( [ this ] ).each(function() {
9920                                                 $( this ).triggerHandler( "remove" );
9921                                         });
9922                                 }
9923                         }
9924                         return _remove.call( $(this), selector, keepData );
9925                 });
9926         };
9927 }
9928
9929 $.widget = function( name, base, prototype ) {
9930         var namespace = name.split( "." )[ 0 ],
9931                 fullName;
9932         name = name.split( "." )[ 1 ];
9933         fullName = namespace + "-" + name;
9934
9935         if ( !prototype ) {
9936                 prototype = base;
9937                 base = $.Widget;
9938         }
9939
9940         // create selector for plugin
9941         $.expr[ ":" ][ fullName ] = function( elem ) {
9942                 return !!$.data( elem, name );
9943         };
9944
9945         $[ namespace ] = $[ namespace ] || {};
9946         $[ namespace ][ name ] = function( options, element ) {
9947                 // allow instantiation without initializing for simple inheritance
9948                 if ( arguments.length ) {
9949                         this._createWidget( options, element );
9950                 }
9951         };
9952
9953         var basePrototype = new base();
9954         // we need to make the options hash a property directly on the new instance
9955         // otherwise we'll modify the options hash on the prototype that we're
9956         // inheriting from
9957 //      $.each( basePrototype, function( key, val ) {
9958 //              if ( $.isPlainObject(val) ) {
9959 //                      basePrototype[ key ] = $.extend( {}, val );
9960 //              }
9961 //      });
9962         basePrototype.options = $.extend( true, {}, basePrototype.options );
9963         $[ namespace ][ name ].prototype = $.extend( true, basePrototype, {
9964                 namespace: namespace,
9965                 widgetName: name,
9966                 widgetEventPrefix: $[ namespace ][ name ].prototype.widgetEventPrefix || name,
9967                 widgetBaseClass: fullName
9968         }, prototype );
9969
9970         $.widget.bridge( name, $[ namespace ][ name ] );
9971 };
9972
9973 $.widget.bridge = function( name, object ) {
9974         $.fn[ name ] = function( options ) {
9975                 var isMethodCall = typeof options === "string",
9976                         args = Array.prototype.slice.call( arguments, 1 ),
9977                         returnValue = this;
9978
9979                 // allow multiple hashes to be passed on init
9980                 options = !isMethodCall && args.length ?
9981                         $.extend.apply( null, [ true, options ].concat(args) ) :
9982                         options;
9983
9984                 // prevent calls to internal methods
9985                 if ( isMethodCall && options.charAt( 0 ) === "_" ) {
9986                         return returnValue;
9987                 }
9988
9989                 if ( isMethodCall ) {
9990                         this.each(function() {
9991                                 var instance = $.data( this, name ),
9992                                         methodValue = instance && $.isFunction( instance[options] ) ?
9993                                                 instance[ options ].apply( instance, args ) :
9994                                                 instance;
9995                                 // TODO: add this back in 1.9 and use $.error() (see #5972)
9996 //                              if ( !instance ) {
9997 //                                      throw "cannot call methods on " + name + " prior to initialization; " +
9998 //                                              "attempted to call method '" + options + "'";
9999 //                              }
10000 //                              if ( !$.isFunction( instance[options] ) ) {
10001 //                                      throw "no such method '" + options + "' for " + name + " widget instance";
10002 //                              }
10003 //                              var methodValue = instance[ options ].apply( instance, args );
10004                                 if ( methodValue !== instance && methodValue !== undefined ) {
10005                                         returnValue = methodValue;
10006                                         return false;
10007                                 }
10008                         });
10009                 } else {
10010                         this.each(function() {
10011                                 var instance = $.data( this, name );
10012                                 if ( instance ) {
10013                                         instance.option( options || {} )._init();
10014                                 } else {
10015                                         $.data( this, name, new object( options, this ) );
10016                                 }
10017                         });
10018                 }
10019
10020                 return returnValue;
10021         };
10022 };
10023
10024 $.Widget = function( options, element ) {
10025         // allow instantiation without initializing for simple inheritance
10026         if ( arguments.length ) {
10027                 this._createWidget( options, element );
10028         }
10029 };
10030
10031 $.Widget.prototype = {
10032         widgetName: "widget",
10033         widgetEventPrefix: "",
10034         options: {
10035                 disabled: false
10036         },
10037         _createWidget: function( options, element ) {
10038                 // $.widget.bridge stores the plugin instance, but we do it anyway
10039                 // so that it's stored even before the _create function runs
10040                 $.data( element, this.widgetName, this );
10041                 this.element = $( element );
10042                 this.options = $.extend( true, {},
10043                         this.options,
10044                         this._getCreateOptions(),
10045                         options );
10046
10047                 var self = this;
10048                 this.element.bind( "remove." + this.widgetName, function() {
10049                         self.destroy();
10050                 });
10051
10052                 this._create();
10053                 this._trigger( "create" );
10054                 this._init();
10055         },
10056         _getCreateOptions: function() {
10057                 return $.metadata && $.metadata.get( this.element[0] )[ this.widgetName ];
10058         },
10059         _create: function() {},
10060         _init: function() {},
10061
10062         destroy: function() {
10063                 this.element
10064                         .unbind( "." + this.widgetName )
10065                         .removeData( this.widgetName );
10066                 this.widget()
10067                         .unbind( "." + this.widgetName )
10068                         .removeAttr( "aria-disabled" )
10069                         .removeClass(
10070                                 this.widgetBaseClass + "-disabled " +
10071                                 "ui-state-disabled" );
10072         },
10073
10074         widget: function() {
10075                 return this.element;
10076         },
10077
10078         option: function( key, value ) {
10079                 var options = key;
10080
10081                 if ( arguments.length === 0 ) {
10082                         // don't return a reference to the internal hash
10083                         return $.extend( {}, this.options );
10084                 }
10085
10086                 if  (typeof key === "string" ) {
10087                         if ( value === undefined ) {
10088                                 return this.options[ key ];
10089                         }
10090                         options = {};
10091                         options[ key ] = value;
10092                 }
10093
10094                 this._setOptions( options );
10095
10096                 return this;
10097         },
10098         _setOptions: function( options ) {
10099                 var self = this;
10100                 $.each( options, function( key, value ) {
10101                         self._setOption( key, value );
10102                 });
10103
10104                 return this;
10105         },
10106         _setOption: function( key, value ) {
10107                 this.options[ key ] = value;
10108
10109                 if ( key === "disabled" ) {
10110                         this.widget()
10111                                 [ value ? "addClass" : "removeClass"](
10112                                         this.widgetBaseClass + "-disabled" + " " +
10113                                         "ui-state-disabled" )
10114                                 .attr( "aria-disabled", value );
10115                 }
10116
10117                 return this;
10118         },
10119
10120         enable: function() {
10121                 return this._setOption( "disabled", false );
10122         },
10123         disable: function() {
10124                 return this._setOption( "disabled", true );
10125         },
10126
10127         _trigger: function( type, event, data ) {
10128                 var callback = this.options[ type ];
10129
10130                 event = $.Event( event );
10131                 event.type = ( type === this.widgetEventPrefix ?
10132                         type :
10133                         this.widgetEventPrefix + type ).toLowerCase();
10134                 data = data || {};
10135
10136                 // copy original event properties over to the new event
10137                 // this would happen if we could call $.event.fix instead of $.Event
10138                 // but we don't have a way to force an event to be fixed multiple times
10139                 if ( event.originalEvent ) {
10140                         for ( var i = $.event.props.length, prop; i; ) {
10141                                 prop = $.event.props[ --i ];
10142                                 event[ prop ] = event.originalEvent[ prop ];
10143                         }
10144                 }
10145
10146                 this.element.trigger( event, data );
10147
10148                 return !( $.isFunction(callback) &&
10149                         callback.call( this.element[0], event, data ) === false ||
10150                         event.isDefaultPrevented() );
10151         }
10152 };
10153
10154 })( jQuery );
10155 /*!
10156  * jQuery UI Mouse 1.8.12
10157  *
10158  * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
10159  * Dual licensed under the MIT or GPL Version 2 licenses.
10160  * http://jquery.org/license
10161  *
10162  * http://docs.jquery.com/UI/Mouse
10163  *
10164  * Depends:
10165  *      jquery.ui.widget.js
10166  */
10167 (function( $, undefined ) {
10168
10169 $.widget("ui.mouse", {
10170         options: {
10171                 cancel: ':input,option',
10172                 distance: 1,
10173                 delay: 0
10174         },
10175         _mouseInit: function() {
10176                 var self = this;
10177
10178                 this.element
10179                         .bind('mousedown.'+this.widgetName, function(event) {
10180                                 return self._mouseDown(event);
10181                         })
10182                         .bind('click.'+this.widgetName, function(event) {
10183                                 if (true === $.data(event.target, self.widgetName + '.preventClickEvent')) {
10184                                     $.removeData(event.target, self.widgetName + '.preventClickEvent');
10185                                         event.stopImmediatePropagation();
10186                                         return false;
10187                                 }
10188                         });
10189
10190                 this.started = false;
10191         },
10192
10193         // TODO: make sure destroying one instance of mouse doesn't mess with
10194         // other instances of mouse
10195         _mouseDestroy: function() {
10196                 this.element.unbind('.'+this.widgetName);
10197         },
10198
10199         _mouseDown: function(event) {
10200                 // don't let more than one widget handle mouseStart
10201                 // TODO: figure out why we have to use originalEvent
10202                 event.originalEvent = event.originalEvent || {};
10203                 if (event.originalEvent.mouseHandled) { return; }
10204
10205                 // we may have missed mouseup (out of window)
10206                 (this._mouseStarted && this._mouseUp(event));
10207
10208                 this._mouseDownEvent = event;
10209
10210                 var self = this,
10211                         btnIsLeft = (event.which == 1),
10212                         elIsCancel = (typeof this.options.cancel == "string" ? $(event.target).parents().add(event.target).filter(this.options.cancel).length : false);
10213                 if (!btnIsLeft || elIsCancel || !this._mouseCapture(event)) {
10214                         return true;
10215                 }
10216
10217                 this.mouseDelayMet = !this.options.delay;
10218                 if (!this.mouseDelayMet) {
10219                         this._mouseDelayTimer = setTimeout(function() {
10220                                 self.mouseDelayMet = true;
10221                         }, this.options.delay);
10222                 }
10223
10224                 if (this._mouseDistanceMet(event) && this._mouseDelayMet(event)) {
10225                         this._mouseStarted = (this._mouseStart(event) !== false);
10226                         if (!this._mouseStarted) {
10227                                 event.preventDefault();
10228                                 return true;
10229                         }
10230                 }
10231
10232                 // Click event may never have fired (Gecko & Opera)
10233                 if (true === $.data(event.target, this.widgetName + '.preventClickEvent')) {
10234                         $.removeData(event.target, this.widgetName + '.preventClickEvent');
10235                 }
10236
10237                 // these delegates are required to keep context
10238                 this._mouseMoveDelegate = function(event) {
10239                         return self._mouseMove(event);
10240                 };
10241                 this._mouseUpDelegate = function(event) {
10242                         return self._mouseUp(event);
10243                 };
10244                 $(document)
10245                         .bind('mousemove.'+this.widgetName, this._mouseMoveDelegate)
10246                         .bind('mouseup.'+this.widgetName, this._mouseUpDelegate);
10247
10248                 event.preventDefault();
10249                 event.originalEvent.mouseHandled = true;
10250                 return true;
10251         },
10252
10253         _mouseMove: function(event) {
10254                 // IE mouseup check - mouseup happened when mouse was out of window
10255                 if ($.browser.msie && !(document.documentMode >= 9) && !event.button) {
10256                         return this._mouseUp(event);
10257                 }
10258
10259                 if (this._mouseStarted) {
10260                         this._mouseDrag(event);
10261                         return event.preventDefault();
10262                 }
10263
10264                 if (this._mouseDistanceMet(event) && this._mouseDelayMet(event)) {
10265                         this._mouseStarted =
10266                                 (this._mouseStart(this._mouseDownEvent, event) !== false);
10267                         (this._mouseStarted ? this._mouseDrag(event) : this._mouseUp(event));
10268                 }
10269
10270                 return !this._mouseStarted;
10271         },
10272
10273         _mouseUp: function(event) {
10274                 $(document)
10275                         .unbind('mousemove.'+this.widgetName, this._mouseMoveDelegate)
10276                         .unbind('mouseup.'+this.widgetName, this._mouseUpDelegate);
10277
10278                 if (this._mouseStarted) {
10279                         this._mouseStarted = false;
10280
10281                         if (event.target == this._mouseDownEvent.target) {
10282                             $.data(event.target, this.widgetName + '.preventClickEvent', true);
10283                         }
10284
10285                         this._mouseStop(event);
10286                 }
10287
10288                 return false;
10289         },
10290
10291         _mouseDistanceMet: function(event) {
10292                 return (Math.max(
10293                                 Math.abs(this._mouseDownEvent.pageX - event.pageX),
10294                                 Math.abs(this._mouseDownEvent.pageY - event.pageY)
10295                         ) >= this.options.distance
10296                 );
10297         },
10298
10299         _mouseDelayMet: function(event) {
10300                 return this.mouseDelayMet;
10301         },
10302
10303         // These are placeholder methods, to be overriden by extending plugin
10304         _mouseStart: function(event) {},
10305         _mouseDrag: function(event) {},
10306         _mouseStop: function(event) {},
10307         _mouseCapture: function(event) { return true; }
10308 });
10309
10310 })(jQuery);
10311 /*
10312  * jQuery UI Draggable 1.8.12
10313  *
10314  * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
10315  * Dual licensed under the MIT or GPL Version 2 licenses.
10316  * http://jquery.org/license
10317  *
10318  * http://docs.jquery.com/UI/Draggables
10319  *
10320  * Depends:
10321  *      jquery.ui.core.js
10322  *      jquery.ui.mouse.js
10323  *      jquery.ui.widget.js
10324  */
10325 (function( $, undefined ) {
10326
10327 $.widget("ui.draggable", $.ui.mouse, {
10328         widgetEventPrefix: "drag",
10329         options: {
10330                 addClasses: true,
10331                 appendTo: "parent",
10332                 axis: false,
10333                 connectToSortable: false,
10334                 containment: false,
10335                 cursor: "auto",
10336                 cursorAt: false,
10337                 grid: false,
10338                 handle: false,
10339                 helper: "original",
10340                 iframeFix: false,
10341                 opacity: false,
10342                 refreshPositions: false,
10343                 revert: false,
10344                 revertDuration: 500,
10345                 scope: "default",
10346                 scroll: true,
10347                 scrollSensitivity: 20,
10348                 scrollSpeed: 20,
10349                 snap: false,
10350                 snapMode: "both",
10351                 snapTolerance: 20,
10352                 stack: false,
10353                 zIndex: false
10354         },
10355         _create: function() {
10356
10357                 if (this.options.helper == 'original' && !(/^(?:r|a|f)/).test(this.element.css("position")))
10358                         this.element[0].style.position = 'relative';
10359
10360                 (this.options.addClasses && this.element.addClass("ui-draggable"));
10361                 (this.options.disabled && this.element.addClass("ui-draggable-disabled"));
10362
10363                 this._mouseInit();
10364
10365         },
10366
10367         destroy: function() {
10368                 if(!this.element.data('draggable')) return;
10369                 this.element
10370                         .removeData("draggable")
10371                         .unbind(".draggable")
10372                         .removeClass("ui-draggable"
10373                                 + " ui-draggable-dragging"
10374                                 + " ui-draggable-disabled");
10375                 this._mouseDestroy();
10376
10377                 return this;
10378         },
10379
10380         _mouseCapture: function(event) {
10381
10382                 var o = this.options;
10383
10384                 // among others, prevent a drag on a resizable-handle
10385                 if (this.helper || o.disabled || $(event.target).is('.ui-resizable-handle'))
10386                         return false;
10387
10388                 //Quit if we're not on a valid handle
10389                 this.handle = this._getHandle(event);
10390                 if (!this.handle)
10391                         return false;
10392
10393                 return true;
10394
10395         },
10396
10397         _mouseStart: function(event) {
10398
10399                 var o = this.options;
10400
10401                 //Create and append the visible helper
10402                 this.helper = this._createHelper(event);
10403
10404                 //Cache the helper size
10405                 this._cacheHelperProportions();
10406
10407                 //If ddmanager is used for droppables, set the global draggable
10408                 if($.ui.ddmanager)
10409                         $.ui.ddmanager.current = this;
10410
10411                 /*
10412                  * - Position generation -
10413                  * This block generates everything position related - it's the core of draggables.
10414                  */
10415
10416                 //Cache the margins of the original element
10417                 this._cacheMargins();
10418
10419                 //Store the helper's css position
10420                 this.cssPosition = this.helper.css("position");
10421                 this.scrollParent = this.helper.scrollParent();
10422
10423                 //The element's absolute position on the page minus margins
10424                 this.offset = this.positionAbs = this.element.offset();
10425                 this.offset = {
10426                         top: this.offset.top - this.margins.top,
10427                         left: this.offset.left - this.margins.left
10428                 };
10429
10430                 $.extend(this.offset, {
10431                         click: { //Where the click happened, relative to the element
10432                                 left: event.pageX - this.offset.left,
10433                                 top: event.pageY - this.offset.top
10434                         },
10435                         parent: this._getParentOffset(),
10436                         relative: this._getRelativeOffset() //This is a relative to absolute position minus the actual position calculation - only used for relative positioned helper
10437                 });
10438
10439                 //Generate the original position
10440                 this.originalPosition = this.position = this._generatePosition(event);
10441                 this.originalPageX = event.pageX;
10442                 this.originalPageY = event.pageY;
10443
10444                 //Adjust the mouse offset relative to the helper if 'cursorAt' is supplied
10445                 (o.cursorAt && this._adjustOffsetFromHelper(o.cursorAt));
10446
10447                 //Set a containment if given in the options
10448                 if(o.containment)
10449                         this._setContainment();
10450
10451                 //Trigger event + callbacks
10452                 if(this._trigger("start", event) === false) {
10453                         this._clear();
10454                         return false;
10455                 }
10456
10457                 //Recache the helper size
10458                 this._cacheHelperProportions();
10459
10460                 //Prepare the droppable offsets
10461                 if ($.ui.ddmanager && !o.dropBehaviour)
10462                         $.ui.ddmanager.prepareOffsets(this, event);
10463
10464                 this.helper.addClass("ui-draggable-dragging");
10465                 this._mouseDrag(event, true); //Execute the drag once - this causes the helper not to be visible before getting its correct position
10466                 return true;
10467         },
10468
10469         _mouseDrag: function(event, noPropagation) {
10470
10471                 //Compute the helpers position
10472                 this.position = this._generatePosition(event);
10473                 this.positionAbs = this._convertPositionTo("absolute");
10474
10475                 //Call plugins and callbacks and use the resulting position if something is returned
10476                 if (!noPropagation) {
10477                         var ui = this._uiHash();
10478                         if(this._trigger('drag', event, ui) === false) {
10479                                 this._mouseUp({});
10480                                 return false;
10481                         }
10482                         this.position = ui.position;
10483                 }
10484
10485                 if(!this.options.axis || this.options.axis != "y") this.helper[0].style.left = this.position.left+'px';
10486                 if(!this.options.axis || this.options.axis != "x") this.helper[0].style.top = this.position.top+'px';
10487                 if($.ui.ddmanager) $.ui.ddmanager.drag(this, event);
10488
10489                 return false;
10490         },
10491
10492         _mouseStop: function(event) {
10493
10494                 //If we are using droppables, inform the manager about the drop
10495                 var dropped = false;
10496                 if ($.ui.ddmanager && !this.options.dropBehaviour)
10497                         dropped = $.ui.ddmanager.drop(this, event);
10498
10499                 //if a drop comes from outside (a sortable)
10500                 if(this.dropped) {
10501                         dropped = this.dropped;
10502                         this.dropped = false;
10503                 }
10504                 
10505                 //if the original element is removed, don't bother to continue if helper is set to "original"
10506                 if((!this.element[0] || !this.element[0].parentNode) && this.options.helper == "original")
10507                         return false;
10508
10509                 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))) {
10510                         var self = this;
10511                         $(this.helper).animate(this.originalPosition, parseInt(this.options.revertDuration, 10), function() {
10512                                 if(self._trigger("stop", event) !== false) {
10513                                         self._clear();
10514                                 }
10515                         });
10516                 } else {
10517                         if(this._trigger("stop", event) !== false) {
10518                                 this._clear();
10519                         }
10520                 }
10521
10522                 return false;
10523         },
10524         
10525         cancel: function() {
10526                 
10527                 if(this.helper.is(".ui-draggable-dragging")) {
10528                         this._mouseUp({});
10529                 } else {
10530                         this._clear();
10531                 }
10532                 
10533                 return this;
10534                 
10535         },
10536
10537         _getHandle: function(event) {
10538
10539                 var handle = !this.options.handle || !$(this.options.handle, this.element).length ? true : false;
10540                 $(this.options.handle, this.element)
10541                         .find("*")
10542                         .andSelf()
10543                         .each(function() {
10544                                 if(this == event.target) handle = true;
10545                         });
10546
10547                 return handle;
10548
10549         },
10550
10551         _createHelper: function(event) {
10552
10553                 var o = this.options;
10554                 var helper = $.isFunction(o.helper) ? $(o.helper.apply(this.element[0], [event])) : (o.helper == 'clone' ? this.element.clone() : this.element);
10555
10556                 if(!helper.parents('body').length)
10557                         helper.appendTo((o.appendTo == 'parent' ? this.element[0].parentNode : o.appendTo));
10558
10559                 if(helper[0] != this.element[0] && !(/(fixed|absolute)/).test(helper.css("position")))
10560                         helper.css("position", "absolute");
10561
10562                 return helper;
10563
10564         },
10565
10566         _adjustOffsetFromHelper: function(obj) {
10567                 if (typeof obj == 'string') {
10568                         obj = obj.split(' ');
10569                 }
10570                 if ($.isArray(obj)) {
10571                         obj = {left: +obj[0], top: +obj[1] || 0};
10572                 }
10573                 if ('left' in obj) {
10574                         this.offset.click.left = obj.left + this.margins.left;
10575                 }
10576                 if ('right' in obj) {
10577                         this.offset.click.left = this.helperProportions.width - obj.right + this.margins.left;
10578                 }
10579                 if ('top' in obj) {
10580                         this.offset.click.top = obj.top + this.margins.top;
10581                 }
10582                 if ('bottom' in obj) {
10583                         this.offset.click.top = this.helperProportions.height - obj.bottom + this.margins.top;
10584                 }
10585         },
10586
10587         _getParentOffset: function() {
10588
10589                 //Get the offsetParent and cache its position
10590                 this.offsetParent = this.helper.offsetParent();
10591                 var po = this.offsetParent.offset();
10592
10593                 // This is a special case where we need to modify a offset calculated on start, since the following happened:
10594                 // 1. The position of the helper is absolute, so it's position is calculated based on the next positioned parent
10595                 // 2. The actual offset parent is a child of the scroll parent, and the scroll parent isn't the document, which means that
10596                 //    the scroll is included in the initial calculation of the offset of the parent, and never recalculated upon drag
10597                 if(this.cssPosition == 'absolute' && this.scrollParent[0] != document && $.ui.contains(this.scrollParent[0], this.offsetParent[0])) {
10598                         po.left += this.scrollParent.scrollLeft();
10599                         po.top += this.scrollParent.scrollTop();
10600                 }
10601
10602                 if((this.offsetParent[0] == document.body) //This needs to be actually done for all browsers, since pageX/pageY includes this information
10603                 || (this.offsetParent[0].tagName && this.offsetParent[0].tagName.toLowerCase() == 'html' && $.browser.msie)) //Ugly IE fix
10604                         po = { top: 0, left: 0 };
10605
10606                 return {
10607                         top: po.top + (parseInt(this.offsetParent.css("borderTopWidth"),10) || 0),
10608                         left: po.left + (parseInt(this.offsetParent.css("borderLeftWidth"),10) || 0)
10609                 };
10610
10611         },
10612
10613         _getRelativeOffset: function() {
10614
10615                 if(this.cssPosition == "relative") {
10616                         var p = this.element.position();
10617                         return {
10618                                 top: p.top - (parseInt(this.helper.css("top"),10) || 0) + this.scrollParent.scrollTop(),
10619                                 left: p.left - (parseInt(this.helper.css("left"),10) || 0) + this.scrollParent.scrollLeft()
10620                         };
10621                 } else {
10622                         return { top: 0, left: 0 };
10623                 }
10624
10625         },
10626
10627         _cacheMargins: function() {
10628                 this.margins = {
10629                         left: (parseInt(this.element.css("marginLeft"),10) || 0),
10630                         top: (parseInt(this.element.css("marginTop"),10) || 0),
10631                         right: (parseInt(this.element.css("marginRight"),10) || 0),
10632                         bottom: (parseInt(this.element.css("marginBottom"),10) || 0)
10633                 };
10634         },
10635
10636         _cacheHelperProportions: function() {
10637                 this.helperProportions = {
10638                         width: this.helper.outerWidth(),
10639                         height: this.helper.outerHeight()
10640                 };
10641         },
10642
10643         _setContainment: function() {
10644
10645                 var o = this.options;
10646                 if(o.containment == 'parent') o.containment = this.helper[0].parentNode;
10647                 if(o.containment == 'document' || o.containment == 'window') this.containment = [
10648                         (o.containment == 'document' ? 0 : $(window).scrollLeft()) - this.offset.relative.left - this.offset.parent.left,
10649                         (o.containment == 'document' ? 0 : $(window).scrollTop()) - this.offset.relative.top - this.offset.parent.top,
10650                         (o.containment == 'document' ? 0 : $(window).scrollLeft()) + $(o.containment == 'document' ? document : window).width() - this.helperProportions.width - this.margins.left,
10651                         (o.containment == 'document' ? 0 : $(window).scrollTop()) + ($(o.containment == 'document' ? document : window).height() || document.body.parentNode.scrollHeight) - this.helperProportions.height - this.margins.top
10652                 ];
10653
10654                 if(!(/^(document|window|parent)$/).test(o.containment) && o.containment.constructor != Array) {
10655                         var ce = $(o.containment)[0]; if(!ce) return;
10656                         var co = $(o.containment).offset();
10657                         var over = ($(ce).css("overflow") != 'hidden');
10658
10659                         this.containment = [
10660                                 co.left + (parseInt($(ce).css("borderLeftWidth"),10) || 0) + (parseInt($(ce).css("paddingLeft"),10) || 0),
10661                                 co.top + (parseInt($(ce).css("borderTopWidth"),10) || 0) + (parseInt($(ce).css("paddingTop"),10) || 0),
10662                                 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 - this.margins.right,
10663                                 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  - this.margins.bottom
10664                         ];
10665                 } else if(o.containment.constructor == Array) {
10666                         this.containment = o.containment;
10667                 }
10668
10669         },
10670
10671         _convertPositionTo: function(d, pos) {
10672
10673                 if(!pos) pos = this.position;
10674                 var mod = d == "absolute" ? 1 : -1;
10675                 var o = this.options, scroll = this.cssPosition == 'absolute' && !(this.scrollParent[0] != document && $.ui.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent, scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName);
10676
10677                 return {
10678                         top: (
10679                                 pos.top                                                                                                                                 // The absolute mouse position
10680                                 + this.offset.relative.top * mod                                                                                // Only for relative positioned nodes: Relative offset from element to offset parent
10681                                 + this.offset.parent.top * mod                                                                                  // The offsetParent's offset without borders (offset + border)
10682                                 - ($.browser.safari && $.browser.version < 526 && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ) * mod)
10683                         ),
10684                         left: (
10685                                 pos.left                                                                                                                                // The absolute mouse position
10686                                 + this.offset.relative.left * mod                                                                               // Only for relative positioned nodes: Relative offset from element to offset parent
10687                                 + this.offset.parent.left * mod                                                                                 // The offsetParent's offset without borders (offset + border)
10688                                 - ($.browser.safari && $.browser.version < 526 && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ) * mod)
10689                         )
10690                 };
10691
10692         },
10693
10694         _generatePosition: function(event) {
10695
10696                 var o = this.options, scroll = this.cssPosition == 'absolute' && !(this.scrollParent[0] != document && $.ui.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent, scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName);
10697                 var pageX = event.pageX;
10698                 var pageY = event.pageY;
10699
10700                 /*
10701                  * - Position constraining -
10702                  * Constrain the position to a mix of grid, containment.
10703                  */
10704
10705                 if(this.originalPosition) { //If we are not dragging yet, we won't check for options
10706
10707                         if(this.containment) {
10708                                 if(event.pageX - this.offset.click.left < this.containment[0]) pageX = this.containment[0] + this.offset.click.left;
10709                                 if(event.pageY - this.offset.click.top < this.containment[1]) pageY = this.containment[1] + this.offset.click.top;
10710                                 if(event.pageX - this.offset.click.left > this.containment[2]) pageX = this.containment[2] + this.offset.click.left;
10711                                 if(event.pageY - this.offset.click.top > this.containment[3]) pageY = this.containment[3] + this.offset.click.top;
10712                         }
10713
10714                         if(o.grid) {
10715                                 var top = this.originalPageY + Math.round((pageY - this.originalPageY) / o.grid[1]) * o.grid[1];
10716                                 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;
10717
10718                                 var left = this.originalPageX + Math.round((pageX - this.originalPageX) / o.grid[0]) * o.grid[0];
10719                                 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;
10720                         }
10721
10722                 }
10723
10724                 return {
10725                         top: (
10726                                 pageY                                                                                                                           // The absolute mouse position
10727                                 - this.offset.click.top                                                                                                 // Click offset (relative to the element)
10728                                 - this.offset.relative.top                                                                                              // Only for relative positioned nodes: Relative offset from element to offset parent
10729                                 - this.offset.parent.top                                                                                                // The offsetParent's offset without borders (offset + border)
10730                                 + ($.browser.safari && $.browser.version < 526 && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ))
10731                         ),
10732                         left: (
10733                                 pageX                                                                                                                           // The absolute mouse position
10734                                 - this.offset.click.left                                                                                                // Click offset (relative to the element)
10735                                 - this.offset.relative.left                                                                                             // Only for relative positioned nodes: Relative offset from element to offset parent
10736                                 - this.offset.parent.left                                                                                               // The offsetParent's offset without borders (offset + border)
10737                                 + ($.browser.safari && $.browser.version < 526 && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ))
10738                         )
10739                 };
10740
10741         },
10742
10743         _clear: function() {
10744                 this.helper.removeClass("ui-draggable-dragging");
10745                 if(this.helper[0] != this.element[0] && !this.cancelHelperRemoval) this.helper.remove();
10746                 //if($.ui.ddmanager) $.ui.ddmanager.current = null;
10747                 this.helper = null;
10748                 this.cancelHelperRemoval = false;
10749         },
10750
10751         // From now on bulk stuff - mainly helpers
10752
10753         _trigger: function(type, event, ui) {
10754                 ui = ui || this._uiHash();
10755                 $.ui.plugin.call(this, type, [event, ui]);
10756                 if(type == "drag") this.positionAbs = this._convertPositionTo("absolute"); //The absolute position has to be recalculated after plugins
10757                 return $.Widget.prototype._trigger.call(this, type, event, ui);
10758         },
10759
10760         plugins: {},
10761
10762         _uiHash: function(event) {
10763                 return {
10764                         helper: this.helper,
10765                         position: this.position,
10766                         originalPosition: this.originalPosition,
10767                         offset: this.positionAbs
10768                 };
10769         }
10770
10771 });
10772
10773 $.extend($.ui.draggable, {
10774         version: "1.8.12"
10775 });
10776
10777 $.ui.plugin.add("draggable", "connectToSortable", {
10778         start: function(event, ui) {
10779
10780                 var inst = $(this).data("draggable"), o = inst.options,
10781                         uiSortable = $.extend({}, ui, { item: inst.element });
10782                 inst.sortables = [];
10783                 $(o.connectToSortable).each(function() {
10784                         var sortable = $.data(this, 'sortable');
10785                         if (sortable && !sortable.options.disabled) {
10786                                 inst.sortables.push({
10787                                         instance: sortable,
10788                                         shouldRevert: sortable.options.revert
10789                                 });
10790                                 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).
10791                                 sortable._trigger("activate", event, uiSortable);
10792                         }
10793                 });
10794
10795         },
10796         stop: function(event, ui) {
10797
10798                 //If we are still over the sortable, we fake the stop event of the sortable, but also remove helper
10799                 var inst = $(this).data("draggable"),
10800                         uiSortable = $.extend({}, ui, { item: inst.element });
10801
10802                 $.each(inst.sortables, function() {
10803                         if(this.instance.isOver) {
10804
10805                                 this.instance.isOver = 0;
10806
10807                                 inst.cancelHelperRemoval = true; //Don't remove the helper in the draggable instance
10808                                 this.instance.cancelHelperRemoval = false; //Remove it in the sortable instance (so sortable plugins like revert still work)
10809
10810                                 //The sortable revert is supported, and we have to set a temporary dropped variable on the draggable to support revert: 'valid/invalid'
10811                                 if(this.shouldRevert) this.instance.options.revert = true;
10812
10813                                 //Trigger the stop of the sortable
10814                                 this.instance._mouseStop(event);
10815
10816                                 this.instance.options.helper = this.instance.options._helper;
10817
10818                                 //If the helper has been the original item, restore properties in the sortable
10819                                 if(inst.options.helper == 'original')
10820                                         this.instance.currentItem.css({ top: 'auto', left: 'auto' });
10821
10822                         } else {
10823                                 this.instance.cancelHelperRemoval = false; //Remove the helper in the sortable instance
10824                                 this.instance._trigger("deactivate", event, uiSortable);
10825                         }
10826
10827                 });
10828
10829         },
10830         drag: function(event, ui) {
10831
10832                 var inst = $(this).data("draggable"), self = this;
10833
10834                 var checkPos = function(o) {
10835                         var dyClick = this.offset.click.top, dxClick = this.offset.click.left;
10836                         var helperTop = this.positionAbs.top, helperLeft = this.positionAbs.left;
10837                         var itemHeight = o.height, itemWidth = o.width;
10838                         var itemTop = o.top, itemLeft = o.left;
10839
10840                         return $.ui.isOver(helperTop + dyClick, helperLeft + dxClick, itemTop, itemLeft, itemHeight, itemWidth);
10841                 };
10842
10843                 $.each(inst.sortables, function(i) {
10844                         
10845                         //Copy over some variables to allow calling the sortable's native _intersectsWith
10846                         this.instance.positionAbs = inst.positionAbs;
10847                         this.instance.helperProportions = inst.helperProportions;
10848                         this.instance.offset.click = inst.offset.click;
10849                         
10850                         if(this.instance._intersectsWith(this.instance.containerCache)) {
10851
10852                                 //If it intersects, we use a little isOver variable and set it once, so our move-in stuff gets fired only once
10853                                 if(!this.instance.isOver) {
10854
10855                                         this.instance.isOver = 1;
10856                                         //Now we fake the start of dragging for the sortable instance,
10857                                         //by cloning the list group item, appending it to the sortable and using it as inst.currentItem
10858                                         //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)
10859                                         this.instance.currentItem = $(self).clone().appendTo(this.instance.element).data("sortable-item", true);
10860                                         this.instance.options._helper = this.instance.options.helper; //Store helper option to later restore it
10861                                         this.instance.options.helper = function() { return ui.helper[0]; };
10862
10863                                         event.target = this.instance.currentItem[0];
10864                                         this.instance._mouseCapture(event, true);
10865                                         this.instance._mouseStart(event, true, true);
10866
10867                                         //Because the browser event is way off the new appended portlet, we modify a couple of variables to reflect the changes
10868                                         this.instance.offset.click.top = inst.offset.click.top;
10869                                         this.instance.offset.click.left = inst.offset.click.left;
10870                                         this.instance.offset.parent.left -= inst.offset.parent.left - this.instance.offset.parent.left;
10871                                         this.instance.offset.parent.top -= inst.offset.parent.top - this.instance.offset.parent.top;
10872
10873                                         inst._trigger("toSortable", event);
10874                                         inst.dropped = this.instance.element; //draggable revert needs that
10875                                         //hack so receive/update callbacks work (mostly)
10876                                         inst.currentItem = inst.element;
10877                                         this.instance.fromOutside = inst;
10878
10879                                 }
10880
10881                                 //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
10882                                 if(this.instance.currentItem) this.instance._mouseDrag(event);
10883
10884                         } else {
10885
10886                                 //If it doesn't intersect with the sortable, and it intersected before,
10887                                 //we fake the drag stop of the sortable, but make sure it doesn't remove the helper by using cancelHelperRemoval
10888                                 if(this.instance.isOver) {
10889
10890                                         this.instance.isOver = 0;
10891                                         this.instance.cancelHelperRemoval = true;
10892                                         
10893                                         //Prevent reverting on this forced stop
10894                                         this.instance.options.revert = false;
10895                                         
10896                                         // The out event needs to be triggered independently
10897                                         this.instance._trigger('out', event, this.instance._uiHash(this.instance));
10898                                         
10899                                         this.instance._mouseStop(event, true);
10900                                         this.instance.options.helper = this.instance.options._helper;
10901
10902                                         //Now we remove our currentItem, the list group clone again, and the placeholder, and animate the helper back to it's original size
10903                                         this.instance.currentItem.remove();
10904                                         if(this.instance.placeholder) this.instance.placeholder.remove();
10905
10906                                         inst._trigger("fromSortable", event);
10907                                         inst.dropped = false; //draggable revert needs that
10908                                 }
10909
10910                         };
10911
10912                 });
10913
10914         }
10915 });
10916
10917 $.ui.plugin.add("draggable", "cursor", {
10918         start: function(event, ui) {
10919                 var t = $('body'), o = $(this).data('draggable').options;
10920                 if (t.css("cursor")) o._cursor = t.css("cursor");
10921                 t.css("cursor", o.cursor);
10922         },
10923         stop: function(event, ui) {
10924                 var o = $(this).data('draggable').options;
10925                 if (o._cursor) $('body').css("cursor", o._cursor);
10926         }
10927 });
10928
10929 $.ui.plugin.add("draggable", "iframeFix", {
10930         start: function(event, ui) {
10931                 var o = $(this).data('draggable').options;
10932                 $(o.iframeFix === true ? "iframe" : o.iframeFix).each(function() {
10933                         $('<div class="ui-draggable-iframeFix" style="background: #fff;"></div>')
10934                         .css({
10935                                 width: this.offsetWidth+"px", height: this.offsetHeight+"px",
10936                                 position: "absolute", opacity: "0.001", zIndex: 1000
10937                         })
10938                         .css($(this).offset())
10939                         .appendTo("body");
10940                 });
10941         },
10942         stop: function(event, ui) {
10943                 $("div.ui-draggable-iframeFix").each(function() { this.parentNode.removeChild(this); }); //Remove frame helpers
10944         }
10945 });
10946
10947 $.ui.plugin.add("draggable", "opacity", {
10948         start: function(event, ui) {
10949                 var t = $(ui.helper), o = $(this).data('draggable').options;
10950                 if(t.css("opacity")) o._opacity = t.css("opacity");
10951                 t.css('opacity', o.opacity);
10952         },
10953         stop: function(event, ui) {
10954                 var o = $(this).data('draggable').options;
10955                 if(o._opacity) $(ui.helper).css('opacity', o._opacity);
10956         }
10957 });
10958
10959 $.ui.plugin.add("draggable", "scroll", {
10960         start: function(event, ui) {
10961                 var i = $(this).data("draggable");
10962                 if(i.scrollParent[0] != document && i.scrollParent[0].tagName != 'HTML') i.overflowOffset = i.scrollParent.offset();
10963         },
10964         drag: function(event, ui) {
10965
10966                 var i = $(this).data("draggable"), o = i.options, scrolled = false;
10967
10968                 if(i.scrollParent[0] != document && i.scrollParent[0].tagName != 'HTML') {
10969
10970                         if(!o.axis || o.axis != 'x') {
10971                                 if((i.overflowOffset.top + i.scrollParent[0].offsetHeight) - event.pageY < o.scrollSensitivity)
10972                                         i.scrollParent[0].scrollTop = scrolled = i.scrollParent[0].scrollTop + o.scrollSpeed;
10973                                 else if(event.pageY - i.overflowOffset.top < o.scrollSensitivity)
10974                                         i.scrollParent[0].scrollTop = scrolled = i.scrollParent[0].scrollTop - o.scrollSpeed;
10975                         }
10976
10977                         if(!o.axis || o.axis != 'y') {
10978                                 if((i.overflowOffset.left + i.scrollParent[0].offsetWidth) - event.pageX < o.scrollSensitivity)
10979                                         i.scrollParent[0].scrollLeft = scrolled = i.scrollParent[0].scrollLeft + o.scrollSpeed;
10980                                 else if(event.pageX - i.overflowOffset.left < o.scrollSensitivity)
10981                                         i.scrollParent[0].scrollLeft = scrolled = i.scrollParent[0].scrollLeft - o.scrollSpeed;
10982                         }
10983
10984                 } else {
10985
10986                         if(!o.axis || o.axis != 'x') {
10987                                 if(event.pageY - $(document).scrollTop() < o.scrollSensitivity)
10988                                         scrolled = $(document).scrollTop($(document).scrollTop() - o.scrollSpeed);
10989                                 else if($(window).height() - (event.pageY - $(document).scrollTop()) < o.scrollSensitivity)
10990                                         scrolled = $(document).scrollTop($(document).scrollTop() + o.scrollSpeed);
10991                         }
10992
10993                         if(!o.axis || o.axis != 'y') {
10994                                 if(event.pageX - $(document).scrollLeft() < o.scrollSensitivity)
10995                                         scrolled = $(document).scrollLeft($(document).scrollLeft() - o.scrollSpeed);
10996                                 else if($(window).width() - (event.pageX - $(document).scrollLeft()) < o.scrollSensitivity)
10997                                         scrolled = $(document).scrollLeft($(document).scrollLeft() + o.scrollSpeed);
10998                         }
10999
11000                 }
11001
11002                 if(scrolled !== false && $.ui.ddmanager && !o.dropBehaviour)
11003                         $.ui.ddmanager.prepareOffsets(i, event);
11004
11005         }
11006 });
11007
11008 $.ui.plugin.add("draggable", "snap", {
11009         start: function(event, ui) {
11010
11011                 var i = $(this).data("draggable"), o = i.options;
11012                 i.snapElements = [];
11013
11014                 $(o.snap.constructor != String ? ( o.snap.items || ':data(draggable)' ) : o.snap).each(function() {
11015                         var $t = $(this); var $o = $t.offset();
11016                         if(this != i.element[0]) i.snapElements.push({
11017                                 item: this,
11018                                 width: $t.outerWidth(), height: $t.outerHeight(),
11019                                 top: $o.top, left: $o.left
11020                         });
11021                 });
11022
11023         },
11024         drag: function(event, ui) {
11025
11026                 var inst = $(this).data("draggable"), o = inst.options;
11027                 var d = o.snapTolerance;
11028
11029                 var x1 = ui.offset.left, x2 = x1 + inst.helperProportions.width,
11030                         y1 = ui.offset.top, y2 = y1 + inst.helperProportions.height;
11031
11032                 for (var i = inst.snapElements.length - 1; i >= 0; i--){
11033
11034                         var l = inst.snapElements[i].left, r = l + inst.snapElements[i].width,
11035                                 t = inst.snapElements[i].top, b = t + inst.snapElements[i].height;
11036
11037                         //Yes, I know, this is insane ;)
11038                         if(!((l-d < x1 && x1 < r+d && t-d < y1 && y1 < b+d) || (l-d < x1 && x1 < r+d && t-d < y2 && y2 < b+d) || (l-d < x2 && x2 < r+d && t-d < y1 && y1 < b+d) || (l-d < x2 && x2 < r+d && t-d < y2 && y2 < b+d))) {
11039                                 if(inst.snapElements[i].snapping) (inst.options.snap.release && inst.options.snap.release.call(inst.element, event, $.extend(inst._uiHash(), { snapItem: inst.snapElements[i].item })));
11040                                 inst.snapElements[i].snapping = false;
11041                                 continue;
11042                         }
11043
11044                         if(o.snapMode != 'inner') {
11045                                 var ts = Math.abs(t - y2) <= d;
11046                                 var bs = Math.abs(b - y1) <= d;
11047                                 var ls = Math.abs(l - x2) <= d;
11048                                 var rs = Math.abs(r - x1) <= d;
11049                                 if(ts) ui.position.top = inst._convertPositionTo("relative", { top: t - inst.helperProportions.height, left: 0 }).top - inst.margins.top;
11050                                 if(bs) ui.position.top = inst._convertPositionTo("relative", { top: b, left: 0 }).top - inst.margins.top;
11051                                 if(ls) ui.position.left = inst._convertPositionTo("relative", { top: 0, left: l - inst.helperProportions.width }).left - inst.margins.left;
11052                                 if(rs) ui.position.left = inst._convertPositionTo("relative", { top: 0, left: r }).left - inst.margins.left;
11053                         }
11054
11055                         var first = (ts || bs || ls || rs);
11056
11057                         if(o.snapMode != 'outer') {
11058                                 var ts = Math.abs(t - y1) <= d;
11059                                 var bs = Math.abs(b - y2) <= d;
11060                                 var ls = Math.abs(l - x1) <= d;
11061                                 var rs = Math.abs(r - x2) <= d;
11062                                 if(ts) ui.position.top = inst._convertPositionTo("relative", { top: t, left: 0 }).top - inst.margins.top;
11063                                 if(bs) ui.position.top = inst._convertPositionTo("relative", { top: b - inst.helperProportions.height, left: 0 }).top - inst.margins.top;
11064                                 if(ls) ui.position.left = inst._convertPositionTo("relative", { top: 0, left: l }).left - inst.margins.left;
11065                                 if(rs) ui.position.left = inst._convertPositionTo("relative", { top: 0, left: r - inst.helperProportions.width }).left - inst.margins.left;
11066                         }
11067
11068                         if(!inst.snapElements[i].snapping && (ts || bs || ls || rs || first))
11069                                 (inst.options.snap.snap && inst.options.snap.snap.call(inst.element, event, $.extend(inst._uiHash(), { snapItem: inst.snapElements[i].item })));
11070                         inst.snapElements[i].snapping = (ts || bs || ls || rs || first);
11071
11072                 };
11073
11074         }
11075 });
11076
11077 $.ui.plugin.add("draggable", "stack", {
11078         start: function(event, ui) {
11079
11080                 var o = $(this).data("draggable").options;
11081
11082                 var group = $.makeArray($(o.stack)).sort(function(a,b) {
11083                         return (parseInt($(a).css("zIndex"),10) || 0) - (parseInt($(b).css("zIndex"),10) || 0);
11084                 });
11085                 if (!group.length) { return; }
11086                 
11087                 var min = parseInt(group[0].style.zIndex) || 0;
11088                 $(group).each(function(i) {
11089                         this.style.zIndex = min + i;
11090                 });
11091
11092                 this[0].style.zIndex = min + group.length;
11093
11094         }
11095 });
11096
11097 $.ui.plugin.add("draggable", "zIndex", {
11098         start: function(event, ui) {
11099                 var t = $(ui.helper), o = $(this).data("draggable").options;
11100                 if(t.css("zIndex")) o._zIndex = t.css("zIndex");
11101                 t.css('zIndex', o.zIndex);
11102         },
11103         stop: function(event, ui) {
11104                 var o = $(this).data("draggable").options;
11105                 if(o._zIndex) $(ui.helper).css('zIndex', o._zIndex);
11106         }
11107 });
11108
11109 })(jQuery);
11110 /*
11111  * jQuery UI Droppable 1.8.12
11112  *
11113  * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
11114  * Dual licensed under the MIT or GPL Version 2 licenses.
11115  * http://jquery.org/license
11116  *
11117  * http://docs.jquery.com/UI/Droppables
11118  *
11119  * Depends:
11120  *      jquery.ui.core.js
11121  *      jquery.ui.widget.js
11122  *      jquery.ui.mouse.js
11123  *      jquery.ui.draggable.js
11124  */
11125 (function( $, undefined ) {
11126
11127 $.widget("ui.droppable", {
11128         widgetEventPrefix: "drop",
11129         options: {
11130                 accept: '*',
11131                 activeClass: false,
11132                 addClasses: true,
11133                 greedy: false,
11134                 hoverClass: false,
11135                 scope: 'default',
11136                 tolerance: 'intersect'
11137         },
11138         _create: function() {
11139
11140                 var o = this.options, accept = o.accept;
11141                 this.isover = 0; this.isout = 1;
11142
11143                 this.accept = $.isFunction(accept) ? accept : function(d) {
11144                         return d.is(accept);
11145                 };
11146
11147                 //Store the droppable's proportions
11148                 this.proportions = { width: this.element[0].offsetWidth, height: this.element[0].offsetHeight };
11149
11150                 // Add the reference and positions to the manager
11151                 $.ui.ddmanager.droppables[o.scope] = $.ui.ddmanager.droppables[o.scope] || [];
11152                 $.ui.ddmanager.droppables[o.scope].push(this);
11153
11154                 (o.addClasses && this.element.addClass("ui-droppable"));
11155
11156         },
11157
11158         destroy: function() {
11159                 var drop = $.ui.ddmanager.droppables[this.options.scope];
11160                 for ( var i = 0; i < drop.length; i++ )
11161                         if ( drop[i] == this )
11162                                 drop.splice(i, 1);
11163
11164                 this.element
11165                         .removeClass("ui-droppable ui-droppable-disabled")
11166                         .removeData("droppable")
11167                         .unbind(".droppable");
11168
11169                 return this;
11170         },
11171
11172         _setOption: function(key, value) {
11173
11174                 if(key == 'accept') {
11175                         this.accept = $.isFunction(value) ? value : function(d) {
11176                                 return d.is(value);
11177                         };
11178                 }
11179                 $.Widget.prototype._setOption.apply(this, arguments);
11180         },
11181
11182         _activate: function(event) {
11183                 var draggable = $.ui.ddmanager.current;
11184                 if(this.options.activeClass) this.element.addClass(this.options.activeClass);
11185                 (draggable && this._trigger('activate', event, this.ui(draggable)));
11186         },
11187
11188         _deactivate: function(event) {
11189                 var draggable = $.ui.ddmanager.current;
11190                 if(this.options.activeClass) this.element.removeClass(this.options.activeClass);
11191                 (draggable && this._trigger('deactivate', event, this.ui(draggable)));
11192         },
11193
11194         _over: function(event) {
11195
11196                 var draggable = $.ui.ddmanager.current;
11197                 if (!draggable || (draggable.currentItem || draggable.element)[0] == this.element[0]) return; // Bail if draggable and droppable are same element
11198
11199                 if (this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) {
11200                         if(this.options.hoverClass) this.element.addClass(this.options.hoverClass);
11201                         this._trigger('over', event, this.ui(draggable));
11202                 }
11203
11204         },
11205
11206         _out: function(event) {
11207
11208                 var draggable = $.ui.ddmanager.current;
11209                 if (!draggable || (draggable.currentItem || draggable.element)[0] == this.element[0]) return; // Bail if draggable and droppable are same element
11210
11211                 if (this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) {
11212                         if(this.options.hoverClass) this.element.removeClass(this.options.hoverClass);
11213                         this._trigger('out', event, this.ui(draggable));
11214                 }
11215
11216         },
11217
11218         _drop: function(event,custom) {
11219
11220                 var draggable = custom || $.ui.ddmanager.current;
11221                 if (!draggable || (draggable.currentItem || draggable.element)[0] == this.element[0]) return false; // Bail if draggable and droppable are same element
11222
11223                 var childrenIntersection = false;
11224                 this.element.find(":data(droppable)").not(".ui-draggable-dragging").each(function() {
11225                         var inst = $.data(this, 'droppable');
11226                         if(
11227                                 inst.options.greedy
11228                                 && !inst.options.disabled
11229                                 && inst.options.scope == draggable.options.scope
11230                                 && inst.accept.call(inst.element[0], (draggable.currentItem || draggable.element))
11231                                 && $.ui.intersect(draggable, $.extend(inst, { offset: inst.element.offset() }), inst.options.tolerance)
11232                         ) { childrenIntersection = true; return false; }
11233                 });
11234                 if(childrenIntersection) return false;
11235
11236                 if(this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) {
11237                         if(this.options.activeClass) this.element.removeClass(this.options.activeClass);
11238                         if(this.options.hoverClass) this.element.removeClass(this.options.hoverClass);
11239                         this._trigger('drop', event, this.ui(draggable));
11240                         return this.element;
11241                 }
11242
11243                 return false;
11244
11245         },
11246
11247         ui: function(c) {
11248                 return {
11249                         draggable: (c.currentItem || c.element),
11250                         helper: c.helper,
11251                         position: c.position,
11252                         offset: c.positionAbs
11253                 };
11254         }
11255
11256 });
11257
11258 $.extend($.ui.droppable, {
11259         version: "1.8.12"
11260 });
11261
11262 $.ui.intersect = function(draggable, droppable, toleranceMode) {
11263
11264         if (!droppable.offset) return false;
11265
11266         var x1 = (draggable.positionAbs || draggable.position.absolute).left, x2 = x1 + draggable.helperProportions.width,
11267                 y1 = (draggable.positionAbs || draggable.position.absolute).top, y2 = y1 + draggable.helperProportions.height;
11268         var l = droppable.offset.left, r = l + droppable.proportions.width,
11269                 t = droppable.offset.top, b = t + droppable.proportions.height;
11270
11271         switch (toleranceMode) {
11272                 case 'fit':
11273                         return (l <= x1 && x2 <= r
11274                                 && t <= y1 && y2 <= b);
11275                         break;
11276                 case 'intersect':
11277                         return (l < x1 + (draggable.helperProportions.width / 2) // Right Half
11278                                 && x2 - (draggable.helperProportions.width / 2) < r // Left Half
11279                                 && t < y1 + (draggable.helperProportions.height / 2) // Bottom Half
11280                                 && y2 - (draggable.helperProportions.height / 2) < b ); // Top Half
11281                         break;
11282                 case 'pointer':
11283                         var draggableLeft = ((draggable.positionAbs || draggable.position.absolute).left + (draggable.clickOffset || draggable.offset.click).left),
11284                                 draggableTop = ((draggable.positionAbs || draggable.position.absolute).top + (draggable.clickOffset || draggable.offset.click).top),
11285                                 isOver = $.ui.isOver(draggableTop, draggableLeft, t, l, droppable.proportions.height, droppable.proportions.width);
11286                         return isOver;
11287                         break;
11288                 case 'touch':
11289                         return (
11290                                         (y1 >= t && y1 <= b) || // Top edge touching
11291                                         (y2 >= t && y2 <= b) || // Bottom edge touching
11292                                         (y1 < t && y2 > b)              // Surrounded vertically
11293                                 ) && (
11294                                         (x1 >= l && x1 <= r) || // Left edge touching
11295                                         (x2 >= l && x2 <= r) || // Right edge touching
11296                                         (x1 < l && x2 > r)              // Surrounded horizontally
11297                                 );
11298                         break;
11299                 default:
11300                         return false;
11301                         break;
11302                 }
11303
11304 };
11305
11306 /*
11307         This manager tracks offsets of draggables and droppables
11308 */
11309 $.ui.ddmanager = {
11310         current: null,
11311         droppables: { 'default': [] },
11312         prepareOffsets: function(t, event) {
11313
11314                 var m = $.ui.ddmanager.droppables[t.options.scope] || [];
11315                 var type = event ? event.type : null; // workaround for #2317
11316                 var list = (t.currentItem || t.element).find(":data(droppable)").andSelf();
11317
11318                 droppablesLoop: for (var i = 0; i < m.length; i++) {
11319
11320                         if(m[i].options.disabled || (t && !m[i].accept.call(m[i].element[0],(t.currentItem || t.element)))) continue;   //No disabled and non-accepted
11321                         for (var j=0; j < list.length; j++) { if(list[j] == m[i].element[0]) { m[i].proportions.height = 0; continue droppablesLoop; } }; //Filter out elements in the current dragged item
11322                         m[i].visible = m[i].element.css("display") != "none"; if(!m[i].visible) continue;                                                                       //If the element is not visible, continue
11323
11324                         if(type == "mousedown") m[i]._activate.call(m[i], event); //Activate the droppable if used directly from draggables
11325
11326                         m[i].offset = m[i].element.offset();
11327                         m[i].proportions = { width: m[i].element[0].offsetWidth, height: m[i].element[0].offsetHeight };
11328
11329                 }
11330
11331         },
11332         drop: function(draggable, event) {
11333
11334                 var dropped = false;
11335                 $.each($.ui.ddmanager.droppables[draggable.options.scope] || [], function() {
11336
11337                         if(!this.options) return;
11338                         if (!this.options.disabled && this.visible && $.ui.intersect(draggable, this, this.options.tolerance))
11339                                 dropped = dropped || this._drop.call(this, event);
11340
11341                         if (!this.options.disabled && this.visible && this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) {
11342                                 this.isout = 1; this.isover = 0;
11343                                 this._deactivate.call(this, event);
11344                         }
11345
11346                 });
11347                 return dropped;
11348
11349         },
11350         drag: function(draggable, event) {
11351
11352                 //If you have a highly dynamic page, you might try this option. It renders positions every time you move the mouse.
11353                 if(draggable.options.refreshPositions) $.ui.ddmanager.prepareOffsets(draggable, event);
11354
11355                 //Run through all droppables and check their positions based on specific tolerance options
11356                 $.each($.ui.ddmanager.droppables[draggable.options.scope] || [], function() {
11357
11358                         if(this.options.disabled || this.greedyChild || !this.visible) return;
11359                         var intersects = $.ui.intersect(draggable, this, this.options.tolerance);
11360
11361                         var c = !intersects && this.isover == 1 ? 'isout' : (intersects && this.isover == 0 ? 'isover' : null);
11362                         if(!c) return;
11363
11364                         var parentInstance;
11365                         if (this.options.greedy) {
11366                                 var parent = this.element.parents(':data(droppable):eq(0)');
11367                                 if (parent.length) {
11368                                         parentInstance = $.data(parent[0], 'droppable');
11369                                         parentInstance.greedyChild = (c == 'isover' ? 1 : 0);
11370                                 }
11371                         }
11372
11373                         // we just moved into a greedy child
11374                         if (parentInstance && c == 'isover') {
11375                                 parentInstance['isover'] = 0;
11376                                 parentInstance['isout'] = 1;
11377                                 parentInstance._out.call(parentInstance, event);
11378                         }
11379
11380                         this[c] = 1; this[c == 'isout' ? 'isover' : 'isout'] = 0;
11381                         this[c == "isover" ? "_over" : "_out"].call(this, event);
11382
11383                         // we just moved out of a greedy child
11384                         if (parentInstance && c == 'isout') {
11385                                 parentInstance['isout'] = 0;
11386                                 parentInstance['isover'] = 1;
11387                                 parentInstance._over.call(parentInstance, event);
11388                         }
11389                 });
11390
11391         }
11392 };
11393
11394 })(jQuery);
11395 /*
11396  * jQuery UI Resizable 1.8.12
11397  *
11398  * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
11399  * Dual licensed under the MIT or GPL Version 2 licenses.
11400  * http://jquery.org/license
11401  *
11402  * http://docs.jquery.com/UI/Resizables
11403  *
11404  * Depends:
11405  *      jquery.ui.core.js
11406  *      jquery.ui.mouse.js
11407  *      jquery.ui.widget.js
11408  */
11409 (function( $, undefined ) {
11410
11411 $.widget("ui.resizable", $.ui.mouse, {
11412         widgetEventPrefix: "resize",
11413         options: {
11414                 alsoResize: false,
11415                 animate: false,
11416                 animateDuration: "slow",
11417                 animateEasing: "swing",
11418                 aspectRatio: false,
11419                 autoHide: false,
11420                 containment: false,
11421                 ghost: false,
11422                 grid: false,
11423                 handles: "e,s,se",
11424                 helper: false,
11425                 maxHeight: null,
11426                 maxWidth: null,
11427                 minHeight: 10,
11428                 minWidth: 10,
11429                 zIndex: 1000
11430         },
11431         _create: function() {
11432
11433                 var self = this, o = this.options;
11434                 this.element.addClass("ui-resizable");
11435
11436                 $.extend(this, {
11437                         _aspectRatio: !!(o.aspectRatio),
11438                         aspectRatio: o.aspectRatio,
11439                         originalElement: this.element,
11440                         _proportionallyResizeElements: [],
11441                         _helper: o.helper || o.ghost || o.animate ? o.helper || 'ui-resizable-helper' : null
11442                 });
11443
11444                 //Wrap the element if it cannot hold child nodes
11445                 if(this.element[0].nodeName.match(/canvas|textarea|input|select|button|img/i)) {
11446
11447                         //Opera fix for relative positioning
11448                         if (/relative/.test(this.element.css('position')) && $.browser.opera)
11449                                 this.element.css({ position: 'relative', top: 'auto', left: 'auto' });
11450
11451                         //Create a wrapper element and set the wrapper to the new current internal element
11452                         this.element.wrap(
11453                                 $('<div class="ui-wrapper" style="overflow: hidden;"></div>').css({
11454                                         position: this.element.css('position'),
11455                                         width: this.element.outerWidth(),
11456                                         height: this.element.outerHeight(),
11457                                         top: this.element.css('top'),
11458                                         left: this.element.css('left')
11459                                 })
11460                         );
11461
11462                         //Overwrite the original this.element
11463                         this.element = this.element.parent().data(
11464                                 "resizable", this.element.data('resizable')
11465                         );
11466
11467                         this.elementIsWrapper = true;
11468
11469                         //Move margins to the wrapper
11470                         this.element.css({ marginLeft: this.originalElement.css("marginLeft"), marginTop: this.originalElement.css("marginTop"), marginRight: this.originalElement.css("marginRight"), marginBottom: this.originalElement.css("marginBottom") });
11471                         this.originalElement.css({ marginLeft: 0, marginTop: 0, marginRight: 0, marginBottom: 0});
11472
11473                         //Prevent Safari textarea resize
11474                         this.originalResizeStyle = this.originalElement.css('resize');
11475                         this.originalElement.css('resize', 'none');
11476
11477                         //Push the actual element to our proportionallyResize internal array
11478                         this._proportionallyResizeElements.push(this.originalElement.css({ position: 'static', zoom: 1, display: 'block' }));
11479
11480                         // avoid IE jump (hard set the margin)
11481                         this.originalElement.css({ margin: this.originalElement.css('margin') });
11482
11483                         // fix handlers offset
11484                         this._proportionallyResize();
11485
11486                 }
11487
11488                 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' });
11489                 if(this.handles.constructor == String) {
11490
11491                         if(this.handles == 'all') this.handles = 'n,e,s,w,se,sw,ne,nw';
11492                         var n = this.handles.split(","); this.handles = {};
11493
11494                         for(var i = 0; i < n.length; i++) {
11495
11496                                 var handle = $.trim(n[i]), hname = 'ui-resizable-'+handle;
11497                                 var axis = $('<div class="ui-resizable-handle ' + hname + '"></div>');
11498
11499                                 // increase zIndex of sw, se, ne, nw axis
11500                                 //TODO : this modifies original option
11501                                 if(/sw|se|ne|nw/.test(handle)) axis.css({ zIndex: ++o.zIndex });
11502
11503                                 //TODO : What's going on here?
11504                                 if ('se' == handle) {
11505                                         axis.addClass('ui-icon ui-icon-gripsmall-diagonal-se');
11506                                 };
11507
11508                                 //Insert into internal handles object and append to element
11509                                 this.handles[handle] = '.ui-resizable-'+handle;
11510                                 this.element.append(axis);
11511                         }
11512
11513                 }
11514
11515                 this._renderAxis = function(target) {
11516
11517                         target = target || this.element;
11518
11519                         for(var i in this.handles) {
11520
11521                                 if(this.handles[i].constructor == String)
11522                                         this.handles[i] = $(this.handles[i], this.element).show();
11523
11524                                 //Apply pad to wrapper element, needed to fix axis position (textarea, inputs, scrolls)
11525                                 if (this.elementIsWrapper && this.originalElement[0].nodeName.match(/textarea|input|select|button/i)) {
11526
11527                                         var axis = $(this.handles[i], this.element), padWrapper = 0;
11528
11529                                         //Checking the correct pad and border
11530                                         padWrapper = /sw|ne|nw|se|n|s/.test(i) ? axis.outerHeight() : axis.outerWidth();
11531
11532                                         //The padding type i have to apply...
11533                                         var padPos = [ 'padding',
11534                                                 /ne|nw|n/.test(i) ? 'Top' :
11535                                                 /se|sw|s/.test(i) ? 'Bottom' :
11536                                                 /^e$/.test(i) ? 'Right' : 'Left' ].join("");
11537
11538                                         target.css(padPos, padWrapper);
11539
11540                                         this._proportionallyResize();
11541
11542                                 }
11543
11544                                 //TODO: What's that good for? There's not anything to be executed left
11545                                 if(!$(this.handles[i]).length)
11546                                         continue;
11547
11548                         }
11549                 };
11550
11551                 //TODO: make renderAxis a prototype function
11552                 this._renderAxis(this.element);
11553
11554                 this._handles = $('.ui-resizable-handle', this.element)
11555                         .disableSelection();
11556
11557                 //Matching axis name
11558                 this._handles.mouseover(function() {
11559                         if (!self.resizing) {
11560                                 if (this.className)
11561                                         var axis = this.className.match(/ui-resizable-(se|sw|ne|nw|n|e|s|w)/i);
11562                                 //Axis, default = se
11563                                 self.axis = axis && axis[1] ? axis[1] : 'se';
11564                         }
11565                 });
11566
11567                 //If we want to auto hide the elements
11568                 if (o.autoHide) {
11569                         this._handles.hide();
11570                         $(this.element)
11571                                 .addClass("ui-resizable-autohide")
11572                                 .hover(function() {
11573                                         $(this).removeClass("ui-resizable-autohide");
11574                                         self._handles.show();
11575                                 },
11576                                 function(){
11577                                         if (!self.resizing) {
11578                                                 $(this).addClass("ui-resizable-autohide");
11579                                                 self._handles.hide();
11580                                         }
11581                                 });
11582                 }
11583
11584                 //Initialize the mouse interaction
11585                 this._mouseInit();
11586
11587         },
11588
11589         destroy: function() {
11590
11591                 this._mouseDestroy();
11592
11593                 var _destroy = function(exp) {
11594                         $(exp).removeClass("ui-resizable ui-resizable-disabled ui-resizable-resizing")
11595                                 .removeData("resizable").unbind(".resizable").find('.ui-resizable-handle').remove();
11596                 };
11597
11598                 //TODO: Unwrap at same DOM position
11599                 if (this.elementIsWrapper) {
11600                         _destroy(this.element);
11601                         var wrapper = this.element;
11602                         wrapper.after(
11603                                 this.originalElement.css({
11604                                         position: wrapper.css('position'),
11605                                         width: wrapper.outerWidth(),
11606                                         height: wrapper.outerHeight(),
11607                                         top: wrapper.css('top'),
11608                                         left: wrapper.css('left')
11609                                 })
11610                         ).remove();
11611                 }
11612
11613                 this.originalElement.css('resize', this.originalResizeStyle);
11614                 _destroy(this.originalElement);
11615
11616                 return this;
11617         },
11618
11619         _mouseCapture: function(event) {
11620                 var handle = false;
11621                 for (var i in this.handles) {
11622                         if ($(this.handles[i])[0] == event.target) {
11623                                 handle = true;
11624                         }
11625                 }
11626
11627                 return !this.options.disabled && handle;
11628         },
11629
11630         _mouseStart: function(event) {
11631
11632                 var o = this.options, iniPos = this.element.position(), el = this.element;
11633
11634                 this.resizing = true;
11635                 this.documentScroll = { top: $(document).scrollTop(), left: $(document).scrollLeft() };
11636
11637                 // bugfix for http://dev.jquery.com/ticket/1749
11638                 if (el.is('.ui-draggable') || (/absolute/).test(el.css('position'))) {
11639                         el.css({ position: 'absolute', top: iniPos.top, left: iniPos.left });
11640                 }
11641
11642                 //Opera fixing relative position
11643                 if ($.browser.opera && (/relative/).test(el.css('position')))
11644                         el.css({ position: 'relative', top: 'auto', left: 'auto' });
11645
11646                 this._renderProxy();
11647
11648                 var curleft = num(this.helper.css('left')), curtop = num(this.helper.css('top'));
11649
11650                 if (o.containment) {
11651                         curleft += $(o.containment).scrollLeft() || 0;
11652                         curtop += $(o.containment).scrollTop() || 0;
11653                 }
11654
11655                 //Store needed variables
11656                 this.offset = this.helper.offset();
11657                 this.position = { left: curleft, top: curtop };
11658                 this.size = this._helper ? { width: el.outerWidth(), height: el.outerHeight() } : { width: el.width(), height: el.height() };
11659                 this.originalSize = this._helper ? { width: el.outerWidth(), height: el.outerHeight() } : { width: el.width(), height: el.height() };
11660                 this.originalPosition = { left: curleft, top: curtop };
11661                 this.sizeDiff = { width: el.outerWidth() - el.width(), height: el.outerHeight() - el.height() };
11662                 this.originalMousePosition = { left: event.pageX, top: event.pageY };
11663
11664                 //Aspect Ratio
11665                 this.aspectRatio = (typeof o.aspectRatio == 'number') ? o.aspectRatio : ((this.originalSize.width / this.originalSize.height) || 1);
11666
11667             var cursor = $('.ui-resizable-' + this.axis).css('cursor');
11668             $('body').css('cursor', cursor == 'auto' ? this.axis + '-resize' : cursor);
11669
11670                 el.addClass("ui-resizable-resizing");
11671                 this._propagate("start", event);
11672                 return true;
11673         },
11674
11675         _mouseDrag: function(event) {
11676
11677                 //Increase performance, avoid regex
11678                 var el = this.helper, o = this.options, props = {},
11679                         self = this, smp = this.originalMousePosition, a = this.axis;
11680
11681                 var dx = (event.pageX-smp.left)||0, dy = (event.pageY-smp.top)||0;
11682                 var trigger = this._change[a];
11683                 if (!trigger) return false;
11684
11685                 // Calculate the attrs that will be change
11686                 var data = trigger.apply(this, [event, dx, dy]), ie6 = $.browser.msie && $.browser.version < 7, csdif = this.sizeDiff;
11687
11688                 if (this._aspectRatio || event.shiftKey)
11689                         data = this._updateRatio(data, event);
11690
11691                 data = this._respectSize(data, event);
11692
11693                 // plugins callbacks need to be called first
11694                 this._propagate("resize", event);
11695
11696                 el.css({
11697                         top: this.position.top + "px", left: this.position.left + "px",
11698                         width: this.size.width + "px", height: this.size.height + "px"
11699                 });
11700
11701                 if (!this._helper && this._proportionallyResizeElements.length)
11702                         this._proportionallyResize();
11703
11704                 this._updateCache(data);
11705
11706                 // calling the user callback at the end
11707                 this._trigger('resize', event, this.ui());
11708
11709                 return false;
11710         },
11711
11712         _mouseStop: function(event) {
11713
11714                 this.resizing = false;
11715                 var o = this.options, self = this;
11716
11717                 if(this._helper) {
11718                         var pr = this._proportionallyResizeElements, ista = pr.length && (/textarea/i).test(pr[0].nodeName),
11719                                 soffseth = ista && $.ui.hasScroll(pr[0], 'left') /* TODO - jump height */ ? 0 : self.sizeDiff.height,
11720                                 soffsetw = ista ? 0 : self.sizeDiff.width;
11721
11722                         var s = { width: (self.helper.width()  - soffsetw), height: (self.helper.height() - soffseth) },
11723                                 left = (parseInt(self.element.css('left'), 10) + (self.position.left - self.originalPosition.left)) || null,
11724                                 top = (parseInt(self.element.css('top'), 10) + (self.position.top - self.originalPosition.top)) || null;
11725
11726                         if (!o.animate)
11727                                 this.element.css($.extend(s, { top: top, left: left }));
11728
11729                         self.helper.height(self.size.height);
11730                         self.helper.width(self.size.width);
11731
11732                         if (this._helper && !o.animate) this._proportionallyResize();
11733                 }
11734
11735                 $('body').css('cursor', 'auto');
11736
11737                 this.element.removeClass("ui-resizable-resizing");
11738
11739                 this._propagate("stop", event);
11740
11741                 if (this._helper) this.helper.remove();
11742                 return false;
11743
11744         },
11745
11746         _updateCache: function(data) {
11747                 var o = this.options;
11748                 this.offset = this.helper.offset();
11749                 if (isNumber(data.left)) this.position.left = data.left;
11750                 if (isNumber(data.top)) this.position.top = data.top;
11751                 if (isNumber(data.height)) this.size.height = data.height;
11752                 if (isNumber(data.width)) this.size.width = data.width;
11753         },
11754
11755         _updateRatio: function(data, event) {
11756
11757                 var o = this.options, cpos = this.position, csize = this.size, a = this.axis;
11758
11759                 if (data.height) data.width = (csize.height * this.aspectRatio);
11760                 else if (data.width) data.height = (csize.width / this.aspectRatio);
11761
11762                 if (a == 'sw') {
11763                         data.left = cpos.left + (csize.width - data.width);
11764                         data.top = null;
11765                 }
11766                 if (a == 'nw') {
11767                         data.top = cpos.top + (csize.height - data.height);
11768                         data.left = cpos.left + (csize.width - data.width);
11769                 }
11770
11771                 return data;
11772         },
11773
11774         _respectSize: function(data, event) {
11775
11776                 var el = this.helper, o = this.options, pRatio = this._aspectRatio || event.shiftKey, a = this.axis,
11777                                 ismaxw = isNumber(data.width) && o.maxWidth && (o.maxWidth < data.width), ismaxh = isNumber(data.height) && o.maxHeight && (o.maxHeight < data.height),
11778                                         isminw = isNumber(data.width) && o.minWidth && (o.minWidth > data.width), isminh = isNumber(data.height) && o.minHeight && (o.minHeight > data.height);
11779
11780                 if (isminw) data.width = o.minWidth;
11781                 if (isminh) data.height = o.minHeight;
11782                 if (ismaxw) data.width = o.maxWidth;
11783                 if (ismaxh) data.height = o.maxHeight;
11784
11785                 var dw = this.originalPosition.left + this.originalSize.width, dh = this.position.top + this.size.height;
11786                 var cw = /sw|nw|w/.test(a), ch = /nw|ne|n/.test(a);
11787
11788                 if (isminw && cw) data.left = dw - o.minWidth;
11789                 if (ismaxw && cw) data.left = dw - o.maxWidth;
11790                 if (isminh && ch)       data.top = dh - o.minHeight;
11791                 if (ismaxh && ch)       data.top = dh - o.maxHeight;
11792
11793                 // fixing jump error on top/left - bug #2330
11794                 var isNotwh = !data.width && !data.height;
11795                 if (isNotwh && !data.left && data.top) data.top = null;
11796                 else if (isNotwh && !data.top && data.left) data.left = null;
11797
11798                 return data;
11799         },
11800
11801         _proportionallyResize: function() {
11802
11803                 var o = this.options;
11804                 if (!this._proportionallyResizeElements.length) return;
11805                 var element = this.helper || this.element;
11806
11807                 for (var i=0; i < this._proportionallyResizeElements.length; i++) {
11808
11809                         var prel = this._proportionallyResizeElements[i];
11810
11811                         if (!this.borderDif) {
11812                                 var b = [prel.css('borderTopWidth'), prel.css('borderRightWidth'), prel.css('borderBottomWidth'), prel.css('borderLeftWidth')],
11813                                         p = [prel.css('paddingTop'), prel.css('paddingRight'), prel.css('paddingBottom'), prel.css('paddingLeft')];
11814
11815                                 this.borderDif = $.map(b, function(v, i) {
11816                                         var border = parseInt(v,10)||0, padding = parseInt(p[i],10)||0;
11817                                         return border + padding;
11818                                 });
11819                         }
11820
11821                         if ($.browser.msie && !(!($(element).is(':hidden') || $(element).parents(':hidden').length)))
11822                                 continue;
11823
11824                         prel.css({
11825                                 height: (element.height() - this.borderDif[0] - this.borderDif[2]) || 0,
11826                                 width: (element.width() - this.borderDif[1] - this.borderDif[3]) || 0
11827                         });
11828
11829                 };
11830
11831         },
11832
11833         _renderProxy: function() {
11834
11835                 var el = this.element, o = this.options;
11836                 this.elementOffset = el.offset();
11837
11838                 if(this._helper) {
11839
11840                         this.helper = this.helper || $('<div style="overflow:hidden;"></div>');
11841
11842                         // fix ie6 offset TODO: This seems broken
11843                         var ie6 = $.browser.msie && $.browser.version < 7, ie6offset = (ie6 ? 1 : 0),
11844                         pxyoffset = ( ie6 ? 2 : -1 );
11845
11846                         this.helper.addClass(this._helper).css({
11847                                 width: this.element.outerWidth() + pxyoffset,
11848                                 height: this.element.outerHeight() + pxyoffset,
11849                                 position: 'absolute',
11850                                 left: this.elementOffset.left - ie6offset +'px',
11851                                 top: this.elementOffset.top - ie6offset +'px',
11852                                 zIndex: ++o.zIndex //TODO: Don't modify option
11853                         });
11854
11855                         this.helper
11856                                 .appendTo("body")
11857                                 .disableSelection();
11858
11859                 } else {
11860                         this.helper = this.element;
11861                 }
11862
11863         },
11864
11865         _change: {
11866                 e: function(event, dx, dy) {
11867                         return { width: this.originalSize.width + dx };
11868                 },
11869                 w: function(event, dx, dy) {
11870                         var o = this.options, cs = this.originalSize, sp = this.originalPosition;
11871                         return { left: sp.left + dx, width: cs.width - dx };
11872                 },
11873                 n: function(event, dx, dy) {
11874                         var o = this.options, cs = this.originalSize, sp = this.originalPosition;
11875                         return { top: sp.top + dy, height: cs.height - dy };
11876                 },
11877                 s: function(event, dx, dy) {
11878                         return { height: this.originalSize.height + dy };
11879                 },
11880                 se: function(event, dx, dy) {
11881                         return $.extend(this._change.s.apply(this, arguments), this._change.e.apply(this, [event, dx, dy]));
11882                 },
11883                 sw: function(event, dx, dy) {
11884                         return $.extend(this._change.s.apply(this, arguments), this._change.w.apply(this, [event, dx, dy]));
11885                 },
11886                 ne: function(event, dx, dy) {
11887                         return $.extend(this._change.n.apply(this, arguments), this._change.e.apply(this, [event, dx, dy]));
11888                 },
11889                 nw: function(event, dx, dy) {
11890                         return $.extend(this._change.n.apply(this, arguments), this._change.w.apply(this, [event, dx, dy]));
11891                 }
11892         },
11893
11894         _propagate: function(n, event) {
11895                 $.ui.plugin.call(this, n, [event, this.ui()]);
11896                 (n != "resize" && this._trigger(n, event, this.ui()));
11897         },
11898
11899         plugins: {},
11900
11901         ui: function() {
11902                 return {
11903                         originalElement: this.originalElement,
11904                         element: this.element,
11905                         helper: this.helper,
11906                         position: this.position,
11907                         size: this.size,
11908                         originalSize: this.originalSize,
11909                         originalPosition: this.originalPosition
11910                 };
11911         }
11912
11913 });
11914
11915 $.extend($.ui.resizable, {
11916         version: "1.8.12"
11917 });
11918
11919 /*
11920  * Resizable Extensions
11921  */
11922
11923 $.ui.plugin.add("resizable", "alsoResize", {
11924
11925         start: function (event, ui) {
11926                 var self = $(this).data("resizable"), o = self.options;
11927
11928                 var _store = function (exp) {
11929                         $(exp).each(function() {
11930                                 var el = $(this);
11931                                 el.data("resizable-alsoresize", {
11932                                         width: parseInt(el.width(), 10), height: parseInt(el.height(), 10),
11933                                         left: parseInt(el.css('left'), 10), top: parseInt(el.css('top'), 10),
11934                                         position: el.css('position') // to reset Opera on stop()
11935                                 });
11936                         });
11937                 };
11938
11939                 if (typeof(o.alsoResize) == 'object' && !o.alsoResize.parentNode) {
11940                         if (o.alsoResize.length) { o.alsoResize = o.alsoResize[0]; _store(o.alsoResize); }
11941                         else { $.each(o.alsoResize, function (exp) { _store(exp); }); }
11942                 }else{
11943                         _store(o.alsoResize);
11944                 }
11945         },
11946
11947         resize: function (event, ui) {
11948                 var self = $(this).data("resizable"), o = self.options, os = self.originalSize, op = self.originalPosition;
11949
11950                 var delta = {
11951                         height: (self.size.height - os.height) || 0, width: (self.size.width - os.width) || 0,
11952                         top: (self.position.top - op.top) || 0, left: (self.position.left - op.left) || 0
11953                 },
11954
11955                 _alsoResize = function (exp, c) {
11956                         $(exp).each(function() {
11957                                 var el = $(this), start = $(this).data("resizable-alsoresize"), style = {}, 
11958                                         css = c && c.length ? c : el.parents(ui.originalElement[0]).length ? ['width', 'height'] : ['width', 'height', 'top', 'left'];
11959
11960                                 $.each(css, function (i, prop) {
11961                                         var sum = (start[prop]||0) + (delta[prop]||0);
11962                                         if (sum && sum >= 0)
11963                                                 style[prop] = sum || null;
11964                                 });
11965
11966                                 // Opera fixing relative position
11967                                 if ($.browser.opera && /relative/.test(el.css('position'))) {
11968                                         self._revertToRelativePosition = true;
11969                                         el.css({ position: 'absolute', top: 'auto', left: 'auto' });
11970                                 }
11971
11972                                 el.css(style);
11973                         });
11974                 };
11975
11976                 if (typeof(o.alsoResize) == 'object' && !o.alsoResize.nodeType) {
11977                         $.each(o.alsoResize, function (exp, c) { _alsoResize(exp, c); });
11978                 }else{
11979                         _alsoResize(o.alsoResize);
11980                 }
11981         },
11982
11983         stop: function (event, ui) {
11984                 var self = $(this).data("resizable"), o = self.options;
11985
11986                 var _reset = function (exp) {
11987                         $(exp).each(function() {
11988                                 var el = $(this);
11989                                 // reset position for Opera - no need to verify it was changed
11990                                 el.css({ position: el.data("resizable-alsoresize").position });
11991                         });
11992                 };
11993
11994                 if (self._revertToRelativePosition) {
11995                         self._revertToRelativePosition = false;
11996                         if (typeof(o.alsoResize) == 'object' && !o.alsoResize.nodeType) {
11997                                 $.each(o.alsoResize, function (exp) { _reset(exp); });
11998                         }else{
11999                                 _reset(o.alsoResize);
12000                         }
12001                 }
12002
12003                 $(this).removeData("resizable-alsoresize");
12004         }
12005 });
12006
12007 $.ui.plugin.add("resizable", "animate", {
12008
12009         stop: function(event, ui) {
12010                 var self = $(this).data("resizable"), o = self.options;
12011
12012                 var pr = self._proportionallyResizeElements, ista = pr.length && (/textarea/i).test(pr[0].nodeName),
12013                                         soffseth = ista && $.ui.hasScroll(pr[0], 'left') /* TODO - jump height */ ? 0 : self.sizeDiff.height,
12014                                                 soffsetw = ista ? 0 : self.sizeDiff.width;
12015
12016                 var style = { width: (self.size.width - soffsetw), height: (self.size.height - soffseth) },
12017                                         left = (parseInt(self.element.css('left'), 10) + (self.position.left - self.originalPosition.left)) || null,
12018                                                 top = (parseInt(self.element.css('top'), 10) + (self.position.top - self.originalPosition.top)) || null;
12019
12020                 self.element.animate(
12021                         $.extend(style, top && left ? { top: top, left: left } : {}), {
12022                                 duration: o.animateDuration,
12023                                 easing: o.animateEasing,
12024                                 step: function() {
12025
12026                                         var data = {
12027                                                 width: parseInt(self.element.css('width'), 10),
12028                                                 height: parseInt(self.element.css('height'), 10),
12029                                                 top: parseInt(self.element.css('top'), 10),
12030                                                 left: parseInt(self.element.css('left'), 10)
12031                                         };
12032
12033                                         if (pr && pr.length) $(pr[0]).css({ width: data.width, height: data.height });
12034
12035                                         // propagating resize, and updating values for each animation step
12036                                         self._updateCache(data);
12037                                         self._propagate("resize", event);
12038
12039                                 }
12040                         }
12041                 );
12042         }
12043
12044 });
12045
12046 $.ui.plugin.add("resizable", "containment", {
12047
12048         start: function(event, ui) {
12049                 var self = $(this).data("resizable"), o = self.options, el = self.element;
12050                 var oc = o.containment, ce = (oc instanceof $) ? oc.get(0) : (/parent/.test(oc)) ? el.parent().get(0) : oc;
12051                 if (!ce) return;
12052
12053                 self.containerElement = $(ce);
12054
12055                 if (/document/.test(oc) || oc == document) {
12056                         self.containerOffset = { left: 0, top: 0 };
12057                         self.containerPosition = { left: 0, top: 0 };
12058
12059                         self.parentData = {
12060                                 element: $(document), left: 0, top: 0,
12061                                 width: $(document).width(), height: $(document).height() || document.body.parentNode.scrollHeight
12062                         };
12063                 }
12064
12065                 // i'm a node, so compute top, left, right, bottom
12066                 else {
12067                         var element = $(ce), p = [];
12068                         $([ "Top", "Right", "Left", "Bottom" ]).each(function(i, name) { p[i] = num(element.css("padding" + name)); });
12069
12070                         self.containerOffset = element.offset();
12071                         self.containerPosition = element.position();
12072                         self.containerSize = { height: (element.innerHeight() - p[3]), width: (element.innerWidth() - p[1]) };
12073
12074                         var co = self.containerOffset, ch = self.containerSize.height,  cw = self.containerSize.width,
12075                                                 width = ($.ui.hasScroll(ce, "left") ? ce.scrollWidth : cw ), height = ($.ui.hasScroll(ce) ? ce.scrollHeight : ch);
12076
12077                         self.parentData = {
12078                                 element: ce, left: co.left, top: co.top, width: width, height: height
12079                         };
12080                 }
12081         },
12082
12083         resize: function(event, ui) {
12084                 var self = $(this).data("resizable"), o = self.options,
12085                                 ps = self.containerSize, co = self.containerOffset, cs = self.size, cp = self.position,
12086                                 pRatio = self._aspectRatio || event.shiftKey, cop = { top:0, left:0 }, ce = self.containerElement;
12087
12088                 if (ce[0] != document && (/static/).test(ce.css('position'))) cop = co;
12089
12090                 if (cp.left < (self._helper ? co.left : 0)) {
12091                         self.size.width = self.size.width + (self._helper ? (self.position.left - co.left) : (self.position.left - cop.left));
12092                         if (pRatio) self.size.height = self.size.width / o.aspectRatio;
12093                         self.position.left = o.helper ? co.left : 0;
12094                 }
12095
12096                 if (cp.top < (self._helper ? co.top : 0)) {
12097                         self.size.height = self.size.height + (self._helper ? (self.position.top - co.top) : self.position.top);
12098                         if (pRatio) self.size.width = self.size.height * o.aspectRatio;
12099                         self.position.top = self._helper ? co.top : 0;
12100                 }
12101
12102                 self.offset.left = self.parentData.left+self.position.left;
12103                 self.offset.top = self.parentData.top+self.position.top;
12104
12105                 var woset = Math.abs( (self._helper ? self.offset.left - cop.left : (self.offset.left - cop.left)) + self.sizeDiff.width ),
12106                                         hoset = Math.abs( (self._helper ? self.offset.top - cop.top : (self.offset.top - co.top)) + self.sizeDiff.height );
12107
12108                 var isParent = self.containerElement.get(0) == self.element.parent().get(0),
12109                     isOffsetRelative = /relative|absolute/.test(self.containerElement.css('position'));
12110
12111                 if(isParent && isOffsetRelative) woset -= self.parentData.left;
12112
12113                 if (woset + self.size.width >= self.parentData.width) {
12114                         self.size.width = self.parentData.width - woset;
12115                         if (pRatio) self.size.height = self.size.width / self.aspectRatio;
12116                 }
12117
12118                 if (hoset + self.size.height >= self.parentData.height) {
12119                         self.size.height = self.parentData.height - hoset;
12120                         if (pRatio) self.size.width = self.size.height * self.aspectRatio;
12121                 }
12122         },
12123
12124         stop: function(event, ui){
12125                 var self = $(this).data("resizable"), o = self.options, cp = self.position,
12126                                 co = self.containerOffset, cop = self.containerPosition, ce = self.containerElement;
12127
12128                 var helper = $(self.helper), ho = helper.offset(), w = helper.outerWidth() - self.sizeDiff.width, h = helper.outerHeight() - self.sizeDiff.height;
12129
12130                 if (self._helper && !o.animate && (/relative/).test(ce.css('position')))
12131                         $(this).css({ left: ho.left - cop.left - co.left, width: w, height: h });
12132
12133                 if (self._helper && !o.animate && (/static/).test(ce.css('position')))
12134                         $(this).css({ left: ho.left - cop.left - co.left, width: w, height: h });
12135
12136         }
12137 });
12138
12139 $.ui.plugin.add("resizable", "ghost", {
12140
12141         start: function(event, ui) {
12142
12143                 var self = $(this).data("resizable"), o = self.options, cs = self.size;
12144
12145                 self.ghost = self.originalElement.clone();
12146                 self.ghost
12147                         .css({ opacity: .25, display: 'block', position: 'relative', height: cs.height, width: cs.width, margin: 0, left: 0, top: 0 })
12148                         .addClass('ui-resizable-ghost')
12149                         .addClass(typeof o.ghost == 'string' ? o.ghost : '');
12150
12151                 self.ghost.appendTo(self.helper);
12152
12153         },
12154
12155         resize: function(event, ui){
12156                 var self = $(this).data("resizable"), o = self.options;
12157                 if (self.ghost) self.ghost.css({ position: 'relative', height: self.size.height, width: self.size.width });
12158         },
12159
12160         stop: function(event, ui){
12161                 var self = $(this).data("resizable"), o = self.options;
12162                 if (self.ghost && self.helper) self.helper.get(0).removeChild(self.ghost.get(0));
12163         }
12164
12165 });
12166
12167 $.ui.plugin.add("resizable", "grid", {
12168
12169         resize: function(event, ui) {
12170                 var self = $(this).data("resizable"), o = self.options, cs = self.size, os = self.originalSize, op = self.originalPosition, a = self.axis, ratio = o._aspectRatio || event.shiftKey;
12171                 o.grid = typeof o.grid == "number" ? [o.grid, o.grid] : o.grid;
12172                 var ox = Math.round((cs.width - os.width) / (o.grid[0]||1)) * (o.grid[0]||1), oy = Math.round((cs.height - os.height) / (o.grid[1]||1)) * (o.grid[1]||1);
12173
12174                 if (/^(se|s|e)$/.test(a)) {
12175                         self.size.width = os.width + ox;
12176                         self.size.height = os.height + oy;
12177                 }
12178                 else if (/^(ne)$/.test(a)) {
12179                         self.size.width = os.width + ox;
12180                         self.size.height = os.height + oy;
12181                         self.position.top = op.top - oy;
12182                 }
12183                 else if (/^(sw)$/.test(a)) {
12184                         self.size.width = os.width + ox;
12185                         self.size.height = os.height + oy;
12186                         self.position.left = op.left - ox;
12187                 }
12188                 else {
12189                         self.size.width = os.width + ox;
12190                         self.size.height = os.height + oy;
12191                         self.position.top = op.top - oy;
12192                         self.position.left = op.left - ox;
12193                 }
12194         }
12195
12196 });
12197
12198 var num = function(v) {
12199         return parseInt(v, 10) || 0;
12200 };
12201
12202 var isNumber = function(value) {
12203         return !isNaN(parseInt(value, 10));
12204 };
12205
12206 })(jQuery);
12207 /*
12208  * jQuery UI Selectable 1.8.12
12209  *
12210  * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
12211  * Dual licensed under the MIT or GPL Version 2 licenses.
12212  * http://jquery.org/license
12213  *
12214  * http://docs.jquery.com/UI/Selectables
12215  *
12216  * Depends:
12217  *      jquery.ui.core.js
12218  *      jquery.ui.mouse.js
12219  *      jquery.ui.widget.js
12220  */
12221 (function( $, undefined ) {
12222
12223 $.widget("ui.selectable", $.ui.mouse, {
12224         options: {
12225                 appendTo: 'body',
12226                 autoRefresh: true,
12227                 distance: 0,
12228                 filter: '*',
12229                 tolerance: 'touch'
12230         },
12231         _create: function() {
12232                 var self = this;
12233
12234                 this.element.addClass("ui-selectable");
12235
12236                 this.dragged = false;
12237
12238                 // cache selectee children based on filter
12239                 var selectees;
12240                 this.refresh = function() {
12241                         selectees = $(self.options.filter, self.element[0]);
12242                         selectees.each(function() {
12243                                 var $this = $(this);
12244                                 var pos = $this.offset();
12245                                 $.data(this, "selectable-item", {
12246                                         element: this,
12247                                         $element: $this,
12248                                         left: pos.left,
12249                                         top: pos.top,
12250                                         right: pos.left + $this.outerWidth(),
12251                                         bottom: pos.top + $this.outerHeight(),
12252                                         startselected: false,
12253                                         selected: $this.hasClass('ui-selected'),
12254                                         selecting: $this.hasClass('ui-selecting'),
12255                                         unselecting: $this.hasClass('ui-unselecting')
12256                                 });
12257                         });
12258                 };
12259                 this.refresh();
12260
12261                 this.selectees = selectees.addClass("ui-selectee");
12262
12263                 this._mouseInit();
12264
12265                 this.helper = $("<div class='ui-selectable-helper'></div>");
12266         },
12267
12268         destroy: function() {
12269                 this.selectees
12270                         .removeClass("ui-selectee")
12271                         .removeData("selectable-item");
12272                 this.element
12273                         .removeClass("ui-selectable ui-selectable-disabled")
12274                         .removeData("selectable")
12275                         .unbind(".selectable");
12276                 this._mouseDestroy();
12277
12278                 return this;
12279         },
12280
12281         _mouseStart: function(event) {
12282                 var self = this;
12283
12284                 this.opos = [event.pageX, event.pageY];
12285
12286                 if (this.options.disabled)
12287                         return;
12288
12289                 var options = this.options;
12290
12291                 this.selectees = $(options.filter, this.element[0]);
12292
12293                 this._trigger("start", event);
12294
12295                 $(options.appendTo).append(this.helper);
12296                 // position helper (lasso)
12297                 this.helper.css({
12298                         "left": event.clientX,
12299                         "top": event.clientY,
12300                         "width": 0,
12301                         "height": 0
12302                 });
12303
12304                 if (options.autoRefresh) {
12305                         this.refresh();
12306                 }
12307
12308                 this.selectees.filter('.ui-selected').each(function() {
12309                         var selectee = $.data(this, "selectable-item");
12310                         selectee.startselected = true;
12311                         if (!event.metaKey) {
12312                                 selectee.$element.removeClass('ui-selected');
12313                                 selectee.selected = false;
12314                                 selectee.$element.addClass('ui-unselecting');
12315                                 selectee.unselecting = true;
12316                                 // selectable UNSELECTING callback
12317                                 self._trigger("unselecting", event, {
12318                                         unselecting: selectee.element
12319                                 });
12320                         }
12321                 });
12322
12323                 $(event.target).parents().andSelf().each(function() {
12324                         var selectee = $.data(this, "selectable-item");
12325                         if (selectee) {
12326                                 var doSelect = !event.metaKey || !selectee.$element.hasClass('ui-selected');
12327                                 selectee.$element
12328                                         .removeClass(doSelect ? "ui-unselecting" : "ui-selected")
12329                                         .addClass(doSelect ? "ui-selecting" : "ui-unselecting");
12330                                 selectee.unselecting = !doSelect;
12331                                 selectee.selecting = doSelect;
12332                                 selectee.selected = doSelect;
12333                                 // selectable (UN)SELECTING callback
12334                                 if (doSelect) {
12335                                         self._trigger("selecting", event, {
12336                                                 selecting: selectee.element
12337                                         });
12338                                 } else {
12339                                         self._trigger("unselecting", event, {
12340                                                 unselecting: selectee.element
12341                                         });
12342                                 }
12343                                 return false;
12344                         }
12345                 });
12346
12347         },
12348
12349         _mouseDrag: function(event) {
12350                 var self = this;
12351                 this.dragged = true;
12352
12353                 if (this.options.disabled)
12354                         return;
12355
12356                 var options = this.options;
12357
12358                 var x1 = this.opos[0], y1 = this.opos[1], x2 = event.pageX, y2 = event.pageY;
12359                 if (x1 > x2) { var tmp = x2; x2 = x1; x1 = tmp; }
12360                 if (y1 > y2) { var tmp = y2; y2 = y1; y1 = tmp; }
12361                 this.helper.css({left: x1, top: y1, width: x2-x1, height: y2-y1});
12362
12363                 this.selectees.each(function() {
12364                         var selectee = $.data(this, "selectable-item");
12365                         //prevent helper from being selected if appendTo: selectable
12366                         if (!selectee || selectee.element == self.element[0])
12367                                 return;
12368                         var hit = false;
12369                         if (options.tolerance == 'touch') {
12370                                 hit = ( !(selectee.left > x2 || selectee.right < x1 || selectee.top > y2 || selectee.bottom < y1) );
12371                         } else if (options.tolerance == 'fit') {
12372                                 hit = (selectee.left > x1 && selectee.right < x2 && selectee.top > y1 && selectee.bottom < y2);
12373                         }
12374
12375                         if (hit) {
12376                                 // SELECT
12377                                 if (selectee.selected) {
12378                                         selectee.$element.removeClass('ui-selected');
12379                                         selectee.selected = false;
12380                                 }
12381                                 if (selectee.unselecting) {
12382                                         selectee.$element.removeClass('ui-unselecting');
12383                                         selectee.unselecting = false;
12384                                 }
12385                                 if (!selectee.selecting) {
12386                                         selectee.$element.addClass('ui-selecting');
12387                                         selectee.selecting = true;
12388                                         // selectable SELECTING callback
12389                                         self._trigger("selecting", event, {
12390                                                 selecting: selectee.element
12391                                         });
12392                                 }
12393                         } else {
12394                                 // UNSELECT
12395                                 if (selectee.selecting) {
12396                                         if (event.metaKey && selectee.startselected) {
12397                                                 selectee.$element.removeClass('ui-selecting');
12398                                                 selectee.selecting = false;
12399                                                 selectee.$element.addClass('ui-selected');
12400                                                 selectee.selected = true;
12401                                         } else {
12402                                                 selectee.$element.removeClass('ui-selecting');
12403                                                 selectee.selecting = false;
12404                                                 if (selectee.startselected) {
12405                                                         selectee.$element.addClass('ui-unselecting');
12406                                                         selectee.unselecting = true;
12407                                                 }
12408                                                 // selectable UNSELECTING callback
12409                                                 self._trigger("unselecting", event, {
12410                                                         unselecting: selectee.element
12411                                                 });
12412                                         }
12413                                 }
12414                                 if (selectee.selected) {
12415                                         if (!event.metaKey && !selectee.startselected) {
12416                                                 selectee.$element.removeClass('ui-selected');
12417                                                 selectee.selected = false;
12418
12419                                                 selectee.$element.addClass('ui-unselecting');
12420                                                 selectee.unselecting = true;
12421                                                 // selectable UNSELECTING callback
12422                                                 self._trigger("unselecting", event, {
12423                                                         unselecting: selectee.element
12424                                                 });
12425                                         }
12426                                 }
12427                         }
12428                 });
12429
12430                 return false;
12431         },
12432
12433         _mouseStop: function(event) {
12434                 var self = this;
12435
12436                 this.dragged = false;
12437
12438                 var options = this.options;
12439
12440                 $('.ui-unselecting', this.element[0]).each(function() {
12441                         var selectee = $.data(this, "selectable-item");
12442                         selectee.$element.removeClass('ui-unselecting');
12443                         selectee.unselecting = false;
12444                         selectee.startselected = false;
12445                         self._trigger("unselected", event, {
12446                                 unselected: selectee.element
12447                         });
12448                 });
12449                 $('.ui-selecting', this.element[0]).each(function() {
12450                         var selectee = $.data(this, "selectable-item");
12451                         selectee.$element.removeClass('ui-selecting').addClass('ui-selected');
12452                         selectee.selecting = false;
12453                         selectee.selected = true;
12454                         selectee.startselected = true;
12455                         self._trigger("selected", event, {
12456                                 selected: selectee.element
12457                         });
12458                 });
12459                 this._trigger("stop", event);
12460
12461                 this.helper.remove();
12462
12463                 return false;
12464         }
12465
12466 });
12467
12468 $.extend($.ui.selectable, {
12469         version: "1.8.12"
12470 });
12471
12472 })(jQuery);
12473 /*
12474  * jQuery UI Sortable 1.8.12
12475  *
12476  * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
12477  * Dual licensed under the MIT or GPL Version 2 licenses.
12478  * http://jquery.org/license
12479  *
12480  * http://docs.jquery.com/UI/Sortables
12481  *
12482  * Depends:
12483  *      jquery.ui.core.js
12484  *      jquery.ui.mouse.js
12485  *      jquery.ui.widget.js
12486  */
12487 (function( $, undefined ) {
12488
12489 $.widget("ui.sortable", $.ui.mouse, {
12490         widgetEventPrefix: "sort",
12491         options: {
12492                 appendTo: "parent",
12493                 axis: false,
12494                 connectWith: false,
12495                 containment: false,
12496                 cursor: 'auto',
12497                 cursorAt: false,
12498                 dropOnEmpty: true,
12499                 forcePlaceholderSize: false,
12500                 forceHelperSize: false,
12501                 grid: false,
12502                 handle: false,
12503                 helper: "original",
12504                 items: '> *',
12505                 opacity: false,
12506                 placeholder: false,
12507                 revert: false,
12508                 scroll: true,
12509                 scrollSensitivity: 20,
12510                 scrollSpeed: 20,
12511                 scope: "default",
12512                 tolerance: "intersect",
12513                 zIndex: 1000
12514         },
12515         _create: function() {
12516
12517                 var o = this.options;
12518                 this.containerCache = {};
12519                 this.element.addClass("ui-sortable");
12520
12521                 //Get the items
12522                 this.refresh();
12523
12524                 //Let's determine if the items are being displayed horizontally
12525                 this.floating = this.items.length ? (/left|right/).test(this.items[0].item.css('float')) || (/inline|table-cell/).test(this.items[0].item.css('display')) : false;
12526
12527                 //Let's determine the parent's offset
12528                 this.offset = this.element.offset();
12529
12530                 //Initialize mouse events for interaction
12531                 this._mouseInit();
12532
12533         },
12534
12535         destroy: function() {
12536                 this.element
12537                         .removeClass("ui-sortable ui-sortable-disabled")
12538                         .removeData("sortable")
12539                         .unbind(".sortable");
12540                 this._mouseDestroy();
12541
12542                 for ( var i = this.items.length - 1; i >= 0; i-- )
12543                         this.items[i].item.removeData("sortable-item");
12544
12545                 return this;
12546         },
12547
12548         _setOption: function(key, value){
12549                 if ( key === "disabled" ) {
12550                         this.options[ key ] = value;
12551         
12552                         this.widget()
12553                                 [ value ? "addClass" : "removeClass"]( "ui-sortable-disabled" );
12554                 } else {
12555                         // Don't call widget base _setOption for disable as it adds ui-state-disabled class
12556                         $.Widget.prototype._setOption.apply(this, arguments);
12557                 }
12558         },
12559
12560         _mouseCapture: function(event, overrideHandle) {
12561
12562                 if (this.reverting) {
12563                         return false;
12564                 }
12565
12566                 if(this.options.disabled || this.options.type == 'static') return false;
12567
12568                 //We have to refresh the items data once first
12569                 this._refreshItems(event);
12570
12571                 //Find out if the clicked node (or one of its parents) is a actual item in this.items
12572                 var currentItem = null, self = this, nodes = $(event.target).parents().each(function() {
12573                         if($.data(this, 'sortable-item') == self) {
12574                                 currentItem = $(this);
12575                                 return false;
12576                         }
12577                 });
12578                 if($.data(event.target, 'sortable-item') == self) currentItem = $(event.target);
12579
12580                 if(!currentItem) return false;
12581                 if(this.options.handle && !overrideHandle) {
12582                         var validHandle = false;
12583
12584                         $(this.options.handle, currentItem).find("*").andSelf().each(function() { if(this == event.target) validHandle = true; });
12585                         if(!validHandle) return false;
12586                 }
12587
12588                 this.currentItem = currentItem;
12589                 this._removeCurrentsFromItems();
12590                 return true;
12591
12592         },
12593
12594         _mouseStart: function(event, overrideHandle, noActivation) {
12595
12596                 var o = this.options, self = this;
12597                 this.currentContainer = this;
12598
12599                 //We only need to call refreshPositions, because the refreshItems call has been moved to mouseCapture
12600                 this.refreshPositions();
12601
12602                 //Create and append the visible helper
12603                 this.helper = this._createHelper(event);
12604
12605                 //Cache the helper size
12606                 this._cacheHelperProportions();
12607
12608                 /*
12609                  * - Position generation -
12610                  * This block generates everything position related - it's the core of draggables.
12611                  */
12612
12613                 //Cache the margins of the original element
12614                 this._cacheMargins();
12615
12616                 //Get the next scrolling parent
12617                 this.scrollParent = this.helper.scrollParent();
12618
12619                 //The element's absolute position on the page minus margins
12620                 this.offset = this.currentItem.offset();
12621                 this.offset = {
12622                         top: this.offset.top - this.margins.top,
12623                         left: this.offset.left - this.margins.left
12624                 };
12625
12626                 // Only after we got the offset, we can change the helper's position to absolute
12627                 // TODO: Still need to figure out a way to make relative sorting possible
12628                 this.helper.css("position", "absolute");
12629                 this.cssPosition = this.helper.css("position");
12630
12631                 $.extend(this.offset, {
12632                         click: { //Where the click happened, relative to the element
12633                                 left: event.pageX - this.offset.left,
12634                                 top: event.pageY - this.offset.top
12635                         },
12636                         parent: this._getParentOffset(),
12637                         relative: this._getRelativeOffset() //This is a relative to absolute position minus the actual position calculation - only used for relative positioned helper
12638                 });
12639
12640                 //Generate the original position
12641                 this.originalPosition = this._generatePosition(event);
12642                 this.originalPageX = event.pageX;
12643                 this.originalPageY = event.pageY;
12644
12645                 //Adjust the mouse offset relative to the helper if 'cursorAt' is supplied
12646                 (o.cursorAt && this._adjustOffsetFromHelper(o.cursorAt));
12647
12648                 //Cache the former DOM position
12649                 this.domPosition = { prev: this.currentItem.prev()[0], parent: this.currentItem.parent()[0] };
12650
12651                 //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
12652                 if(this.helper[0] != this.currentItem[0]) {
12653                         this.currentItem.hide();
12654                 }
12655
12656                 //Create the placeholder
12657                 this._createPlaceholder();
12658
12659                 //Set a containment if given in the options
12660                 if(o.containment)
12661                         this._setContainment();
12662
12663                 if(o.cursor) { // cursor option
12664                         if ($('body').css("cursor")) this._storedCursor = $('body').css("cursor");
12665                         $('body').css("cursor", o.cursor);
12666                 }
12667
12668                 if(o.opacity) { // opacity option
12669                         if (this.helper.css("opacity")) this._storedOpacity = this.helper.css("opacity");
12670                         this.helper.css("opacity", o.opacity);
12671                 }
12672
12673                 if(o.zIndex) { // zIndex option
12674                         if (this.helper.css("zIndex")) this._storedZIndex = this.helper.css("zIndex");
12675                         this.helper.css("zIndex", o.zIndex);
12676                 }
12677
12678                 //Prepare scrolling
12679                 if(this.scrollParent[0] != document && this.scrollParent[0].tagName != 'HTML')
12680                         this.overflowOffset = this.scrollParent.offset();
12681
12682                 //Call callbacks
12683                 this._trigger("start", event, this._uiHash());
12684
12685                 //Recache the helper size
12686                 if(!this._preserveHelperProportions)
12687                         this._cacheHelperProportions();
12688
12689
12690                 //Post 'activate' events to possible containers
12691                 if(!noActivation) {
12692                          for (var i = this.containers.length - 1; i >= 0; i--) { this.containers[i]._trigger("activate", event, self._uiHash(this)); }
12693                 }
12694
12695                 //Prepare possible droppables
12696                 if($.ui.ddmanager)
12697                         $.ui.ddmanager.current = this;
12698
12699                 if ($.ui.ddmanager && !o.dropBehaviour)
12700                         $.ui.ddmanager.prepareOffsets(this, event);
12701
12702                 this.dragging = true;
12703
12704                 this.helper.addClass("ui-sortable-helper");
12705                 this._mouseDrag(event); //Execute the drag once - this causes the helper not to be visible before getting its correct position
12706                 return true;
12707
12708         },
12709
12710         _mouseDrag: function(event) {
12711
12712                 //Compute the helpers position
12713                 this.position = this._generatePosition(event);
12714                 this.positionAbs = this._convertPositionTo("absolute");
12715
12716                 if (!this.lastPositionAbs) {
12717                         this.lastPositionAbs = this.positionAbs;
12718                 }
12719
12720                 //Do scrolling
12721                 if(this.options.scroll) {
12722                         var o = this.options, scrolled = false;
12723                         if(this.scrollParent[0] != document && this.scrollParent[0].tagName != 'HTML') {
12724
12725                                 if((this.overflowOffset.top + this.scrollParent[0].offsetHeight) - event.pageY < o.scrollSensitivity)
12726                                         this.scrollParent[0].scrollTop = scrolled = this.scrollParent[0].scrollTop + o.scrollSpeed;
12727                                 else if(event.pageY - this.overflowOffset.top < o.scrollSensitivity)
12728                                         this.scrollParent[0].scrollTop = scrolled = this.scrollParent[0].scrollTop - o.scrollSpeed;
12729
12730                                 if((this.overflowOffset.left + this.scrollParent[0].offsetWidth) - event.pageX < o.scrollSensitivity)
12731                                         this.scrollParent[0].scrollLeft = scrolled = this.scrollParent[0].scrollLeft + o.scrollSpeed;
12732                                 else if(event.pageX - this.overflowOffset.left < o.scrollSensitivity)
12733                                         this.scrollParent[0].scrollLeft = scrolled = this.scrollParent[0].scrollLeft - o.scrollSpeed;
12734
12735                         } else {
12736
12737                                 if(event.pageY - $(document).scrollTop() < o.scrollSensitivity)
12738                                         scrolled = $(document).scrollTop($(document).scrollTop() - o.scrollSpeed);
12739                                 else if($(window).height() - (event.pageY - $(document).scrollTop()) < o.scrollSensitivity)
12740                                         scrolled = $(document).scrollTop($(document).scrollTop() + o.scrollSpeed);
12741
12742                                 if(event.pageX - $(document).scrollLeft() < o.scrollSensitivity)
12743                                         scrolled = $(document).scrollLeft($(document).scrollLeft() - o.scrollSpeed);
12744                                 else if($(window).width() - (event.pageX - $(document).scrollLeft()) < o.scrollSensitivity)
12745                                         scrolled = $(document).scrollLeft($(document).scrollLeft() + o.scrollSpeed);
12746
12747                         }
12748
12749                         if(scrolled !== false && $.ui.ddmanager && !o.dropBehaviour)
12750                                 $.ui.ddmanager.prepareOffsets(this, event);
12751                 }
12752
12753                 //Regenerate the absolute position used for position checks
12754                 this.positionAbs = this._convertPositionTo("absolute");
12755
12756                 //Set the helper position
12757                 if(!this.options.axis || this.options.axis != "y") this.helper[0].style.left = this.position.left+'px';
12758                 if(!this.options.axis || this.options.axis != "x") this.helper[0].style.top = this.position.top+'px';
12759
12760                 //Rearrange
12761                 for (var i = this.items.length - 1; i >= 0; i--) {
12762
12763                         //Cache variables and intersection, continue if no intersection
12764                         var item = this.items[i], itemElement = item.item[0], intersection = this._intersectsWithPointer(item);
12765                         if (!intersection) continue;
12766
12767                         if(itemElement != this.currentItem[0] //cannot intersect with itself
12768                                 &&      this.placeholder[intersection == 1 ? "next" : "prev"]()[0] != itemElement //no useless actions that have been done before
12769                                 &&      !$.ui.contains(this.placeholder[0], itemElement) //no action if the item moved is the parent of the item checked
12770                                 && (this.options.type == 'semi-dynamic' ? !$.ui.contains(this.element[0], itemElement) : true)
12771                                 //&& itemElement.parentNode == this.placeholder[0].parentNode // only rearrange items within the same container
12772                         ) {
12773
12774                                 this.direction = intersection == 1 ? "down" : "up";
12775
12776                                 if (this.options.tolerance == "pointer" || this._intersectsWithSides(item)) {
12777                                         this._rearrange(event, item);
12778                                 } else {
12779                                         break;
12780                                 }
12781
12782                                 this._trigger("change", event, this._uiHash());
12783                                 break;
12784                         }
12785                 }
12786
12787                 //Post events to containers
12788                 this._contactContainers(event);
12789
12790                 //Interconnect with droppables
12791                 if($.ui.ddmanager) $.ui.ddmanager.drag(this, event);
12792
12793                 //Call callbacks
12794                 this._trigger('sort', event, this._uiHash());
12795
12796                 this.lastPositionAbs = this.positionAbs;
12797                 return false;
12798
12799         },
12800
12801         _mouseStop: function(event, noPropagation) {
12802
12803                 if(!event) return;
12804
12805                 //If we are using droppables, inform the manager about the drop
12806                 if ($.ui.ddmanager && !this.options.dropBehaviour)
12807                         $.ui.ddmanager.drop(this, event);
12808
12809                 if(this.options.revert) {
12810                         var self = this;
12811                         var cur = self.placeholder.offset();
12812
12813                         self.reverting = true;
12814
12815                         $(this.helper).animate({
12816                                 left: cur.left - this.offset.parent.left - self.margins.left + (this.offsetParent[0] == document.body ? 0 : this.offsetParent[0].scrollLeft),
12817                                 top: cur.top - this.offset.parent.top - self.margins.top + (this.offsetParent[0] == document.body ? 0 : this.offsetParent[0].scrollTop)
12818                         }, parseInt(this.options.revert, 10) || 500, function() {
12819                                 self._clear(event);
12820                         });
12821                 } else {
12822                         this._clear(event, noPropagation);
12823                 }
12824
12825                 return false;
12826
12827         },
12828
12829         cancel: function() {
12830
12831                 var self = this;
12832
12833                 if(this.dragging) {
12834
12835                         this._mouseUp({ target: null });
12836
12837                         if(this.options.helper == "original")
12838                                 this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper");
12839                         else
12840                                 this.currentItem.show();
12841
12842                         //Post deactivating events to containers
12843                         for (var i = this.containers.length - 1; i >= 0; i--){
12844                                 this.containers[i]._trigger("deactivate", null, self._uiHash(this));
12845                                 if(this.containers[i].containerCache.over) {
12846                                         this.containers[i]._trigger("out", null, self._uiHash(this));
12847                                         this.containers[i].containerCache.over = 0;
12848                                 }
12849                         }
12850
12851                 }
12852
12853                 if (this.placeholder) {
12854                         //$(this.placeholder[0]).remove(); would have been the jQuery way - unfortunately, it unbinds ALL events from the original node!
12855                         if(this.placeholder[0].parentNode) this.placeholder[0].parentNode.removeChild(this.placeholder[0]);
12856                         if(this.options.helper != "original" && this.helper && this.helper[0].parentNode) this.helper.remove();
12857
12858                         $.extend(this, {
12859                                 helper: null,
12860                                 dragging: false,
12861                                 reverting: false,
12862                                 _noFinalSort: null
12863                         });
12864
12865                         if(this.domPosition.prev) {
12866                                 $(this.domPosition.prev).after(this.currentItem);
12867                         } else {
12868                                 $(this.domPosition.parent).prepend(this.currentItem);
12869                         }
12870                 }
12871
12872                 return this;
12873
12874         },
12875
12876         serialize: function(o) {
12877
12878                 var items = this._getItemsAsjQuery(o && o.connected);
12879                 var str = []; o = o || {};
12880
12881                 $(items).each(function() {
12882                         var res = ($(o.item || this).attr(o.attribute || 'id') || '').match(o.expression || (/(.+)[-=_](.+)/));
12883                         if(res) str.push((o.key || res[1]+'[]')+'='+(o.key && o.expression ? res[1] : res[2]));
12884                 });
12885
12886                 if(!str.length && o.key) {
12887                         str.push(o.key + '=');
12888                 }
12889
12890                 return str.join('&');
12891
12892         },
12893
12894         toArray: function(o) {
12895
12896                 var items = this._getItemsAsjQuery(o && o.connected);
12897                 var ret = []; o = o || {};
12898
12899                 items.each(function() { ret.push($(o.item || this).attr(o.attribute || 'id') || ''); });
12900                 return ret;
12901
12902         },
12903
12904         /* Be careful with the following core functions */
12905         _intersectsWith: function(item) {
12906
12907                 var x1 = this.positionAbs.left,
12908                         x2 = x1 + this.helperProportions.width,
12909                         y1 = this.positionAbs.top,
12910                         y2 = y1 + this.helperProportions.height;
12911
12912                 var l = item.left,
12913                         r = l + item.width,
12914                         t = item.top,
12915                         b = t + item.height;
12916
12917                 var dyClick = this.offset.click.top,
12918                         dxClick = this.offset.click.left;
12919
12920                 var isOverElement = (y1 + dyClick) > t && (y1 + dyClick) < b && (x1 + dxClick) > l && (x1 + dxClick) < r;
12921
12922                 if(        this.options.tolerance == "pointer"
12923                         || this.options.forcePointerForContainers
12924                         || (this.options.tolerance != "pointer" && this.helperProportions[this.floating ? 'width' : 'height'] > item[this.floating ? 'width' : 'height'])
12925                 ) {
12926                         return isOverElement;
12927                 } else {
12928
12929                         return (l < x1 + (this.helperProportions.width / 2) // Right Half
12930                                 && x2 - (this.helperProportions.width / 2) < r // Left Half
12931                                 && t < y1 + (this.helperProportions.height / 2) // Bottom Half
12932                                 && y2 - (this.helperProportions.height / 2) < b ); // Top Half
12933
12934                 }
12935         },
12936
12937         _intersectsWithPointer: function(item) {
12938
12939                 var isOverElementHeight = $.ui.isOverAxis(this.positionAbs.top + this.offset.click.top, item.top, item.height),
12940                         isOverElementWidth = $.ui.isOverAxis(this.positionAbs.left + this.offset.click.left, item.left, item.width),
12941                         isOverElement = isOverElementHeight && isOverElementWidth,
12942                         verticalDirection = this._getDragVerticalDirection(),
12943                         horizontalDirection = this._getDragHorizontalDirection();
12944
12945                 if (!isOverElement)
12946                         return false;
12947
12948                 return this.floating ?
12949                         ( ((horizontalDirection && horizontalDirection == "right") || verticalDirection == "down") ? 2 : 1 )
12950                         : ( verticalDirection && (verticalDirection == "down" ? 2 : 1) );
12951
12952         },
12953
12954         _intersectsWithSides: function(item) {
12955
12956                 var isOverBottomHalf = $.ui.isOverAxis(this.positionAbs.top + this.offset.click.top, item.top + (item.height/2), item.height),
12957                         isOverRightHalf = $.ui.isOverAxis(this.positionAbs.left + this.offset.click.left, item.left + (item.width/2), item.width),
12958                         verticalDirection = this._getDragVerticalDirection(),
12959                         horizontalDirection = this._getDragHorizontalDirection();
12960
12961                 if (this.floating && horizontalDirection) {
12962                         return ((horizontalDirection == "right" && isOverRightHalf) || (horizontalDirection == "left" && !isOverRightHalf));
12963                 } else {
12964                         return verticalDirection && ((verticalDirection == "down" && isOverBottomHalf) || (verticalDirection == "up" && !isOverBottomHalf));
12965                 }
12966
12967         },
12968
12969         _getDragVerticalDirection: function() {
12970                 var delta = this.positionAbs.top - this.lastPositionAbs.top;
12971                 return delta != 0 && (delta > 0 ? "down" : "up");
12972         },
12973
12974         _getDragHorizontalDirection: function() {
12975                 var delta = this.positionAbs.left - this.lastPositionAbs.left;
12976                 return delta != 0 && (delta > 0 ? "right" : "left");
12977         },
12978
12979         refresh: function(event) {
12980                 this._refreshItems(event);
12981                 this.refreshPositions();
12982                 return this;
12983         },
12984
12985         _connectWith: function() {
12986                 var options = this.options;
12987                 return options.connectWith.constructor == String
12988                         ? [options.connectWith]
12989                         : options.connectWith;
12990         },
12991         
12992         _getItemsAsjQuery: function(connected) {
12993
12994                 var self = this;
12995                 var items = [];
12996                 var queries = [];
12997                 var connectWith = this._connectWith();
12998
12999                 if(connectWith && connected) {
13000                         for (var i = connectWith.length - 1; i >= 0; i--){
13001                                 var cur = $(connectWith[i]);
13002                                 for (var j = cur.length - 1; j >= 0; j--){
13003                                         var inst = $.data(cur[j], 'sortable');
13004                                         if(inst && inst != this && !inst.options.disabled) {
13005                                                 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]);
13006                                         }
13007                                 };
13008                         };
13009                 }
13010
13011                 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]);
13012
13013                 for (var i = queries.length - 1; i >= 0; i--){
13014                         queries[i][0].each(function() {
13015                                 items.push(this);
13016                         });
13017                 };
13018
13019                 return $(items);
13020
13021         },
13022
13023         _removeCurrentsFromItems: function() {
13024
13025                 var list = this.currentItem.find(":data(sortable-item)");
13026
13027                 for (var i=0; i < this.items.length; i++) {
13028
13029                         for (var j=0; j < list.length; j++) {
13030                                 if(list[j] == this.items[i].item[0])
13031                                         this.items.splice(i,1);
13032                         };
13033
13034                 };
13035
13036         },
13037
13038         _refreshItems: function(event) {
13039
13040                 this.items = [];
13041                 this.containers = [this];
13042                 var items = this.items;
13043                 var self = this;
13044                 var queries = [[$.isFunction(this.options.items) ? this.options.items.call(this.element[0], event, { item: this.currentItem }) : $(this.options.items, this.element), this]];
13045                 var connectWith = this._connectWith();
13046
13047                 if(connectWith) {
13048                         for (var i = connectWith.length - 1; i >= 0; i--){
13049                                 var cur = $(connectWith[i]);
13050                                 for (var j = cur.length - 1; j >= 0; j--){
13051                                         var inst = $.data(cur[j], 'sortable');
13052                                         if(inst && inst != this && !inst.options.disabled) {
13053                                                 queries.push([$.isFunction(inst.options.items) ? inst.options.items.call(inst.element[0], event, { item: this.currentItem }) : $(inst.options.items, inst.element), inst]);
13054                                                 this.containers.push(inst);
13055                                         }
13056                                 };
13057                         };
13058                 }
13059
13060                 for (var i = queries.length - 1; i >= 0; i--) {
13061                         var targetData = queries[i][1];
13062                         var _queries = queries[i][0];
13063
13064                         for (var j=0, queriesLength = _queries.length; j < queriesLength; j++) {
13065                                 var item = $(_queries[j]);
13066
13067                                 item.data('sortable-item', targetData); // Data for target checking (mouse manager)
13068
13069                                 items.push({
13070                                         item: item,
13071                                         instance: targetData,
13072                                         width: 0, height: 0,
13073                                         left: 0, top: 0
13074                                 });
13075                         };
13076                 };
13077
13078         },
13079
13080         refreshPositions: function(fast) {
13081
13082                 //This has to be redone because due to the item being moved out/into the offsetParent, the offsetParent's position will change
13083                 if(this.offsetParent && this.helper) {
13084                         this.offset.parent = this._getParentOffset();
13085                 }
13086
13087                 for (var i = this.items.length - 1; i >= 0; i--){
13088                         var item = this.items[i];
13089
13090                         //We ignore calculating positions of all connected containers when we're not over them
13091                         if(item.instance != this.currentContainer && this.currentContainer && item.item[0] != this.currentItem[0])
13092                                 continue;
13093
13094                         var t = this.options.toleranceElement ? $(this.options.toleranceElement, item.item) : item.item;
13095
13096                         if (!fast) {
13097                                 item.width = t.outerWidth();
13098                                 item.height = t.outerHeight();
13099                         }
13100
13101                         var p = t.offset();
13102                         item.left = p.left;
13103                         item.top = p.top;
13104                 };
13105
13106                 if(this.options.custom && this.options.custom.refreshContainers) {
13107                         this.options.custom.refreshContainers.call(this);
13108                 } else {
13109                         for (var i = this.containers.length - 1; i >= 0; i--){
13110                                 var p = this.containers[i].element.offset();
13111                                 this.containers[i].containerCache.left = p.left;
13112                                 this.containers[i].containerCache.top = p.top;
13113                                 this.containers[i].containerCache.width = this.containers[i].element.outerWidth();
13114                                 this.containers[i].containerCache.height = this.containers[i].element.outerHeight();
13115                         };
13116                 }
13117
13118                 return this;
13119         },
13120
13121         _createPlaceholder: function(that) {
13122
13123                 var self = that || this, o = self.options;
13124
13125                 if(!o.placeholder || o.placeholder.constructor == String) {
13126                         var className = o.placeholder;
13127                         o.placeholder = {
13128                                 element: function() {
13129
13130                                         var el = $(document.createElement(self.currentItem[0].nodeName))
13131                                                 .addClass(className || self.currentItem[0].className+" ui-sortable-placeholder")
13132                                                 .removeClass("ui-sortable-helper")[0];
13133
13134                                         if(!className)
13135                                                 el.style.visibility = "hidden";
13136
13137                                         return el;
13138                                 },
13139                                 update: function(container, p) {
13140
13141                                         // 1. If a className is set as 'placeholder option, we don't force sizes - the class is responsible for that
13142                                         // 2. The option 'forcePlaceholderSize can be enabled to force it even if a class name is specified
13143                                         if(className && !o.forcePlaceholderSize) return;
13144
13145                                         //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
13146                                         if(!p.height()) { p.height(self.currentItem.innerHeight() - parseInt(self.currentItem.css('paddingTop')||0, 10) - parseInt(self.currentItem.css('paddingBottom')||0, 10)); };
13147                                         if(!p.width()) { p.width(self.currentItem.innerWidth() - parseInt(self.currentItem.css('paddingLeft')||0, 10) - parseInt(self.currentItem.css('paddingRight')||0, 10)); };
13148                                 }
13149                         };
13150                 }
13151
13152                 //Create the placeholder
13153                 self.placeholder = $(o.placeholder.element.call(self.element, self.currentItem));
13154
13155                 //Append it after the actual current item
13156                 self.currentItem.after(self.placeholder);
13157
13158                 //Update the size of the placeholder (TODO: Logic to fuzzy, see line 316/317)
13159                 o.placeholder.update(self, self.placeholder);
13160
13161         },
13162
13163         _contactContainers: function(event) {
13164                 
13165                 // get innermost container that intersects with item 
13166                 var innermostContainer = null, innermostIndex = null;           
13167                 
13168                 
13169                 for (var i = this.containers.length - 1; i >= 0; i--){
13170
13171                         // never consider a container that's located within the item itself 
13172                         if($.ui.contains(this.currentItem[0], this.containers[i].element[0]))
13173                                 continue;
13174
13175                         if(this._intersectsWith(this.containers[i].containerCache)) {
13176
13177                                 // if we've already found a container and it's more "inner" than this, then continue 
13178                                 if(innermostContainer && $.ui.contains(this.containers[i].element[0], innermostContainer.element[0]))
13179                                         continue;
13180
13181                                 innermostContainer = this.containers[i]; 
13182                                 innermostIndex = i;
13183                                         
13184                         } else {
13185                                 // container doesn't intersect. trigger "out" event if necessary 
13186                                 if(this.containers[i].containerCache.over) {
13187                                         this.containers[i]._trigger("out", event, this._uiHash(this));
13188                                         this.containers[i].containerCache.over = 0;
13189                                 }
13190                         }
13191
13192                 }
13193                 
13194                 // if no intersecting containers found, return 
13195                 if(!innermostContainer) return; 
13196
13197                 // move the item into the container if it's not there already
13198                 if(this.containers.length === 1) {
13199                         this.containers[innermostIndex]._trigger("over", event, this._uiHash(this));
13200                         this.containers[innermostIndex].containerCache.over = 1;
13201                 } else if(this.currentContainer != this.containers[innermostIndex]) { 
13202
13203                         //When entering a new container, we will find the item with the least distance and append our item near it 
13204                         var dist = 10000; var itemWithLeastDistance = null; var base = this.positionAbs[this.containers[innermostIndex].floating ? 'left' : 'top']; 
13205                         for (var j = this.items.length - 1; j >= 0; j--) { 
13206                                 if(!$.ui.contains(this.containers[innermostIndex].element[0], this.items[j].item[0])) continue; 
13207                                 var cur = this.items[j][this.containers[innermostIndex].floating ? 'left' : 'top']; 
13208                                 if(Math.abs(cur - base) < dist) { 
13209                                         dist = Math.abs(cur - base); itemWithLeastDistance = this.items[j]; 
13210                                 } 
13211                         } 
13212
13213                         if(!itemWithLeastDistance && !this.options.dropOnEmpty) //Check if dropOnEmpty is enabled 
13214                                 return; 
13215
13216                         this.currentContainer = this.containers[innermostIndex]; 
13217                         itemWithLeastDistance ? this._rearrange(event, itemWithLeastDistance, null, true) : this._rearrange(event, null, this.containers[innermostIndex].element, true); 
13218                         this._trigger("change", event, this._uiHash()); 
13219                         this.containers[innermostIndex]._trigger("change", event, this._uiHash(this)); 
13220
13221                         //Update the placeholder 
13222                         this.options.placeholder.update(this.currentContainer, this.placeholder); 
13223                 
13224                         this.containers[innermostIndex]._trigger("over", event, this._uiHash(this)); 
13225                         this.containers[innermostIndex].containerCache.over = 1;
13226                 } 
13227         
13228                 
13229         },
13230
13231         _createHelper: function(event) {
13232
13233                 var o = this.options;
13234                 var helper = $.isFunction(o.helper) ? $(o.helper.apply(this.element[0], [event, this.currentItem])) : (o.helper == 'clone' ? this.currentItem.clone() : this.currentItem);
13235
13236                 if(!helper.parents('body').length) //Add the helper to the DOM if that didn't happen already
13237                         $(o.appendTo != 'parent' ? o.appendTo : this.currentItem[0].parentNode)[0].appendChild(helper[0]);
13238
13239                 if(helper[0] == this.currentItem[0])
13240                         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") };
13241
13242                 if(helper[0].style.width == '' || o.forceHelperSize) helper.width(this.currentItem.width());
13243                 if(helper[0].style.height == '' || o.forceHelperSize) helper.height(this.currentItem.height());
13244
13245                 return helper;
13246
13247         },
13248
13249         _adjustOffsetFromHelper: function(obj) {
13250                 if (typeof obj == 'string') {
13251                         obj = obj.split(' ');
13252                 }
13253                 if ($.isArray(obj)) {
13254                         obj = {left: +obj[0], top: +obj[1] || 0};
13255                 }
13256                 if ('left' in obj) {
13257                         this.offset.click.left = obj.left + this.margins.left;
13258                 }
13259                 if ('right' in obj) {
13260                         this.offset.click.left = this.helperProportions.width - obj.right + this.margins.left;
13261                 }
13262                 if ('top' in obj) {
13263                         this.offset.click.top = obj.top + this.margins.top;
13264                 }
13265                 if ('bottom' in obj) {
13266                         this.offset.click.top = this.helperProportions.height - obj.bottom + this.margins.top;
13267                 }
13268         },
13269
13270         _getParentOffset: function() {
13271
13272
13273                 //Get the offsetParent and cache its position
13274                 this.offsetParent = this.helper.offsetParent();
13275                 var po = this.offsetParent.offset();
13276
13277                 // This is a special case where we need to modify a offset calculated on start, since the following happened:
13278                 // 1. The position of the helper is absolute, so it's position is calculated based on the next positioned parent
13279                 // 2. The actual offset parent is a child of the scroll parent, and the scroll parent isn't the document, which means that
13280                 //    the scroll is included in the initial calculation of the offset of the parent, and never recalculated upon drag
13281                 if(this.cssPosition == 'absolute' && this.scrollParent[0] != document && $.ui.contains(this.scrollParent[0], this.offsetParent[0])) {
13282                         po.left += this.scrollParent.scrollLeft();
13283                         po.top += this.scrollParent.scrollTop();
13284                 }
13285
13286                 if((this.offsetParent[0] == document.body) //This needs to be actually done for all browsers, since pageX/pageY includes this information
13287                 || (this.offsetParent[0].tagName && this.offsetParent[0].tagName.toLowerCase() == 'html' && $.browser.msie)) //Ugly IE fix
13288                         po = { top: 0, left: 0 };
13289
13290                 return {
13291                         top: po.top + (parseInt(this.offsetParent.css("borderTopWidth"),10) || 0),
13292                         left: po.left + (parseInt(this.offsetParent.css("borderLeftWidth"),10) || 0)
13293                 };
13294
13295         },
13296
13297         _getRelativeOffset: function() {
13298
13299                 if(this.cssPosition == "relative") {
13300                         var p = this.currentItem.position();
13301                         return {
13302                                 top: p.top - (parseInt(this.helper.css("top"),10) || 0) + this.scrollParent.scrollTop(),
13303                                 left: p.left - (parseInt(this.helper.css("left"),10) || 0) + this.scrollParent.scrollLeft()
13304                         };
13305                 } else {
13306                         return { top: 0, left: 0 };
13307                 }
13308
13309         },
13310
13311         _cacheMargins: function() {
13312                 this.margins = {
13313                         left: (parseInt(this.currentItem.css("marginLeft"),10) || 0),
13314                         top: (parseInt(this.currentItem.css("marginTop"),10) || 0)
13315                 };
13316         },
13317
13318         _cacheHelperProportions: function() {
13319                 this.helperProportions = {
13320                         width: this.helper.outerWidth(),
13321                         height: this.helper.outerHeight()
13322                 };
13323         },
13324
13325         _setContainment: function() {
13326
13327                 var o = this.options;
13328                 if(o.containment == 'parent') o.containment = this.helper[0].parentNode;
13329                 if(o.containment == 'document' || o.containment == 'window') this.containment = [
13330                         0 - this.offset.relative.left - this.offset.parent.left,
13331                         0 - this.offset.relative.top - this.offset.parent.top,
13332                         $(o.containment == 'document' ? document : window).width() - this.helperProportions.width - this.margins.left,
13333                         ($(o.containment == 'document' ? document : window).height() || document.body.parentNode.scrollHeight) - this.helperProportions.height - this.margins.top
13334                 ];
13335
13336                 if(!(/^(document|window|parent)$/).test(o.containment)) {
13337                         var ce = $(o.containment)[0];
13338                         var co = $(o.containment).offset();
13339                         var over = ($(ce).css("overflow") != 'hidden');
13340
13341                         this.containment = [
13342                                 co.left + (parseInt($(ce).css("borderLeftWidth"),10) || 0) + (parseInt($(ce).css("paddingLeft"),10) || 0) - this.margins.left,
13343                                 co.top + (parseInt($(ce).css("borderTopWidth"),10) || 0) + (parseInt($(ce).css("paddingTop"),10) || 0) - this.margins.top,
13344                                 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,
13345                                 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
13346                         ];
13347                 }
13348
13349         },
13350
13351         _convertPositionTo: function(d, pos) {
13352
13353                 if(!pos) pos = this.position;
13354                 var mod = d == "absolute" ? 1 : -1;
13355                 var o = this.options, scroll = this.cssPosition == 'absolute' && !(this.scrollParent[0] != document && $.ui.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent, scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName);
13356
13357                 return {
13358                         top: (
13359                                 pos.top                                                                                                                                 // The absolute mouse position
13360                                 + this.offset.relative.top * mod                                                                                // Only for relative positioned nodes: Relative offset from element to offset parent
13361                                 + this.offset.parent.top * mod                                                                                  // The offsetParent's offset without borders (offset + border)
13362                                 - ($.browser.safari && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ) * mod)
13363                         ),
13364                         left: (
13365                                 pos.left                                                                                                                                // The absolute mouse position
13366                                 + this.offset.relative.left * mod                                                                               // Only for relative positioned nodes: Relative offset from element to offset parent
13367                                 + this.offset.parent.left * mod                                                                                 // The offsetParent's offset without borders (offset + border)
13368                                 - ($.browser.safari && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ) * mod)
13369                         )
13370                 };
13371
13372         },
13373
13374         _generatePosition: function(event) {
13375
13376                 var o = this.options, scroll = this.cssPosition == 'absolute' && !(this.scrollParent[0] != document && $.ui.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent, scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName);
13377
13378                 // This is another very weird special case that only happens for relative elements:
13379                 // 1. If the css position is relative
13380                 // 2. and the scroll parent is the document or similar to the offset parent
13381                 // we have to refresh the relative offset during the scroll so there are no jumps
13382                 if(this.cssPosition == 'relative' && !(this.scrollParent[0] != document && this.scrollParent[0] != this.offsetParent[0])) {
13383                         this.offset.relative = this._getRelativeOffset();
13384                 }
13385
13386                 var pageX = event.pageX;
13387                 var pageY = event.pageY;
13388
13389                 /*
13390                  * - Position constraining -
13391                  * Constrain the position to a mix of grid, containment.
13392                  */
13393
13394                 if(this.originalPosition) { //If we are not dragging yet, we won't check for options
13395
13396                         if(this.containment) {
13397                                 if(event.pageX - this.offset.click.left < this.containment[0]) pageX = this.containment[0] + this.offset.click.left;
13398                                 if(event.pageY - this.offset.click.top < this.containment[1]) pageY = this.containment[1] + this.offset.click.top;
13399                                 if(event.pageX - this.offset.click.left > this.containment[2]) pageX = this.containment[2] + this.offset.click.left;
13400                                 if(event.pageY - this.offset.click.top > this.containment[3]) pageY = this.containment[3] + this.offset.click.top;
13401                         }
13402
13403                         if(o.grid) {
13404                                 var top = this.originalPageY + Math.round((pageY - this.originalPageY) / o.grid[1]) * o.grid[1];
13405                                 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;
13406
13407                                 var left = this.originalPageX + Math.round((pageX - this.originalPageX) / o.grid[0]) * o.grid[0];
13408                                 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;
13409                         }
13410
13411                 }
13412
13413                 return {
13414                         top: (
13415                                 pageY                                                                                                                           // The absolute mouse position
13416                                 - this.offset.click.top                                                                                                 // Click offset (relative to the element)
13417                                 - this.offset.relative.top                                                                                              // Only for relative positioned nodes: Relative offset from element to offset parent
13418                                 - this.offset.parent.top                                                                                                // The offsetParent's offset without borders (offset + border)
13419                                 + ($.browser.safari && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ))
13420                         ),
13421                         left: (
13422                                 pageX                                                                                                                           // The absolute mouse position
13423                                 - this.offset.click.left                                                                                                // Click offset (relative to the element)
13424                                 - this.offset.relative.left                                                                                             // Only for relative positioned nodes: Relative offset from element to offset parent
13425                                 - this.offset.parent.left                                                                                               // The offsetParent's offset without borders (offset + border)
13426                                 + ($.browser.safari && this.cssPosition == 'fixed' ? 0 : ( this.cssPosition == 'fixed' ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ))
13427                         )
13428                 };
13429
13430         },
13431
13432         _rearrange: function(event, i, a, hardRefresh) {
13433
13434                 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));
13435
13436                 //Various things done here to improve the performance:
13437                 // 1. we create a setTimeout, that calls refreshPositions
13438                 // 2. on the instance, we have a counter variable, that get's higher after every append
13439                 // 3. on the local scope, we copy the counter variable, and check in the timeout, if it's still the same
13440                 // 4. this lets only the last addition to the timeout stack through
13441                 this.counter = this.counter ? ++this.counter : 1;
13442                 var self = this, counter = this.counter;
13443
13444                 window.setTimeout(function() {
13445                         if(counter == self.counter) self.refreshPositions(!hardRefresh); //Precompute after each DOM insertion, NOT on mousemove
13446                 },0);
13447
13448         },
13449
13450         _clear: function(event, noPropagation) {
13451
13452                 this.reverting = false;
13453                 // We delay all events that have to be triggered to after the point where the placeholder has been removed and
13454                 // everything else normalized again
13455                 var delayedTriggers = [], self = this;
13456
13457                 // We first have to update the dom position of the actual currentItem
13458                 // Note: don't do it if the current item is already removed (by a user), or it gets reappended (see #4088)
13459                 if(!this._noFinalSort && this.currentItem[0].parentNode) this.placeholder.before(this.currentItem);
13460                 this._noFinalSort = null;
13461
13462                 if(this.helper[0] == this.currentItem[0]) {
13463                         for(var i in this._storedCSS) {
13464                                 if(this._storedCSS[i] == 'auto' || this._storedCSS[i] == 'static') this._storedCSS[i] = '';
13465                         }
13466                         this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper");
13467                 } else {
13468                         this.currentItem.show();
13469                 }
13470
13471                 if(this.fromOutside && !noPropagation) delayedTriggers.push(function(event) { this._trigger("receive", event, this._uiHash(this.fromOutside)); });
13472                 if((this.fromOutside || this.domPosition.prev != this.currentItem.prev().not(".ui-sortable-helper")[0] || this.domPosition.parent != this.currentItem.parent()[0]) && !noPropagation) delayedTriggers.push(function(event) { this._trigger("update", event, this._uiHash()); }); //Trigger update callback if the DOM position has changed
13473                 if(!$.ui.contains(this.element[0], this.currentItem[0])) { //Node was moved out of the current element
13474                         if(!noPropagation) delayedTriggers.push(function(event) { this._trigger("remove", event, this._uiHash()); });
13475                         for (var i = this.containers.length - 1; i >= 0; i--){
13476                                 if($.ui.contains(this.containers[i].element[0], this.currentItem[0]) && !noPropagation) {
13477                                         delayedTriggers.push((function(c) { return function(event) { c._trigger("receive", event, this._uiHash(this)); };  }).call(this, this.containers[i]));
13478                                         delayedTriggers.push((function(c) { return function(event) { c._trigger("update", event, this._uiHash(this));  }; }).call(this, this.containers[i]));
13479                                 }
13480                         };
13481                 };
13482
13483                 //Post events to containers
13484                 for (var i = this.containers.length - 1; i >= 0; i--){
13485                         if(!noPropagation) delayedTriggers.push((function(c) { return function(event) { c._trigger("deactivate", event, this._uiHash(this)); };  }).call(this, this.containers[i]));
13486                         if(this.containers[i].containerCache.over) {
13487                                 delayedTriggers.push((function(c) { return function(event) { c._trigger("out", event, this._uiHash(this)); };  }).call(this, this.containers[i]));
13488                                 this.containers[i].containerCache.over = 0;
13489                         }
13490                 }
13491
13492                 //Do what was originally in plugins
13493                 if(this._storedCursor) $('body').css("cursor", this._storedCursor); //Reset cursor
13494                 if(this._storedOpacity) this.helper.css("opacity", this._storedOpacity); //Reset opacity
13495                 if(this._storedZIndex) this.helper.css("zIndex", this._storedZIndex == 'auto' ? '' : this._storedZIndex); //Reset z-index
13496
13497                 this.dragging = false;
13498                 if(this.cancelHelperRemoval) {
13499                         if(!noPropagation) {
13500                                 this._trigger("beforeStop", event, this._uiHash());
13501                                 for (var i=0; i < delayedTriggers.length; i++) { delayedTriggers[i].call(this, event); }; //Trigger all delayed events
13502                                 this._trigger("stop", event, this._uiHash());
13503                         }
13504                         return false;
13505                 }
13506
13507                 if(!noPropagation) this._trigger("beforeStop", event, this._uiHash());
13508
13509                 //$(this.placeholder[0]).remove(); would have been the jQuery way - unfortunately, it unbinds ALL events from the original node!
13510                 this.placeholder[0].parentNode.removeChild(this.placeholder[0]);
13511
13512                 if(this.helper[0] != this.currentItem[0]) this.helper.remove(); this.helper = null;
13513
13514                 if(!noPropagation) {
13515                         for (var i=0; i < delayedTriggers.length; i++) { delayedTriggers[i].call(this, event); }; //Trigger all delayed events
13516                         this._trigger("stop", event, this._uiHash());
13517                 }
13518
13519                 this.fromOutside = false;
13520                 return true;
13521
13522         },
13523
13524         _trigger: function() {
13525                 if ($.Widget.prototype._trigger.apply(this, arguments) === false) {
13526                         this.cancel();
13527                 }
13528         },
13529
13530         _uiHash: function(inst) {
13531                 var self = inst || this;
13532                 return {
13533                         helper: self.helper,
13534                         placeholder: self.placeholder || $([]),
13535                         position: self.position,
13536                         originalPosition: self.originalPosition,
13537                         offset: self.positionAbs,
13538                         item: self.currentItem,
13539                         sender: inst ? inst.element : null
13540                 };
13541         }
13542
13543 });
13544
13545 $.extend($.ui.sortable, {
13546         version: "1.8.12"
13547 });
13548
13549 })(jQuery);
13550 /*
13551  * jQuery UI Effects 1.8.12
13552  *
13553  * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
13554  * Dual licensed under the MIT or GPL Version 2 licenses.
13555  * http://jquery.org/license
13556  *
13557  * http://docs.jquery.com/UI/Effects/
13558  */
13559 ;jQuery.effects || (function($, undefined) {
13560
13561 $.effects = {};
13562
13563
13564
13565 /******************************************************************************/
13566 /****************************** COLOR ANIMATIONS ******************************/
13567 /******************************************************************************/
13568
13569 // override the animation for color styles
13570 $.each(['backgroundColor', 'borderBottomColor', 'borderLeftColor',
13571         'borderRightColor', 'borderTopColor', 'borderColor', 'color', 'outlineColor'],
13572 function(i, attr) {
13573         $.fx.step[attr] = function(fx) {
13574                 if (!fx.colorInit) {
13575                         fx.start = getColor(fx.elem, attr);
13576                         fx.end = getRGB(fx.end);
13577                         fx.colorInit = true;
13578                 }
13579
13580                 fx.elem.style[attr] = 'rgb(' +
13581                         Math.max(Math.min(parseInt((fx.pos * (fx.end[0] - fx.start[0])) + fx.start[0], 10), 255), 0) + ',' +
13582                         Math.max(Math.min(parseInt((fx.pos * (fx.end[1] - fx.start[1])) + fx.start[1], 10), 255), 0) + ',' +
13583                         Math.max(Math.min(parseInt((fx.pos * (fx.end[2] - fx.start[2])) + fx.start[2], 10), 255), 0) + ')';
13584         };
13585 });
13586
13587 // Color Conversion functions from highlightFade
13588 // By Blair Mitchelmore
13589 // http://jquery.offput.ca/highlightFade/
13590
13591 // Parse strings looking for color tuples [255,255,255]
13592 function getRGB(color) {
13593                 var result;
13594
13595                 // Check if we're already dealing with an array of colors
13596                 if ( color && color.constructor == Array && color.length == 3 )
13597                                 return color;
13598
13599                 // Look for rgb(num,num,num)
13600                 if (result = /rgb\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*\)/.exec(color))
13601                                 return [parseInt(result[1],10), parseInt(result[2],10), parseInt(result[3],10)];
13602
13603                 // Look for rgb(num%,num%,num%)
13604                 if (result = /rgb\(\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*\)/.exec(color))
13605                                 return [parseFloat(result[1])*2.55, parseFloat(result[2])*2.55, parseFloat(result[3])*2.55];
13606
13607                 // Look for #a0b1c2
13608                 if (result = /#([a-fA-F0-9]{2})([a-fA-F0-9]{2})([a-fA-F0-9]{2})/.exec(color))
13609                                 return [parseInt(result[1],16), parseInt(result[2],16), parseInt(result[3],16)];
13610
13611                 // Look for #fff
13612                 if (result = /#([a-fA-F0-9])([a-fA-F0-9])([a-fA-F0-9])/.exec(color))
13613                                 return [parseInt(result[1]+result[1],16), parseInt(result[2]+result[2],16), parseInt(result[3]+result[3],16)];
13614
13615                 // Look for rgba(0, 0, 0, 0) == transparent in Safari 3
13616                 if (result = /rgba\(0, 0, 0, 0\)/.exec(color))
13617                                 return colors['transparent'];
13618
13619                 // Otherwise, we're most likely dealing with a named color
13620                 return colors[$.trim(color).toLowerCase()];
13621 }
13622
13623 function getColor(elem, attr) {
13624                 var color;
13625
13626                 do {
13627                                 color = $.curCSS(elem, attr);
13628
13629                                 // Keep going until we find an element that has color, or we hit the body
13630                                 if ( color != '' && color != 'transparent' || $.nodeName(elem, "body") )
13631                                                 break;
13632
13633                                 attr = "backgroundColor";
13634                 } while ( elem = elem.parentNode );
13635
13636                 return getRGB(color);
13637 };
13638
13639 // Some named colors to work with
13640 // From Interface by Stefan Petre
13641 // http://interface.eyecon.ro/
13642
13643 var colors = {
13644         aqua:[0,255,255],
13645         azure:[240,255,255],
13646         beige:[245,245,220],
13647         black:[0,0,0],
13648         blue:[0,0,255],
13649         brown:[165,42,42],
13650         cyan:[0,255,255],
13651         darkblue:[0,0,139],
13652         darkcyan:[0,139,139],
13653         darkgrey:[169,169,169],
13654         darkgreen:[0,100,0],
13655         darkkhaki:[189,183,107],
13656         darkmagenta:[139,0,139],
13657         darkolivegreen:[85,107,47],
13658         darkorange:[255,140,0],
13659         darkorchid:[153,50,204],
13660         darkred:[139,0,0],
13661         darksalmon:[233,150,122],
13662         darkviolet:[148,0,211],
13663         fuchsia:[255,0,255],
13664         gold:[255,215,0],
13665         green:[0,128,0],
13666         indigo:[75,0,130],
13667         khaki:[240,230,140],
13668         lightblue:[173,216,230],
13669         lightcyan:[224,255,255],
13670         lightgreen:[144,238,144],
13671         lightgrey:[211,211,211],
13672         lightpink:[255,182,193],
13673         lightyellow:[255,255,224],
13674         lime:[0,255,0],
13675         magenta:[255,0,255],
13676         maroon:[128,0,0],
13677         navy:[0,0,128],
13678         olive:[128,128,0],
13679         orange:[255,165,0],
13680         pink:[255,192,203],
13681         purple:[128,0,128],
13682         violet:[128,0,128],
13683         red:[255,0,0],
13684         silver:[192,192,192],
13685         white:[255,255,255],
13686         yellow:[255,255,0],
13687         transparent: [255,255,255]
13688 };
13689
13690
13691
13692 /******************************************************************************/
13693 /****************************** CLASS ANIMATIONS ******************************/
13694 /******************************************************************************/
13695
13696 var classAnimationActions = ['add', 'remove', 'toggle'],
13697         shorthandStyles = {
13698                 border: 1,
13699                 borderBottom: 1,
13700                 borderColor: 1,
13701                 borderLeft: 1,
13702                 borderRight: 1,
13703                 borderTop: 1,
13704                 borderWidth: 1,
13705                 margin: 1,
13706                 padding: 1
13707         };
13708
13709 function getElementStyles() {
13710         var style = document.defaultView
13711                         ? document.defaultView.getComputedStyle(this, null)
13712                         : this.currentStyle,
13713                 newStyle = {},
13714                 key,
13715                 camelCase;
13716
13717         // webkit enumerates style porperties
13718         if (style && style.length && style[0] && style[style[0]]) {
13719                 var len = style.length;
13720                 while (len--) {
13721                         key = style[len];
13722                         if (typeof style[key] == 'string') {
13723                                 camelCase = key.replace(/\-(\w)/g, function(all, letter){
13724                                         return letter.toUpperCase();
13725                                 });
13726                                 newStyle[camelCase] = style[key];
13727                         }
13728                 }
13729         } else {
13730                 for (key in style) {
13731                         if (typeof style[key] === 'string') {
13732                                 newStyle[key] = style[key];
13733                         }
13734                 }
13735         }
13736         
13737         return newStyle;
13738 }
13739
13740 function filterStyles(styles) {
13741         var name, value;
13742         for (name in styles) {
13743                 value = styles[name];
13744                 if (
13745                         // ignore null and undefined values
13746                         value == null ||
13747                         // ignore functions (when does this occur?)
13748                         $.isFunction(value) ||
13749                         // shorthand styles that need to be expanded
13750                         name in shorthandStyles ||
13751                         // ignore scrollbars (break in IE)
13752                         (/scrollbar/).test(name) ||
13753
13754                         // only colors or values that can be converted to numbers
13755                         (!(/color/i).test(name) && isNaN(parseFloat(value)))
13756                 ) {
13757                         delete styles[name];
13758                 }
13759         }
13760         
13761         return styles;
13762 }
13763
13764 function styleDifference(oldStyle, newStyle) {
13765         var diff = { _: 0 }, // http://dev.jquery.com/ticket/5459
13766                 name;
13767
13768         for (name in newStyle) {
13769                 if (oldStyle[name] != newStyle[name]) {
13770                         diff[name] = newStyle[name];
13771                 }
13772         }
13773
13774         return diff;
13775 }
13776
13777 $.effects.animateClass = function(value, duration, easing, callback) {
13778         if ($.isFunction(easing)) {
13779                 callback = easing;
13780                 easing = null;
13781         }
13782
13783         return this.queue('fx', function() {
13784                 var that = $(this),
13785                         originalStyleAttr = that.attr('style') || ' ',
13786                         originalStyle = filterStyles(getElementStyles.call(this)),
13787                         newStyle,
13788                         className = that.attr('className');
13789
13790                 $.each(classAnimationActions, function(i, action) {
13791                         if (value[action]) {
13792                                 that[action + 'Class'](value[action]);
13793                         }
13794                 });
13795                 newStyle = filterStyles(getElementStyles.call(this));
13796                 that.attr('className', className);
13797
13798                 that.animate(styleDifference(originalStyle, newStyle), duration, easing, function() {
13799                         $.each(classAnimationActions, function(i, action) {
13800                                 if (value[action]) { that[action + 'Class'](value[action]); }
13801                         });
13802                         // work around bug in IE by clearing the cssText before setting it
13803                         if (typeof that.attr('style') == 'object') {
13804                                 that.attr('style').cssText = '';
13805                                 that.attr('style').cssText = originalStyleAttr;
13806                         } else {
13807                                 that.attr('style', originalStyleAttr);
13808                         }
13809                         if (callback) { callback.apply(this, arguments); }
13810                 });
13811
13812                 // $.animate adds a function to the end of the queue
13813                 // but we want it at the front
13814                 var queue = $.queue(this),
13815                         anim = queue.splice(queue.length - 1, 1)[0];
13816                 queue.splice(1, 0, anim);
13817                 $.dequeue(this);
13818         });
13819 };
13820
13821 $.fn.extend({
13822         _addClass: $.fn.addClass,
13823         addClass: function(classNames, speed, easing, callback) {
13824                 return speed ? $.effects.animateClass.apply(this, [{ add: classNames },speed,easing,callback]) : this._addClass(classNames);
13825         },
13826
13827         _removeClass: $.fn.removeClass,
13828         removeClass: function(classNames,speed,easing,callback) {
13829                 return speed ? $.effects.animateClass.apply(this, [{ remove: classNames },speed,easing,callback]) : this._removeClass(classNames);
13830         },
13831
13832         _toggleClass: $.fn.toggleClass,
13833         toggleClass: function(classNames, force, speed, easing, callback) {
13834                 if ( typeof force == "boolean" || force === undefined ) {
13835                         if ( !speed ) {
13836                                 // without speed parameter;
13837                                 return this._toggleClass(classNames, force);
13838                         } else {
13839                                 return $.effects.animateClass.apply(this, [(force?{add:classNames}:{remove:classNames}),speed,easing,callback]);
13840                         }
13841                 } else {
13842                         // without switch parameter;
13843                         return $.effects.animateClass.apply(this, [{ toggle: classNames },force,speed,easing]);
13844                 }
13845         },
13846
13847         switchClass: function(remove,add,speed,easing,callback) {
13848                 return $.effects.animateClass.apply(this, [{ add: add, remove: remove },speed,easing,callback]);
13849         }
13850 });
13851
13852
13853
13854 /******************************************************************************/
13855 /*********************************** EFFECTS **********************************/
13856 /******************************************************************************/
13857
13858 $.extend($.effects, {
13859         version: "1.8.12",
13860
13861         // Saves a set of properties in a data storage
13862         save: function(element, set) {
13863                 for(var i=0; i < set.length; i++) {
13864                         if(set[i] !== null) element.data("ec.storage."+set[i], element[0].style[set[i]]);
13865                 }
13866         },
13867
13868         // Restores a set of previously saved properties from a data storage
13869         restore: function(element, set) {
13870                 for(var i=0; i < set.length; i++) {
13871                         if(set[i] !== null) element.css(set[i], element.data("ec.storage."+set[i]));
13872                 }
13873         },
13874
13875         setMode: function(el, mode) {
13876                 if (mode == 'toggle') mode = el.is(':hidden') ? 'show' : 'hide'; // Set for toggle
13877                 return mode;
13878         },
13879
13880         getBaseline: function(origin, original) { // Translates a [top,left] array into a baseline value
13881                 // this should be a little more flexible in the future to handle a string & hash
13882                 var y, x;
13883                 switch (origin[0]) {
13884                         case 'top': y = 0; break;
13885                         case 'middle': y = 0.5; break;
13886                         case 'bottom': y = 1; break;
13887                         default: y = origin[0] / original.height;
13888                 };
13889                 switch (origin[1]) {
13890                         case 'left': x = 0; break;
13891                         case 'center': x = 0.5; break;
13892                         case 'right': x = 1; break;
13893                         default: x = origin[1] / original.width;
13894                 };
13895                 return {x: x, y: y};
13896         },
13897
13898         // Wraps the element around a wrapper that copies position properties
13899         createWrapper: function(element) {
13900
13901                 // if the element is already wrapped, return it
13902                 if (element.parent().is('.ui-effects-wrapper')) {
13903                         return element.parent();
13904                 }
13905
13906                 // wrap the element
13907                 var props = {
13908                                 width: element.outerWidth(true),
13909                                 height: element.outerHeight(true),
13910                                 'float': element.css('float')
13911                         },
13912                         wrapper = $('<div></div>')
13913                                 .addClass('ui-effects-wrapper')
13914                                 .css({
13915                                         fontSize: '100%',
13916                                         background: 'transparent',
13917                                         border: 'none',
13918                                         margin: 0,
13919                                         padding: 0
13920                                 });
13921
13922                 element.wrap(wrapper);
13923                 wrapper = element.parent(); //Hotfix for jQuery 1.4 since some change in wrap() seems to actually loose the reference to the wrapped element
13924
13925                 // transfer positioning properties to the wrapper
13926                 if (element.css('position') == 'static') {
13927                         wrapper.css({ position: 'relative' });
13928                         element.css({ position: 'relative' });
13929                 } else {
13930                         $.extend(props, {
13931                                 position: element.css('position'),
13932                                 zIndex: element.css('z-index')
13933                         });
13934                         $.each(['top', 'left', 'bottom', 'right'], function(i, pos) {
13935                                 props[pos] = element.css(pos);
13936                                 if (isNaN(parseInt(props[pos], 10))) {
13937                                         props[pos] = 'auto';
13938                                 }
13939                         });
13940                         element.css({position: 'relative', top: 0, left: 0, right: 'auto', bottom: 'auto' });
13941                 }
13942
13943                 return wrapper.css(props).show();
13944         },
13945
13946         removeWrapper: function(element) {
13947                 if (element.parent().is('.ui-effects-wrapper'))
13948                         return element.parent().replaceWith(element);
13949                 return element;
13950         },
13951
13952         setTransition: function(element, list, factor, value) {
13953                 value = value || {};
13954                 $.each(list, function(i, x){
13955                         unit = element.cssUnit(x);
13956                         if (unit[0] > 0) value[x] = unit[0] * factor + unit[1];
13957                 });
13958                 return value;
13959         }
13960 });
13961
13962
13963 function _normalizeArguments(effect, options, speed, callback) {
13964         // shift params for method overloading
13965         if (typeof effect == 'object') {
13966                 callback = options;
13967                 speed = null;
13968                 options = effect;
13969                 effect = options.effect;
13970         }
13971         if ($.isFunction(options)) {
13972                 callback = options;
13973                 speed = null;
13974                 options = {};
13975         }
13976         if (typeof options == 'number' || $.fx.speeds[options]) {
13977                 callback = speed;
13978                 speed = options;
13979                 options = {};
13980         }
13981         if ($.isFunction(speed)) {
13982                 callback = speed;
13983                 speed = null;
13984         }
13985
13986         options = options || {};
13987
13988         speed = speed || options.duration;
13989         speed = $.fx.off ? 0 : typeof speed == 'number'
13990                 ? speed : speed in $.fx.speeds ? $.fx.speeds[speed] : $.fx.speeds._default;
13991
13992         callback = callback || options.complete;
13993
13994         return [effect, options, speed, callback];
13995 }
13996
13997 function standardSpeed( speed ) {
13998         // valid standard speeds
13999         if ( !speed || typeof speed === "number" || $.fx.speeds[ speed ] ) {
14000                 return true;
14001         }
14002         
14003         // invalid strings - treat as "normal" speed
14004         if ( typeof speed === "string" && !$.effects[ speed ] ) {
14005                 return true;
14006         }
14007         
14008         return false;
14009 }
14010
14011 $.fn.extend({
14012         effect: function(effect, options, speed, callback) {
14013                 var args = _normalizeArguments.apply(this, arguments),
14014                         // TODO: make effects take actual parameters instead of a hash
14015                         args2 = {
14016                                 options: args[1],
14017                                 duration: args[2],
14018                                 callback: args[3]
14019                         },
14020                         mode = args2.options.mode,
14021                         effectMethod = $.effects[effect];
14022                 
14023                 if ( $.fx.off || !effectMethod ) {
14024                         // delegate to the original method (e.g., .show()) if possible
14025                         if ( mode ) {
14026                                 return this[ mode ]( args2.duration, args2.callback );
14027                         } else {
14028                                 return this.each(function() {
14029                                         if ( args2.callback ) {
14030                                                 args2.callback.call( this );
14031                                         }
14032                                 });
14033                         }
14034                 }
14035                 
14036                 return effectMethod.call(this, args2);
14037         },
14038
14039         _show: $.fn.show,
14040         show: function(speed) {
14041                 if ( standardSpeed( speed ) ) {
14042                         return this._show.apply(this, arguments);
14043                 } else {
14044                         var args = _normalizeArguments.apply(this, arguments);
14045                         args[1].mode = 'show';
14046                         return this.effect.apply(this, args);
14047                 }
14048         },
14049
14050         _hide: $.fn.hide,
14051         hide: function(speed) {
14052                 if ( standardSpeed( speed ) ) {
14053                         return this._hide.apply(this, arguments);
14054                 } else {
14055                         var args = _normalizeArguments.apply(this, arguments);
14056                         args[1].mode = 'hide';
14057                         return this.effect.apply(this, args);
14058                 }
14059         },
14060
14061         // jQuery core overloads toggle and creates _toggle
14062         __toggle: $.fn.toggle,
14063         toggle: function(speed) {
14064                 if ( standardSpeed( speed ) || typeof speed === "boolean" || $.isFunction( speed ) ) {
14065                         return this.__toggle.apply(this, arguments);
14066                 } else {
14067                         var args = _normalizeArguments.apply(this, arguments);
14068                         args[1].mode = 'toggle';
14069                         return this.effect.apply(this, args);
14070                 }
14071         },
14072
14073         // helper functions
14074         cssUnit: function(key) {
14075                 var style = this.css(key), val = [];
14076                 $.each( ['em','px','%','pt'], function(i, unit){
14077                         if(style.indexOf(unit) > 0)
14078                                 val = [parseFloat(style), unit];
14079                 });
14080                 return val;
14081         }
14082 });
14083
14084
14085
14086 /******************************************************************************/
14087 /*********************************** EASING ***********************************/
14088 /******************************************************************************/
14089
14090 /*
14091  * jQuery Easing v1.3 - http://gsgd.co.uk/sandbox/jquery/easing/
14092  *
14093  * Uses the built in easing capabilities added In jQuery 1.1
14094  * to offer multiple easing options
14095  *
14096  * TERMS OF USE - jQuery Easing
14097  *
14098  * Open source under the BSD License.
14099  *
14100  * Copyright 2008 George McGinley Smith
14101  * All rights reserved.
14102  *
14103  * Redistribution and use in source and binary forms, with or without modification,
14104  * are permitted provided that the following conditions are met:
14105  *
14106  * Redistributions of source code must retain the above copyright notice, this list of
14107  * conditions and the following disclaimer.
14108  * Redistributions in binary form must reproduce the above copyright notice, this list
14109  * of conditions and the following disclaimer in the documentation and/or other materials
14110  * provided with the distribution.
14111  *
14112  * Neither the name of the author nor the names of contributors may be used to endorse
14113  * or promote products derived from this software without specific prior written permission.
14114  *
14115  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
14116  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
14117  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
14118  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
14119  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
14120  * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
14121  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
14122  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
14123  * OF THE POSSIBILITY OF SUCH DAMAGE.
14124  *
14125 */
14126
14127 // t: current time, b: begInnIng value, c: change In value, d: duration
14128 $.easing.jswing = $.easing.swing;
14129
14130 $.extend($.easing,
14131 {
14132         def: 'easeOutQuad',
14133         swing: function (x, t, b, c, d) {
14134                 //alert($.easing.default);
14135                 return $.easing[$.easing.def](x, t, b, c, d);
14136         },
14137         easeInQuad: function (x, t, b, c, d) {
14138                 return c*(t/=d)*t + b;
14139         },
14140         easeOutQuad: function (x, t, b, c, d) {
14141                 return -c *(t/=d)*(t-2) + b;
14142         },
14143         easeInOutQuad: function (x, t, b, c, d) {
14144                 if ((t/=d/2) < 1) return c/2*t*t + b;
14145                 return -c/2 * ((--t)*(t-2) - 1) + b;
14146         },
14147         easeInCubic: function (x, t, b, c, d) {
14148                 return c*(t/=d)*t*t + b;
14149         },
14150         easeOutCubic: function (x, t, b, c, d) {
14151                 return c*((t=t/d-1)*t*t + 1) + b;
14152         },
14153         easeInOutCubic: function (x, t, b, c, d) {
14154                 if ((t/=d/2) < 1) return c/2*t*t*t + b;
14155                 return c/2*((t-=2)*t*t + 2) + b;
14156         },
14157         easeInQuart: function (x, t, b, c, d) {
14158                 return c*(t/=d)*t*t*t + b;
14159         },
14160         easeOutQuart: function (x, t, b, c, d) {
14161                 return -c * ((t=t/d-1)*t*t*t - 1) + b;
14162         },
14163         easeInOutQuart: function (x, t, b, c, d) {
14164                 if ((t/=d/2) < 1) return c/2*t*t*t*t + b;
14165                 return -c/2 * ((t-=2)*t*t*t - 2) + b;
14166         },
14167         easeInQuint: function (x, t, b, c, d) {
14168                 return c*(t/=d)*t*t*t*t + b;
14169         },
14170         easeOutQuint: function (x, t, b, c, d) {
14171                 return c*((t=t/d-1)*t*t*t*t + 1) + b;
14172         },
14173         easeInOutQuint: function (x, t, b, c, d) {
14174                 if ((t/=d/2) < 1) return c/2*t*t*t*t*t + b;
14175                 return c/2*((t-=2)*t*t*t*t + 2) + b;
14176         },
14177         easeInSine: function (x, t, b, c, d) {
14178                 return -c * Math.cos(t/d * (Math.PI/2)) + c + b;
14179         },
14180         easeOutSine: function (x, t, b, c, d) {
14181                 return c * Math.sin(t/d * (Math.PI/2)) + b;
14182         },
14183         easeInOutSine: function (x, t, b, c, d) {
14184                 return -c/2 * (Math.cos(Math.PI*t/d) - 1) + b;
14185         },
14186         easeInExpo: function (x, t, b, c, d) {
14187                 return (t==0) ? b : c * Math.pow(2, 10 * (t/d - 1)) + b;
14188         },
14189         easeOutExpo: function (x, t, b, c, d) {
14190                 return (t==d) ? b+c : c * (-Math.pow(2, -10 * t/d) + 1) + b;
14191         },
14192         easeInOutExpo: function (x, t, b, c, d) {
14193                 if (t==0) return b;
14194                 if (t==d) return b+c;
14195                 if ((t/=d/2) < 1) return c/2 * Math.pow(2, 10 * (t - 1)) + b;
14196                 return c/2 * (-Math.pow(2, -10 * --t) + 2) + b;
14197         },
14198         easeInCirc: function (x, t, b, c, d) {
14199                 return -c * (Math.sqrt(1 - (t/=d)*t) - 1) + b;
14200         },
14201         easeOutCirc: function (x, t, b, c, d) {
14202                 return c * Math.sqrt(1 - (t=t/d-1)*t) + b;
14203         },
14204         easeInOutCirc: function (x, t, b, c, d) {
14205                 if ((t/=d/2) < 1) return -c/2 * (Math.sqrt(1 - t*t) - 1) + b;
14206                 return c/2 * (Math.sqrt(1 - (t-=2)*t) + 1) + b;
14207         },
14208         easeInElastic: function (x, t, b, c, d) {
14209                 var s=1.70158;var p=0;var a=c;
14210                 if (t==0) return b;  if ((t/=d)==1) return b+c;  if (!p) p=d*.3;
14211                 if (a < Math.abs(c)) { a=c; var s=p/4; }
14212                 else var s = p/(2*Math.PI) * Math.asin (c/a);
14213                 return -(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )) + b;
14214         },
14215         easeOutElastic: function (x, t, b, c, d) {
14216                 var s=1.70158;var p=0;var a=c;
14217                 if (t==0) return b;  if ((t/=d)==1) return b+c;  if (!p) p=d*.3;
14218                 if (a < Math.abs(c)) { a=c; var s=p/4; }
14219                 else var s = p/(2*Math.PI) * Math.asin (c/a);
14220                 return a*Math.pow(2,-10*t) * Math.sin( (t*d-s)*(2*Math.PI)/p ) + c + b;
14221         },
14222         easeInOutElastic: function (x, t, b, c, d) {
14223                 var s=1.70158;var p=0;var a=c;
14224                 if (t==0) return b;  if ((t/=d/2)==2) return b+c;  if (!p) p=d*(.3*1.5);
14225                 if (a < Math.abs(c)) { a=c; var s=p/4; }
14226                 else var s = p/(2*Math.PI) * Math.asin (c/a);
14227                 if (t < 1) return -.5*(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )) + b;
14228                 return a*Math.pow(2,-10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )*.5 + c + b;
14229         },
14230         easeInBack: function (x, t, b, c, d, s) {
14231                 if (s == undefined) s = 1.70158;
14232                 return c*(t/=d)*t*((s+1)*t - s) + b;
14233         },
14234         easeOutBack: function (x, t, b, c, d, s) {
14235                 if (s == undefined) s = 1.70158;
14236                 return c*((t=t/d-1)*t*((s+1)*t + s) + 1) + b;
14237         },
14238         easeInOutBack: function (x, t, b, c, d, s) {
14239                 if (s == undefined) s = 1.70158;
14240                 if ((t/=d/2) < 1) return c/2*(t*t*(((s*=(1.525))+1)*t - s)) + b;
14241                 return c/2*((t-=2)*t*(((s*=(1.525))+1)*t + s) + 2) + b;
14242         },
14243         easeInBounce: function (x, t, b, c, d) {
14244                 return c - $.easing.easeOutBounce (x, d-t, 0, c, d) + b;
14245         },
14246         easeOutBounce: function (x, t, b, c, d) {
14247                 if ((t/=d) < (1/2.75)) {
14248                         return c*(7.5625*t*t) + b;
14249                 } else if (t < (2/2.75)) {
14250                         return c*(7.5625*(t-=(1.5/2.75))*t + .75) + b;
14251                 } else if (t < (2.5/2.75)) {
14252                         return c*(7.5625*(t-=(2.25/2.75))*t + .9375) + b;
14253                 } else {
14254                         return c*(7.5625*(t-=(2.625/2.75))*t + .984375) + b;
14255                 }
14256         },
14257         easeInOutBounce: function (x, t, b, c, d) {
14258                 if (t < d/2) return $.easing.easeInBounce (x, t*2, 0, c, d) * .5 + b;
14259                 return $.easing.easeOutBounce (x, t*2-d, 0, c, d) * .5 + c*.5 + b;
14260         }
14261 });
14262
14263 /*
14264  *
14265  * TERMS OF USE - EASING EQUATIONS
14266  *
14267  * Open source under the BSD License.
14268  *
14269  * Copyright 2001 Robert Penner
14270  * All rights reserved.
14271  *
14272  * Redistribution and use in source and binary forms, with or without modification,
14273  * are permitted provided that the following conditions are met:
14274  *
14275  * Redistributions of source code must retain the above copyright notice, this list of
14276  * conditions and the following disclaimer.
14277  * Redistributions in binary form must reproduce the above copyright notice, this list
14278  * of conditions and the following disclaimer in the documentation and/or other materials
14279  * provided with the distribution.
14280  *
14281  * Neither the name of the author nor the names of contributors may be used to endorse
14282  * or promote products derived from this software without specific prior written permission.
14283  *
14284  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
14285  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
14286  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
14287  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
14288  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
14289  * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
14290  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
14291  * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
14292  * OF THE POSSIBILITY OF SUCH DAMAGE.
14293  *
14294  */
14295
14296 })(jQuery);
14297 /*
14298  * jQuery UI Effects Blind 1.8.12
14299  *
14300  * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
14301  * Dual licensed under the MIT or GPL Version 2 licenses.
14302  * http://jquery.org/license
14303  *
14304  * http://docs.jquery.com/UI/Effects/Blind
14305  *
14306  * Depends:
14307  *      jquery.effects.core.js
14308  */
14309 (function( $, undefined ) {
14310
14311 $.effects.blind = function(o) {
14312
14313         return this.queue(function() {
14314
14315                 // Create element
14316                 var el = $(this), props = ['position','top','bottom','left','right'];
14317
14318                 // Set options
14319                 var mode = $.effects.setMode(el, o.options.mode || 'hide'); // Set Mode
14320                 var direction = o.options.direction || 'vertical'; // Default direction
14321
14322                 // Adjust
14323                 $.effects.save(el, props); el.show(); // Save & Show
14324                 var wrapper = $.effects.createWrapper(el).css({overflow:'hidden'}); // Create Wrapper
14325                 var ref = (direction == 'vertical') ? 'height' : 'width';
14326                 var distance = (direction == 'vertical') ? wrapper.height() : wrapper.width();
14327                 if(mode == 'show') wrapper.css(ref, 0); // Shift
14328
14329                 // Animation
14330                 var animation = {};
14331                 animation[ref] = mode == 'show' ? distance : 0;
14332
14333                 // Animate
14334                 wrapper.animate(animation, o.duration, o.options.easing, function() {
14335                         if(mode == 'hide') el.hide(); // Hide
14336                         $.effects.restore(el, props); $.effects.removeWrapper(el); // Restore
14337                         if(o.callback) o.callback.apply(el[0], arguments); // Callback
14338                         el.dequeue();
14339                 });
14340
14341         });
14342
14343 };
14344
14345 })(jQuery);
14346 /*
14347  * jQuery UI Effects Bounce 1.8.12
14348  *
14349  * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
14350  * Dual licensed under the MIT or GPL Version 2 licenses.
14351  * http://jquery.org/license
14352  *
14353  * http://docs.jquery.com/UI/Effects/Bounce
14354  *
14355  * Depends:
14356  *      jquery.effects.core.js
14357  */
14358 (function( $, undefined ) {
14359
14360 $.effects.bounce = function(o) {
14361
14362         return this.queue(function() {
14363
14364                 // Create element
14365                 var el = $(this), props = ['position','top','bottom','left','right'];
14366
14367                 // Set options
14368                 var mode = $.effects.setMode(el, o.options.mode || 'effect'); // Set Mode
14369                 var direction = o.options.direction || 'up'; // Default direction
14370                 var distance = o.options.distance || 20; // Default distance
14371                 var times = o.options.times || 5; // Default # of times
14372                 var speed = o.duration || 250; // Default speed per bounce
14373                 if (/show|hide/.test(mode)) props.push('opacity'); // Avoid touching opacity to prevent clearType and PNG issues in IE
14374
14375                 // Adjust
14376                 $.effects.save(el, props); el.show(); // Save & Show
14377                 $.effects.createWrapper(el); // Create Wrapper
14378                 var ref = (direction == 'up' || direction == 'down') ? 'top' : 'left';
14379                 var motion = (direction == 'up' || direction == 'left') ? 'pos' : 'neg';
14380                 var distance = o.options.distance || (ref == 'top' ? el.outerHeight({margin:true}) / 3 : el.outerWidth({margin:true}) / 3);
14381                 if (mode == 'show') el.css('opacity', 0).css(ref, motion == 'pos' ? -distance : distance); // Shift
14382                 if (mode == 'hide') distance = distance / (times * 2);
14383                 if (mode != 'hide') times--;
14384
14385                 // Animate
14386                 if (mode == 'show') { // Show Bounce
14387                         var animation = {opacity: 1};
14388                         animation[ref] = (motion == 'pos' ? '+=' : '-=') + distance;
14389                         el.animate(animation, speed / 2, o.options.easing);
14390                         distance = distance / 2;
14391                         times--;
14392                 };
14393                 for (var i = 0; i < times; i++) { // Bounces
14394                         var animation1 = {}, animation2 = {};
14395                         animation1[ref] = (motion == 'pos' ? '-=' : '+=') + distance;
14396                         animation2[ref] = (motion == 'pos' ? '+=' : '-=') + distance;
14397                         el.animate(animation1, speed / 2, o.options.easing).animate(animation2, speed / 2, o.options.easing);
14398                         distance = (mode == 'hide') ? distance * 2 : distance / 2;
14399                 };
14400                 if (mode == 'hide') { // Last Bounce
14401                         var animation = {opacity: 0};
14402                         animation[ref] = (motion == 'pos' ? '-=' : '+=')  + distance;
14403                         el.animate(animation, speed / 2, o.options.easing, function(){
14404                                 el.hide(); // Hide
14405                                 $.effects.restore(el, props); $.effects.removeWrapper(el); // Restore
14406                                 if(o.callback) o.callback.apply(this, arguments); // Callback
14407                         });
14408                 } else {
14409                         var animation1 = {}, animation2 = {};
14410                         animation1[ref] = (motion == 'pos' ? '-=' : '+=') + distance;
14411                         animation2[ref] = (motion == 'pos' ? '+=' : '-=') + distance;
14412                         el.animate(animation1, speed / 2, o.options.easing).animate(animation2, speed / 2, o.options.easing, function(){
14413                                 $.effects.restore(el, props); $.effects.removeWrapper(el); // Restore
14414                                 if(o.callback) o.callback.apply(this, arguments); // Callback
14415                         });
14416                 };
14417                 el.queue('fx', function() { el.dequeue(); });
14418                 el.dequeue();
14419         });
14420
14421 };
14422
14423 })(jQuery);
14424 /*
14425  * jQuery UI Effects Clip 1.8.12
14426  *
14427  * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
14428  * Dual licensed under the MIT or GPL Version 2 licenses.
14429  * http://jquery.org/license
14430  *
14431  * http://docs.jquery.com/UI/Effects/Clip
14432  *
14433  * Depends:
14434  *      jquery.effects.core.js
14435  */
14436 (function( $, undefined ) {
14437
14438 $.effects.clip = function(o) {
14439
14440         return this.queue(function() {
14441
14442                 // Create element
14443                 var el = $(this), props = ['position','top','bottom','left','right','height','width'];
14444
14445                 // Set options
14446                 var mode = $.effects.setMode(el, o.options.mode || 'hide'); // Set Mode
14447                 var direction = o.options.direction || 'vertical'; // Default direction
14448
14449                 // Adjust
14450                 $.effects.save(el, props); el.show(); // Save & Show
14451                 var wrapper = $.effects.createWrapper(el).css({overflow:'hidden'}); // Create Wrapper
14452                 var animate = el[0].tagName == 'IMG' ? wrapper : el;
14453                 var ref = {
14454                         size: (direction == 'vertical') ? 'height' : 'width',
14455                         position: (direction == 'vertical') ? 'top' : 'left'
14456                 };
14457                 var distance = (direction == 'vertical') ? animate.height() : animate.width();
14458                 if(mode == 'show') { animate.css(ref.size, 0); animate.css(ref.position, distance / 2); } // Shift
14459
14460                 // Animation
14461                 var animation = {};
14462                 animation[ref.size] = mode == 'show' ? distance : 0;
14463                 animation[ref.position] = mode == 'show' ? 0 : distance / 2;
14464
14465                 // Animate
14466                 animate.animate(animation, { queue: false, duration: o.duration, easing: o.options.easing, complete: function() {
14467                         if(mode == 'hide') el.hide(); // Hide
14468                         $.effects.restore(el, props); $.effects.removeWrapper(el); // Restore
14469                         if(o.callback) o.callback.apply(el[0], arguments); // Callback
14470                         el.dequeue();
14471                 }});
14472
14473         });
14474
14475 };
14476
14477 })(jQuery);
14478 /*
14479  * jQuery UI Effects Drop 1.8.12
14480  *
14481  * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
14482  * Dual licensed under the MIT or GPL Version 2 licenses.
14483  * http://jquery.org/license
14484  *
14485  * http://docs.jquery.com/UI/Effects/Drop
14486  *
14487  * Depends:
14488  *      jquery.effects.core.js
14489  */
14490 (function( $, undefined ) {
14491
14492 $.effects.drop = function(o) {
14493
14494         return this.queue(function() {
14495
14496                 // Create element
14497                 var el = $(this), props = ['position','top','bottom','left','right','opacity'];
14498
14499                 // Set options
14500                 var mode = $.effects.setMode(el, o.options.mode || 'hide'); // Set Mode
14501                 var direction = o.options.direction || 'left'; // Default Direction
14502
14503                 // Adjust
14504                 $.effects.save(el, props); el.show(); // Save & Show
14505                 $.effects.createWrapper(el); // Create Wrapper
14506                 var ref = (direction == 'up' || direction == 'down') ? 'top' : 'left';
14507                 var motion = (direction == 'up' || direction == 'left') ? 'pos' : 'neg';
14508                 var distance = o.options.distance || (ref == 'top' ? el.outerHeight({margin:true}) / 2 : el.outerWidth({margin:true}) / 2);
14509                 if (mode == 'show') el.css('opacity', 0).css(ref, motion == 'pos' ? -distance : distance); // Shift
14510
14511                 // Animation
14512                 var animation = {opacity: mode == 'show' ? 1 : 0};
14513                 animation[ref] = (mode == 'show' ? (motion == 'pos' ? '+=' : '-=') : (motion == 'pos' ? '-=' : '+=')) + distance;
14514
14515                 // Animate
14516                 el.animate(animation, { queue: false, duration: o.duration, easing: o.options.easing, complete: function() {
14517                         if(mode == 'hide') el.hide(); // Hide
14518                         $.effects.restore(el, props); $.effects.removeWrapper(el); // Restore
14519                         if(o.callback) o.callback.apply(this, arguments); // Callback
14520                         el.dequeue();
14521                 }});
14522
14523         });
14524
14525 };
14526
14527 })(jQuery);
14528 /*
14529  * jQuery UI Effects Explode 1.8.12
14530  *
14531  * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
14532  * Dual licensed under the MIT or GPL Version 2 licenses.
14533  * http://jquery.org/license
14534  *
14535  * http://docs.jquery.com/UI/Effects/Explode
14536  *
14537  * Depends:
14538  *      jquery.effects.core.js
14539  */
14540 (function( $, undefined ) {
14541
14542 $.effects.explode = function(o) {
14543
14544         return this.queue(function() {
14545
14546         var rows = o.options.pieces ? Math.round(Math.sqrt(o.options.pieces)) : 3;
14547         var cells = o.options.pieces ? Math.round(Math.sqrt(o.options.pieces)) : 3;
14548
14549         o.options.mode = o.options.mode == 'toggle' ? ($(this).is(':visible') ? 'hide' : 'show') : o.options.mode;
14550         var el = $(this).show().css('visibility', 'hidden');
14551         var offset = el.offset();
14552
14553         //Substract the margins - not fixing the problem yet.
14554         offset.top -= parseInt(el.css("marginTop"),10) || 0;
14555         offset.left -= parseInt(el.css("marginLeft"),10) || 0;
14556
14557         var width = el.outerWidth(true);
14558         var height = el.outerHeight(true);
14559
14560         for(var i=0;i<rows;i++) { // =
14561                 for(var j=0;j<cells;j++) { // ||
14562                         el
14563                                 .clone()
14564                                 .appendTo('body')
14565                                 .wrap('<div></div>')
14566                                 .css({
14567                                         position: 'absolute',
14568                                         visibility: 'visible',
14569                                         left: -j*(width/cells),
14570                                         top: -i*(height/rows)
14571                                 })
14572                                 .parent()
14573                                 .addClass('ui-effects-explode')
14574                                 .css({
14575                                         position: 'absolute',
14576                                         overflow: 'hidden',
14577                                         width: width/cells,
14578                                         height: height/rows,
14579                                         left: offset.left + j*(width/cells) + (o.options.mode == 'show' ? (j-Math.floor(cells/2))*(width/cells) : 0),
14580                                         top: offset.top + i*(height/rows) + (o.options.mode == 'show' ? (i-Math.floor(rows/2))*(height/rows) : 0),
14581                                         opacity: o.options.mode == 'show' ? 0 : 1
14582                                 }).animate({
14583                                         left: offset.left + j*(width/cells) + (o.options.mode == 'show' ? 0 : (j-Math.floor(cells/2))*(width/cells)),
14584                                         top: offset.top + i*(height/rows) + (o.options.mode == 'show' ? 0 : (i-Math.floor(rows/2))*(height/rows)),
14585                                         opacity: o.options.mode == 'show' ? 1 : 0
14586                                 }, o.duration || 500);
14587                 }
14588         }
14589
14590         // Set a timeout, to call the callback approx. when the other animations have finished
14591         setTimeout(function() {
14592
14593                 o.options.mode == 'show' ? el.css({ visibility: 'visible' }) : el.css({ visibility: 'visible' }).hide();
14594                                 if(o.callback) o.callback.apply(el[0]); // Callback
14595                                 el.dequeue();
14596
14597                                 $('div.ui-effects-explode').remove();
14598
14599         }, o.duration || 500);
14600
14601
14602         });
14603
14604 };
14605
14606 })(jQuery);
14607 /*
14608  * jQuery UI Effects Fade 1.8.12
14609  *
14610  * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
14611  * Dual licensed under the MIT or GPL Version 2 licenses.
14612  * http://jquery.org/license
14613  *
14614  * http://docs.jquery.com/UI/Effects/Fade
14615  *
14616  * Depends:
14617  *      jquery.effects.core.js
14618  */
14619 (function( $, undefined ) {
14620
14621 $.effects.fade = function(o) {
14622         return this.queue(function() {
14623                 var elem = $(this),
14624                         mode = $.effects.setMode(elem, o.options.mode || 'hide');
14625
14626                 elem.animate({ opacity: mode }, {
14627                         queue: false,
14628                         duration: o.duration,
14629                         easing: o.options.easing,
14630                         complete: function() {
14631                                 (o.callback && o.callback.apply(this, arguments));
14632                                 elem.dequeue();
14633                         }
14634                 });
14635         });
14636 };
14637
14638 })(jQuery);
14639 /*
14640  * jQuery UI Effects Fold 1.8.12
14641  *
14642  * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
14643  * Dual licensed under the MIT or GPL Version 2 licenses.
14644  * http://jquery.org/license
14645  *
14646  * http://docs.jquery.com/UI/Effects/Fold
14647  *
14648  * Depends:
14649  *      jquery.effects.core.js
14650  */
14651 (function( $, undefined ) {
14652
14653 $.effects.fold = function(o) {
14654
14655         return this.queue(function() {
14656
14657                 // Create element
14658                 var el = $(this), props = ['position','top','bottom','left','right'];
14659
14660                 // Set options
14661                 var mode = $.effects.setMode(el, o.options.mode || 'hide'); // Set Mode
14662                 var size = o.options.size || 15; // Default fold size
14663                 var horizFirst = !(!o.options.horizFirst); // Ensure a boolean value
14664                 var duration = o.duration ? o.duration / 2 : $.fx.speeds._default / 2;
14665
14666                 // Adjust
14667                 $.effects.save(el, props); el.show(); // Save & Show
14668                 var wrapper = $.effects.createWrapper(el).css({overflow:'hidden'}); // Create Wrapper
14669                 var widthFirst = ((mode == 'show') != horizFirst);
14670                 var ref = widthFirst ? ['width', 'height'] : ['height', 'width'];
14671                 var distance = widthFirst ? [wrapper.width(), wrapper.height()] : [wrapper.height(), wrapper.width()];
14672                 var percent = /([0-9]+)%/.exec(size);
14673                 if(percent) size = parseInt(percent[1],10) / 100 * distance[mode == 'hide' ? 0 : 1];
14674                 if(mode == 'show') wrapper.css(horizFirst ? {height: 0, width: size} : {height: size, width: 0}); // Shift
14675
14676                 // Animation
14677                 var animation1 = {}, animation2 = {};
14678                 animation1[ref[0]] = mode == 'show' ? distance[0] : size;
14679                 animation2[ref[1]] = mode == 'show' ? distance[1] : 0;
14680
14681                 // Animate
14682                 wrapper.animate(animation1, duration, o.options.easing)
14683                 .animate(animation2, duration, o.options.easing, function() {
14684                         if(mode == 'hide') el.hide(); // Hide
14685                         $.effects.restore(el, props); $.effects.removeWrapper(el); // Restore
14686                         if(o.callback) o.callback.apply(el[0], arguments); // Callback
14687                         el.dequeue();
14688                 });
14689
14690         });
14691
14692 };
14693
14694 })(jQuery);
14695 /*
14696  * jQuery UI Effects Highlight 1.8.12
14697  *
14698  * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
14699  * Dual licensed under the MIT or GPL Version 2 licenses.
14700  * http://jquery.org/license
14701  *
14702  * http://docs.jquery.com/UI/Effects/Highlight
14703  *
14704  * Depends:
14705  *      jquery.effects.core.js
14706  */
14707 (function( $, undefined ) {
14708
14709 $.effects.highlight = function(o) {
14710         return this.queue(function() {
14711                 var elem = $(this),
14712                         props = ['backgroundImage', 'backgroundColor', 'opacity'],
14713                         mode = $.effects.setMode(elem, o.options.mode || 'show'),
14714                         animation = {
14715                                 backgroundColor: elem.css('backgroundColor')
14716                         };
14717
14718                 if (mode == 'hide') {
14719                         animation.opacity = 0;
14720                 }
14721
14722                 $.effects.save(elem, props);
14723                 elem
14724                         .show()
14725                         .css({
14726                                 backgroundImage: 'none',
14727                                 backgroundColor: o.options.color || '#ffff99'
14728                         })
14729                         .animate(animation, {
14730                                 queue: false,
14731                                 duration: o.duration,
14732                                 easing: o.options.easing,
14733                                 complete: function() {
14734                                         (mode == 'hide' && elem.hide());
14735                                         $.effects.restore(elem, props);
14736                                         (mode == 'show' && !$.support.opacity && this.style.removeAttribute('filter'));
14737                                         (o.callback && o.callback.apply(this, arguments));
14738                                         elem.dequeue();
14739                                 }
14740                         });
14741         });
14742 };
14743
14744 })(jQuery);
14745 /*
14746  * jQuery UI Effects Pulsate 1.8.12
14747  *
14748  * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
14749  * Dual licensed under the MIT or GPL Version 2 licenses.
14750  * http://jquery.org/license
14751  *
14752  * http://docs.jquery.com/UI/Effects/Pulsate
14753  *
14754  * Depends:
14755  *      jquery.effects.core.js
14756  */
14757 (function( $, undefined ) {
14758
14759 $.effects.pulsate = function(o) {
14760         return this.queue(function() {
14761                 var elem = $(this),
14762                         mode = $.effects.setMode(elem, o.options.mode || 'show');
14763                         times = ((o.options.times || 5) * 2) - 1;
14764                         duration = o.duration ? o.duration / 2 : $.fx.speeds._default / 2,
14765                         isVisible = elem.is(':visible'),
14766                         animateTo = 0;
14767
14768                 if (!isVisible) {
14769                         elem.css('opacity', 0).show();
14770                         animateTo = 1;
14771                 }
14772
14773                 if ((mode == 'hide' && isVisible) || (mode == 'show' && !isVisible)) {
14774                         times--;
14775                 }
14776
14777                 for (var i = 0; i < times; i++) {
14778                         elem.animate({ opacity: animateTo }, duration, o.options.easing);
14779                         animateTo = (animateTo + 1) % 2;
14780                 }
14781
14782                 elem.animate({ opacity: animateTo }, duration, o.options.easing, function() {
14783                         if (animateTo == 0) {
14784                                 elem.hide();
14785                         }
14786                         (o.callback && o.callback.apply(this, arguments));
14787                 });
14788
14789                 elem
14790                         .queue('fx', function() { elem.dequeue(); })
14791                         .dequeue();
14792         });
14793 };
14794
14795 })(jQuery);
14796 /*
14797  * jQuery UI Effects Scale 1.8.12
14798  *
14799  * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
14800  * Dual licensed under the MIT or GPL Version 2 licenses.
14801  * http://jquery.org/license
14802  *
14803  * http://docs.jquery.com/UI/Effects/Scale
14804  *
14805  * Depends:
14806  *      jquery.effects.core.js
14807  */
14808 (function( $, undefined ) {
14809
14810 $.effects.puff = function(o) {
14811         return this.queue(function() {
14812                 var elem = $(this),
14813                         mode = $.effects.setMode(elem, o.options.mode || 'hide'),
14814                         percent = parseInt(o.options.percent, 10) || 150,
14815                         factor = percent / 100,
14816                         original = { height: elem.height(), width: elem.width() };
14817
14818                 $.extend(o.options, {
14819                         fade: true,
14820                         mode: mode,
14821                         percent: mode == 'hide' ? percent : 100,
14822                         from: mode == 'hide'
14823                                 ? original
14824                                 : {
14825                                         height: original.height * factor,
14826                                         width: original.width * factor
14827                                 }
14828                 });
14829
14830                 elem.effect('scale', o.options, o.duration, o.callback);
14831                 elem.dequeue();
14832         });
14833 };
14834
14835 $.effects.scale = function(o) {
14836
14837         return this.queue(function() {
14838
14839                 // Create element
14840                 var el = $(this);
14841
14842                 // Set options
14843                 var options = $.extend(true, {}, o.options);
14844                 var mode = $.effects.setMode(el, o.options.mode || 'effect'); // Set Mode
14845                 var percent = parseInt(o.options.percent,10) || (parseInt(o.options.percent,10) == 0 ? 0 : (mode == 'hide' ? 0 : 100)); // Set default scaling percent
14846                 var direction = o.options.direction || 'both'; // Set default axis
14847                 var origin = o.options.origin; // The origin of the scaling
14848                 if (mode != 'effect') { // Set default origin and restore for show/hide
14849                         options.origin = origin || ['middle','center'];
14850                         options.restore = true;
14851                 }
14852                 var original = {height: el.height(), width: el.width()}; // Save original
14853                 el.from = o.options.from || (mode == 'show' ? {height: 0, width: 0} : original); // Default from state
14854
14855                 // Adjust
14856                 var factor = { // Set scaling factor
14857                         y: direction != 'horizontal' ? (percent / 100) : 1,
14858                         x: direction != 'vertical' ? (percent / 100) : 1
14859                 };
14860                 el.to = {height: original.height * factor.y, width: original.width * factor.x}; // Set to state
14861
14862                 if (o.options.fade) { // Fade option to support puff
14863                         if (mode == 'show') {el.from.opacity = 0; el.to.opacity = 1;};
14864                         if (mode == 'hide') {el.from.opacity = 1; el.to.opacity = 0;};
14865                 };
14866
14867                 // Animation
14868                 options.from = el.from; options.to = el.to; options.mode = mode;
14869
14870                 // Animate
14871                 el.effect('size', options, o.duration, o.callback);
14872                 el.dequeue();
14873         });
14874
14875 };
14876
14877 $.effects.size = function(o) {
14878
14879         return this.queue(function() {
14880
14881                 // Create element
14882                 var el = $(this), props = ['position','top','bottom','left','right','width','height','overflow','opacity'];
14883                 var props1 = ['position','top','bottom','left','right','overflow','opacity']; // Always restore
14884                 var props2 = ['width','height','overflow']; // Copy for children
14885                 var cProps = ['fontSize'];
14886                 var vProps = ['borderTopWidth', 'borderBottomWidth', 'paddingTop', 'paddingBottom'];
14887                 var hProps = ['borderLeftWidth', 'borderRightWidth', 'paddingLeft', 'paddingRight'];
14888
14889                 // Set options
14890                 var mode = $.effects.setMode(el, o.options.mode || 'effect'); // Set Mode
14891                 var restore = o.options.restore || false; // Default restore
14892                 var scale = o.options.scale || 'both'; // Default scale mode
14893                 var origin = o.options.origin; // The origin of the sizing
14894                 var original = {height: el.height(), width: el.width()}; // Save original
14895                 el.from = o.options.from || original; // Default from state
14896                 el.to = o.options.to || original; // Default to state
14897                 // Adjust
14898                 if (origin) { // Calculate baseline shifts
14899                         var baseline = $.effects.getBaseline(origin, original);
14900                         el.from.top = (original.height - el.from.height) * baseline.y;
14901                         el.from.left = (original.width - el.from.width) * baseline.x;
14902                         el.to.top = (original.height - el.to.height) * baseline.y;
14903                         el.to.left = (original.width - el.to.width) * baseline.x;
14904                 };
14905                 var factor = { // Set scaling factor
14906                         from: {y: el.from.height / original.height, x: el.from.width / original.width},
14907                         to: {y: el.to.height / original.height, x: el.to.width / original.width}
14908                 };
14909                 if (scale == 'box' || scale == 'both') { // Scale the css box
14910                         if (factor.from.y != factor.to.y) { // Vertical props scaling
14911                                 props = props.concat(vProps);
14912                                 el.from = $.effects.setTransition(el, vProps, factor.from.y, el.from);
14913                                 el.to = $.effects.setTransition(el, vProps, factor.to.y, el.to);
14914                         };
14915                         if (factor.from.x != factor.to.x) { // Horizontal props scaling
14916                                 props = props.concat(hProps);
14917                                 el.from = $.effects.setTransition(el, hProps, factor.from.x, el.from);
14918                                 el.to = $.effects.setTransition(el, hProps, factor.to.x, el.to);
14919                         };
14920                 };
14921                 if (scale == 'content' || scale == 'both') { // Scale the content
14922                         if (factor.from.y != factor.to.y) { // Vertical props scaling
14923                                 props = props.concat(cProps);
14924                                 el.from = $.effects.setTransition(el, cProps, factor.from.y, el.from);
14925                                 el.to = $.effects.setTransition(el, cProps, factor.to.y, el.to);
14926                         };
14927                 };
14928                 $.effects.save(el, restore ? props : props1); el.show(); // Save & Show
14929                 $.effects.createWrapper(el); // Create Wrapper
14930                 el.css('overflow','hidden').css(el.from); // Shift
14931
14932                 // Animate
14933                 if (scale == 'content' || scale == 'both') { // Scale the children
14934                         vProps = vProps.concat(['marginTop','marginBottom']).concat(cProps); // Add margins/font-size
14935                         hProps = hProps.concat(['marginLeft','marginRight']); // Add margins
14936                         props2 = props.concat(vProps).concat(hProps); // Concat
14937                         el.find("*[width]").each(function(){
14938                                 child = $(this);
14939                                 if (restore) $.effects.save(child, props2);
14940                                 var c_original = {height: child.height(), width: child.width()}; // Save original
14941                                 child.from = {height: c_original.height * factor.from.y, width: c_original.width * factor.from.x};
14942                                 child.to = {height: c_original.height * factor.to.y, width: c_original.width * factor.to.x};
14943                                 if (factor.from.y != factor.to.y) { // Vertical props scaling
14944                                         child.from = $.effects.setTransition(child, vProps, factor.from.y, child.from);
14945                                         child.to = $.effects.setTransition(child, vProps, factor.to.y, child.to);
14946                                 };
14947                                 if (factor.from.x != factor.to.x) { // Horizontal props scaling
14948                                         child.from = $.effects.setTransition(child, hProps, factor.from.x, child.from);
14949                                         child.to = $.effects.setTransition(child, hProps, factor.to.x, child.to);
14950                                 };
14951                                 child.css(child.from); // Shift children
14952                                 child.animate(child.to, o.duration, o.options.easing, function(){
14953                                         if (restore) $.effects.restore(child, props2); // Restore children
14954                                 }); // Animate children
14955                         });
14956                 };
14957
14958                 // Animate
14959                 el.animate(el.to, { queue: false, duration: o.duration, easing: o.options.easing, complete: function() {
14960                         if (el.to.opacity === 0) {
14961                                 el.css('opacity', el.from.opacity);
14962                         }
14963                         if(mode == 'hide') el.hide(); // Hide
14964                         $.effects.restore(el, restore ? props : props1); $.effects.removeWrapper(el); // Restore
14965                         if(o.callback) o.callback.apply(this, arguments); // Callback
14966                         el.dequeue();
14967                 }});
14968
14969         });
14970
14971 };
14972
14973 })(jQuery);
14974 /*
14975  * jQuery UI Effects Shake 1.8.12
14976  *
14977  * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
14978  * Dual licensed under the MIT or GPL Version 2 licenses.
14979  * http://jquery.org/license
14980  *
14981  * http://docs.jquery.com/UI/Effects/Shake
14982  *
14983  * Depends:
14984  *      jquery.effects.core.js
14985  */
14986 (function( $, undefined ) {
14987
14988 $.effects.shake = function(o) {
14989
14990         return this.queue(function() {
14991
14992                 // Create element
14993                 var el = $(this), props = ['position','top','bottom','left','right'];
14994
14995                 // Set options
14996                 var mode = $.effects.setMode(el, o.options.mode || 'effect'); // Set Mode
14997                 var direction = o.options.direction || 'left'; // Default direction
14998                 var distance = o.options.distance || 20; // Default distance
14999                 var times = o.options.times || 3; // Default # of times
15000                 var speed = o.duration || o.options.duration || 140; // Default speed per shake
15001
15002                 // Adjust
15003                 $.effects.save(el, props); el.show(); // Save & Show
15004                 $.effects.createWrapper(el); // Create Wrapper
15005                 var ref = (direction == 'up' || direction == 'down') ? 'top' : 'left';
15006                 var motion = (direction == 'up' || direction == 'left') ? 'pos' : 'neg';
15007
15008                 // Animation
15009                 var animation = {}, animation1 = {}, animation2 = {};
15010                 animation[ref] = (motion == 'pos' ? '-=' : '+=')  + distance;
15011                 animation1[ref] = (motion == 'pos' ? '+=' : '-=')  + distance * 2;
15012                 animation2[ref] = (motion == 'pos' ? '-=' : '+=')  + distance * 2;
15013
15014                 // Animate
15015                 el.animate(animation, speed, o.options.easing);
15016                 for (var i = 1; i < times; i++) { // Shakes
15017                         el.animate(animation1, speed, o.options.easing).animate(animation2, speed, o.options.easing);
15018                 };
15019                 el.animate(animation1, speed, o.options.easing).
15020                 animate(animation, speed / 2, o.options.easing, function(){ // Last shake
15021                         $.effects.restore(el, props); $.effects.removeWrapper(el); // Restore
15022                         if(o.callback) o.callback.apply(this, arguments); // Callback
15023                 });
15024                 el.queue('fx', function() { el.dequeue(); });
15025                 el.dequeue();
15026         });
15027
15028 };
15029
15030 })(jQuery);
15031 /*
15032  * jQuery UI Effects Slide 1.8.12
15033  *
15034  * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
15035  * Dual licensed under the MIT or GPL Version 2 licenses.
15036  * http://jquery.org/license
15037  *
15038  * http://docs.jquery.com/UI/Effects/Slide
15039  *
15040  * Depends:
15041  *      jquery.effects.core.js
15042  */
15043 (function( $, undefined ) {
15044
15045 $.effects.slide = function(o) {
15046
15047         return this.queue(function() {
15048
15049                 // Create element
15050                 var el = $(this), props = ['position','top','bottom','left','right'];
15051
15052                 // Set options
15053                 var mode = $.effects.setMode(el, o.options.mode || 'show'); // Set Mode
15054                 var direction = o.options.direction || 'left'; // Default Direction
15055
15056                 // Adjust
15057                 $.effects.save(el, props); el.show(); // Save & Show
15058                 $.effects.createWrapper(el).css({overflow:'hidden'}); // Create Wrapper
15059                 var ref = (direction == 'up' || direction == 'down') ? 'top' : 'left';
15060                 var motion = (direction == 'up' || direction == 'left') ? 'pos' : 'neg';
15061                 var distance = o.options.distance || (ref == 'top' ? el.outerHeight({margin:true}) : el.outerWidth({margin:true}));
15062                 if (mode == 'show') el.css(ref, motion == 'pos' ? (isNaN(distance) ? "-" + distance : -distance) : distance); // Shift
15063
15064                 // Animation
15065                 var animation = {};
15066                 animation[ref] = (mode == 'show' ? (motion == 'pos' ? '+=' : '-=') : (motion == 'pos' ? '-=' : '+=')) + distance;
15067
15068                 // Animate
15069                 el.animate(animation, { queue: false, duration: o.duration, easing: o.options.easing, complete: function() {
15070                         if(mode == 'hide') el.hide(); // Hide
15071                         $.effects.restore(el, props); $.effects.removeWrapper(el); // Restore
15072                         if(o.callback) o.callback.apply(this, arguments); // Callback
15073                         el.dequeue();
15074                 }});
15075
15076         });
15077
15078 };
15079
15080 })(jQuery);
15081 /*
15082  * jQuery UI Effects Transfer 1.8.12
15083  *
15084  * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
15085  * Dual licensed under the MIT or GPL Version 2 licenses.
15086  * http://jquery.org/license
15087  *
15088  * http://docs.jquery.com/UI/Effects/Transfer
15089  *
15090  * Depends:
15091  *      jquery.effects.core.js
15092  */
15093 (function( $, undefined ) {
15094
15095 $.effects.transfer = function(o) {
15096         return this.queue(function() {
15097                 var elem = $(this),
15098                         target = $(o.options.to),
15099                         endPosition = target.offset(),
15100                         animation = {
15101                                 top: endPosition.top,
15102                                 left: endPosition.left,
15103                                 height: target.innerHeight(),
15104                                 width: target.innerWidth()
15105                         },
15106                         startPosition = elem.offset(),
15107                         transfer = $('<div class="ui-effects-transfer"></div>')
15108                                 .appendTo(document.body)
15109                                 .addClass(o.options.className)
15110                                 .css({
15111                                         top: startPosition.top,
15112                                         left: startPosition.left,
15113                                         height: elem.innerHeight(),
15114                                         width: elem.innerWidth(),
15115                                         position: 'absolute'
15116                                 })
15117                                 .animate(animation, o.duration, o.options.easing, function() {
15118                                         transfer.remove();
15119                                         (o.callback && o.callback.apply(elem[0], arguments));
15120                                         elem.dequeue();
15121                                 });
15122         });
15123 };
15124
15125 })(jQuery);
15126 /*
15127  * jQuery UI Accordion 1.8.12
15128  *
15129  * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
15130  * Dual licensed under the MIT or GPL Version 2 licenses.
15131  * http://jquery.org/license
15132  *
15133  * http://docs.jquery.com/UI/Accordion
15134  *
15135  * Depends:
15136  *      jquery.ui.core.js
15137  *      jquery.ui.widget.js
15138  */
15139 (function( $, undefined ) {
15140
15141 $.widget( "ui.accordion", {
15142         options: {
15143                 active: 0,
15144                 animated: "slide",
15145                 autoHeight: true,
15146                 clearStyle: false,
15147                 collapsible: false,
15148                 event: "click",
15149                 fillSpace: false,
15150                 header: "> li > :first-child,> :not(li):even",
15151                 icons: {
15152                         header: "ui-icon-triangle-1-e",
15153                         headerSelected: "ui-icon-triangle-1-s"
15154                 },
15155                 navigation: false,
15156                 navigationFilter: function() {
15157                         return this.href.toLowerCase() === location.href.toLowerCase();
15158                 }
15159         },
15160
15161         _create: function() {
15162                 var self = this,
15163                         options = self.options;
15164
15165                 self.running = 0;
15166
15167                 self.element
15168                         .addClass( "ui-accordion ui-widget ui-helper-reset" )
15169                         // in lack of child-selectors in CSS
15170                         // we need to mark top-LIs in a UL-accordion for some IE-fix
15171                         .children( "li" )
15172                                 .addClass( "ui-accordion-li-fix" );
15173
15174                 self.headers = self.element.find( options.header )
15175                         .addClass( "ui-accordion-header ui-helper-reset ui-state-default ui-corner-all" )
15176                         .bind( "mouseenter.accordion", function() {
15177                                 if ( options.disabled ) {
15178                                         return;
15179                                 }
15180                                 $( this ).addClass( "ui-state-hover" );
15181                         })
15182                         .bind( "mouseleave.accordion", function() {
15183                                 if ( options.disabled ) {
15184                                         return;
15185                                 }
15186                                 $( this ).removeClass( "ui-state-hover" );
15187                         })
15188                         .bind( "focus.accordion", function() {
15189                                 if ( options.disabled ) {
15190                                         return;
15191                                 }
15192                                 $( this ).addClass( "ui-state-focus" );
15193                         })
15194                         .bind( "blur.accordion", function() {
15195                                 if ( options.disabled ) {
15196                                         return;
15197                                 }
15198                                 $( this ).removeClass( "ui-state-focus" );
15199                         });
15200
15201                 self.headers.next()
15202                         .addClass( "ui-accordion-content ui-helper-reset ui-widget-content ui-corner-bottom" );
15203
15204                 if ( options.navigation ) {
15205                         var current = self.element.find( "a" ).filter( options.navigationFilter ).eq( 0 );
15206                         if ( current.length ) {
15207                                 var header = current.closest( ".ui-accordion-header" );
15208                                 if ( header.length ) {
15209                                         // anchor within header
15210                                         self.active = header;
15211                                 } else {
15212                                         // anchor within content
15213                                         self.active = current.closest( ".ui-accordion-content" ).prev();
15214                                 }
15215                         }
15216                 }
15217
15218                 self.active = self._findActive( self.active || options.active )
15219                         .addClass( "ui-state-default ui-state-active" )
15220                         .toggleClass( "ui-corner-all" )
15221                         .toggleClass( "ui-corner-top" );
15222                 self.active.next().addClass( "ui-accordion-content-active" );
15223
15224                 self._createIcons();
15225                 self.resize();
15226                 
15227                 // ARIA
15228                 self.element.attr( "role", "tablist" );
15229
15230                 self.headers
15231                         .attr( "role", "tab" )
15232                         .bind( "keydown.accordion", function( event ) {
15233                                 return self._keydown( event );
15234                         })
15235                         .next()
15236                                 .attr( "role", "tabpanel" );
15237
15238                 self.headers
15239                         .not( self.active || "" )
15240                         .attr({
15241                                 "aria-expanded": "false",
15242                                 "aria-selected": "false",
15243                                 tabIndex: -1
15244                         })
15245                         .next()
15246                                 .hide();
15247
15248                 // make sure at least one header is in the tab order
15249                 if ( !self.active.length ) {
15250                         self.headers.eq( 0 ).attr( "tabIndex", 0 );
15251                 } else {
15252                         self.active
15253                                 .attr({
15254                                         "aria-expanded": "true",
15255                                         "aria-selected": "true",
15256                                         tabIndex: 0
15257                                 });
15258                 }
15259
15260                 // only need links in tab order for Safari
15261                 if ( !$.browser.safari ) {
15262                         self.headers.find( "a" ).attr( "tabIndex", -1 );
15263                 }
15264
15265                 if ( options.event ) {
15266                         self.headers.bind( options.event.split(" ").join(".accordion ") + ".accordion", function(event) {
15267                                 self._clickHandler.call( self, event, this );
15268                                 event.preventDefault();
15269                         });
15270                 }
15271         },
15272
15273         _createIcons: function() {
15274                 var options = this.options;
15275                 if ( options.icons ) {
15276                         $( "<span></span>" )
15277                                 .addClass( "ui-icon " + options.icons.header )
15278                                 .prependTo( this.headers );
15279                         this.active.children( ".ui-icon" )
15280                                 .toggleClass(options.icons.header)
15281                                 .toggleClass(options.icons.headerSelected);
15282                         this.element.addClass( "ui-accordion-icons" );
15283                 }
15284         },
15285
15286         _destroyIcons: function() {
15287                 this.headers.children( ".ui-icon" ).remove();
15288                 this.element.removeClass( "ui-accordion-icons" );
15289         },
15290
15291         destroy: function() {
15292                 var options = this.options;
15293
15294                 this.element
15295                         .removeClass( "ui-accordion ui-widget ui-helper-reset" )
15296                         .removeAttr( "role" );
15297
15298                 this.headers
15299                         .unbind( ".accordion" )
15300                         .removeClass( "ui-accordion-header ui-accordion-disabled ui-helper-reset ui-state-default ui-corner-all ui-state-active ui-state-disabled ui-corner-top" )
15301                         .removeAttr( "role" )
15302                         .removeAttr( "aria-expanded" )
15303                         .removeAttr( "aria-selected" )
15304                         .removeAttr( "tabIndex" );
15305
15306                 this.headers.find( "a" ).removeAttr( "tabIndex" );
15307                 this._destroyIcons();
15308                 var contents = this.headers.next()
15309                         .css( "display", "" )
15310                         .removeAttr( "role" )
15311                         .removeClass( "ui-helper-reset ui-widget-content ui-corner-bottom ui-accordion-content ui-accordion-content-active ui-accordion-disabled ui-state-disabled" );
15312                 if ( options.autoHeight || options.fillHeight ) {
15313                         contents.css( "height", "" );
15314                 }
15315
15316                 return $.Widget.prototype.destroy.call( this );
15317         },
15318
15319         _setOption: function( key, value ) {
15320                 $.Widget.prototype._setOption.apply( this, arguments );
15321                         
15322                 if ( key == "active" ) {
15323                         this.activate( value );
15324                 }
15325                 if ( key == "icons" ) {
15326                         this._destroyIcons();
15327                         if ( value ) {
15328                                 this._createIcons();
15329                         }
15330                 }
15331                 // #5332 - opacity doesn't cascade to positioned elements in IE
15332                 // so we need to add the disabled class to the headers and panels
15333                 if ( key == "disabled" ) {
15334                         this.headers.add(this.headers.next())
15335                                 [ value ? "addClass" : "removeClass" ](
15336                                         "ui-accordion-disabled ui-state-disabled" );
15337                 }
15338         },
15339
15340         _keydown: function( event ) {
15341                 if ( this.options.disabled || event.altKey || event.ctrlKey ) {
15342                         return;
15343                 }
15344
15345                 var keyCode = $.ui.keyCode,
15346                         length = this.headers.length,
15347                         currentIndex = this.headers.index( event.target ),
15348                         toFocus = false;
15349
15350                 switch ( event.keyCode ) {
15351                         case keyCode.RIGHT:
15352                         case keyCode.DOWN:
15353                                 toFocus = this.headers[ ( currentIndex + 1 ) % length ];
15354                                 break;
15355                         case keyCode.LEFT:
15356                         case keyCode.UP:
15357                                 toFocus = this.headers[ ( currentIndex - 1 + length ) % length ];
15358                                 break;
15359                         case keyCode.SPACE:
15360                         case keyCode.ENTER:
15361                                 this._clickHandler( { target: event.target }, event.target );
15362                                 event.preventDefault();
15363                 }
15364
15365                 if ( toFocus ) {
15366                         $( event.target ).attr( "tabIndex", -1 );
15367                         $( toFocus ).attr( "tabIndex", 0 );
15368                         toFocus.focus();
15369                         return false;
15370                 }
15371
15372                 return true;
15373         },
15374
15375         resize: function() {
15376                 var options = this.options,
15377                         maxHeight;
15378
15379                 if ( options.fillSpace ) {
15380                         if ( $.browser.msie ) {
15381                                 var defOverflow = this.element.parent().css( "overflow" );
15382                                 this.element.parent().css( "overflow", "hidden");
15383                         }
15384                         maxHeight = this.element.parent().height();
15385                         if ($.browser.msie) {
15386                                 this.element.parent().css( "overflow", defOverflow );
15387                         }
15388
15389                         this.headers.each(function() {
15390                                 maxHeight -= $( this ).outerHeight( true );
15391                         });
15392
15393                         this.headers.next()
15394                                 .each(function() {
15395                                         $( this ).height( Math.max( 0, maxHeight -
15396                                                 $( this ).innerHeight() + $( this ).height() ) );
15397                                 })
15398                                 .css( "overflow", "auto" );
15399                 } else if ( options.autoHeight ) {
15400                         maxHeight = 0;
15401                         this.headers.next()
15402                                 .each(function() {
15403                                         maxHeight = Math.max( maxHeight, $( this ).height( "" ).height() );
15404                                 })
15405                                 .height( maxHeight );
15406                 }
15407
15408                 return this;
15409         },
15410
15411         activate: function( index ) {
15412                 // TODO this gets called on init, changing the option without an explicit call for that
15413                 this.options.active = index;
15414                 // call clickHandler with custom event
15415                 var active = this._findActive( index )[ 0 ];
15416                 this._clickHandler( { target: active }, active );
15417
15418                 return this;
15419         },
15420
15421         _findActive: function( selector ) {
15422                 return selector
15423                         ? typeof selector === "number"
15424                                 ? this.headers.filter( ":eq(" + selector + ")" )
15425                                 : this.headers.not( this.headers.not( selector ) )
15426                         : selector === false
15427                                 ? $( [] )
15428                                 : this.headers.filter( ":eq(0)" );
15429         },
15430
15431         // TODO isn't event.target enough? why the separate target argument?
15432         _clickHandler: function( event, target ) {
15433                 var options = this.options;
15434                 if ( options.disabled ) {
15435                         return;
15436                 }
15437
15438                 // called only when using activate(false) to close all parts programmatically
15439                 if ( !event.target ) {
15440                         if ( !options.collapsible ) {
15441                                 return;
15442                         }
15443                         this.active
15444                                 .removeClass( "ui-state-active ui-corner-top" )
15445                                 .addClass( "ui-state-default ui-corner-all" )
15446                                 .children( ".ui-icon" )
15447                                         .removeClass( options.icons.headerSelected )
15448                                         .addClass( options.icons.header );
15449                         this.active.next().addClass( "ui-accordion-content-active" );
15450                         var toHide = this.active.next(),
15451                                 data = {
15452                                         options: options,
15453                                         newHeader: $( [] ),
15454                                         oldHeader: options.active,
15455                                         newContent: $( [] ),
15456                                         oldContent: toHide
15457                                 },
15458                                 toShow = ( this.active = $( [] ) );
15459                         this._toggle( toShow, toHide, data );
15460                         return;
15461                 }
15462
15463                 // get the click target
15464                 var clicked = $( event.currentTarget || target ),
15465                         clickedIsActive = clicked[0] === this.active[0];
15466
15467                 // TODO the option is changed, is that correct?
15468                 // TODO if it is correct, shouldn't that happen after determining that the click is valid?
15469                 options.active = options.collapsible && clickedIsActive ?
15470                         false :
15471                         this.headers.index( clicked );
15472
15473                 // if animations are still active, or the active header is the target, ignore click
15474                 if ( this.running || ( !options.collapsible && clickedIsActive ) ) {
15475                         return;
15476                 }
15477
15478                 // find elements to show and hide
15479                 var active = this.active,
15480                         toShow = clicked.next(),
15481                         toHide = this.active.next(),
15482                         data = {
15483                                 options: options,
15484                                 newHeader: clickedIsActive && options.collapsible ? $([]) : clicked,
15485                                 oldHeader: this.active,
15486                                 newContent: clickedIsActive && options.collapsible ? $([]) : toShow,
15487                                 oldContent: toHide
15488                         },
15489                         down = this.headers.index( this.active[0] ) > this.headers.index( clicked[0] );
15490
15491                 // when the call to ._toggle() comes after the class changes
15492                 // it causes a very odd bug in IE 8 (see #6720)
15493                 this.active = clickedIsActive ? $([]) : clicked;
15494                 this._toggle( toShow, toHide, data, clickedIsActive, down );
15495
15496                 // switch classes
15497                 active
15498                         .removeClass( "ui-state-active ui-corner-top" )
15499                         .addClass( "ui-state-default ui-corner-all" )
15500                         .children( ".ui-icon" )
15501                                 .removeClass( options.icons.headerSelected )
15502                                 .addClass( options.icons.header );
15503                 if ( !clickedIsActive ) {
15504                         clicked
15505                                 .removeClass( "ui-state-default ui-corner-all" )
15506                                 .addClass( "ui-state-active ui-corner-top" )
15507                                 .children( ".ui-icon" )
15508                                         .removeClass( options.icons.header )
15509                                         .addClass( options.icons.headerSelected );
15510                         clicked
15511                                 .next()
15512                                 .addClass( "ui-accordion-content-active" );
15513                 }
15514
15515                 return;
15516         },
15517
15518         _toggle: function( toShow, toHide, data, clickedIsActive, down ) {
15519                 var self = this,
15520                         options = self.options;
15521
15522                 self.toShow = toShow;
15523                 self.toHide = toHide;
15524                 self.data = data;
15525
15526                 var complete = function() {
15527                         if ( !self ) {
15528                                 return;
15529                         }
15530                         return self._completed.apply( self, arguments );
15531                 };
15532
15533                 // trigger changestart event
15534                 self._trigger( "changestart", null, self.data );
15535
15536                 // count elements to animate
15537                 self.running = toHide.size() === 0 ? toShow.size() : toHide.size();
15538
15539                 if ( options.animated ) {
15540                         var animOptions = {};
15541
15542                         if ( options.collapsible && clickedIsActive ) {
15543                                 animOptions = {
15544                                         toShow: $( [] ),
15545                                         toHide: toHide,
15546                                         complete: complete,
15547                                         down: down,
15548                                         autoHeight: options.autoHeight || options.fillSpace
15549                                 };
15550                         } else {
15551                                 animOptions = {
15552                                         toShow: toShow,
15553                                         toHide: toHide,
15554                                         complete: complete,
15555                                         down: down,
15556                                         autoHeight: options.autoHeight || options.fillSpace
15557                                 };
15558                         }
15559
15560                         if ( !options.proxied ) {
15561                                 options.proxied = options.animated;
15562                         }
15563
15564                         if ( !options.proxiedDuration ) {
15565                                 options.proxiedDuration = options.duration;
15566                         }
15567
15568                         options.animated = $.isFunction( options.proxied ) ?
15569                                 options.proxied( animOptions ) :
15570                                 options.proxied;
15571
15572                         options.duration = $.isFunction( options.proxiedDuration ) ?
15573                                 options.proxiedDuration( animOptions ) :
15574                                 options.proxiedDuration;
15575
15576                         var animations = $.ui.accordion.animations,
15577                                 duration = options.duration,
15578                                 easing = options.animated;
15579
15580                         if ( easing && !animations[ easing ] && !$.easing[ easing ] ) {
15581                                 easing = "slide";
15582                         }
15583                         if ( !animations[ easing ] ) {
15584                                 animations[ easing ] = function( options ) {
15585                                         this.slide( options, {
15586                                                 easing: easing,
15587                                                 duration: duration || 700
15588                                         });
15589                                 };
15590                         }
15591
15592                         animations[ easing ]( animOptions );
15593                 } else {
15594                         if ( options.collapsible && clickedIsActive ) {
15595                                 toShow.toggle();
15596                         } else {
15597                                 toHide.hide();
15598                                 toShow.show();
15599                         }
15600
15601                         complete( true );
15602                 }
15603
15604                 // TODO assert that the blur and focus triggers are really necessary, remove otherwise
15605                 toHide.prev()
15606                         .attr({
15607                                 "aria-expanded": "false",
15608                                 "aria-selected": "false",
15609                                 tabIndex: -1
15610                         })
15611                         .blur();
15612                 toShow.prev()
15613                         .attr({
15614                                 "aria-expanded": "true",
15615                                 "aria-selected": "true",
15616                                 tabIndex: 0
15617                         })
15618                         .focus();
15619         },
15620
15621         _completed: function( cancel ) {
15622                 this.running = cancel ? 0 : --this.running;
15623                 if ( this.running ) {
15624                         return;
15625                 }
15626
15627                 if ( this.options.clearStyle ) {
15628                         this.toShow.add( this.toHide ).css({
15629                                 height: "",
15630                                 overflow: ""
15631                         });
15632                 }
15633
15634                 // other classes are removed before the animation; this one needs to stay until completed
15635                 this.toHide.removeClass( "ui-accordion-content-active" );
15636                 // Work around for rendering bug in IE (#5421)
15637                 if ( this.toHide.length ) {
15638                         this.toHide.parent()[0].className = this.toHide.parent()[0].className;
15639                 }
15640
15641                 this._trigger( "change", null, this.data );
15642         }
15643 });
15644
15645 $.extend( $.ui.accordion, {
15646         version: "1.8.12",
15647         animations: {
15648                 slide: function( options, additions ) {
15649                         options = $.extend({
15650                                 easing: "swing",
15651                                 duration: 300
15652                         }, options, additions );
15653                         if ( !options.toHide.size() ) {
15654                                 options.toShow.animate({
15655                                         height: "show",
15656                                         paddingTop: "show",
15657                                         paddingBottom: "show"
15658                                 }, options );
15659                                 return;
15660                         }
15661                         if ( !options.toShow.size() ) {
15662                                 options.toHide.animate({
15663                                         height: "hide",
15664                                         paddingTop: "hide",
15665                                         paddingBottom: "hide"
15666                                 }, options );
15667                                 return;
15668                         }
15669                         var overflow = options.toShow.css( "overflow" ),
15670                                 percentDone = 0,
15671                                 showProps = {},
15672                                 hideProps = {},
15673                                 fxAttrs = [ "height", "paddingTop", "paddingBottom" ],
15674                                 originalWidth;
15675                         // fix width before calculating height of hidden element
15676                         var s = options.toShow;
15677                         originalWidth = s[0].style.width;
15678                         s.width( parseInt( s.parent().width(), 10 )
15679                                 - parseInt( s.css( "paddingLeft" ), 10 )
15680                                 - parseInt( s.css( "paddingRight" ), 10 )
15681                                 - ( parseInt( s.css( "borderLeftWidth" ), 10 ) || 0 )
15682                                 - ( parseInt( s.css( "borderRightWidth" ), 10) || 0 ) );
15683
15684                         $.each( fxAttrs, function( i, prop ) {
15685                                 hideProps[ prop ] = "hide";
15686
15687                                 var parts = ( "" + $.css( options.toShow[0], prop ) ).match( /^([\d+-.]+)(.*)$/ );
15688                                 showProps[ prop ] = {
15689                                         value: parts[ 1 ],
15690                                         unit: parts[ 2 ] || "px"
15691                                 };
15692                         });
15693                         options.toShow.css({ height: 0, overflow: "hidden" }).show();
15694                         options.toHide
15695                                 .filter( ":hidden" )
15696                                         .each( options.complete )
15697                                 .end()
15698                                 .filter( ":visible" )
15699                                 .animate( hideProps, {
15700                                 step: function( now, settings ) {
15701                                         // only calculate the percent when animating height
15702                                         // IE gets very inconsistent results when animating elements
15703                                         // with small values, which is common for padding
15704                                         if ( settings.prop == "height" ) {
15705                                                 percentDone = ( settings.end - settings.start === 0 ) ? 0 :
15706                                                         ( settings.now - settings.start ) / ( settings.end - settings.start );
15707                                         }
15708
15709                                         options.toShow[ 0 ].style[ settings.prop ] =
15710                                                 ( percentDone * showProps[ settings.prop ].value )
15711                                                 + showProps[ settings.prop ].unit;
15712                                 },
15713                                 duration: options.duration,
15714                                 easing: options.easing,
15715                                 complete: function() {
15716                                         if ( !options.autoHeight ) {
15717                                                 options.toShow.css( "height", "" );
15718                                         }
15719                                         options.toShow.css({
15720                                                 width: originalWidth,
15721                                                 overflow: overflow
15722                                         });
15723                                         options.complete();
15724                                 }
15725                         });
15726                 },
15727                 bounceslide: function( options ) {
15728                         this.slide( options, {
15729                                 easing: options.down ? "easeOutBounce" : "swing",
15730                                 duration: options.down ? 1000 : 200
15731                         });
15732                 }
15733         }
15734 });
15735
15736 })( jQuery );
15737 /*
15738  * jQuery UI Autocomplete 1.8.12
15739  *
15740  * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
15741  * Dual licensed under the MIT or GPL Version 2 licenses.
15742  * http://jquery.org/license
15743  *
15744  * http://docs.jquery.com/UI/Autocomplete
15745  *
15746  * Depends:
15747  *      jquery.ui.core.js
15748  *      jquery.ui.widget.js
15749  *      jquery.ui.position.js
15750  */
15751 (function( $, undefined ) {
15752
15753 // used to prevent race conditions with remote data sources
15754 var requestIndex = 0;
15755
15756 $.widget( "ui.autocomplete", {
15757         options: {
15758                 appendTo: "body",
15759                 autoFocus: false,
15760                 delay: 300,
15761                 minLength: 1,
15762                 position: {
15763                         my: "left top",
15764                         at: "left bottom",
15765                         collision: "none"
15766                 },
15767                 source: null
15768         },
15769
15770         pending: 0,
15771
15772         _create: function() {
15773                 var self = this,
15774                         doc = this.element[ 0 ].ownerDocument,
15775                         suppressKeyPress;
15776
15777                 this.element
15778                         .addClass( "ui-autocomplete-input" )
15779                         .attr( "autocomplete", "off" )
15780                         // TODO verify these actually work as intended
15781                         .attr({
15782                                 role: "textbox",
15783                                 "aria-autocomplete": "list",
15784                                 "aria-haspopup": "true"
15785                         })
15786                         .bind( "keydown.autocomplete", function( event ) {
15787                                 if ( self.options.disabled || self.element.attr( "readonly" ) ) {
15788                                         return;
15789                                 }
15790
15791                                 suppressKeyPress = false;
15792                                 var keyCode = $.ui.keyCode;
15793                                 switch( event.keyCode ) {
15794                                 case keyCode.PAGE_UP:
15795                                         self._move( "previousPage", event );
15796                                         break;
15797                                 case keyCode.PAGE_DOWN:
15798                                         self._move( "nextPage", event );
15799                                         break;
15800                                 case keyCode.UP:
15801                                         self._move( "previous", event );
15802                                         // prevent moving cursor to beginning of text field in some browsers
15803                                         event.preventDefault();
15804                                         break;
15805                                 case keyCode.DOWN:
15806                                         self._move( "next", event );
15807                                         // prevent moving cursor to end of text field in some browsers
15808                                         event.preventDefault();
15809                                         break;
15810                                 case keyCode.ENTER:
15811                                 case keyCode.NUMPAD_ENTER:
15812                                         // when menu is open and has focus
15813                                         if ( self.menu.active ) {
15814                                                 // #6055 - Opera still allows the keypress to occur
15815                                                 // which causes forms to submit
15816                                                 suppressKeyPress = true;
15817                                                 event.preventDefault();
15818                                         }
15819                                         //passthrough - ENTER and TAB both select the current element
15820                                 case keyCode.TAB:
15821                                         if ( !self.menu.active ) {
15822                                                 return;
15823                                         }
15824                                         self.menu.select( event );
15825                                         break;
15826                                 case keyCode.ESCAPE:
15827                                         self.element.val( self.term );
15828                                         self.close( event );
15829                                         break;
15830                                 default:
15831                                         // keypress is triggered before the input value is changed
15832                                         clearTimeout( self.searching );
15833                                         self.searching = setTimeout(function() {
15834                                                 // only search if the value has changed
15835                                                 if ( self.term != self.element.val() ) {
15836                                                         self.selectedItem = null;
15837                                                         self.search( null, event );
15838                                                 }
15839                                         }, self.options.delay );
15840                                         break;
15841                                 }
15842                         })
15843                         .bind( "keypress.autocomplete", function( event ) {
15844                                 if ( suppressKeyPress ) {
15845                                         suppressKeyPress = false;
15846                                         event.preventDefault();
15847                                 }
15848                         })
15849                         .bind( "focus.autocomplete", function() {
15850                                 if ( self.options.disabled ) {
15851                                         return;
15852                                 }
15853
15854                                 self.selectedItem = null;
15855                                 self.previous = self.element.val();
15856                         })
15857                         .bind( "blur.autocomplete", function( event ) {
15858                                 if ( self.options.disabled ) {
15859                                         return;
15860                                 }
15861
15862                                 clearTimeout( self.searching );
15863                                 // clicks on the menu (or a button to trigger a search) will cause a blur event
15864                                 self.closing = setTimeout(function() {
15865                                         self.close( event );
15866                                         self._change( event );
15867                                 }, 150 );
15868                         });
15869                 this._initSource();
15870                 this.response = function() {
15871                         return self._response.apply( self, arguments );
15872                 };
15873                 this.menu = $( "<ul></ul>" )
15874                         .addClass( "ui-autocomplete" )
15875                         .appendTo( $( this.options.appendTo || "body", doc )[0] )
15876                         // prevent the close-on-blur in case of a "slow" click on the menu (long mousedown)
15877                         .mousedown(function( event ) {
15878                                 // clicking on the scrollbar causes focus to shift to the body
15879                                 // but we can't detect a mouseup or a click immediately afterward
15880                                 // so we have to track the next mousedown and close the menu if
15881                                 // the user clicks somewhere outside of the autocomplete
15882                                 var menuElement = self.menu.element[ 0 ];
15883                                 if ( !$( event.target ).closest( ".ui-menu-item" ).length ) {
15884                                         setTimeout(function() {
15885                                                 $( document ).one( 'mousedown', function( event ) {
15886                                                         if ( event.target !== self.element[ 0 ] &&
15887                                                                 event.target !== menuElement &&
15888                                                                 !$.ui.contains( menuElement, event.target ) ) {
15889                                                                 self.close();
15890                                                         }
15891                                                 });
15892                                         }, 1 );
15893                                 }
15894
15895                                 // use another timeout to make sure the blur-event-handler on the input was already triggered
15896                                 setTimeout(function() {
15897                                         clearTimeout( self.closing );
15898                                 }, 13);
15899                         })
15900                         .menu({
15901                                 focus: function( event, ui ) {
15902                                         var item = ui.item.data( "item.autocomplete" );
15903                                         if ( false !== self._trigger( "focus", event, { item: item } ) ) {
15904                                                 // use value to match what will end up in the input, if it was a key event
15905                                                 if ( /^key/.test(event.originalEvent.type) ) {
15906                                                         self.element.val( item.value );
15907                                                 }
15908                                         }
15909                                 },
15910                                 selected: function( event, ui ) {
15911                                         var item = ui.item.data( "item.autocomplete" ),
15912                                                 previous = self.previous;
15913
15914                                         // only trigger when focus was lost (click on menu)
15915                                         if ( self.element[0] !== doc.activeElement ) {
15916                                                 self.element.focus();
15917                                                 self.previous = previous;
15918                                                 // #6109 - IE triggers two focus events and the second
15919                                                 // is asynchronous, so we need to reset the previous
15920                                                 // term synchronously and asynchronously :-(
15921                                                 setTimeout(function() {
15922                                                         self.previous = previous;
15923                                                         self.selectedItem = item;
15924                                                 }, 1);
15925                                         }
15926
15927                                         if ( false !== self._trigger( "select", event, { item: item } ) ) {
15928                                                 self.element.val( item.value );
15929                                         }
15930                                         // reset the term after the select event
15931                                         // this allows custom select handling to work properly
15932                                         self.term = self.element.val();
15933
15934                                         self.close( event );
15935                                         self.selectedItem = item;
15936                                 },
15937                                 blur: function( event, ui ) {
15938                                         // don't set the value of the text field if it's already correct
15939                                         // this prevents moving the cursor unnecessarily
15940                                         if ( self.menu.element.is(":visible") &&
15941                                                 ( self.element.val() !== self.term ) ) {
15942                                                 self.element.val( self.term );
15943                                         }
15944                                 }
15945                         })
15946                         .zIndex( this.element.zIndex() + 1 )
15947                         // workaround for jQuery bug #5781 http://dev.jquery.com/ticket/5781
15948                         .css({ top: 0, left: 0 })
15949                         .hide()
15950                         .data( "menu" );
15951                 if ( $.fn.bgiframe ) {
15952                          this.menu.element.bgiframe();
15953                 }
15954         },
15955
15956         destroy: function() {
15957                 this.element
15958                         .removeClass( "ui-autocomplete-input" )
15959                         .removeAttr( "autocomplete" )
15960                         .removeAttr( "role" )
15961                         .removeAttr( "aria-autocomplete" )
15962                         .removeAttr( "aria-haspopup" );
15963                 this.menu.element.remove();
15964                 $.Widget.prototype.destroy.call( this );
15965         },
15966
15967         _setOption: function( key, value ) {
15968                 $.Widget.prototype._setOption.apply( this, arguments );
15969                 if ( key === "source" ) {
15970                         this._initSource();
15971                 }
15972                 if ( key === "appendTo" ) {
15973                         this.menu.element.appendTo( $( value || "body", this.element[0].ownerDocument )[0] )
15974                 }
15975                 if ( key === "disabled" && value && this.xhr ) {
15976                         this.xhr.abort();
15977                 }
15978         },
15979
15980         _initSource: function() {
15981                 var self = this,
15982                         array,
15983                         url;
15984                 if ( $.isArray(this.options.source) ) {
15985                         array = this.options.source;
15986                         this.source = function( request, response ) {
15987                                 response( $.ui.autocomplete.filter(array, request.term) );
15988                         };
15989                 } else if ( typeof this.options.source === "string" ) {
15990                         url = this.options.source;
15991                         this.source = function( request, response ) {
15992                                 if ( self.xhr ) {
15993                                         self.xhr.abort();
15994                                 }
15995                                 self.xhr = $.ajax({
15996                                         url: url,
15997                                         data: request,
15998                                         dataType: "json",
15999                                         autocompleteRequest: ++requestIndex,
16000                                         success: function( data, status ) {
16001                                                 if ( this.autocompleteRequest === requestIndex ) {
16002                                                         response( data );
16003                                                 }
16004                                         },
16005                                         error: function() {
16006                                                 if ( this.autocompleteRequest === requestIndex ) {
16007                                                         response( [] );
16008                                                 }
16009                                         }
16010                                 });
16011                         };
16012                 } else {
16013                         this.source = this.options.source;
16014                 }
16015         },
16016
16017         search: function( value, event ) {
16018                 value = value != null ? value : this.element.val();
16019
16020                 // always save the actual value, not the one passed as an argument
16021                 this.term = this.element.val();
16022
16023                 if ( value.length < this.options.minLength ) {
16024                         return this.close( event );
16025                 }
16026
16027                 clearTimeout( this.closing );
16028                 if ( this._trigger( "search", event ) === false ) {
16029                         return;
16030                 }
16031
16032                 return this._search( value );
16033         },
16034
16035         _search: function( value ) {
16036                 this.pending++;
16037                 this.element.addClass( "ui-autocomplete-loading" );
16038
16039                 this.source( { term: value }, this.response );
16040         },
16041
16042         _response: function( content ) {
16043                 if ( !this.options.disabled && content && content.length ) {
16044                         content = this._normalize( content );
16045                         this._suggest( content );
16046                         this._trigger( "open" );
16047                 } else {
16048                         this.close();
16049                 }
16050                 this.pending--;
16051                 if ( !this.pending ) {
16052                         this.element.removeClass( "ui-autocomplete-loading" );
16053                 }
16054         },
16055
16056         close: function( event ) {
16057                 clearTimeout( this.closing );
16058                 if ( this.menu.element.is(":visible") ) {
16059                         this.menu.element.hide();
16060                         this.menu.deactivate();
16061                         this._trigger( "close", event );
16062                 }
16063         },
16064         
16065         _change: function( event ) {
16066                 if ( this.previous !== this.element.val() ) {
16067                         this._trigger( "change", event, { item: this.selectedItem } );
16068                 }
16069         },
16070
16071         _normalize: function( items ) {
16072                 // assume all items have the right format when the first item is complete
16073                 if ( items.length && items[0].label && items[0].value ) {
16074                         return items;
16075                 }
16076                 return $.map( items, function(item) {
16077                         if ( typeof item === "string" ) {
16078                                 return {
16079                                         label: item,
16080                                         value: item
16081                                 };
16082                         }
16083                         return $.extend({
16084                                 label: item.label || item.value,
16085                                 value: item.value || item.label
16086                         }, item );
16087                 });
16088         },
16089
16090         _suggest: function( items ) {
16091                 var ul = this.menu.element
16092                         .empty()
16093                         .zIndex( this.element.zIndex() + 1 );
16094                 this._renderMenu( ul, items );
16095                 // TODO refresh should check if the active item is still in the dom, removing the need for a manual deactivate
16096                 this.menu.deactivate();
16097                 this.menu.refresh();
16098
16099                 // size and position menu
16100                 ul.show();
16101                 this._resizeMenu();
16102                 ul.position( $.extend({
16103                         of: this.element
16104                 }, this.options.position ));
16105
16106                 if ( this.options.autoFocus ) {
16107                         this.menu.next( new $.Event("mouseover") );
16108                 }
16109         },
16110
16111         _resizeMenu: function() {
16112                 var ul = this.menu.element;
16113                 ul.outerWidth( Math.max(
16114                         ul.width( "" ).outerWidth(),
16115                         this.element.outerWidth()
16116                 ) );
16117         },
16118
16119         _renderMenu: function( ul, items ) {
16120                 var self = this;
16121                 $.each( items, function( index, item ) {
16122                         self._renderItem( ul, item );
16123                 });
16124         },
16125
16126         _renderItem: function( ul, item) {
16127                 return $( "<li></li>" )
16128                         .data( "item.autocomplete", item )
16129                         .append( $( "<a></a>" ).text( item.label ) )
16130                         .appendTo( ul );
16131         },
16132
16133         _move: function( direction, event ) {
16134                 if ( !this.menu.element.is(":visible") ) {
16135                         this.search( null, event );
16136                         return;
16137                 }
16138                 if ( this.menu.first() && /^previous/.test(direction) ||
16139                                 this.menu.last() && /^next/.test(direction) ) {
16140                         this.element.val( this.term );
16141                         this.menu.deactivate();
16142                         return;
16143                 }
16144                 this.menu[ direction ]( event );
16145         },
16146
16147         widget: function() {
16148                 return this.menu.element;
16149         }
16150 });
16151
16152 $.extend( $.ui.autocomplete, {
16153         escapeRegex: function( value ) {
16154                 return value.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&");
16155         },
16156         filter: function(array, term) {
16157                 var matcher = new RegExp( $.ui.autocomplete.escapeRegex(term), "i" );
16158                 return $.grep( array, function(value) {
16159                         return matcher.test( value.label || value.value || value );
16160                 });
16161         }
16162 });
16163
16164 }( jQuery ));
16165
16166 /*
16167  * jQuery UI Menu (not officially released)
16168  * 
16169  * This widget isn't yet finished and the API is subject to change. We plan to finish
16170  * it for the next release. You're welcome to give it a try anyway and give us feedback,
16171  * as long as you're okay with migrating your code later on. We can help with that, too.
16172  *
16173  * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
16174  * Dual licensed under the MIT or GPL Version 2 licenses.
16175  * http://jquery.org/license
16176  *
16177  * http://docs.jquery.com/UI/Menu
16178  *
16179  * Depends:
16180  *      jquery.ui.core.js
16181  *  jquery.ui.widget.js
16182  */
16183 (function($) {
16184
16185 $.widget("ui.menu", {
16186         _create: function() {
16187                 var self = this;
16188                 this.element
16189                         .addClass("ui-menu ui-widget ui-widget-content ui-corner-all")
16190                         .attr({
16191                                 role: "listbox",
16192                                 "aria-activedescendant": "ui-active-menuitem"
16193                         })
16194                         .click(function( event ) {
16195                                 if ( !$( event.target ).closest( ".ui-menu-item a" ).length ) {
16196                                         return;
16197                                 }
16198                                 // temporary
16199                                 event.preventDefault();
16200                                 self.select( event );
16201                         });
16202                 this.refresh();
16203         },
16204         
16205         refresh: function() {
16206                 var self = this;
16207
16208                 // don't refresh list items that are already adapted
16209                 var items = this.element.children("li:not(.ui-menu-item):has(a)")
16210                         .addClass("ui-menu-item")
16211                         .attr("role", "menuitem");
16212                 
16213                 items.children("a")
16214                         .addClass("ui-corner-all")
16215                         .attr("tabindex", -1)
16216                         // mouseenter doesn't work with event delegation
16217                         .mouseenter(function( event ) {
16218                                 self.activate( event, $(this).parent() );
16219                         })
16220                         .mouseleave(function() {
16221                                 self.deactivate();
16222                         });
16223         },
16224
16225         activate: function( event, item ) {
16226                 this.deactivate();
16227                 if (this.hasScroll()) {
16228                         var offset = item.offset().top - this.element.offset().top,
16229                                 scroll = this.element.attr("scrollTop"),
16230                                 elementHeight = this.element.height();
16231                         if (offset < 0) {
16232                                 this.element.attr("scrollTop", scroll + offset);
16233                         } else if (offset >= elementHeight) {
16234                                 this.element.attr("scrollTop", scroll + offset - elementHeight + item.height());
16235                         }
16236                 }
16237                 this.active = item.eq(0)
16238                         .children("a")
16239                                 .addClass("ui-state-hover")
16240                                 .attr("id", "ui-active-menuitem")
16241                         .end();
16242                 this._trigger("focus", event, { item: item });
16243         },
16244
16245         deactivate: function() {
16246                 if (!this.active) { return; }
16247
16248                 this.active.children("a")
16249                         .removeClass("ui-state-hover")
16250                         .removeAttr("id");
16251                 this._trigger("blur");
16252                 this.active = null;
16253         },
16254
16255         next: function(event) {
16256                 this.move("next", ".ui-menu-item:first", event);
16257         },
16258
16259         previous: function(event) {
16260                 this.move("prev", ".ui-menu-item:last", event);
16261         },
16262
16263         first: function() {
16264                 return this.active && !this.active.prevAll(".ui-menu-item").length;
16265         },
16266
16267         last: function() {
16268                 return this.active && !this.active.nextAll(".ui-menu-item").length;
16269         },
16270
16271         move: function(direction, edge, event) {
16272                 if (!this.active) {
16273                         this.activate(event, this.element.children(edge));
16274                         return;
16275                 }
16276                 var next = this.active[direction + "All"](".ui-menu-item").eq(0);
16277                 if (next.length) {
16278                         this.activate(event, next);
16279                 } else {
16280                         this.activate(event, this.element.children(edge));
16281                 }
16282         },
16283
16284         // TODO merge with previousPage
16285         nextPage: function(event) {
16286                 if (this.hasScroll()) {
16287                         // TODO merge with no-scroll-else
16288                         if (!this.active || this.last()) {
16289                                 this.activate(event, this.element.children(".ui-menu-item:first"));
16290                                 return;
16291                         }
16292                         var base = this.active.offset().top,
16293                                 height = this.element.height(),
16294                                 result = this.element.children(".ui-menu-item").filter(function() {
16295                                         var close = $(this).offset().top - base - height + $(this).height();
16296                                         // TODO improve approximation
16297                                         return close < 10 && close > -10;
16298                                 });
16299
16300                         // TODO try to catch this earlier when scrollTop indicates the last page anyway
16301                         if (!result.length) {
16302                                 result = this.element.children(".ui-menu-item:last");
16303                         }
16304                         this.activate(event, result);
16305                 } else {
16306                         this.activate(event, this.element.children(".ui-menu-item")
16307                                 .filter(!this.active || this.last() ? ":first" : ":last"));
16308                 }
16309         },
16310
16311         // TODO merge with nextPage
16312         previousPage: function(event) {
16313                 if (this.hasScroll()) {
16314                         // TODO merge with no-scroll-else
16315                         if (!this.active || this.first()) {
16316                                 this.activate(event, this.element.children(".ui-menu-item:last"));
16317                                 return;
16318                         }
16319
16320                         var base = this.active.offset().top,
16321                                 height = this.element.height();
16322                                 result = this.element.children(".ui-menu-item").filter(function() {
16323                                         var close = $(this).offset().top - base + height - $(this).height();
16324                                         // TODO improve approximation
16325                                         return close < 10 && close > -10;
16326                                 });
16327
16328                         // TODO try to catch this earlier when scrollTop indicates the last page anyway
16329                         if (!result.length) {
16330                                 result = this.element.children(".ui-menu-item:first");
16331                         }
16332                         this.activate(event, result);
16333                 } else {
16334                         this.activate(event, this.element.children(".ui-menu-item")
16335                                 .filter(!this.active || this.first() ? ":last" : ":first"));
16336                 }
16337         },
16338
16339         hasScroll: function() {
16340                 return this.element.height() < this.element.attr("scrollHeight");
16341         },
16342
16343         select: function( event ) {
16344                 this._trigger("selected", event, { item: this.active });
16345         }
16346 });
16347
16348 }(jQuery));
16349 /*
16350  * jQuery UI Button 1.8.12
16351  *
16352  * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
16353  * Dual licensed under the MIT or GPL Version 2 licenses.
16354  * http://jquery.org/license
16355  *
16356  * http://docs.jquery.com/UI/Button
16357  *
16358  * Depends:
16359  *      jquery.ui.core.js
16360  *      jquery.ui.widget.js
16361  */
16362 (function( $, undefined ) {
16363
16364 var lastActive,
16365         baseClasses = "ui-button ui-widget ui-state-default ui-corner-all",
16366         stateClasses = "ui-state-hover ui-state-active ",
16367         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",
16368         formResetHandler = function( event ) {
16369                 $( ":ui-button", event.target.form ).each(function() {
16370                         var inst = $( this ).data( "button" );
16371                         setTimeout(function() {
16372                                 inst.refresh();
16373                         }, 1 );
16374                 });
16375         },
16376         radioGroup = function( radio ) {
16377                 var name = radio.name,
16378                         form = radio.form,
16379                         radios = $( [] );
16380                 if ( name ) {
16381                         if ( form ) {
16382                                 radios = $( form ).find( "[name='" + name + "']" );
16383                         } else {
16384                                 radios = $( "[name='" + name + "']", radio.ownerDocument )
16385                                         .filter(function() {
16386                                                 return !this.form;
16387                                         });
16388                         }
16389                 }
16390                 return radios;
16391         };
16392
16393 $.widget( "ui.button", {
16394         options: {
16395                 disabled: null,
16396                 text: true,
16397                 label: null,
16398                 icons: {
16399                         primary: null,
16400                         secondary: null
16401                 }
16402         },
16403         _create: function() {
16404                 this.element.closest( "form" )
16405                         .unbind( "reset.button" )
16406                         .bind( "reset.button", formResetHandler );
16407
16408                 if ( typeof this.options.disabled !== "boolean" ) {
16409                         this.options.disabled = this.element.attr( "disabled" );
16410                 }
16411
16412                 this._determineButtonType();
16413                 this.hasTitle = !!this.buttonElement.attr( "title" );
16414
16415                 var self = this,
16416                         options = this.options,
16417                         toggleButton = this.type === "checkbox" || this.type === "radio",
16418                         hoverClass = "ui-state-hover" + ( !toggleButton ? " ui-state-active" : "" ),
16419                         focusClass = "ui-state-focus";
16420
16421                 if ( options.label === null ) {
16422                         options.label = this.buttonElement.html();
16423                 }
16424
16425                 if ( this.element.is( ":disabled" ) ) {
16426                         options.disabled = true;
16427                 }
16428
16429                 this.buttonElement
16430                         .addClass( baseClasses )
16431                         .attr( "role", "button" )
16432                         .bind( "mouseenter.button", function() {
16433                                 if ( options.disabled ) {
16434                                         return;
16435                                 }
16436                                 $( this ).addClass( "ui-state-hover" );
16437                                 if ( this === lastActive ) {
16438                                         $( this ).addClass( "ui-state-active" );
16439                                 }
16440                         })
16441                         .bind( "mouseleave.button", function() {
16442                                 if ( options.disabled ) {
16443                                         return;
16444                                 }
16445                                 $( this ).removeClass( hoverClass );
16446                         })
16447                         .bind( "focus.button", function() {
16448                                 // no need to check disabled, focus won't be triggered anyway
16449                                 $( this ).addClass( focusClass );
16450                         })
16451                         .bind( "blur.button", function() {
16452                                 $( this ).removeClass( focusClass );
16453                         });
16454
16455                 if ( toggleButton ) {
16456                         this.element.bind( "change.button", function() {
16457                                 self.refresh();
16458                         });
16459                 }
16460
16461                 if ( this.type === "checkbox" ) {
16462                         this.buttonElement.bind( "click.button", function() {
16463                                 if ( options.disabled ) {
16464                                         return false;
16465                                 }
16466                                 $( this ).toggleClass( "ui-state-active" );
16467                                 self.buttonElement.attr( "aria-pressed", self.element[0].checked );
16468                         });
16469                 } else if ( this.type === "radio" ) {
16470                         this.buttonElement.bind( "click.button", function() {
16471                                 if ( options.disabled ) {
16472                                         return false;
16473                                 }
16474                                 $( this ).addClass( "ui-state-active" );
16475                                 self.buttonElement.attr( "aria-pressed", true );
16476
16477                                 var radio = self.element[ 0 ];
16478                                 radioGroup( radio )
16479                                         .not( radio )
16480                                         .map(function() {
16481                                                 return $( this ).button( "widget" )[ 0 ];
16482                                         })
16483                                         .removeClass( "ui-state-active" )
16484                                         .attr( "aria-pressed", false );
16485                         });
16486                 } else {
16487                         this.buttonElement
16488                                 .bind( "mousedown.button", function() {
16489                                         if ( options.disabled ) {
16490                                                 return false;
16491                                         }
16492                                         $( this ).addClass( "ui-state-active" );
16493                                         lastActive = this;
16494                                         $( document ).one( "mouseup", function() {
16495                                                 lastActive = null;
16496                                         });
16497                                 })
16498                                 .bind( "mouseup.button", function() {
16499                                         if ( options.disabled ) {
16500                                                 return false;
16501                                         }
16502                                         $( this ).removeClass( "ui-state-active" );
16503                                 })
16504                                 .bind( "keydown.button", function(event) {
16505                                         if ( options.disabled ) {
16506                                                 return false;
16507                                         }
16508                                         if ( event.keyCode == $.ui.keyCode.SPACE || event.keyCode == $.ui.keyCode.ENTER ) {
16509                                                 $( this ).addClass( "ui-state-active" );
16510                                         }
16511                                 })
16512                                 .bind( "keyup.button", function() {
16513                                         $( this ).removeClass( "ui-state-active" );
16514                                 });
16515
16516                         if ( this.buttonElement.is("a") ) {
16517                                 this.buttonElement.keyup(function(event) {
16518                                         if ( event.keyCode === $.ui.keyCode.SPACE ) {
16519                                                 // TODO pass through original event correctly (just as 2nd argument doesn't work)
16520                                                 $( this ).click();
16521                                         }
16522                                 });
16523                         }
16524                 }
16525
16526                 // TODO: pull out $.Widget's handling for the disabled option into
16527                 // $.Widget.prototype._setOptionDisabled so it's easy to proxy and can
16528                 // be overridden by individual plugins
16529                 this._setOption( "disabled", options.disabled );
16530         },
16531
16532         _determineButtonType: function() {
16533
16534                 if ( this.element.is(":checkbox") ) {
16535                         this.type = "checkbox";
16536                 } else if ( this.element.is(":radio") ) {
16537                         this.type = "radio";
16538                 } else if ( this.element.is("input") ) {
16539                         this.type = "input";
16540                 } else {
16541                         this.type = "button";
16542                 }
16543
16544                 if ( this.type === "checkbox" || this.type === "radio" ) {
16545                         // we don't search against the document in case the element
16546                         // is disconnected from the DOM
16547                         var ancestor = this.element.parents().filter(":last"),
16548                                 labelSelector = "label[for=" + this.element.attr("id") + "]";
16549                         this.buttonElement = ancestor.find( labelSelector );
16550                         if ( !this.buttonElement.length ) {
16551                                 ancestor = ancestor.length ? ancestor.siblings() : this.element.siblings();
16552                                 this.buttonElement = ancestor.filter( labelSelector );
16553                                 if ( !this.buttonElement.length ) {
16554                                         this.buttonElement = ancestor.find( labelSelector );
16555                                 }
16556                         }
16557                         this.element.addClass( "ui-helper-hidden-accessible" );
16558
16559                         var checked = this.element.is( ":checked" );
16560                         if ( checked ) {
16561                                 this.buttonElement.addClass( "ui-state-active" );
16562                         }
16563                         this.buttonElement.attr( "aria-pressed", checked );
16564                 } else {
16565                         this.buttonElement = this.element;
16566                 }
16567         },
16568
16569         widget: function() {
16570                 return this.buttonElement;
16571         },
16572
16573         destroy: function() {
16574                 this.element
16575                         .removeClass( "ui-helper-hidden-accessible" );
16576                 this.buttonElement
16577                         .removeClass( baseClasses + " " + stateClasses + " " + typeClasses )
16578                         .removeAttr( "role" )
16579                         .removeAttr( "aria-pressed" )
16580                         .html( this.buttonElement.find(".ui-button-text").html() );
16581
16582                 if ( !this.hasTitle ) {
16583                         this.buttonElement.removeAttr( "title" );
16584                 }
16585
16586                 $.Widget.prototype.destroy.call( this );
16587         },
16588
16589         _setOption: function( key, value ) {
16590                 $.Widget.prototype._setOption.apply( this, arguments );
16591                 if ( key === "disabled" ) {
16592                         if ( value ) {
16593                                 this.element.attr( "disabled", true );
16594                         } else {
16595                                 this.element.removeAttr( "disabled" );
16596                         }
16597                 }
16598                 this._resetButton();
16599         },
16600
16601         refresh: function() {
16602                 var isDisabled = this.element.is( ":disabled" );
16603                 if ( isDisabled !== this.options.disabled ) {
16604                         this._setOption( "disabled", isDisabled );
16605                 }
16606                 if ( this.type === "radio" ) {
16607                         radioGroup( this.element[0] ).each(function() {
16608                                 if ( $( this ).is( ":checked" ) ) {
16609                                         $( this ).button( "widget" )
16610                                                 .addClass( "ui-state-active" )
16611                                                 .attr( "aria-pressed", true );
16612                                 } else {
16613                                         $( this ).button( "widget" )
16614                                                 .removeClass( "ui-state-active" )
16615                                                 .attr( "aria-pressed", false );
16616                                 }
16617                         });
16618                 } else if ( this.type === "checkbox" ) {
16619                         if ( this.element.is( ":checked" ) ) {
16620                                 this.buttonElement
16621                                         .addClass( "ui-state-active" )
16622                                         .attr( "aria-pressed", true );
16623                         } else {
16624                                 this.buttonElement
16625                                         .removeClass( "ui-state-active" )
16626                                         .attr( "aria-pressed", false );
16627                         }
16628                 }
16629         },
16630
16631         _resetButton: function() {
16632                 if ( this.type === "input" ) {
16633                         if ( this.options.label ) {
16634                                 this.element.val( this.options.label );
16635                         }
16636                         return;
16637                 }
16638                 var buttonElement = this.buttonElement.removeClass( typeClasses ),
16639                         buttonText = $( "<span></span>" )
16640                                 .addClass( "ui-button-text" )
16641                                 .html( this.options.label )
16642                                 .appendTo( buttonElement.empty() )
16643                                 .text(),
16644                         icons = this.options.icons,
16645                         multipleIcons = icons.primary && icons.secondary,
16646                         buttonClasses = [];  
16647
16648                 if ( icons.primary || icons.secondary ) {
16649                         if ( this.options.text ) {
16650                                 buttonClasses.push( "ui-button-text-icon" + ( multipleIcons ? "s" : ( icons.primary ? "-primary" : "-secondary" ) ) );
16651                         }
16652
16653                         if ( icons.primary ) {
16654                                 buttonElement.prepend( "<span class='ui-button-icon-primary ui-icon " + icons.primary + "'></span>" );
16655                         }
16656
16657                         if ( icons.secondary ) {
16658                                 buttonElement.append( "<span class='ui-button-icon-secondary ui-icon " + icons.secondary + "'></span>" );
16659                         }
16660
16661                         if ( !this.options.text ) {
16662                                 buttonClasses.push( multipleIcons ? "ui-button-icons-only" : "ui-button-icon-only" );
16663
16664                                 if ( !this.hasTitle ) {
16665                                         buttonElement.attr( "title", buttonText );
16666                                 }
16667                         }
16668                 } else {
16669                         buttonClasses.push( "ui-button-text-only" );
16670                 }
16671                 buttonElement.addClass( buttonClasses.join( " " ) );
16672         }
16673 });
16674
16675 $.widget( "ui.buttonset", {
16676         options: {
16677                 items: ":button, :submit, :reset, :checkbox, :radio, a, :data(button)"
16678         },
16679
16680         _create: function() {
16681                 this.element.addClass( "ui-buttonset" );
16682         },
16683         
16684         _init: function() {
16685                 this.refresh();
16686         },
16687
16688         _setOption: function( key, value ) {
16689                 if ( key === "disabled" ) {
16690                         this.buttons.button( "option", key, value );
16691                 }
16692
16693                 $.Widget.prototype._setOption.apply( this, arguments );
16694         },
16695         
16696         refresh: function() {
16697                 this.buttons = this.element.find( this.options.items )
16698                         .filter( ":ui-button" )
16699                                 .button( "refresh" )
16700                         .end()
16701                         .not( ":ui-button" )
16702                                 .button()
16703                         .end()
16704                         .map(function() {
16705                                 return $( this ).button( "widget" )[ 0 ];
16706                         })
16707                                 .removeClass( "ui-corner-all ui-corner-left ui-corner-right" )
16708                                 .filter( ":first" )
16709                                         .addClass( "ui-corner-left" )
16710                                 .end()
16711                                 .filter( ":last" )
16712                                         .addClass( "ui-corner-right" )
16713                                 .end()
16714                         .end();
16715         },
16716
16717         destroy: function() {
16718                 this.element.removeClass( "ui-buttonset" );
16719                 this.buttons
16720                         .map(function() {
16721                                 return $( this ).button( "widget" )[ 0 ];
16722                         })
16723                                 .removeClass( "ui-corner-left ui-corner-right" )
16724                         .end()
16725                         .button( "destroy" );
16726
16727                 $.Widget.prototype.destroy.call( this );
16728         }
16729 });
16730
16731 }( jQuery ) );
16732 /*
16733  * jQuery UI Datepicker 1.8.12
16734  *
16735  * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
16736  * Dual licensed under the MIT or GPL Version 2 licenses.
16737  * http://jquery.org/license
16738  *
16739  * http://docs.jquery.com/UI/Datepicker
16740  *
16741  * Depends:
16742  *      jquery.ui.core.js
16743  */
16744 (function( $, undefined ) {
16745
16746 $.extend($.ui, { datepicker: { version: "1.8.12" } });
16747
16748 var PROP_NAME = 'datepicker';
16749 var dpuuid = new Date().getTime();
16750
16751 /* Date picker manager.
16752    Use the singleton instance of this class, $.datepicker, to interact with the date picker.
16753    Settings for (groups of) date pickers are maintained in an instance object,
16754    allowing multiple different settings on the same page. */
16755
16756 function Datepicker() {
16757         this.debug = false; // Change this to true to start debugging
16758         this._curInst = null; // The current instance in use
16759         this._keyEvent = false; // If the last event was a key event
16760         this._disabledInputs = []; // List of date picker inputs that have been disabled
16761         this._datepickerShowing = false; // True if the popup picker is showing , false if not
16762         this._inDialog = false; // True if showing within a "dialog", false if not
16763         this._mainDivId = 'ui-datepicker-div'; // The ID of the main datepicker division
16764         this._inlineClass = 'ui-datepicker-inline'; // The name of the inline marker class
16765         this._appendClass = 'ui-datepicker-append'; // The name of the append marker class
16766         this._triggerClass = 'ui-datepicker-trigger'; // The name of the trigger marker class
16767         this._dialogClass = 'ui-datepicker-dialog'; // The name of the dialog marker class
16768         this._disableClass = 'ui-datepicker-disabled'; // The name of the disabled covering marker class
16769         this._unselectableClass = 'ui-datepicker-unselectable'; // The name of the unselectable cell marker class
16770         this._currentClass = 'ui-datepicker-current-day'; // The name of the current day marker class
16771         this._dayOverClass = 'ui-datepicker-days-cell-over'; // The name of the day hover marker class
16772         this.regional = []; // Available regional settings, indexed by language code
16773         this.regional[''] = { // Default regional settings
16774                 closeText: 'Done', // Display text for close link
16775                 prevText: 'Prev', // Display text for previous month link
16776                 nextText: 'Next', // Display text for next month link
16777                 currentText: 'Today', // Display text for current month link
16778                 monthNames: ['January','February','March','April','May','June',
16779                         'July','August','September','October','November','December'], // Names of months for drop-down and formatting
16780                 monthNamesShort: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'], // For formatting
16781                 dayNames: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'], // For formatting
16782                 dayNamesShort: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'], // For formatting
16783                 dayNamesMin: ['Su','Mo','Tu','We','Th','Fr','Sa'], // Column headings for days starting at Sunday
16784                 weekHeader: 'Wk', // Column header for week of the year
16785                 dateFormat: 'mm/dd/yy', // See format options on parseDate
16786                 firstDay: 0, // The first day of the week, Sun = 0, Mon = 1, ...
16787                 isRTL: false, // True if right-to-left language, false if left-to-right
16788                 showMonthAfterYear: false, // True if the year select precedes month, false for month then year
16789                 yearSuffix: '' // Additional text to append to the year in the month headers
16790         };
16791         this._defaults = { // Global defaults for all the date picker instances
16792                 showOn: 'focus', // 'focus' for popup on focus,
16793                         // 'button' for trigger button, or 'both' for either
16794                 showAnim: 'fadeIn', // Name of jQuery animation for popup
16795                 showOptions: {}, // Options for enhanced animations
16796                 defaultDate: null, // Used when field is blank: actual date,
16797                         // +/-number for offset from today, null for today
16798                 appendText: '', // Display text following the input box, e.g. showing the format
16799                 buttonText: '...', // Text for trigger button
16800                 buttonImage: '', // URL for trigger button image
16801                 buttonImageOnly: false, // True if the image appears alone, false if it appears on a button
16802                 hideIfNoPrevNext: false, // True to hide next/previous month links
16803                         // if not applicable, false to just disable them
16804                 navigationAsDateFormat: false, // True if date formatting applied to prev/today/next links
16805                 gotoCurrent: false, // True if today link goes back to current selection instead
16806                 changeMonth: false, // True if month can be selected directly, false if only prev/next
16807                 changeYear: false, // True if year can be selected directly, false if only prev/next
16808                 yearRange: 'c-10:c+10', // Range of years to display in drop-down,
16809                         // either relative to today's year (-nn:+nn), relative to currently displayed year
16810                         // (c-nn:c+nn), absolute (nnnn:nnnn), or a combination of the above (nnnn:-n)
16811                 showOtherMonths: false, // True to show dates in other months, false to leave blank
16812                 selectOtherMonths: false, // True to allow selection of dates in other months, false for unselectable
16813                 showWeek: false, // True to show week of the year, false to not show it
16814                 calculateWeek: this.iso8601Week, // How to calculate the week of the year,
16815                         // takes a Date and returns the number of the week for it
16816                 shortYearCutoff: '+10', // Short year values < this are in the current century,
16817                         // > this are in the previous century,
16818                         // string value starting with '+' for current year + value
16819                 minDate: null, // The earliest selectable date, or null for no limit
16820                 maxDate: null, // The latest selectable date, or null for no limit
16821                 duration: 'fast', // Duration of display/closure
16822                 beforeShowDay: null, // Function that takes a date and returns an array with
16823                         // [0] = true if selectable, false if not, [1] = custom CSS class name(s) or '',
16824                         // [2] = cell title (optional), e.g. $.datepicker.noWeekends
16825                 beforeShow: null, // Function that takes an input field and
16826                         // returns a set of custom settings for the date picker
16827                 onSelect: null, // Define a callback function when a date is selected
16828                 onChangeMonthYear: null, // Define a callback function when the month or year is changed
16829                 onClose: null, // Define a callback function when the datepicker is closed
16830                 numberOfMonths: 1, // Number of months to show at a time
16831                 showCurrentAtPos: 0, // The position in multipe months at which to show the current month (starting at 0)
16832                 stepMonths: 1, // Number of months to step back/forward
16833                 stepBigMonths: 12, // Number of months to step back/forward for the big links
16834                 altField: '', // Selector for an alternate field to store selected dates into
16835                 altFormat: '', // The date format to use for the alternate field
16836                 constrainInput: true, // The input is constrained by the current date format
16837                 showButtonPanel: false, // True to show button panel, false to not show it
16838                 autoSize: false // True to size the input for the date format, false to leave as is
16839         };
16840         $.extend(this._defaults, this.regional['']);
16841         this.dpDiv = $('<div id="' + this._mainDivId + '" class="ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all"></div>');
16842 }
16843
16844 $.extend(Datepicker.prototype, {
16845         /* Class name added to elements to indicate already configured with a date picker. */
16846         markerClassName: 'hasDatepicker',
16847
16848         /* Debug logging (if enabled). */
16849         log: function () {
16850                 if (this.debug)
16851                         console.log.apply('', arguments);
16852         },
16853         
16854         // TODO rename to "widget" when switching to widget factory
16855         _widgetDatepicker: function() {
16856                 return this.dpDiv;
16857         },
16858
16859         /* Override the default settings for all instances of the date picker.
16860            @param  settings  object - the new settings to use as defaults (anonymous object)
16861            @return the manager object */
16862         setDefaults: function(settings) {
16863                 extendRemove(this._defaults, settings || {});
16864                 return this;
16865         },
16866
16867         /* Attach the date picker to a jQuery selection.
16868            @param  target    element - the target input field or division or span
16869            @param  settings  object - the new settings to use for this date picker instance (anonymous) */
16870         _attachDatepicker: function(target, settings) {
16871                 // check for settings on the control itself - in namespace 'date:'
16872                 var inlineSettings = null;
16873                 for (var attrName in this._defaults) {
16874                         var attrValue = target.getAttribute('date:' + attrName);
16875                         if (attrValue) {
16876                                 inlineSettings = inlineSettings || {};
16877                                 try {
16878                                         inlineSettings[attrName] = eval(attrValue);
16879                                 } catch (err) {
16880                                         inlineSettings[attrName] = attrValue;
16881                                 }
16882                         }
16883                 }
16884                 var nodeName = target.nodeName.toLowerCase();
16885                 var inline = (nodeName == 'div' || nodeName == 'span');
16886                 if (!target.id) {
16887                         this.uuid += 1;
16888                         target.id = 'dp' + this.uuid;
16889                 }
16890                 var inst = this._newInst($(target), inline);
16891                 inst.settings = $.extend({}, settings || {}, inlineSettings || {});
16892                 if (nodeName == 'input') {
16893                         this._connectDatepicker(target, inst);
16894                 } else if (inline) {
16895                         this._inlineDatepicker(target, inst);
16896                 }
16897         },
16898
16899         /* Create a new instance object. */
16900         _newInst: function(target, inline) {
16901                 var id = target[0].id.replace(/([^A-Za-z0-9_-])/g, '\\\\$1'); // escape jQuery meta chars
16902                 return {id: id, input: target, // associated target
16903                         selectedDay: 0, selectedMonth: 0, selectedYear: 0, // current selection
16904                         drawMonth: 0, drawYear: 0, // month being drawn
16905                         inline: inline, // is datepicker inline or not
16906                         dpDiv: (!inline ? this.dpDiv : // presentation div
16907                         $('<div class="' + this._inlineClass + ' ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all"></div>'))};
16908         },
16909
16910         /* Attach the date picker to an input field. */
16911         _connectDatepicker: function(target, inst) {
16912                 var input = $(target);
16913                 inst.append = $([]);
16914                 inst.trigger = $([]);
16915                 if (input.hasClass(this.markerClassName))
16916                         return;
16917                 this._attachments(input, inst);
16918                 input.addClass(this.markerClassName).keydown(this._doKeyDown).
16919                         keypress(this._doKeyPress).keyup(this._doKeyUp).
16920                         bind("setData.datepicker", function(event, key, value) {
16921                                 inst.settings[key] = value;
16922                         }).bind("getData.datepicker", function(event, key) {
16923                                 return this._get(inst, key);
16924                         });
16925                 this._autoSize(inst);
16926                 $.data(target, PROP_NAME, inst);
16927         },
16928
16929         /* Make attachments based on settings. */
16930         _attachments: function(input, inst) {
16931                 var appendText = this._get(inst, 'appendText');
16932                 var isRTL = this._get(inst, 'isRTL');
16933                 if (inst.append)
16934                         inst.append.remove();
16935                 if (appendText) {
16936                         inst.append = $('<span class="' + this._appendClass + '">' + appendText + '</span>');
16937                         input[isRTL ? 'before' : 'after'](inst.append);
16938                 }
16939                 input.unbind('focus', this._showDatepicker);
16940                 if (inst.trigger)
16941                         inst.trigger.remove();
16942                 var showOn = this._get(inst, 'showOn');
16943                 if (showOn == 'focus' || showOn == 'both') // pop-up date picker when in the marked field
16944                         input.focus(this._showDatepicker);
16945                 if (showOn == 'button' || showOn == 'both') { // pop-up date picker when button clicked
16946                         var buttonText = this._get(inst, 'buttonText');
16947                         var buttonImage = this._get(inst, 'buttonImage');
16948                         inst.trigger = $(this._get(inst, 'buttonImageOnly') ?
16949                                 $('<img/>').addClass(this._triggerClass).
16950                                         attr({ src: buttonImage, alt: buttonText, title: buttonText }) :
16951                                 $('<button type="button"></button>').addClass(this._triggerClass).
16952                                         html(buttonImage == '' ? buttonText : $('<img/>').attr(
16953                                         { src:buttonImage, alt:buttonText, title:buttonText })));
16954                         input[isRTL ? 'before' : 'after'](inst.trigger);
16955                         inst.trigger.click(function() {
16956                                 if ($.datepicker._datepickerShowing && $.datepicker._lastInput == input[0])
16957                                         $.datepicker._hideDatepicker();
16958                                 else
16959                                         $.datepicker._showDatepicker(input[0]);
16960                                 return false;
16961                         });
16962                 }
16963         },
16964
16965         /* Apply the maximum length for the date format. */
16966         _autoSize: function(inst) {
16967                 if (this._get(inst, 'autoSize') && !inst.inline) {
16968                         var date = new Date(2009, 12 - 1, 20); // Ensure double digits
16969                         var dateFormat = this._get(inst, 'dateFormat');
16970                         if (dateFormat.match(/[DM]/)) {
16971                                 var findMax = function(names) {
16972                                         var max = 0;
16973                                         var maxI = 0;
16974                                         for (var i = 0; i < names.length; i++) {
16975                                                 if (names[i].length > max) {
16976                                                         max = names[i].length;
16977                                                         maxI = i;
16978                                                 }
16979                                         }
16980                                         return maxI;
16981                                 };
16982                                 date.setMonth(findMax(this._get(inst, (dateFormat.match(/MM/) ?
16983                                         'monthNames' : 'monthNamesShort'))));
16984                                 date.setDate(findMax(this._get(inst, (dateFormat.match(/DD/) ?
16985                                         'dayNames' : 'dayNamesShort'))) + 20 - date.getDay());
16986                         }
16987                         inst.input.attr('size', this._formatDate(inst, date).length);
16988                 }
16989         },
16990
16991         /* Attach an inline date picker to a div. */
16992         _inlineDatepicker: function(target, inst) {
16993                 var divSpan = $(target);
16994                 if (divSpan.hasClass(this.markerClassName))
16995                         return;
16996                 divSpan.addClass(this.markerClassName).append(inst.dpDiv).
16997                         bind("setData.datepicker", function(event, key, value){
16998                                 inst.settings[key] = value;
16999                         }).bind("getData.datepicker", function(event, key){
17000                                 return this._get(inst, key);
17001                         });
17002                 $.data(target, PROP_NAME, inst);
17003                 this._setDate(inst, this._getDefaultDate(inst), true);
17004                 this._updateDatepicker(inst);
17005                 this._updateAlternate(inst);
17006                 inst.dpDiv.show();
17007         },
17008
17009         /* Pop-up the date picker in a "dialog" box.
17010            @param  input     element - ignored
17011            @param  date      string or Date - the initial date to display
17012            @param  onSelect  function - the function to call when a date is selected
17013            @param  settings  object - update the dialog date picker instance's settings (anonymous object)
17014            @param  pos       int[2] - coordinates for the dialog's position within the screen or
17015                              event - with x/y coordinates or
17016                              leave empty for default (screen centre)
17017            @return the manager object */
17018         _dialogDatepicker: function(input, date, onSelect, settings, pos) {
17019                 var inst = this._dialogInst; // internal instance
17020                 if (!inst) {
17021                         this.uuid += 1;
17022                         var id = 'dp' + this.uuid;
17023                         this._dialogInput = $('<input type="text" id="' + id +
17024                                 '" style="position: absolute; top: -100px; width: 0px; z-index: -10;"/>');
17025                         this._dialogInput.keydown(this._doKeyDown);
17026                         $('body').append(this._dialogInput);
17027                         inst = this._dialogInst = this._newInst(this._dialogInput, false);
17028                         inst.settings = {};
17029                         $.data(this._dialogInput[0], PROP_NAME, inst);
17030                 }
17031                 extendRemove(inst.settings, settings || {});
17032                 date = (date && date.constructor == Date ? this._formatDate(inst, date) : date);
17033                 this._dialogInput.val(date);
17034
17035                 this._pos = (pos ? (pos.length ? pos : [pos.pageX, pos.pageY]) : null);
17036                 if (!this._pos) {
17037                         var browserWidth = document.documentElement.clientWidth;
17038                         var browserHeight = document.documentElement.clientHeight;
17039                         var scrollX = document.documentElement.scrollLeft || document.body.scrollLeft;
17040                         var scrollY = document.documentElement.scrollTop || document.body.scrollTop;
17041                         this._pos = // should use actual width/height below
17042                                 [(browserWidth / 2) - 100 + scrollX, (browserHeight / 2) - 150 + scrollY];
17043                 }
17044
17045                 // move input on screen for focus, but hidden behind dialog
17046                 this._dialogInput.css('left', (this._pos[0] + 20) + 'px').css('top', this._pos[1] + 'px');
17047                 inst.settings.onSelect = onSelect;
17048                 this._inDialog = true;
17049                 this.dpDiv.addClass(this._dialogClass);
17050                 this._showDatepicker(this._dialogInput[0]);
17051                 if ($.blockUI)
17052                         $.blockUI(this.dpDiv);
17053                 $.data(this._dialogInput[0], PROP_NAME, inst);
17054                 return this;
17055         },
17056
17057         /* Detach a datepicker from its control.
17058            @param  target    element - the target input field or division or span */
17059         _destroyDatepicker: function(target) {
17060                 var $target = $(target);
17061                 var inst = $.data(target, PROP_NAME);
17062                 if (!$target.hasClass(this.markerClassName)) {
17063                         return;
17064                 }
17065                 var nodeName = target.nodeName.toLowerCase();
17066                 $.removeData(target, PROP_NAME);
17067                 if (nodeName == 'input') {
17068                         inst.append.remove();
17069                         inst.trigger.remove();
17070                         $target.removeClass(this.markerClassName).
17071                                 unbind('focus', this._showDatepicker).
17072                                 unbind('keydown', this._doKeyDown).
17073                                 unbind('keypress', this._doKeyPress).
17074                                 unbind('keyup', this._doKeyUp);
17075                 } else if (nodeName == 'div' || nodeName == 'span')
17076                         $target.removeClass(this.markerClassName).empty();
17077         },
17078
17079         /* Enable the date picker to a jQuery selection.
17080            @param  target    element - the target input field or division or span */
17081         _enableDatepicker: function(target) {
17082                 var $target = $(target);
17083                 var inst = $.data(target, PROP_NAME);
17084                 if (!$target.hasClass(this.markerClassName)) {
17085                         return;
17086                 }
17087                 var nodeName = target.nodeName.toLowerCase();
17088                 if (nodeName == 'input') {
17089                         target.disabled = false;
17090                         inst.trigger.filter('button').
17091                                 each(function() { this.disabled = false; }).end().
17092                                 filter('img').css({opacity: '1.0', cursor: ''});
17093                 }
17094                 else if (nodeName == 'div' || nodeName == 'span') {
17095                         var inline = $target.children('.' + this._inlineClass);
17096                         inline.children().removeClass('ui-state-disabled');
17097                 }
17098                 this._disabledInputs = $.map(this._disabledInputs,
17099                         function(value) { return (value == target ? null : value); }); // delete entry
17100         },
17101
17102         /* Disable the date picker to a jQuery selection.
17103            @param  target    element - the target input field or division or span */
17104         _disableDatepicker: function(target) {
17105                 var $target = $(target);
17106                 var inst = $.data(target, PROP_NAME);
17107                 if (!$target.hasClass(this.markerClassName)) {
17108                         return;
17109                 }
17110                 var nodeName = target.nodeName.toLowerCase();
17111                 if (nodeName == 'input') {
17112                         target.disabled = true;
17113                         inst.trigger.filter('button').
17114                                 each(function() { this.disabled = true; }).end().
17115                                 filter('img').css({opacity: '0.5', cursor: 'default'});
17116                 }
17117                 else if (nodeName == 'div' || nodeName == 'span') {
17118                         var inline = $target.children('.' + this._inlineClass);
17119                         inline.children().addClass('ui-state-disabled');
17120                 }
17121                 this._disabledInputs = $.map(this._disabledInputs,
17122                         function(value) { return (value == target ? null : value); }); // delete entry
17123                 this._disabledInputs[this._disabledInputs.length] = target;
17124         },
17125
17126         /* Is the first field in a jQuery collection disabled as a datepicker?
17127            @param  target    element - the target input field or division or span
17128            @return boolean - true if disabled, false if enabled */
17129         _isDisabledDatepicker: function(target) {
17130                 if (!target) {
17131                         return false;
17132                 }
17133                 for (var i = 0; i < this._disabledInputs.length; i++) {
17134                         if (this._disabledInputs[i] == target)
17135                                 return true;
17136                 }
17137                 return false;
17138         },
17139
17140         /* Retrieve the instance data for the target control.
17141            @param  target  element - the target input field or division or span
17142            @return  object - the associated instance data
17143            @throws  error if a jQuery problem getting data */
17144         _getInst: function(target) {
17145                 try {
17146                         return $.data(target, PROP_NAME);
17147                 }
17148                 catch (err) {
17149                         throw 'Missing instance data for this datepicker';
17150                 }
17151         },
17152
17153         /* Update or retrieve the settings for a date picker attached to an input field or division.
17154            @param  target  element - the target input field or division or span
17155            @param  name    object - the new settings to update or
17156                            string - the name of the setting to change or retrieve,
17157                            when retrieving also 'all' for all instance settings or
17158                            'defaults' for all global defaults
17159            @param  value   any - the new value for the setting
17160                            (omit if above is an object or to retrieve a value) */
17161         _optionDatepicker: function(target, name, value) {
17162                 var inst = this._getInst(target);
17163                 if (arguments.length == 2 && typeof name == 'string') {
17164                         return (name == 'defaults' ? $.extend({}, $.datepicker._defaults) :
17165                                 (inst ? (name == 'all' ? $.extend({}, inst.settings) :
17166                                 this._get(inst, name)) : null));
17167                 }
17168                 var settings = name || {};
17169                 if (typeof name == 'string') {
17170                         settings = {};
17171                         settings[name] = value;
17172                 }
17173                 if (inst) {
17174                         if (this._curInst == inst) {
17175                                 this._hideDatepicker();
17176                         }
17177                         var date = this._getDateDatepicker(target, true);
17178                         var minDate = this._getMinMaxDate(inst, 'min');
17179                         var maxDate = this._getMinMaxDate(inst, 'max');
17180                         extendRemove(inst.settings, settings);
17181                         // reformat the old minDate/maxDate values if dateFormat changes and a new minDate/maxDate isn't provided
17182                         if (minDate !== null && settings['dateFormat'] !== undefined && settings['minDate'] === undefined)
17183                                 inst.settings.minDate = this._formatDate(inst, minDate);
17184                         if (maxDate !== null && settings['dateFormat'] !== undefined && settings['maxDate'] === undefined)
17185                                 inst.settings.maxDate = this._formatDate(inst, maxDate);
17186                         this._attachments($(target), inst);
17187                         this._autoSize(inst);
17188                         this._setDateDatepicker(target, date);
17189                         this._updateDatepicker(inst);
17190                 }
17191         },
17192
17193         // change method deprecated
17194         _changeDatepicker: function(target, name, value) {
17195                 this._optionDatepicker(target, name, value);
17196         },
17197
17198         /* Redraw the date picker attached to an input field or division.
17199            @param  target  element - the target input field or division or span */
17200         _refreshDatepicker: function(target) {
17201                 var inst = this._getInst(target);
17202                 if (inst) {
17203                         this._updateDatepicker(inst);
17204                 }
17205         },
17206
17207         /* Set the dates for a jQuery selection.
17208            @param  target   element - the target input field or division or span
17209            @param  date     Date - the new date */
17210         _setDateDatepicker: function(target, date) {
17211                 var inst = this._getInst(target);
17212                 if (inst) {
17213                         this._setDate(inst, date);
17214                         this._updateDatepicker(inst);
17215                         this._updateAlternate(inst);
17216                 }
17217         },
17218
17219         /* Get the date(s) for the first entry in a jQuery selection.
17220            @param  target     element - the target input field or division or span
17221            @param  noDefault  boolean - true if no default date is to be used
17222            @return Date - the current date */
17223         _getDateDatepicker: function(target, noDefault) {
17224                 var inst = this._getInst(target);
17225                 if (inst && !inst.inline)
17226                         this._setDateFromField(inst, noDefault);
17227                 return (inst ? this._getDate(inst) : null);
17228         },
17229
17230         /* Handle keystrokes. */
17231         _doKeyDown: function(event) {
17232                 var inst = $.datepicker._getInst(event.target);
17233                 var handled = true;
17234                 var isRTL = inst.dpDiv.is('.ui-datepicker-rtl');
17235                 inst._keyEvent = true;
17236                 if ($.datepicker._datepickerShowing)
17237                         switch (event.keyCode) {
17238                                 case 9: $.datepicker._hideDatepicker();
17239                                                 handled = false;
17240                                                 break; // hide on tab out
17241                                 case 13: var sel = $('td.' + $.datepicker._dayOverClass + ':not(.' + 
17242                                                                         $.datepicker._currentClass + ')', inst.dpDiv);
17243                                                 if (sel[0])
17244                                                         $.datepicker._selectDay(event.target, inst.selectedMonth, inst.selectedYear, sel[0]);
17245                                                 else
17246                                                         $.datepicker._hideDatepicker();
17247                                                 return false; // don't submit the form
17248                                                 break; // select the value on enter
17249                                 case 27: $.datepicker._hideDatepicker();
17250                                                 break; // hide on escape
17251                                 case 33: $.datepicker._adjustDate(event.target, (event.ctrlKey ?
17252                                                         -$.datepicker._get(inst, 'stepBigMonths') :
17253                                                         -$.datepicker._get(inst, 'stepMonths')), 'M');
17254                                                 break; // previous month/year on page up/+ ctrl
17255                                 case 34: $.datepicker._adjustDate(event.target, (event.ctrlKey ?
17256                                                         +$.datepicker._get(inst, 'stepBigMonths') :
17257                                                         +$.datepicker._get(inst, 'stepMonths')), 'M');
17258                                                 break; // next month/year on page down/+ ctrl
17259                                 case 35: if (event.ctrlKey || event.metaKey) $.datepicker._clearDate(event.target);
17260                                                 handled = event.ctrlKey || event.metaKey;
17261                                                 break; // clear on ctrl or command +end
17262                                 case 36: if (event.ctrlKey || event.metaKey) $.datepicker._gotoToday(event.target);
17263                                                 handled = event.ctrlKey || event.metaKey;
17264                                                 break; // current on ctrl or command +home
17265                                 case 37: if (event.ctrlKey || event.metaKey) $.datepicker._adjustDate(event.target, (isRTL ? +1 : -1), 'D');
17266                                                 handled = event.ctrlKey || event.metaKey;
17267                                                 // -1 day on ctrl or command +left
17268                                                 if (event.originalEvent.altKey) $.datepicker._adjustDate(event.target, (event.ctrlKey ?
17269                                                                         -$.datepicker._get(inst, 'stepBigMonths') :
17270                                                                         -$.datepicker._get(inst, 'stepMonths')), 'M');
17271                                                 // next month/year on alt +left on Mac
17272                                                 break;
17273                                 case 38: if (event.ctrlKey || event.metaKey) $.datepicker._adjustDate(event.target, -7, 'D');
17274                                                 handled = event.ctrlKey || event.metaKey;
17275                                                 break; // -1 week on ctrl or command +up
17276                                 case 39: if (event.ctrlKey || event.metaKey) $.datepicker._adjustDate(event.target, (isRTL ? -1 : +1), 'D');
17277                                                 handled = event.ctrlKey || event.metaKey;
17278                                                 // +1 day on ctrl or command +right
17279                                                 if (event.originalEvent.altKey) $.datepicker._adjustDate(event.target, (event.ctrlKey ?
17280                                                                         +$.datepicker._get(inst, 'stepBigMonths') :
17281                                                                         +$.datepicker._get(inst, 'stepMonths')), 'M');
17282                                                 // next month/year on alt +right
17283                                                 break;
17284                                 case 40: if (event.ctrlKey || event.metaKey) $.datepicker._adjustDate(event.target, +7, 'D');
17285                                                 handled = event.ctrlKey || event.metaKey;
17286                                                 break; // +1 week on ctrl or command +down
17287                                 default: handled = false;
17288                         }
17289                 else if (event.keyCode == 36 && event.ctrlKey) // display the date picker on ctrl+home
17290                         $.datepicker._showDatepicker(this);
17291                 else {
17292                         handled = false;
17293                 }
17294                 if (handled) {
17295                         event.preventDefault();
17296                         event.stopPropagation();
17297                 }
17298         },
17299
17300         /* Filter entered characters - based on date format. */
17301         _doKeyPress: function(event) {
17302                 var inst = $.datepicker._getInst(event.target);
17303                 if ($.datepicker._get(inst, 'constrainInput')) {
17304                         var chars = $.datepicker._possibleChars($.datepicker._get(inst, 'dateFormat'));
17305                         var chr = String.fromCharCode(event.charCode == undefined ? event.keyCode : event.charCode);
17306                         return event.ctrlKey || event.metaKey || (chr < ' ' || !chars || chars.indexOf(chr) > -1);
17307                 }
17308         },
17309
17310         /* Synchronise manual entry and field/alternate field. */
17311         _doKeyUp: function(event) {
17312                 var inst = $.datepicker._getInst(event.target);
17313                 if (inst.input.val() != inst.lastVal) {
17314                         try {
17315                                 var date = $.datepicker.parseDate($.datepicker._get(inst, 'dateFormat'),
17316                                         (inst.input ? inst.input.val() : null),
17317                                         $.datepicker._getFormatConfig(inst));
17318                                 if (date) { // only if valid
17319                                         $.datepicker._setDateFromField(inst);
17320                                         $.datepicker._updateAlternate(inst);
17321                                         $.datepicker._updateDatepicker(inst);
17322                                 }
17323                         }
17324                         catch (event) {
17325                                 $.datepicker.log(event);
17326                         }
17327                 }
17328                 return true;
17329         },
17330
17331         /* Pop-up the date picker for a given input field.
17332            @param  input  element - the input field attached to the date picker or
17333                           event - if triggered by focus */
17334         _showDatepicker: function(input) {
17335                 input = input.target || input;
17336                 if (input.nodeName.toLowerCase() != 'input') // find from button/image trigger
17337                         input = $('input', input.parentNode)[0];
17338                 if ($.datepicker._isDisabledDatepicker(input) || $.datepicker._lastInput == input) // already here
17339                         return;
17340                 var inst = $.datepicker._getInst(input);
17341                 if ($.datepicker._curInst && $.datepicker._curInst != inst) {
17342                         $.datepicker._curInst.dpDiv.stop(true, true);
17343                 }
17344                 var beforeShow = $.datepicker._get(inst, 'beforeShow');
17345                 extendRemove(inst.settings, (beforeShow ? beforeShow.apply(input, [input, inst]) : {}));
17346                 inst.lastVal = null;
17347                 $.datepicker._lastInput = input;
17348                 $.datepicker._setDateFromField(inst);
17349                 if ($.datepicker._inDialog) // hide cursor
17350                         input.value = '';
17351                 if (!$.datepicker._pos) { // position below input
17352                         $.datepicker._pos = $.datepicker._findPos(input);
17353                         $.datepicker._pos[1] += input.offsetHeight; // add the height
17354                 }
17355                 var isFixed = false;
17356                 $(input).parents().each(function() {
17357                         isFixed |= $(this).css('position') == 'fixed';
17358                         return !isFixed;
17359                 });
17360                 if (isFixed && $.browser.opera) { // correction for Opera when fixed and scrolled
17361                         $.datepicker._pos[0] -= document.documentElement.scrollLeft;
17362                         $.datepicker._pos[1] -= document.documentElement.scrollTop;
17363                 }
17364                 var offset = {left: $.datepicker._pos[0], top: $.datepicker._pos[1]};
17365                 $.datepicker._pos = null;
17366                 //to avoid flashes on Firefox
17367                 inst.dpDiv.empty();
17368                 // determine sizing offscreen
17369                 inst.dpDiv.css({position: 'absolute', display: 'block', top: '-1000px'});
17370                 $.datepicker._updateDatepicker(inst);
17371                 // fix width for dynamic number of date pickers
17372                 // and adjust position before showing
17373                 offset = $.datepicker._checkOffset(inst, offset, isFixed);
17374                 inst.dpDiv.css({position: ($.datepicker._inDialog && $.blockUI ?
17375                         'static' : (isFixed ? 'fixed' : 'absolute')), display: 'none',
17376                         left: offset.left + 'px', top: offset.top + 'px'});
17377                 if (!inst.inline) {
17378                         var showAnim = $.datepicker._get(inst, 'showAnim');
17379                         var duration = $.datepicker._get(inst, 'duration');
17380                         var postProcess = function() {
17381                                 $.datepicker._datepickerShowing = true;
17382                                 var cover = inst.dpDiv.find('iframe.ui-datepicker-cover'); // IE6- only
17383                                 if( !! cover.length ){
17384                                         var borders = $.datepicker._getBorders(inst.dpDiv);
17385                                         cover.css({left: -borders[0], top: -borders[1],
17386                                                 width: inst.dpDiv.outerWidth(), height: inst.dpDiv.outerHeight()});
17387                                 }
17388                         };
17389                         inst.dpDiv.zIndex($(input).zIndex()+1);
17390                         if ($.effects && $.effects[showAnim])
17391                                 inst.dpDiv.show(showAnim, $.datepicker._get(inst, 'showOptions'), duration, postProcess);
17392                         else
17393                                 inst.dpDiv[showAnim || 'show']((showAnim ? duration : null), postProcess);
17394                         if (!showAnim || !duration)
17395                                 postProcess();
17396                         if (inst.input.is(':visible') && !inst.input.is(':disabled'))
17397                                 inst.input.focus();
17398                         $.datepicker._curInst = inst;
17399                 }
17400         },
17401
17402         /* Generate the date picker content. */
17403         _updateDatepicker: function(inst) {
17404                 var self = this;
17405                 var borders = $.datepicker._getBorders(inst.dpDiv);
17406                 inst.dpDiv.empty().append(this._generateHTML(inst));
17407                 var cover = inst.dpDiv.find('iframe.ui-datepicker-cover'); // IE6- only
17408                 if( !!cover.length ){ //avoid call to outerXXXX() when not in IE6
17409                         cover.css({left: -borders[0], top: -borders[1], width: inst.dpDiv.outerWidth(), height: inst.dpDiv.outerHeight()})
17410                 }
17411                 inst.dpDiv.find('button, .ui-datepicker-prev, .ui-datepicker-next, .ui-datepicker-calendar td a')
17412                                 .bind('mouseout', function(){
17413                                         $(this).removeClass('ui-state-hover');
17414                                         if(this.className.indexOf('ui-datepicker-prev') != -1) $(this).removeClass('ui-datepicker-prev-hover');
17415                                         if(this.className.indexOf('ui-datepicker-next') != -1) $(this).removeClass('ui-datepicker-next-hover');
17416                                 })
17417                                 .bind('mouseover', function(){
17418                                         if (!self._isDisabledDatepicker( inst.inline ? inst.dpDiv.parent()[0] : inst.input[0])) {
17419                                                 $(this).parents('.ui-datepicker-calendar').find('a').removeClass('ui-state-hover');
17420                                                 $(this).addClass('ui-state-hover');
17421                                                 if(this.className.indexOf('ui-datepicker-prev') != -1) $(this).addClass('ui-datepicker-prev-hover');
17422                                                 if(this.className.indexOf('ui-datepicker-next') != -1) $(this).addClass('ui-datepicker-next-hover');
17423                                         }
17424                                 })
17425                         .end()
17426                         .find('.' + this._dayOverClass + ' a')
17427                                 .trigger('mouseover')
17428                         .end();
17429                 var numMonths = this._getNumberOfMonths(inst);
17430                 var cols = numMonths[1];
17431                 var width = 17;
17432                 if (cols > 1)
17433                         inst.dpDiv.addClass('ui-datepicker-multi-' + cols).css('width', (width * cols) + 'em');
17434                 else
17435                         inst.dpDiv.removeClass('ui-datepicker-multi-2 ui-datepicker-multi-3 ui-datepicker-multi-4').width('');
17436                 inst.dpDiv[(numMonths[0] != 1 || numMonths[1] != 1 ? 'add' : 'remove') +
17437                         'Class']('ui-datepicker-multi');
17438                 inst.dpDiv[(this._get(inst, 'isRTL') ? 'add' : 'remove') +
17439                         'Class']('ui-datepicker-rtl');
17440                 if (inst == $.datepicker._curInst && $.datepicker._datepickerShowing && inst.input &&
17441                                 // #6694 - don't focus the input if it's already focused
17442                                 // this breaks the change event in IE
17443                                 inst.input.is(':visible') && !inst.input.is(':disabled') && inst.input[0] != document.activeElement)
17444                         inst.input.focus();
17445                 // deffered render of the years select (to avoid flashes on Firefox) 
17446                 if( inst.yearshtml ){
17447                         var origyearshtml = inst.yearshtml;
17448                         setTimeout(function(){
17449                                 //assure that inst.yearshtml didn't change.
17450                                 if( origyearshtml === inst.yearshtml ){
17451                                         inst.dpDiv.find('select.ui-datepicker-year:first').replaceWith(inst.yearshtml);
17452                                 }
17453                                 origyearshtml = inst.yearshtml = null;
17454                         }, 0);
17455                 }
17456         },
17457
17458         /* Retrieve the size of left and top borders for an element.
17459            @param  elem  (jQuery object) the element of interest
17460            @return  (number[2]) the left and top borders */
17461         _getBorders: function(elem) {
17462                 var convert = function(value) {
17463                         return {thin: 1, medium: 2, thick: 3}[value] || value;
17464                 };
17465                 return [parseFloat(convert(elem.css('border-left-width'))),
17466                         parseFloat(convert(elem.css('border-top-width')))];
17467         },
17468
17469         /* Check positioning to remain on screen. */
17470         _checkOffset: function(inst, offset, isFixed) {
17471                 var dpWidth = inst.dpDiv.outerWidth();
17472                 var dpHeight = inst.dpDiv.outerHeight();
17473                 var inputWidth = inst.input ? inst.input.outerWidth() : 0;
17474                 var inputHeight = inst.input ? inst.input.outerHeight() : 0;
17475                 var viewWidth = document.documentElement.clientWidth + $(document).scrollLeft();
17476                 var viewHeight = document.documentElement.clientHeight + $(document).scrollTop();
17477
17478                 offset.left -= (this._get(inst, 'isRTL') ? (dpWidth - inputWidth) : 0);
17479                 offset.left -= (isFixed && offset.left == inst.input.offset().left) ? $(document).scrollLeft() : 0;
17480                 offset.top -= (isFixed && offset.top == (inst.input.offset().top + inputHeight)) ? $(document).scrollTop() : 0;
17481
17482                 // now check if datepicker is showing outside window viewport - move to a better place if so.
17483                 offset.left -= Math.min(offset.left, (offset.left + dpWidth > viewWidth && viewWidth > dpWidth) ?
17484                         Math.abs(offset.left + dpWidth - viewWidth) : 0);
17485                 offset.top -= Math.min(offset.top, (offset.top + dpHeight > viewHeight && viewHeight > dpHeight) ?
17486                         Math.abs(dpHeight + inputHeight) : 0);
17487
17488                 return offset;
17489         },
17490
17491         /* Find an object's position on the screen. */
17492         _findPos: function(obj) {
17493                 var inst = this._getInst(obj);
17494                 var isRTL = this._get(inst, 'isRTL');
17495         while (obj && (obj.type == 'hidden' || obj.nodeType != 1 || $.expr.filters.hidden(obj))) {
17496             obj = obj[isRTL ? 'previousSibling' : 'nextSibling'];
17497         }
17498         var position = $(obj).offset();
17499             return [position.left, position.top];
17500         },
17501
17502         /* Hide the date picker from view.
17503            @param  input  element - the input field attached to the date picker */
17504         _hideDatepicker: function(input) {
17505                 var inst = this._curInst;
17506                 if (!inst || (input && inst != $.data(input, PROP_NAME)))
17507                         return;
17508                 if (this._datepickerShowing) {
17509                         var showAnim = this._get(inst, 'showAnim');
17510                         var duration = this._get(inst, 'duration');
17511                         var postProcess = function() {
17512                                 $.datepicker._tidyDialog(inst);
17513                                 this._curInst = null;
17514                         };
17515                         if ($.effects && $.effects[showAnim])
17516                                 inst.dpDiv.hide(showAnim, $.datepicker._get(inst, 'showOptions'), duration, postProcess);
17517                         else
17518                                 inst.dpDiv[(showAnim == 'slideDown' ? 'slideUp' :
17519                                         (showAnim == 'fadeIn' ? 'fadeOut' : 'hide'))]((showAnim ? duration : null), postProcess);
17520                         if (!showAnim)
17521                                 postProcess();
17522                         var onClose = this._get(inst, 'onClose');
17523                         if (onClose)
17524                                 onClose.apply((inst.input ? inst.input[0] : null),
17525                                         [(inst.input ? inst.input.val() : ''), inst]);  // trigger custom callback
17526                         this._datepickerShowing = false;
17527                         this._lastInput = null;
17528                         if (this._inDialog) {
17529                                 this._dialogInput.css({ position: 'absolute', left: '0', top: '-100px' });
17530                                 if ($.blockUI) {
17531                                         $.unblockUI();
17532                                         $('body').append(this.dpDiv);
17533                                 }
17534                         }
17535                         this._inDialog = false;
17536                 }
17537         },
17538
17539         /* Tidy up after a dialog display. */
17540         _tidyDialog: function(inst) {
17541                 inst.dpDiv.removeClass(this._dialogClass).unbind('.ui-datepicker-calendar');
17542         },
17543
17544         /* Close date picker if clicked elsewhere. */
17545         _checkExternalClick: function(event) {
17546                 if (!$.datepicker._curInst)
17547                         return;
17548                 var $target = $(event.target);
17549                 if ($target[0].id != $.datepicker._mainDivId &&
17550                                 $target.parents('#' + $.datepicker._mainDivId).length == 0 &&
17551                                 !$target.hasClass($.datepicker.markerClassName) &&
17552                                 !$target.hasClass($.datepicker._triggerClass) &&
17553                                 $.datepicker._datepickerShowing && !($.datepicker._inDialog && $.blockUI))
17554                         $.datepicker._hideDatepicker();
17555         },
17556
17557         /* Adjust one of the date sub-fields. */
17558         _adjustDate: function(id, offset, period) {
17559                 var target = $(id);
17560                 var inst = this._getInst(target[0]);
17561                 if (this._isDisabledDatepicker(target[0])) {
17562                         return;
17563                 }
17564                 this._adjustInstDate(inst, offset +
17565                         (period == 'M' ? this._get(inst, 'showCurrentAtPos') : 0), // undo positioning
17566                         period);
17567                 this._updateDatepicker(inst);
17568         },
17569
17570         /* Action for current link. */
17571         _gotoToday: function(id) {
17572                 var target = $(id);
17573                 var inst = this._getInst(target[0]);
17574                 if (this._get(inst, 'gotoCurrent') && inst.currentDay) {
17575                         inst.selectedDay = inst.currentDay;
17576                         inst.drawMonth = inst.selectedMonth = inst.currentMonth;
17577                         inst.drawYear = inst.selectedYear = inst.currentYear;
17578                 }
17579                 else {
17580                         var date = new Date();
17581                         inst.selectedDay = date.getDate();
17582                         inst.drawMonth = inst.selectedMonth = date.getMonth();
17583                         inst.drawYear = inst.selectedYear = date.getFullYear();
17584                 }
17585                 this._notifyChange(inst);
17586                 this._adjustDate(target);
17587         },
17588
17589         /* Action for selecting a new month/year. */
17590         _selectMonthYear: function(id, select, period) {
17591                 var target = $(id);
17592                 var inst = this._getInst(target[0]);
17593                 inst._selectingMonthYear = false;
17594                 inst['selected' + (period == 'M' ? 'Month' : 'Year')] =
17595                 inst['draw' + (period == 'M' ? 'Month' : 'Year')] =
17596                         parseInt(select.options[select.selectedIndex].value,10);
17597                 this._notifyChange(inst);
17598                 this._adjustDate(target);
17599         },
17600
17601         /* Restore input focus after not changing month/year. */
17602         _clickMonthYear: function(id) {
17603                 var target = $(id);
17604                 var inst = this._getInst(target[0]);
17605                 if (inst.input && inst._selectingMonthYear) {
17606                         setTimeout(function() {
17607                                 inst.input.focus();
17608                         }, 0);
17609                 }
17610                 inst._selectingMonthYear = !inst._selectingMonthYear;
17611         },
17612
17613         /* Action for selecting a day. */
17614         _selectDay: function(id, month, year, td) {
17615                 var target = $(id);
17616                 if ($(td).hasClass(this._unselectableClass) || this._isDisabledDatepicker(target[0])) {
17617                         return;
17618                 }
17619                 var inst = this._getInst(target[0]);
17620                 inst.selectedDay = inst.currentDay = $('a', td).html();
17621                 inst.selectedMonth = inst.currentMonth = month;
17622                 inst.selectedYear = inst.currentYear = year;
17623                 this._selectDate(id, this._formatDate(inst,
17624                         inst.currentDay, inst.currentMonth, inst.currentYear));
17625         },
17626
17627         /* Erase the input field and hide the date picker. */
17628         _clearDate: function(id) {
17629                 var target = $(id);
17630                 var inst = this._getInst(target[0]);
17631                 this._selectDate(target, '');
17632         },
17633
17634         /* Update the input field with the selected date. */
17635         _selectDate: function(id, dateStr) {
17636                 var target = $(id);
17637                 var inst = this._getInst(target[0]);
17638                 dateStr = (dateStr != null ? dateStr : this._formatDate(inst));
17639                 if (inst.input)
17640                         inst.input.val(dateStr);
17641                 this._updateAlternate(inst);
17642                 var onSelect = this._get(inst, 'onSelect');
17643                 if (onSelect)
17644                         onSelect.apply((inst.input ? inst.input[0] : null), [dateStr, inst]);  // trigger custom callback
17645                 else if (inst.input)
17646                         inst.input.trigger('change'); // fire the change event
17647                 if (inst.inline)
17648                         this._updateDatepicker(inst);
17649                 else {
17650                         this._hideDatepicker();
17651                         this._lastInput = inst.input[0];
17652                         if (typeof(inst.input[0]) != 'object')
17653                                 inst.input.focus(); // restore focus
17654                         this._lastInput = null;
17655                 }
17656         },
17657
17658         /* Update any alternate field to synchronise with the main field. */
17659         _updateAlternate: function(inst) {
17660                 var altField = this._get(inst, 'altField');
17661                 if (altField) { // update alternate field too
17662                         var altFormat = this._get(inst, 'altFormat') || this._get(inst, 'dateFormat');
17663                         var date = this._getDate(inst);
17664                         var dateStr = this.formatDate(altFormat, date, this._getFormatConfig(inst));
17665                         $(altField).each(function() { $(this).val(dateStr); });
17666                 }
17667         },
17668
17669         /* Set as beforeShowDay function to prevent selection of weekends.
17670            @param  date  Date - the date to customise
17671            @return [boolean, string] - is this date selectable?, what is its CSS class? */
17672         noWeekends: function(date) {
17673                 var day = date.getDay();
17674                 return [(day > 0 && day < 6), ''];
17675         },
17676
17677         /* Set as calculateWeek to determine the week of the year based on the ISO 8601 definition.
17678            @param  date  Date - the date to get the week for
17679            @return  number - the number of the week within the year that contains this date */
17680         iso8601Week: function(date) {
17681                 var checkDate = new Date(date.getTime());
17682                 // Find Thursday of this week starting on Monday
17683                 checkDate.setDate(checkDate.getDate() + 4 - (checkDate.getDay() || 7));
17684                 var time = checkDate.getTime();
17685                 checkDate.setMonth(0); // Compare with Jan 1
17686                 checkDate.setDate(1);
17687                 return Math.floor(Math.round((time - checkDate) / 86400000) / 7) + 1;
17688         },
17689
17690         /* Parse a string value into a date object.
17691            See formatDate below for the possible formats.
17692
17693            @param  format    string - the expected format of the date
17694            @param  value     string - the date in the above format
17695            @param  settings  Object - attributes include:
17696                              shortYearCutoff  number - the cutoff year for determining the century (optional)
17697                              dayNamesShort    string[7] - abbreviated names of the days from Sunday (optional)
17698                              dayNames         string[7] - names of the days from Sunday (optional)
17699                              monthNamesShort  string[12] - abbreviated names of the months (optional)
17700                              monthNames       string[12] - names of the months (optional)
17701            @return  Date - the extracted date value or null if value is blank */
17702         parseDate: function (format, value, settings) {
17703                 if (format == null || value == null)
17704                         throw 'Invalid arguments';
17705                 value = (typeof value == 'object' ? value.toString() : value + '');
17706                 if (value == '')
17707                         return null;
17708                 var shortYearCutoff = (settings ? settings.shortYearCutoff : null) || this._defaults.shortYearCutoff;
17709                 shortYearCutoff = (typeof shortYearCutoff != 'string' ? shortYearCutoff :
17710                                 new Date().getFullYear() % 100 + parseInt(shortYearCutoff, 10));
17711                 var dayNamesShort = (settings ? settings.dayNamesShort : null) || this._defaults.dayNamesShort;
17712                 var dayNames = (settings ? settings.dayNames : null) || this._defaults.dayNames;
17713                 var monthNamesShort = (settings ? settings.monthNamesShort : null) || this._defaults.monthNamesShort;
17714                 var monthNames = (settings ? settings.monthNames : null) || this._defaults.monthNames;
17715                 var year = -1;
17716                 var month = -1;
17717                 var day = -1;
17718                 var doy = -1;
17719                 var literal = false;
17720                 // Check whether a format character is doubled
17721                 var lookAhead = function(match) {
17722                         var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) == match);
17723                         if (matches)
17724                                 iFormat++;
17725                         return matches;
17726                 };
17727                 // Extract a number from the string value
17728                 var getNumber = function(match) {
17729                         var isDoubled = lookAhead(match);
17730                         var size = (match == '@' ? 14 : (match == '!' ? 20 :
17731                                 (match == 'y' && isDoubled ? 4 : (match == 'o' ? 3 : 2))));
17732                         var digits = new RegExp('^\\d{1,' + size + '}');
17733                         var num = value.substring(iValue).match(digits);
17734                         if (!num)
17735                                 throw 'Missing number at position ' + iValue;
17736                         iValue += num[0].length;
17737                         return parseInt(num[0], 10);
17738                 };
17739                 // Extract a name from the string value and convert to an index
17740                 var getName = function(match, shortNames, longNames) {
17741                         var names = (lookAhead(match) ? longNames : shortNames);
17742                         for (var i = 0; i < names.length; i++) {
17743                                 if (value.substr(iValue, names[i].length).toLowerCase() == names[i].toLowerCase()) {
17744                                         iValue += names[i].length;
17745                                         return i + 1;
17746                                 }
17747                         }
17748                         throw 'Unknown name at position ' + iValue;
17749                 };
17750                 // Confirm that a literal character matches the string value
17751                 var checkLiteral = function() {
17752                         if (value.charAt(iValue) != format.charAt(iFormat))
17753                                 throw 'Unexpected literal at position ' + iValue;
17754                         iValue++;
17755                 };
17756                 var iValue = 0;
17757                 for (var iFormat = 0; iFormat < format.length; iFormat++) {
17758                         if (literal)
17759                                 if (format.charAt(iFormat) == "'" && !lookAhead("'"))
17760                                         literal = false;
17761                                 else
17762                                         checkLiteral();
17763                         else
17764                                 switch (format.charAt(iFormat)) {
17765                                         case 'd':
17766                                                 day = getNumber('d');
17767                                                 break;
17768                                         case 'D':
17769                                                 getName('D', dayNamesShort, dayNames);
17770                                                 break;
17771                                         case 'o':
17772                                                 doy = getNumber('o');
17773                                                 break;
17774                                         case 'm':
17775                                                 month = getNumber('m');
17776                                                 break;
17777                                         case 'M':
17778                                                 month = getName('M', monthNamesShort, monthNames);
17779                                                 break;
17780                                         case 'y':
17781                                                 year = getNumber('y');
17782                                                 break;
17783                                         case '@':
17784                                                 var date = new Date(getNumber('@'));
17785                                                 year = date.getFullYear();
17786                                                 month = date.getMonth() + 1;
17787                                                 day = date.getDate();
17788                                                 break;
17789                                         case '!':
17790                                                 var date = new Date((getNumber('!') - this._ticksTo1970) / 10000);
17791                                                 year = date.getFullYear();
17792                                                 month = date.getMonth() + 1;
17793                                                 day = date.getDate();
17794                                                 break;
17795                                         case "'":
17796                                                 if (lookAhead("'"))
17797                                                         checkLiteral();
17798                                                 else
17799                                                         literal = true;
17800                                                 break;
17801                                         default:
17802                                                 checkLiteral();
17803                                 }
17804                 }
17805                 if (year == -1)
17806                         year = new Date().getFullYear();
17807                 else if (year < 100)
17808                         year += new Date().getFullYear() - new Date().getFullYear() % 100 +
17809                                 (year <= shortYearCutoff ? 0 : -100);
17810                 if (doy > -1) {
17811                         month = 1;
17812                         day = doy;
17813                         do {
17814                                 var dim = this._getDaysInMonth(year, month - 1);
17815                                 if (day <= dim)
17816                                         break;
17817                                 month++;
17818                                 day -= dim;
17819                         } while (true);
17820                 }
17821                 var date = this._daylightSavingAdjust(new Date(year, month - 1, day));
17822                 if (date.getFullYear() != year || date.getMonth() + 1 != month || date.getDate() != day)
17823                         throw 'Invalid date'; // E.g. 31/02/00
17824                 return date;
17825         },
17826
17827         /* Standard date formats. */
17828         ATOM: 'yy-mm-dd', // RFC 3339 (ISO 8601)
17829         COOKIE: 'D, dd M yy',
17830         ISO_8601: 'yy-mm-dd',
17831         RFC_822: 'D, d M y',
17832         RFC_850: 'DD, dd-M-y',
17833         RFC_1036: 'D, d M y',
17834         RFC_1123: 'D, d M yy',
17835         RFC_2822: 'D, d M yy',
17836         RSS: 'D, d M y', // RFC 822
17837         TICKS: '!',
17838         TIMESTAMP: '@',
17839         W3C: 'yy-mm-dd', // ISO 8601
17840
17841         _ticksTo1970: (((1970 - 1) * 365 + Math.floor(1970 / 4) - Math.floor(1970 / 100) +
17842                 Math.floor(1970 / 400)) * 24 * 60 * 60 * 10000000),
17843
17844         /* Format a date object into a string value.
17845            The format can be combinations of the following:
17846            d  - day of month (no leading zero)
17847            dd - day of month (two digit)
17848            o  - day of year (no leading zeros)
17849            oo - day of year (three digit)
17850            D  - day name short
17851            DD - day name long
17852            m  - month of year (no leading zero)
17853            mm - month of year (two digit)
17854            M  - month name short
17855            MM - month name long
17856            y  - year (two digit)
17857            yy - year (four digit)
17858            @ - Unix timestamp (ms since 01/01/1970)
17859            ! - Windows ticks (100ns since 01/01/0001)
17860            '...' - literal text
17861            '' - single quote
17862
17863            @param  format    string - the desired format of the date
17864            @param  date      Date - the date value to format
17865            @param  settings  Object - attributes include:
17866                              dayNamesShort    string[7] - abbreviated names of the days from Sunday (optional)
17867                              dayNames         string[7] - names of the days from Sunday (optional)
17868                              monthNamesShort  string[12] - abbreviated names of the months (optional)
17869                              monthNames       string[12] - names of the months (optional)
17870            @return  string - the date in the above format */
17871         formatDate: function (format, date, settings) {
17872                 if (!date)
17873                         return '';
17874                 var dayNamesShort = (settings ? settings.dayNamesShort : null) || this._defaults.dayNamesShort;
17875                 var dayNames = (settings ? settings.dayNames : null) || this._defaults.dayNames;
17876                 var monthNamesShort = (settings ? settings.monthNamesShort : null) || this._defaults.monthNamesShort;
17877                 var monthNames = (settings ? settings.monthNames : null) || this._defaults.monthNames;
17878                 // Check whether a format character is doubled
17879                 var lookAhead = function(match) {
17880                         var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) == match);
17881                         if (matches)
17882                                 iFormat++;
17883                         return matches;
17884                 };
17885                 // Format a number, with leading zero if necessary
17886                 var formatNumber = function(match, value, len) {
17887                         var num = '' + value;
17888                         if (lookAhead(match))
17889                                 while (num.length < len)
17890                                         num = '0' + num;
17891                         return num;
17892                 };
17893                 // Format a name, short or long as requested
17894                 var formatName = function(match, value, shortNames, longNames) {
17895                         return (lookAhead(match) ? longNames[value] : shortNames[value]);
17896                 };
17897                 var output = '';
17898                 var literal = false;
17899                 if (date)
17900                         for (var iFormat = 0; iFormat < format.length; iFormat++) {
17901                                 if (literal)
17902                                         if (format.charAt(iFormat) == "'" && !lookAhead("'"))
17903                                                 literal = false;
17904                                         else
17905                                                 output += format.charAt(iFormat);
17906                                 else
17907                                         switch (format.charAt(iFormat)) {
17908                                                 case 'd':
17909                                                         output += formatNumber('d', date.getDate(), 2);
17910                                                         break;
17911                                                 case 'D':
17912                                                         output += formatName('D', date.getDay(), dayNamesShort, dayNames);
17913                                                         break;
17914                                                 case 'o':
17915                                                         output += formatNumber('o',
17916                                                                 (date.getTime() - new Date(date.getFullYear(), 0, 0).getTime()) / 86400000, 3);
17917                                                         break;
17918                                                 case 'm':
17919                                                         output += formatNumber('m', date.getMonth() + 1, 2);
17920                                                         break;
17921                                                 case 'M':
17922                                                         output += formatName('M', date.getMonth(), monthNamesShort, monthNames);
17923                                                         break;
17924                                                 case 'y':
17925                                                         output += (lookAhead('y') ? date.getFullYear() :
17926                                                                 (date.getYear() % 100 < 10 ? '0' : '') + date.getYear() % 100);
17927                                                         break;
17928                                                 case '@':
17929                                                         output += date.getTime();
17930                                                         break;
17931                                                 case '!':
17932                                                         output += date.getTime() * 10000 + this._ticksTo1970;
17933                                                         break;
17934                                                 case "'":
17935                                                         if (lookAhead("'"))
17936                                                                 output += "'";
17937                                                         else
17938                                                                 literal = true;
17939                                                         break;
17940                                                 default:
17941                                                         output += format.charAt(iFormat);
17942                                         }
17943                         }
17944                 return output;
17945         },
17946
17947         /* Extract all possible characters from the date format. */
17948         _possibleChars: function (format) {
17949                 var chars = '';
17950                 var literal = false;
17951                 // Check whether a format character is doubled
17952                 var lookAhead = function(match) {
17953                         var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) == match);
17954                         if (matches)
17955                                 iFormat++;
17956                         return matches;
17957                 };
17958                 for (var iFormat = 0; iFormat < format.length; iFormat++)
17959                         if (literal)
17960                                 if (format.charAt(iFormat) == "'" && !lookAhead("'"))
17961                                         literal = false;
17962                                 else
17963                                         chars += format.charAt(iFormat);
17964                         else
17965                                 switch (format.charAt(iFormat)) {
17966                                         case 'd': case 'm': case 'y': case '@':
17967                                                 chars += '0123456789';
17968                                                 break;
17969                                         case 'D': case 'M':
17970                                                 return null; // Accept anything
17971                                         case "'":
17972                                                 if (lookAhead("'"))
17973                                                         chars += "'";
17974                                                 else
17975                                                         literal = true;
17976                                                 break;
17977                                         default:
17978                                                 chars += format.charAt(iFormat);
17979                                 }
17980                 return chars;
17981         },
17982
17983         /* Get a setting value, defaulting if necessary. */
17984         _get: function(inst, name) {
17985                 return inst.settings[name] !== undefined ?
17986                         inst.settings[name] : this._defaults[name];
17987         },
17988
17989         /* Parse existing date and initialise date picker. */
17990         _setDateFromField: function(inst, noDefault) {
17991                 if (inst.input.val() == inst.lastVal) {
17992                         return;
17993                 }
17994                 var dateFormat = this._get(inst, 'dateFormat');
17995                 var dates = inst.lastVal = inst.input ? inst.input.val() : null;
17996                 var date, defaultDate;
17997                 date = defaultDate = this._getDefaultDate(inst);
17998                 var settings = this._getFormatConfig(inst);
17999                 try {
18000                         date = this.parseDate(dateFormat, dates, settings) || defaultDate;
18001                 } catch (event) {
18002                         this.log(event);
18003                         dates = (noDefault ? '' : dates);
18004                 }
18005                 inst.selectedDay = date.getDate();
18006                 inst.drawMonth = inst.selectedMonth = date.getMonth();
18007                 inst.drawYear = inst.selectedYear = date.getFullYear();
18008                 inst.currentDay = (dates ? date.getDate() : 0);
18009                 inst.currentMonth = (dates ? date.getMonth() : 0);
18010                 inst.currentYear = (dates ? date.getFullYear() : 0);
18011                 this._adjustInstDate(inst);
18012         },
18013
18014         /* Retrieve the default date shown on opening. */
18015         _getDefaultDate: function(inst) {
18016                 return this._restrictMinMax(inst,
18017                         this._determineDate(inst, this._get(inst, 'defaultDate'), new Date()));
18018         },
18019
18020         /* A date may be specified as an exact value or a relative one. */
18021         _determineDate: function(inst, date, defaultDate) {
18022                 var offsetNumeric = function(offset) {
18023                         var date = new Date();
18024                         date.setDate(date.getDate() + offset);
18025                         return date;
18026                 };
18027                 var offsetString = function(offset) {
18028                         try {
18029                                 return $.datepicker.parseDate($.datepicker._get(inst, 'dateFormat'),
18030                                         offset, $.datepicker._getFormatConfig(inst));
18031                         }
18032                         catch (e) {
18033                                 // Ignore
18034                         }
18035                         var date = (offset.toLowerCase().match(/^c/) ?
18036                                 $.datepicker._getDate(inst) : null) || new Date();
18037                         var year = date.getFullYear();
18038                         var month = date.getMonth();
18039                         var day = date.getDate();
18040                         var pattern = /([+-]?[0-9]+)\s*(d|D|w|W|m|M|y|Y)?/g;
18041                         var matches = pattern.exec(offset);
18042                         while (matches) {
18043                                 switch (matches[2] || 'd') {
18044                                         case 'd' : case 'D' :
18045                                                 day += parseInt(matches[1],10); break;
18046                                         case 'w' : case 'W' :
18047                                                 day += parseInt(matches[1],10) * 7; break;
18048                                         case 'm' : case 'M' :
18049                                                 month += parseInt(matches[1],10);
18050                                                 day = Math.min(day, $.datepicker._getDaysInMonth(year, month));
18051                                                 break;
18052                                         case 'y': case 'Y' :
18053                                                 year += parseInt(matches[1],10);
18054                                                 day = Math.min(day, $.datepicker._getDaysInMonth(year, month));
18055                                                 break;
18056                                 }
18057                                 matches = pattern.exec(offset);
18058                         }
18059                         return new Date(year, month, day);
18060                 };
18061                 var newDate = (date == null || date === '' ? defaultDate : (typeof date == 'string' ? offsetString(date) :
18062                         (typeof date == 'number' ? (isNaN(date) ? defaultDate : offsetNumeric(date)) : new Date(date.getTime()))));
18063                 newDate = (newDate && newDate.toString() == 'Invalid Date' ? defaultDate : newDate);
18064                 if (newDate) {
18065                         newDate.setHours(0);
18066                         newDate.setMinutes(0);
18067                         newDate.setSeconds(0);
18068                         newDate.setMilliseconds(0);
18069                 }
18070                 return this._daylightSavingAdjust(newDate);
18071         },
18072
18073         /* Handle switch to/from daylight saving.
18074            Hours may be non-zero on daylight saving cut-over:
18075            > 12 when midnight changeover, but then cannot generate
18076            midnight datetime, so jump to 1AM, otherwise reset.
18077            @param  date  (Date) the date to check
18078            @return  (Date) the corrected date */
18079         _daylightSavingAdjust: function(date) {
18080                 if (!date) return null;
18081                 date.setHours(date.getHours() > 12 ? date.getHours() + 2 : 0);
18082                 return date;
18083         },
18084
18085         /* Set the date(s) directly. */
18086         _setDate: function(inst, date, noChange) {
18087                 var clear = !date;
18088                 var origMonth = inst.selectedMonth;
18089                 var origYear = inst.selectedYear;
18090                 var newDate = this._restrictMinMax(inst, this._determineDate(inst, date, new Date()));
18091                 inst.selectedDay = inst.currentDay = newDate.getDate();
18092                 inst.drawMonth = inst.selectedMonth = inst.currentMonth = newDate.getMonth();
18093                 inst.drawYear = inst.selectedYear = inst.currentYear = newDate.getFullYear();
18094                 if ((origMonth != inst.selectedMonth || origYear != inst.selectedYear) && !noChange)
18095                         this._notifyChange(inst);
18096                 this._adjustInstDate(inst);
18097                 if (inst.input) {
18098                         inst.input.val(clear ? '' : this._formatDate(inst));
18099                 }
18100         },
18101
18102         /* Retrieve the date(s) directly. */
18103         _getDate: function(inst) {
18104                 var startDate = (!inst.currentYear || (inst.input && inst.input.val() == '') ? null :
18105                         this._daylightSavingAdjust(new Date(
18106                         inst.currentYear, inst.currentMonth, inst.currentDay)));
18107                         return startDate;
18108         },
18109
18110         /* Generate the HTML for the current state of the date picker. */
18111         _generateHTML: function(inst) {
18112                 var today = new Date();
18113                 today = this._daylightSavingAdjust(
18114                         new Date(today.getFullYear(), today.getMonth(), today.getDate())); // clear time
18115                 var isRTL = this._get(inst, 'isRTL');
18116                 var showButtonPanel = this._get(inst, 'showButtonPanel');
18117                 var hideIfNoPrevNext = this._get(inst, 'hideIfNoPrevNext');
18118                 var navigationAsDateFormat = this._get(inst, 'navigationAsDateFormat');
18119                 var numMonths = this._getNumberOfMonths(inst);
18120                 var showCurrentAtPos = this._get(inst, 'showCurrentAtPos');
18121                 var stepMonths = this._get(inst, 'stepMonths');
18122                 var isMultiMonth = (numMonths[0] != 1 || numMonths[1] != 1);
18123                 var currentDate = this._daylightSavingAdjust((!inst.currentDay ? new Date(9999, 9, 9) :
18124                         new Date(inst.currentYear, inst.currentMonth, inst.currentDay)));
18125                 var minDate = this._getMinMaxDate(inst, 'min');
18126                 var maxDate = this._getMinMaxDate(inst, 'max');
18127                 var drawMonth = inst.drawMonth - showCurrentAtPos;
18128                 var drawYear = inst.drawYear;
18129                 if (drawMonth < 0) {
18130                         drawMonth += 12;
18131                         drawYear--;
18132                 }
18133                 if (maxDate) {
18134                         var maxDraw = this._daylightSavingAdjust(new Date(maxDate.getFullYear(),
18135                                 maxDate.getMonth() - (numMonths[0] * numMonths[1]) + 1, maxDate.getDate()));
18136                         maxDraw = (minDate && maxDraw < minDate ? minDate : maxDraw);
18137                         while (this._daylightSavingAdjust(new Date(drawYear, drawMonth, 1)) > maxDraw) {
18138                                 drawMonth--;
18139                                 if (drawMonth < 0) {
18140                                         drawMonth = 11;
18141                                         drawYear--;
18142                                 }
18143                         }
18144                 }
18145                 inst.drawMonth = drawMonth;
18146                 inst.drawYear = drawYear;
18147                 var prevText = this._get(inst, 'prevText');
18148                 prevText = (!navigationAsDateFormat ? prevText : this.formatDate(prevText,
18149                         this._daylightSavingAdjust(new Date(drawYear, drawMonth - stepMonths, 1)),
18150                         this._getFormatConfig(inst)));
18151                 var prev = (this._canAdjustMonth(inst, -1, drawYear, drawMonth) ?
18152                         '<a class="ui-datepicker-prev ui-corner-all" onclick="DP_jQuery_' + dpuuid +
18153                         '.datepicker._adjustDate(\'#' + inst.id + '\', -' + stepMonths + ', \'M\');"' +
18154                         ' title="' + prevText + '"><span class="ui-icon ui-icon-circle-triangle-' + ( isRTL ? 'e' : 'w') + '">' + prevText + '</span></a>' :
18155                         (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>'));
18156                 var nextText = this._get(inst, 'nextText');
18157                 nextText = (!navigationAsDateFormat ? nextText : this.formatDate(nextText,
18158                         this._daylightSavingAdjust(new Date(drawYear, drawMonth + stepMonths, 1)),
18159                         this._getFormatConfig(inst)));
18160                 var next = (this._canAdjustMonth(inst, +1, drawYear, drawMonth) ?
18161                         '<a class="ui-datepicker-next ui-corner-all" onclick="DP_jQuery_' + dpuuid +
18162                         '.datepicker._adjustDate(\'#' + inst.id + '\', +' + stepMonths + ', \'M\');"' +
18163                         ' title="' + nextText + '"><span class="ui-icon ui-icon-circle-triangle-' + ( isRTL ? 'w' : 'e') + '">' + nextText + '</span></a>' :
18164                         (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>'));
18165                 var currentText = this._get(inst, 'currentText');
18166                 var gotoDate = (this._get(inst, 'gotoCurrent') && inst.currentDay ? currentDate : today);
18167                 currentText = (!navigationAsDateFormat ? currentText :
18168                         this.formatDate(currentText, gotoDate, this._getFormatConfig(inst)));
18169                 var controls = (!inst.inline ? '<button type="button" class="ui-datepicker-close ui-state-default ui-priority-primary ui-corner-all" onclick="DP_jQuery_' + dpuuid +
18170                         '.datepicker._hideDatepicker();">' + this._get(inst, 'closeText') + '</button>' : '');
18171                 var buttonPanel = (showButtonPanel) ? '<div class="ui-datepicker-buttonpane ui-widget-content">' + (isRTL ? controls : '') +
18172                         (this._isInRange(inst, gotoDate) ? '<button type="button" class="ui-datepicker-current ui-state-default ui-priority-secondary ui-corner-all" onclick="DP_jQuery_' + dpuuid +
18173                         '.datepicker._gotoToday(\'#' + inst.id + '\');"' +
18174                         '>' + currentText + '</button>' : '') + (isRTL ? '' : controls) + '</div>' : '';
18175                 var firstDay = parseInt(this._get(inst, 'firstDay'),10);
18176                 firstDay = (isNaN(firstDay) ? 0 : firstDay);
18177                 var showWeek = this._get(inst, 'showWeek');
18178                 var dayNames = this._get(inst, 'dayNames');
18179                 var dayNamesShort = this._get(inst, 'dayNamesShort');
18180                 var dayNamesMin = this._get(inst, 'dayNamesMin');
18181                 var monthNames = this._get(inst, 'monthNames');
18182                 var monthNamesShort = this._get(inst, 'monthNamesShort');
18183                 var beforeShowDay = this._get(inst, 'beforeShowDay');
18184                 var showOtherMonths = this._get(inst, 'showOtherMonths');
18185                 var selectOtherMonths = this._get(inst, 'selectOtherMonths');
18186                 var calculateWeek = this._get(inst, 'calculateWeek') || this.iso8601Week;
18187                 var defaultDate = this._getDefaultDate(inst);
18188                 var html = '';
18189                 for (var row = 0; row < numMonths[0]; row++) {
18190                         var group = '';
18191                         for (var col = 0; col < numMonths[1]; col++) {
18192                                 var selectedDate = this._daylightSavingAdjust(new Date(drawYear, drawMonth, inst.selectedDay));
18193                                 var cornerClass = ' ui-corner-all';
18194                                 var calender = '';
18195                                 if (isMultiMonth) {
18196                                         calender += '<div class="ui-datepicker-group';
18197                                         if (numMonths[1] > 1)
18198                                                 switch (col) {
18199                                                         case 0: calender += ' ui-datepicker-group-first';
18200                                                                 cornerClass = ' ui-corner-' + (isRTL ? 'right' : 'left'); break;
18201                                                         case numMonths[1]-1: calender += ' ui-datepicker-group-last';
18202                                                                 cornerClass = ' ui-corner-' + (isRTL ? 'left' : 'right'); break;
18203                                                         default: calender += ' ui-datepicker-group-middle'; cornerClass = ''; break;
18204                                                 }
18205                                         calender += '">';
18206                                 }
18207                                 calender += '<div class="ui-datepicker-header ui-widget-header ui-helper-clearfix' + cornerClass + '">' +
18208                                         (/all|left/.test(cornerClass) && row == 0 ? (isRTL ? next : prev) : '') +
18209                                         (/all|right/.test(cornerClass) && row == 0 ? (isRTL ? prev : next) : '') +
18210                                         this._generateMonthYearHeader(inst, drawMonth, drawYear, minDate, maxDate,
18211                                         row > 0 || col > 0, monthNames, monthNamesShort) + // draw month headers
18212                                         '</div><table class="ui-datepicker-calendar"><thead>' +
18213                                         '<tr>';
18214                                 var thead = (showWeek ? '<th class="ui-datepicker-week-col">' + this._get(inst, 'weekHeader') + '</th>' : '');
18215                                 for (var dow = 0; dow < 7; dow++) { // days of the week
18216                                         var day = (dow + firstDay) % 7;
18217                                         thead += '<th' + ((dow + firstDay + 6) % 7 >= 5 ? ' class="ui-datepicker-week-end"' : '') + '>' +
18218                                                 '<span title="' + dayNames[day] + '">' + dayNamesMin[day] + '</span></th>';
18219                                 }
18220                                 calender += thead + '</tr></thead><tbody>';
18221                                 var daysInMonth = this._getDaysInMonth(drawYear, drawMonth);
18222                                 if (drawYear == inst.selectedYear && drawMonth == inst.selectedMonth)
18223                                         inst.selectedDay = Math.min(inst.selectedDay, daysInMonth);
18224                                 var leadDays = (this._getFirstDayOfMonth(drawYear, drawMonth) - firstDay + 7) % 7;
18225                                 var numRows = (isMultiMonth ? 6 : Math.ceil((leadDays + daysInMonth) / 7)); // calculate the number of rows to generate
18226                                 var printDate = this._daylightSavingAdjust(new Date(drawYear, drawMonth, 1 - leadDays));
18227                                 for (var dRow = 0; dRow < numRows; dRow++) { // create date picker rows
18228                                         calender += '<tr>';
18229                                         var tbody = (!showWeek ? '' : '<td class="ui-datepicker-week-col">' +
18230                                                 this._get(inst, 'calculateWeek')(printDate) + '</td>');
18231                                         for (var dow = 0; dow < 7; dow++) { // create date picker days
18232                                                 var daySettings = (beforeShowDay ?
18233                                                         beforeShowDay.apply((inst.input ? inst.input[0] : null), [printDate]) : [true, '']);
18234                                                 var otherMonth = (printDate.getMonth() != drawMonth);
18235                                                 var unselectable = (otherMonth && !selectOtherMonths) || !daySettings[0] ||
18236                                                         (minDate && printDate < minDate) || (maxDate && printDate > maxDate);
18237                                                 tbody += '<td class="' +
18238                                                         ((dow + firstDay + 6) % 7 >= 5 ? ' ui-datepicker-week-end' : '') + // highlight weekends
18239                                                         (otherMonth ? ' ui-datepicker-other-month' : '') + // highlight days from other months
18240                                                         ((printDate.getTime() == selectedDate.getTime() && drawMonth == inst.selectedMonth && inst._keyEvent) || // user pressed key
18241                                                         (defaultDate.getTime() == printDate.getTime() && defaultDate.getTime() == selectedDate.getTime()) ?
18242                                                         // or defaultDate is current printedDate and defaultDate is selectedDate
18243                                                         ' ' + this._dayOverClass : '') + // highlight selected day
18244                                                         (unselectable ? ' ' + this._unselectableClass + ' ui-state-disabled': '') +  // highlight unselectable days
18245                                                         (otherMonth && !showOtherMonths ? '' : ' ' + daySettings[1] + // highlight custom dates
18246                                                         (printDate.getTime() == currentDate.getTime() ? ' ' + this._currentClass : '') + // highlight selected day
18247                                                         (printDate.getTime() == today.getTime() ? ' ui-datepicker-today' : '')) + '"' + // highlight today (if different)
18248                                                         ((!otherMonth || showOtherMonths) && daySettings[2] ? ' title="' + daySettings[2] + '"' : '') + // cell title
18249                                                         (unselectable ? '' : ' onclick="DP_jQuery_' + dpuuid + '.datepicker._selectDay(\'#' +
18250                                                         inst.id + '\',' + printDate.getMonth() + ',' + printDate.getFullYear() + ', this);return false;"') + '>' + // actions
18251                                                         (otherMonth && !showOtherMonths ? '&#xa0;' : // display for other months
18252                                                         (unselectable ? '<span class="ui-state-default">' + printDate.getDate() + '</span>' : '<a class="ui-state-default' +
18253                                                         (printDate.getTime() == today.getTime() ? ' ui-state-highlight' : '') +
18254                                                         (printDate.getTime() == currentDate.getTime() ? ' ui-state-active' : '') + // highlight selected day
18255                                                         (otherMonth ? ' ui-priority-secondary' : '') + // distinguish dates from other months
18256                                                         '" href="#">' + printDate.getDate() + '</a>')) + '</td>'; // display selectable date
18257                                                 printDate.setDate(printDate.getDate() + 1);
18258                                                 printDate = this._daylightSavingAdjust(printDate);
18259                                         }
18260                                         calender += tbody + '</tr>';
18261                                 }
18262                                 drawMonth++;
18263                                 if (drawMonth > 11) {
18264                                         drawMonth = 0;
18265                                         drawYear++;
18266                                 }
18267                                 calender += '</tbody></table>' + (isMultiMonth ? '</div>' + 
18268                                                         ((numMonths[0] > 0 && col == numMonths[1]-1) ? '<div class="ui-datepicker-row-break"></div>' : '') : '');
18269                                 group += calender;
18270                         }
18271                         html += group;
18272                 }
18273                 html += buttonPanel + ($.browser.msie && parseInt($.browser.version,10) < 7 && !inst.inline ?
18274                         '<iframe src="javascript:false;" class="ui-datepicker-cover" frameborder="0"></iframe>' : '');
18275                 inst._keyEvent = false;
18276                 return html;
18277         },
18278
18279         /* Generate the month and year header. */
18280         _generateMonthYearHeader: function(inst, drawMonth, drawYear, minDate, maxDate,
18281                         secondary, monthNames, monthNamesShort) {
18282                 var changeMonth = this._get(inst, 'changeMonth');
18283                 var changeYear = this._get(inst, 'changeYear');
18284                 var showMonthAfterYear = this._get(inst, 'showMonthAfterYear');
18285                 var html = '<div class="ui-datepicker-title">';
18286                 var monthHtml = '';
18287                 // month selection
18288                 if (secondary || !changeMonth)
18289                         monthHtml += '<span class="ui-datepicker-month">' + monthNames[drawMonth] + '</span>';
18290                 else {
18291                         var inMinYear = (minDate && minDate.getFullYear() == drawYear);
18292                         var inMaxYear = (maxDate && maxDate.getFullYear() == drawYear);
18293                         monthHtml += '<select class="ui-datepicker-month" ' +
18294                                 'onchange="DP_jQuery_' + dpuuid + '.datepicker._selectMonthYear(\'#' + inst.id + '\', this, \'M\');" ' +
18295                                 'onclick="DP_jQuery_' + dpuuid + '.datepicker._clickMonthYear(\'#' + inst.id + '\');"' +
18296                                 '>';
18297                         for (var month = 0; month < 12; month++) {
18298                                 if ((!inMinYear || month >= minDate.getMonth()) &&
18299                                                 (!inMaxYear || month <= maxDate.getMonth()))
18300                                         monthHtml += '<option value="' + month + '"' +
18301                                                 (month == drawMonth ? ' selected="selected"' : '') +
18302                                                 '>' + monthNamesShort[month] + '</option>';
18303                         }
18304                         monthHtml += '</select>';
18305                 }
18306                 if (!showMonthAfterYear)
18307                         html += monthHtml + (secondary || !(changeMonth && changeYear) ? '&#xa0;' : '');
18308                 // year selection
18309                 if ( !inst.yearshtml ) {
18310                         inst.yearshtml = '';
18311                         if (secondary || !changeYear)
18312                                 html += '<span class="ui-datepicker-year">' + drawYear + '</span>';
18313                         else {
18314                                 // determine range of years to display
18315                                 var years = this._get(inst, 'yearRange').split(':');
18316                                 var thisYear = new Date().getFullYear();
18317                                 var determineYear = function(value) {
18318                                         var year = (value.match(/c[+-].*/) ? drawYear + parseInt(value.substring(1), 10) :
18319                                                 (value.match(/[+-].*/) ? thisYear + parseInt(value, 10) :
18320                                                 parseInt(value, 10)));
18321                                         return (isNaN(year) ? thisYear : year);
18322                                 };
18323                                 var year = determineYear(years[0]);
18324                                 var endYear = Math.max(year, determineYear(years[1] || ''));
18325                                 year = (minDate ? Math.max(year, minDate.getFullYear()) : year);
18326                                 endYear = (maxDate ? Math.min(endYear, maxDate.getFullYear()) : endYear);
18327                                 inst.yearshtml += '<select class="ui-datepicker-year" ' +
18328                                         'onchange="DP_jQuery_' + dpuuid + '.datepicker._selectMonthYear(\'#' + inst.id + '\', this, \'Y\');" ' +
18329                                         'onclick="DP_jQuery_' + dpuuid + '.datepicker._clickMonthYear(\'#' + inst.id + '\');"' +
18330                                         '>';
18331                                 for (; year <= endYear; year++) {
18332                                         inst.yearshtml += '<option value="' + year + '"' +
18333                                                 (year == drawYear ? ' selected="selected"' : '') +
18334                                                 '>' + year + '</option>';
18335                                 }
18336                                 inst.yearshtml += '</select>';
18337                                 //when showing there is no need for later update
18338                                 if( ! $.browser.mozilla ){
18339                                         html += inst.yearshtml;
18340                                         inst.yearshtml = null;
18341                                 } else {
18342                                         // will be replaced later with inst.yearshtml
18343                                         html += '<select class="ui-datepicker-year"><option value="' + drawYear + '" selected="selected">' + drawYear + '</option></select>';
18344                                 }
18345                         }
18346                 }
18347                 html += this._get(inst, 'yearSuffix');
18348                 if (showMonthAfterYear)
18349                         html += (secondary || !(changeMonth && changeYear) ? '&#xa0;' : '') + monthHtml;
18350                 html += '</div>'; // Close datepicker_header
18351                 return html;
18352         },
18353
18354         /* Adjust one of the date sub-fields. */
18355         _adjustInstDate: function(inst, offset, period) {
18356                 var year = inst.drawYear + (period == 'Y' ? offset : 0);
18357                 var month = inst.drawMonth + (period == 'M' ? offset : 0);
18358                 var day = Math.min(inst.selectedDay, this._getDaysInMonth(year, month)) +
18359                         (period == 'D' ? offset : 0);
18360                 var date = this._restrictMinMax(inst,
18361                         this._daylightSavingAdjust(new Date(year, month, day)));
18362                 inst.selectedDay = date.getDate();
18363                 inst.drawMonth = inst.selectedMonth = date.getMonth();
18364                 inst.drawYear = inst.selectedYear = date.getFullYear();
18365                 if (period == 'M' || period == 'Y')
18366                         this._notifyChange(inst);
18367         },
18368
18369         /* Ensure a date is within any min/max bounds. */
18370         _restrictMinMax: function(inst, date) {
18371                 var minDate = this._getMinMaxDate(inst, 'min');
18372                 var maxDate = this._getMinMaxDate(inst, 'max');
18373                 var newDate = (minDate && date < minDate ? minDate : date);
18374                 newDate = (maxDate && newDate > maxDate ? maxDate : newDate);
18375                 return newDate;
18376         },
18377
18378         /* Notify change of month/year. */
18379         _notifyChange: function(inst) {
18380                 var onChange = this._get(inst, 'onChangeMonthYear');
18381                 if (onChange)
18382                         onChange.apply((inst.input ? inst.input[0] : null),
18383                                 [inst.selectedYear, inst.selectedMonth + 1, inst]);
18384         },
18385
18386         /* Determine the number of months to show. */
18387         _getNumberOfMonths: function(inst) {
18388                 var numMonths = this._get(inst, 'numberOfMonths');
18389                 return (numMonths == null ? [1, 1] : (typeof numMonths == 'number' ? [1, numMonths] : numMonths));
18390         },
18391
18392         /* Determine the current maximum date - ensure no time components are set. */
18393         _getMinMaxDate: function(inst, minMax) {
18394                 return this._determineDate(inst, this._get(inst, minMax + 'Date'), null);
18395         },
18396
18397         /* Find the number of days in a given month. */
18398         _getDaysInMonth: function(year, month) {
18399                 return 32 - this._daylightSavingAdjust(new Date(year, month, 32)).getDate();
18400         },
18401
18402         /* Find the day of the week of the first of a month. */
18403         _getFirstDayOfMonth: function(year, month) {
18404                 return new Date(year, month, 1).getDay();
18405         },
18406
18407         /* Determines if we should allow a "next/prev" month display change. */
18408         _canAdjustMonth: function(inst, offset, curYear, curMonth) {
18409                 var numMonths = this._getNumberOfMonths(inst);
18410                 var date = this._daylightSavingAdjust(new Date(curYear,
18411                         curMonth + (offset < 0 ? offset : numMonths[0] * numMonths[1]), 1));
18412                 if (offset < 0)
18413                         date.setDate(this._getDaysInMonth(date.getFullYear(), date.getMonth()));
18414                 return this._isInRange(inst, date);
18415         },
18416
18417         /* Is the given date in the accepted range? */
18418         _isInRange: function(inst, date) {
18419                 var minDate = this._getMinMaxDate(inst, 'min');
18420                 var maxDate = this._getMinMaxDate(inst, 'max');
18421                 return ((!minDate || date.getTime() >= minDate.getTime()) &&
18422                         (!maxDate || date.getTime() <= maxDate.getTime()));
18423         },
18424
18425         /* Provide the configuration settings for formatting/parsing. */
18426         _getFormatConfig: function(inst) {
18427                 var shortYearCutoff = this._get(inst, 'shortYearCutoff');
18428                 shortYearCutoff = (typeof shortYearCutoff != 'string' ? shortYearCutoff :
18429                         new Date().getFullYear() % 100 + parseInt(shortYearCutoff, 10));
18430                 return {shortYearCutoff: shortYearCutoff,
18431                         dayNamesShort: this._get(inst, 'dayNamesShort'), dayNames: this._get(inst, 'dayNames'),
18432                         monthNamesShort: this._get(inst, 'monthNamesShort'), monthNames: this._get(inst, 'monthNames')};
18433         },
18434
18435         /* Format the given date for display. */
18436         _formatDate: function(inst, day, month, year) {
18437                 if (!day) {
18438                         inst.currentDay = inst.selectedDay;
18439                         inst.currentMonth = inst.selectedMonth;
18440                         inst.currentYear = inst.selectedYear;
18441                 }
18442                 var date = (day ? (typeof day == 'object' ? day :
18443                         this._daylightSavingAdjust(new Date(year, month, day))) :
18444                         this._daylightSavingAdjust(new Date(inst.currentYear, inst.currentMonth, inst.currentDay)));
18445                 return this.formatDate(this._get(inst, 'dateFormat'), date, this._getFormatConfig(inst));
18446         }
18447 });
18448
18449 /* jQuery extend now ignores nulls! */
18450 function extendRemove(target, props) {
18451         $.extend(target, props);
18452         for (var name in props)
18453                 if (props[name] == null || props[name] == undefined)
18454                         target[name] = props[name];
18455         return target;
18456 };
18457
18458 /* Determine whether an object is an array. */
18459 function isArray(a) {
18460         return (a && (($.browser.safari && typeof a == 'object' && a.length) ||
18461                 (a.constructor && a.constructor.toString().match(/\Array\(\)/))));
18462 };
18463
18464 /* Invoke the datepicker functionality.
18465    @param  options  string - a command, optionally followed by additional parameters or
18466                     Object - settings for attaching new datepicker functionality
18467    @return  jQuery object */
18468 $.fn.datepicker = function(options){
18469         
18470         /* Verify an empty collection wasn't passed - Fixes #6976 */
18471         if ( !this.length ) {
18472                 return this;
18473         }
18474         
18475         /* Initialise the date picker. */
18476         if (!$.datepicker.initialized) {
18477                 $(document).mousedown($.datepicker._checkExternalClick).
18478                         find('body').append($.datepicker.dpDiv);
18479                 $.datepicker.initialized = true;
18480         }
18481
18482         var otherArgs = Array.prototype.slice.call(arguments, 1);
18483         if (typeof options == 'string' && (options == 'isDisabled' || options == 'getDate' || options == 'widget'))
18484                 return $.datepicker['_' + options + 'Datepicker'].
18485                         apply($.datepicker, [this[0]].concat(otherArgs));
18486         if (options == 'option' && arguments.length == 2 && typeof arguments[1] == 'string')
18487                 return $.datepicker['_' + options + 'Datepicker'].
18488                         apply($.datepicker, [this[0]].concat(otherArgs));
18489         return this.each(function() {
18490                 typeof options == 'string' ?
18491                         $.datepicker['_' + options + 'Datepicker'].
18492                                 apply($.datepicker, [this].concat(otherArgs)) :
18493                         $.datepicker._attachDatepicker(this, options);
18494         });
18495 };
18496
18497 $.datepicker = new Datepicker(); // singleton instance
18498 $.datepicker.initialized = false;
18499 $.datepicker.uuid = new Date().getTime();
18500 $.datepicker.version = "1.8.12";
18501
18502 // Workaround for #4055
18503 // Add another global to avoid noConflict issues with inline event handlers
18504 window['DP_jQuery_' + dpuuid] = $;
18505
18506 })(jQuery);
18507 /*
18508  * jQuery UI Dialog 1.8.12
18509  *
18510  * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
18511  * Dual licensed under the MIT or GPL Version 2 licenses.
18512  * http://jquery.org/license
18513  *
18514  * http://docs.jquery.com/UI/Dialog
18515  *
18516  * Depends:
18517  *      jquery.ui.core.js
18518  *      jquery.ui.widget.js
18519  *  jquery.ui.button.js
18520  *      jquery.ui.draggable.js
18521  *      jquery.ui.mouse.js
18522  *      jquery.ui.position.js
18523  *      jquery.ui.resizable.js
18524  */
18525 (function( $, undefined ) {
18526
18527 var uiDialogClasses =
18528                 'ui-dialog ' +
18529                 'ui-widget ' +
18530                 'ui-widget-content ' +
18531                 'ui-corner-all ',
18532         sizeRelatedOptions = {
18533                 buttons: true,
18534                 height: true,
18535                 maxHeight: true,
18536                 maxWidth: true,
18537                 minHeight: true,
18538                 minWidth: true,
18539                 width: true
18540         },
18541         resizableRelatedOptions = {
18542                 maxHeight: true,
18543                 maxWidth: true,
18544                 minHeight: true,
18545                 minWidth: true
18546         },
18547         // support for jQuery 1.3.2 - handle common attrFn methods for dialog
18548         attrFn = $.attrFn || {
18549                 val: true,
18550                 css: true,
18551                 html: true,
18552                 text: true,
18553                 data: true,
18554                 width: true,
18555                 height: true,
18556                 offset: true,
18557                 click: true
18558         };
18559
18560 $.widget("ui.dialog", {
18561         options: {
18562                 autoOpen: true,
18563                 buttons: {},
18564                 closeOnEscape: true,
18565                 closeText: 'close',
18566                 dialogClass: '',
18567                 draggable: true,
18568                 hide: null,
18569                 height: 'auto',
18570                 maxHeight: false,
18571                 maxWidth: false,
18572                 minHeight: 150,
18573                 minWidth: 150,
18574                 modal: false,
18575                 position: {
18576                         my: 'center',
18577                         at: 'center',
18578                         collision: 'fit',
18579                         // ensure that the titlebar is never outside the document
18580                         using: function(pos) {
18581                                 var topOffset = $(this).css(pos).offset().top;
18582                                 if (topOffset < 0) {
18583                                         $(this).css('top', pos.top - topOffset);
18584                                 }
18585                         }
18586                 },
18587                 resizable: true,
18588                 show: null,
18589                 stack: true,
18590                 title: '',
18591                 width: 300,
18592                 zIndex: 1000
18593         },
18594
18595         _create: function() {
18596                 this.originalTitle = this.element.attr('title');
18597                 // #5742 - .attr() might return a DOMElement
18598                 if ( typeof this.originalTitle !== "string" ) {
18599                         this.originalTitle = "";
18600                 }
18601
18602                 this.options.title = this.options.title || this.originalTitle;
18603                 var self = this,
18604                         options = self.options,
18605
18606                         title = options.title || '&#160;',
18607                         titleId = $.ui.dialog.getTitleId(self.element),
18608
18609                         uiDialog = (self.uiDialog = $('<div></div>'))
18610                                 .appendTo(document.body)
18611                                 .hide()
18612                                 .addClass(uiDialogClasses + options.dialogClass)
18613                                 .css({
18614                                         zIndex: options.zIndex
18615                                 })
18616                                 // setting tabIndex makes the div focusable
18617                                 // setting outline to 0 prevents a border on focus in Mozilla
18618                                 .attr('tabIndex', -1).css('outline', 0).keydown(function(event) {
18619                                         if (options.closeOnEscape && event.keyCode &&
18620                                                 event.keyCode === $.ui.keyCode.ESCAPE) {
18621                                                 
18622                                                 self.close(event);
18623                                                 event.preventDefault();
18624                                         }
18625                                 })
18626                                 .attr({
18627                                         role: 'dialog',
18628                                         'aria-labelledby': titleId
18629                                 })
18630                                 .mousedown(function(event) {
18631                                         self.moveToTop(false, event);
18632                                 }),
18633
18634                         uiDialogContent = self.element
18635                                 .show()
18636                                 .removeAttr('title')
18637                                 .addClass(
18638                                         'ui-dialog-content ' +
18639                                         'ui-widget-content')
18640                                 .appendTo(uiDialog),
18641
18642                         uiDialogTitlebar = (self.uiDialogTitlebar = $('<div></div>'))
18643                                 .addClass(
18644                                         'ui-dialog-titlebar ' +
18645                                         'ui-widget-header ' +
18646                                         'ui-corner-top ' +
18647                                         'ui-helper-clearfix'
18648                                 )
18649                                 .prependTo(uiDialog),
18650
18651                         uiDialogTitlebarClose = $('<a href="#"></a>')
18652                                 .addClass(
18653                                         'ui-dialog-titlebar-close ' +
18654                                         'ui-corner-all'
18655                                 )
18656                                 .attr('role', 'button')
18657                                 .hover(
18658                                         function() {
18659                                                 uiDialogTitlebarClose.addClass('ui-state-hover');
18660                                         },
18661                                         function() {
18662                                                 uiDialogTitlebarClose.removeClass('ui-state-hover');
18663                                         }
18664                                 )
18665                                 .focus(function() {
18666                                         uiDialogTitlebarClose.addClass('ui-state-focus');
18667                                 })
18668                                 .blur(function() {
18669                                         uiDialogTitlebarClose.removeClass('ui-state-focus');
18670                                 })
18671                                 .click(function(event) {
18672                                         self.close(event);
18673                                         return false;
18674                                 })
18675                                 .appendTo(uiDialogTitlebar),
18676
18677                         uiDialogTitlebarCloseText = (self.uiDialogTitlebarCloseText = $('<span></span>'))
18678                                 .addClass(
18679                                         'ui-icon ' +
18680                                         'ui-icon-closethick'
18681                                 )
18682                                 .text(options.closeText)
18683                                 .appendTo(uiDialogTitlebarClose),
18684
18685                         uiDialogTitle = $('<span></span>')
18686                                 .addClass('ui-dialog-title')
18687                                 .attr('id', titleId)
18688                                 .html(title)
18689                                 .prependTo(uiDialogTitlebar);
18690
18691                 //handling of deprecated beforeclose (vs beforeClose) option
18692                 //Ticket #4669 http://dev.jqueryui.com/ticket/4669
18693                 //TODO: remove in 1.9pre
18694                 if ($.isFunction(options.beforeclose) && !$.isFunction(options.beforeClose)) {
18695                         options.beforeClose = options.beforeclose;
18696                 }
18697
18698                 uiDialogTitlebar.find("*").add(uiDialogTitlebar).disableSelection();
18699
18700                 if (options.draggable && $.fn.draggable) {
18701                         self._makeDraggable();
18702                 }
18703                 if (options.resizable && $.fn.resizable) {
18704                         self._makeResizable();
18705                 }
18706
18707                 self._createButtons(options.buttons);
18708                 self._isOpen = false;
18709
18710                 if ($.fn.bgiframe) {
18711                         uiDialog.bgiframe();
18712                 }
18713         },
18714
18715         _init: function() {
18716                 if ( this.options.autoOpen ) {
18717                         this.open();
18718                 }
18719         },
18720
18721         destroy: function() {
18722                 var self = this;
18723                 
18724                 if (self.overlay) {
18725                         self.overlay.destroy();
18726                 }
18727                 self.uiDialog.hide();
18728                 self.element
18729                         .unbind('.dialog')
18730                         .removeData('dialog')
18731                         .removeClass('ui-dialog-content ui-widget-content')
18732                         .hide().appendTo('body');
18733                 self.uiDialog.remove();
18734
18735                 if (self.originalTitle) {
18736                         self.element.attr('title', self.originalTitle);
18737                 }
18738
18739                 return self;
18740         },
18741
18742         widget: function() {
18743                 return this.uiDialog;
18744         },
18745
18746         close: function(event) {
18747                 var self = this,
18748                         maxZ, thisZ;
18749                 
18750                 if (false === self._trigger('beforeClose', event)) {
18751                         return;
18752                 }
18753
18754                 if (self.overlay) {
18755                         self.overlay.destroy();
18756                 }
18757                 self.uiDialog.unbind('keypress.ui-dialog');
18758
18759                 self._isOpen = false;
18760
18761                 if (self.options.hide) {
18762                         self.uiDialog.hide(self.options.hide, function() {
18763                                 self._trigger('close', event);
18764                         });
18765                 } else {
18766                         self.uiDialog.hide();
18767                         self._trigger('close', event);
18768                 }
18769
18770                 $.ui.dialog.overlay.resize();
18771
18772                 // adjust the maxZ to allow other modal dialogs to continue to work (see #4309)
18773                 if (self.options.modal) {
18774                         maxZ = 0;
18775                         $('.ui-dialog').each(function() {
18776                                 if (this !== self.uiDialog[0]) {
18777                                         thisZ = $(this).css('z-index');
18778                                         if(!isNaN(thisZ)) {
18779                                                 maxZ = Math.max(maxZ, thisZ);
18780                                         }
18781                                 }
18782                         });
18783                         $.ui.dialog.maxZ = maxZ;
18784                 }
18785
18786                 return self;
18787         },
18788
18789         isOpen: function() {
18790                 return this._isOpen;
18791         },
18792
18793         // the force parameter allows us to move modal dialogs to their correct
18794         // position on open
18795         moveToTop: function(force, event) {
18796                 var self = this,
18797                         options = self.options,
18798                         saveScroll;
18799
18800                 if ((options.modal && !force) ||
18801                         (!options.stack && !options.modal)) {
18802                         return self._trigger('focus', event);
18803                 }
18804
18805                 if (options.zIndex > $.ui.dialog.maxZ) {
18806                         $.ui.dialog.maxZ = options.zIndex;
18807                 }
18808                 if (self.overlay) {
18809                         $.ui.dialog.maxZ += 1;
18810                         self.overlay.$el.css('z-index', $.ui.dialog.overlay.maxZ = $.ui.dialog.maxZ);
18811                 }
18812
18813                 //Save and then restore scroll since Opera 9.5+ resets when parent z-Index is changed.
18814                 //  http://ui.jquery.com/bugs/ticket/3193
18815                 saveScroll = { scrollTop: self.element.attr('scrollTop'), scrollLeft: self.element.attr('scrollLeft') };
18816                 $.ui.dialog.maxZ += 1;
18817                 self.uiDialog.css('z-index', $.ui.dialog.maxZ);
18818                 self.element.attr(saveScroll);
18819                 self._trigger('focus', event);
18820
18821                 return self;
18822         },
18823
18824         open: function() {
18825                 if (this._isOpen) { return; }
18826
18827                 var self = this,
18828                         options = self.options,
18829                         uiDialog = self.uiDialog;
18830
18831                 self.overlay = options.modal ? new $.ui.dialog.overlay(self) : null;
18832                 self._size();
18833                 self._position(options.position);
18834                 uiDialog.show(options.show);
18835                 self.moveToTop(true);
18836
18837                 // prevent tabbing out of modal dialogs
18838                 if (options.modal) {
18839                         uiDialog.bind('keypress.ui-dialog', function(event) {
18840                                 if (event.keyCode !== $.ui.keyCode.TAB) {
18841                                         return;
18842                                 }
18843
18844                                 var tabbables = $(':tabbable', this),
18845                                         first = tabbables.filter(':first'),
18846                                         last  = tabbables.filter(':last');
18847
18848                                 if (event.target === last[0] && !event.shiftKey) {
18849                                         first.focus(1);
18850                                         return false;
18851                                 } else if (event.target === first[0] && event.shiftKey) {
18852                                         last.focus(1);
18853                                         return false;
18854                                 }
18855                         });
18856                 }
18857
18858                 // set focus to the first tabbable element in the content area or the first button
18859                 // if there are no tabbable elements, set focus on the dialog itself
18860                 $(self.element.find(':tabbable').get().concat(
18861                         uiDialog.find('.ui-dialog-buttonpane :tabbable').get().concat(
18862                                 uiDialog.get()))).eq(0).focus();
18863
18864                 self._isOpen = true;
18865                 self._trigger('open');
18866
18867                 return self;
18868         },
18869
18870         _createButtons: function(buttons) {
18871                 var self = this,
18872                         hasButtons = false,
18873                         uiDialogButtonPane = $('<div></div>')
18874                                 .addClass(
18875                                         'ui-dialog-buttonpane ' +
18876                                         'ui-widget-content ' +
18877                                         'ui-helper-clearfix'
18878                                 ),
18879                         uiButtonSet = $( "<div></div>" )
18880                                 .addClass( "ui-dialog-buttonset" )
18881                                 .appendTo( uiDialogButtonPane );
18882
18883                 // if we already have a button pane, remove it
18884                 self.uiDialog.find('.ui-dialog-buttonpane').remove();
18885
18886                 if (typeof buttons === 'object' && buttons !== null) {
18887                         $.each(buttons, function() {
18888                                 return !(hasButtons = true);
18889                         });
18890                 }
18891                 if (hasButtons) {
18892                         $.each(buttons, function(name, props) {
18893                                 props = $.isFunction( props ) ?
18894                                         { click: props, text: name } :
18895                                         props;
18896                                 var button = $('<button type="button"></button>')
18897                                         .click(function() {
18898                                                 props.click.apply(self.element[0], arguments);
18899                                         })
18900                                         .appendTo(uiButtonSet);
18901                                 // can't use .attr( props, true ) with jQuery 1.3.2.
18902                                 $.each( props, function( key, value ) {
18903                                         if ( key === "click" ) {
18904                                                 return;
18905                                         }
18906                                         if ( key in attrFn ) {
18907                                                 button[ key ]( value );
18908                                         } else {
18909                                                 button.attr( key, value );
18910                                         }
18911                                 });
18912                                 if ($.fn.button) {
18913                                         button.button();
18914                                 }
18915                         });
18916                         uiDialogButtonPane.appendTo(self.uiDialog);
18917                 }
18918         },
18919
18920         _makeDraggable: function() {
18921                 var self = this,
18922                         options = self.options,
18923                         doc = $(document),
18924                         heightBeforeDrag;
18925
18926                 function filteredUi(ui) {
18927                         return {
18928                                 position: ui.position,
18929                                 offset: ui.offset
18930                         };
18931                 }
18932
18933                 self.uiDialog.draggable({
18934                         cancel: '.ui-dialog-content, .ui-dialog-titlebar-close',
18935                         handle: '.ui-dialog-titlebar',
18936                         containment: 'document',
18937                         start: function(event, ui) {
18938                                 heightBeforeDrag = options.height === "auto" ? "auto" : $(this).height();
18939                                 $(this).height($(this).height()).addClass("ui-dialog-dragging");
18940                                 self._trigger('dragStart', event, filteredUi(ui));
18941                         },
18942                         drag: function(event, ui) {
18943                                 self._trigger('drag', event, filteredUi(ui));
18944                         },
18945                         stop: function(event, ui) {
18946                                 options.position = [ui.position.left - doc.scrollLeft(),
18947                                         ui.position.top - doc.scrollTop()];
18948                                 $(this).removeClass("ui-dialog-dragging").height(heightBeforeDrag);
18949                                 self._trigger('dragStop', event, filteredUi(ui));
18950                                 $.ui.dialog.overlay.resize();
18951                         }
18952                 });
18953         },
18954
18955         _makeResizable: function(handles) {
18956                 handles = (handles === undefined ? this.options.resizable : handles);
18957                 var self = this,
18958                         options = self.options,
18959                         // .ui-resizable has position: relative defined in the stylesheet
18960                         // but dialogs have to use absolute or fixed positioning
18961                         position = self.uiDialog.css('position'),
18962                         resizeHandles = (typeof handles === 'string' ?
18963                                 handles :
18964                                 'n,e,s,w,se,sw,ne,nw'
18965                         );
18966
18967                 function filteredUi(ui) {
18968                         return {
18969                                 originalPosition: ui.originalPosition,
18970                                 originalSize: ui.originalSize,
18971                                 position: ui.position,
18972                                 size: ui.size
18973                         };
18974                 }
18975
18976                 self.uiDialog.resizable({
18977                         cancel: '.ui-dialog-content',
18978                         containment: 'document',
18979                         alsoResize: self.element,
18980                         maxWidth: options.maxWidth,
18981                         maxHeight: options.maxHeight,
18982                         minWidth: options.minWidth,
18983                         minHeight: self._minHeight(),
18984                         handles: resizeHandles,
18985                         start: function(event, ui) {
18986                                 $(this).addClass("ui-dialog-resizing");
18987                                 self._trigger('resizeStart', event, filteredUi(ui));
18988                         },
18989                         resize: function(event, ui) {
18990                                 self._trigger('resize', event, filteredUi(ui));
18991                         },
18992                         stop: function(event, ui) {
18993                                 $(this).removeClass("ui-dialog-resizing");
18994                                 options.height = $(this).height();
18995                                 options.width = $(this).width();
18996                                 self._trigger('resizeStop', event, filteredUi(ui));
18997                                 $.ui.dialog.overlay.resize();
18998                         }
18999                 })
19000                 .css('position', position)
19001                 .find('.ui-resizable-se').addClass('ui-icon ui-icon-grip-diagonal-se');
19002         },
19003
19004         _minHeight: function() {
19005                 var options = this.options;
19006
19007                 if (options.height === 'auto') {
19008                         return options.minHeight;
19009                 } else {
19010                         return Math.min(options.minHeight, options.height);
19011                 }
19012         },
19013
19014         _position: function(position) {
19015                 var myAt = [],
19016                         offset = [0, 0],
19017                         isVisible;
19018
19019                 if (position) {
19020                         // deep extending converts arrays to objects in jQuery <= 1.3.2 :-(
19021         //              if (typeof position == 'string' || $.isArray(position)) {
19022         //                      myAt = $.isArray(position) ? position : position.split(' ');
19023
19024                         if (typeof position === 'string' || (typeof position === 'object' && '0' in position)) {
19025                                 myAt = position.split ? position.split(' ') : [position[0], position[1]];
19026                                 if (myAt.length === 1) {
19027                                         myAt[1] = myAt[0];
19028                                 }
19029
19030                                 $.each(['left', 'top'], function(i, offsetPosition) {
19031                                         if (+myAt[i] === myAt[i]) {
19032                                                 offset[i] = myAt[i];
19033                                                 myAt[i] = offsetPosition;
19034                                         }
19035                                 });
19036
19037                                 position = {
19038                                         my: myAt.join(" "),
19039                                         at: myAt.join(" "),
19040                                         offset: offset.join(" ")
19041                                 };
19042                         } 
19043
19044                         position = $.extend({}, $.ui.dialog.prototype.options.position, position);
19045                 } else {
19046                         position = $.ui.dialog.prototype.options.position;
19047                 }
19048
19049                 // need to show the dialog to get the actual offset in the position plugin
19050                 isVisible = this.uiDialog.is(':visible');
19051                 if (!isVisible) {
19052                         this.uiDialog.show();
19053                 }
19054                 this.uiDialog
19055                         // workaround for jQuery bug #5781 http://dev.jquery.com/ticket/5781
19056                         .css({ top: 0, left: 0 })
19057                         .position($.extend({ of: window }, position));
19058                 if (!isVisible) {
19059                         this.uiDialog.hide();
19060                 }
19061         },
19062
19063         _setOptions: function( options ) {
19064                 var self = this,
19065                         resizableOptions = {},
19066                         resize = false;
19067
19068                 $.each( options, function( key, value ) {
19069                         self._setOption( key, value );
19070                         
19071                         if ( key in sizeRelatedOptions ) {
19072                                 resize = true;
19073                         }
19074                         if ( key in resizableRelatedOptions ) {
19075                                 resizableOptions[ key ] = value;
19076                         }
19077                 });
19078
19079                 if ( resize ) {
19080                         this._size();
19081                 }
19082                 if ( this.uiDialog.is( ":data(resizable)" ) ) {
19083                         this.uiDialog.resizable( "option", resizableOptions );
19084                 }
19085         },
19086
19087         _setOption: function(key, value){
19088                 var self = this,
19089                         uiDialog = self.uiDialog;
19090
19091                 switch (key) {
19092                         //handling of deprecated beforeclose (vs beforeClose) option
19093                         //Ticket #4669 http://dev.jqueryui.com/ticket/4669
19094                         //TODO: remove in 1.9pre
19095                         case "beforeclose":
19096                                 key = "beforeClose";
19097                                 break;
19098                         case "buttons":
19099                                 self._createButtons(value);
19100                                 break;
19101                         case "closeText":
19102                                 // ensure that we always pass a string
19103                                 self.uiDialogTitlebarCloseText.text("" + value);
19104                                 break;
19105                         case "dialogClass":
19106                                 uiDialog
19107                                         .removeClass(self.options.dialogClass)
19108                                         .addClass(uiDialogClasses + value);
19109                                 break;
19110                         case "disabled":
19111                                 if (value) {
19112                                         uiDialog.addClass('ui-dialog-disabled');
19113                                 } else {
19114                                         uiDialog.removeClass('ui-dialog-disabled');
19115                                 }
19116                                 break;
19117                         case "draggable":
19118                                 var isDraggable = uiDialog.is( ":data(draggable)" );
19119                                 if ( isDraggable && !value ) {
19120                                         uiDialog.draggable( "destroy" );
19121                                 }
19122                                 
19123                                 if ( !isDraggable && value ) {
19124                                         self._makeDraggable();
19125                                 }
19126                                 break;
19127                         case "position":
19128                                 self._position(value);
19129                                 break;
19130                         case "resizable":
19131                                 // currently resizable, becoming non-resizable
19132                                 var isResizable = uiDialog.is( ":data(resizable)" );
19133                                 if (isResizable && !value) {
19134                                         uiDialog.resizable('destroy');
19135                                 }
19136
19137                                 // currently resizable, changing handles
19138                                 if (isResizable && typeof value === 'string') {
19139                                         uiDialog.resizable('option', 'handles', value);
19140                                 }
19141
19142                                 // currently non-resizable, becoming resizable
19143                                 if (!isResizable && value !== false) {
19144                                         self._makeResizable(value);
19145                                 }
19146                                 break;
19147                         case "title":
19148                                 // convert whatever was passed in o a string, for html() to not throw up
19149                                 $(".ui-dialog-title", self.uiDialogTitlebar).html("" + (value || '&#160;'));
19150                                 break;
19151                 }
19152
19153                 $.Widget.prototype._setOption.apply(self, arguments);
19154         },
19155
19156         _size: function() {
19157                 /* If the user has resized the dialog, the .ui-dialog and .ui-dialog-content
19158                  * divs will both have width and height set, so we need to reset them
19159                  */
19160                 var options = this.options,
19161                         nonContentHeight,
19162                         minContentHeight,
19163                         isVisible = this.uiDialog.is( ":visible" );
19164
19165                 // reset content sizing
19166                 this.element.show().css({
19167                         width: 'auto',
19168                         minHeight: 0,
19169                         height: 0
19170                 });
19171
19172                 if (options.minWidth > options.width) {
19173                         options.width = options.minWidth;
19174                 }
19175
19176                 // reset wrapper sizing
19177                 // determine the height of all the non-content elements
19178                 nonContentHeight = this.uiDialog.css({
19179                                 height: 'auto',
19180                                 width: options.width
19181                         })
19182                         .height();
19183                 minContentHeight = Math.max( 0, options.minHeight - nonContentHeight );
19184                 
19185                 if ( options.height === "auto" ) {
19186                         // only needed for IE6 support
19187                         if ( $.support.minHeight ) {
19188                                 this.element.css({
19189                                         minHeight: minContentHeight,
19190                                         height: "auto"
19191                                 });
19192                         } else {
19193                                 this.uiDialog.show();
19194                                 var autoHeight = this.element.css( "height", "auto" ).height();
19195                                 if ( !isVisible ) {
19196                                         this.uiDialog.hide();
19197                                 }
19198                                 this.element.height( Math.max( autoHeight, minContentHeight ) );
19199                         }
19200                 } else {
19201                         this.element.height( Math.max( options.height - nonContentHeight, 0 ) );
19202                 }
19203
19204                 if (this.uiDialog.is(':data(resizable)')) {
19205                         this.uiDialog.resizable('option', 'minHeight', this._minHeight());
19206                 }
19207         }
19208 });
19209
19210 $.extend($.ui.dialog, {
19211         version: "1.8.12",
19212
19213         uuid: 0,
19214         maxZ: 0,
19215
19216         getTitleId: function($el) {
19217                 var id = $el.attr('id');
19218                 if (!id) {
19219                         this.uuid += 1;
19220                         id = this.uuid;
19221                 }
19222                 return 'ui-dialog-title-' + id;
19223         },
19224
19225         overlay: function(dialog) {
19226                 this.$el = $.ui.dialog.overlay.create(dialog);
19227         }
19228 });
19229
19230 $.extend($.ui.dialog.overlay, {
19231         instances: [],
19232         // reuse old instances due to IE memory leak with alpha transparency (see #5185)
19233         oldInstances: [],
19234         maxZ: 0,
19235         events: $.map('focus,mousedown,mouseup,keydown,keypress,click'.split(','),
19236                 function(event) { return event + '.dialog-overlay'; }).join(' '),
19237         create: function(dialog) {
19238                 if (this.instances.length === 0) {
19239                         // prevent use of anchors and inputs
19240                         // we use a setTimeout in case the overlay is created from an
19241                         // event that we're going to be cancelling (see #2804)
19242                         setTimeout(function() {
19243                                 // handle $(el).dialog().dialog('close') (see #4065)
19244                                 if ($.ui.dialog.overlay.instances.length) {
19245                                         $(document).bind($.ui.dialog.overlay.events, function(event) {
19246                                                 // stop events if the z-index of the target is < the z-index of the overlay
19247                                                 // we cannot return true when we don't want to cancel the event (#3523)
19248                                                 if ($(event.target).zIndex() < $.ui.dialog.overlay.maxZ) {
19249                                                         return false;
19250                                                 }
19251                                         });
19252                                 }
19253                         }, 1);
19254
19255                         // allow closing by pressing the escape key
19256                         $(document).bind('keydown.dialog-overlay', function(event) {
19257                                 if (dialog.options.closeOnEscape && event.keyCode &&
19258                                         event.keyCode === $.ui.keyCode.ESCAPE) {
19259                                         
19260                                         dialog.close(event);
19261                                         event.preventDefault();
19262                                 }
19263                         });
19264
19265                         // handle window resize
19266                         $(window).bind('resize.dialog-overlay', $.ui.dialog.overlay.resize);
19267                 }
19268
19269                 var $el = (this.oldInstances.pop() || $('<div></div>').addClass('ui-widget-overlay'))
19270                         .appendTo(document.body)
19271                         .css({
19272                                 width: this.width(),
19273                                 height: this.height()
19274                         });
19275
19276                 if ($.fn.bgiframe) {
19277                         $el.bgiframe();
19278                 }
19279
19280                 this.instances.push($el);
19281                 return $el;
19282         },
19283
19284         destroy: function($el) {
19285                 var indexOf = $.inArray($el, this.instances);
19286                 if (indexOf != -1){
19287                         this.oldInstances.push(this.instances.splice(indexOf, 1)[0]);
19288                 }
19289
19290                 if (this.instances.length === 0) {
19291                         $([document, window]).unbind('.dialog-overlay');
19292                 }
19293
19294                 $el.remove();
19295                 
19296                 // adjust the maxZ to allow other modal dialogs to continue to work (see #4309)
19297                 var maxZ = 0;
19298                 $.each(this.instances, function() {
19299                         maxZ = Math.max(maxZ, this.css('z-index'));
19300                 });
19301                 this.maxZ = maxZ;
19302         },
19303
19304         height: function() {
19305                 var scrollHeight,
19306                         offsetHeight;
19307                 // handle IE 6
19308                 if ($.browser.msie && $.browser.version < 7) {
19309                         scrollHeight = Math.max(
19310                                 document.documentElement.scrollHeight,
19311                                 document.body.scrollHeight
19312                         );
19313                         offsetHeight = Math.max(
19314                                 document.documentElement.offsetHeight,
19315                                 document.body.offsetHeight
19316                         );
19317
19318                         if (scrollHeight < offsetHeight) {
19319                                 return $(window).height() + 'px';
19320                         } else {
19321                                 return scrollHeight + 'px';
19322                         }
19323                 // handle "good" browsers
19324                 } else {
19325                         return $(document).height() + 'px';
19326                 }
19327         },
19328
19329         width: function() {
19330                 var scrollWidth,
19331                         offsetWidth;
19332                 // handle IE 6
19333                 if ($.browser.msie && $.browser.version < 7) {
19334                         scrollWidth = Math.max(
19335                                 document.documentElement.scrollWidth,
19336                                 document.body.scrollWidth
19337                         );
19338                         offsetWidth = Math.max(
19339                                 document.documentElement.offsetWidth,
19340                                 document.body.offsetWidth
19341                         );
19342
19343                         if (scrollWidth < offsetWidth) {
19344                                 return $(window).width() + 'px';
19345                         } else {
19346                                 return scrollWidth + 'px';
19347                         }
19348                 // handle "good" browsers
19349                 } else {
19350                         return $(document).width() + 'px';
19351                 }
19352         },
19353
19354         resize: function() {
19355                 /* If the dialog is draggable and the user drags it past the
19356                  * right edge of the window, the document becomes wider so we
19357                  * need to stretch the overlay. If the user then drags the
19358                  * dialog back to the left, the document will become narrower,
19359                  * so we need to shrink the overlay to the appropriate size.
19360                  * This is handled by shrinking the overlay before setting it
19361                  * to the full document size.
19362                  */
19363                 var $overlays = $([]);
19364                 $.each($.ui.dialog.overlay.instances, function() {
19365                         $overlays = $overlays.add(this);
19366                 });
19367
19368                 $overlays.css({
19369                         width: 0,
19370                         height: 0
19371                 }).css({
19372                         width: $.ui.dialog.overlay.width(),
19373                         height: $.ui.dialog.overlay.height()
19374                 });
19375         }
19376 });
19377
19378 $.extend($.ui.dialog.overlay.prototype, {
19379         destroy: function() {
19380                 $.ui.dialog.overlay.destroy(this.$el);
19381         }
19382 });
19383
19384 }(jQuery));
19385 /*
19386  * jQuery UI Position 1.8.12
19387  *
19388  * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
19389  * Dual licensed under the MIT or GPL Version 2 licenses.
19390  * http://jquery.org/license
19391  *
19392  * http://docs.jquery.com/UI/Position
19393  */
19394 (function( $, undefined ) {
19395
19396 $.ui = $.ui || {};
19397
19398 var horizontalPositions = /left|center|right/,
19399         verticalPositions = /top|center|bottom/,
19400         center = "center",
19401         _position = $.fn.position,
19402         _offset = $.fn.offset;
19403
19404 $.fn.position = function( options ) {
19405         if ( !options || !options.of ) {
19406                 return _position.apply( this, arguments );
19407         }
19408
19409         // make a copy, we don't want to modify arguments
19410         options = $.extend( {}, options );
19411
19412         var target = $( options.of ),
19413                 targetElem = target[0],
19414                 collision = ( options.collision || "flip" ).split( " " ),
19415                 offset = options.offset ? options.offset.split( " " ) : [ 0, 0 ],
19416                 targetWidth,
19417                 targetHeight,
19418                 basePosition;
19419
19420         if ( targetElem.nodeType === 9 ) {
19421                 targetWidth = target.width();
19422                 targetHeight = target.height();
19423                 basePosition = { top: 0, left: 0 };
19424         // TODO: use $.isWindow() in 1.9
19425         } else if ( targetElem.setTimeout ) {
19426                 targetWidth = target.width();
19427                 targetHeight = target.height();
19428                 basePosition = { top: target.scrollTop(), left: target.scrollLeft() };
19429         } else if ( targetElem.preventDefault ) {
19430                 // force left top to allow flipping
19431                 options.at = "left top";
19432                 targetWidth = targetHeight = 0;
19433                 basePosition = { top: options.of.pageY, left: options.of.pageX };
19434         } else {
19435                 targetWidth = target.outerWidth();
19436                 targetHeight = target.outerHeight();
19437                 basePosition = target.offset();
19438         }
19439
19440         // force my and at to have valid horizontal and veritcal positions
19441         // if a value is missing or invalid, it will be converted to center 
19442         $.each( [ "my", "at" ], function() {
19443                 var pos = ( options[this] || "" ).split( " " );
19444                 if ( pos.length === 1) {
19445                         pos = horizontalPositions.test( pos[0] ) ?
19446                                 pos.concat( [center] ) :
19447                                 verticalPositions.test( pos[0] ) ?
19448                                         [ center ].concat( pos ) :
19449                                         [ center, center ];
19450                 }
19451                 pos[ 0 ] = horizontalPositions.test( pos[0] ) ? pos[ 0 ] : center;
19452                 pos[ 1 ] = verticalPositions.test( pos[1] ) ? pos[ 1 ] : center;
19453                 options[ this ] = pos;
19454         });
19455
19456         // normalize collision option
19457         if ( collision.length === 1 ) {
19458                 collision[ 1 ] = collision[ 0 ];
19459         }
19460
19461         // normalize offset option
19462         offset[ 0 ] = parseInt( offset[0], 10 ) || 0;
19463         if ( offset.length === 1 ) {
19464                 offset[ 1 ] = offset[ 0 ];
19465         }
19466         offset[ 1 ] = parseInt( offset[1], 10 ) || 0;
19467
19468         if ( options.at[0] === "right" ) {
19469                 basePosition.left += targetWidth;
19470         } else if ( options.at[0] === center ) {
19471                 basePosition.left += targetWidth / 2;
19472         }
19473
19474         if ( options.at[1] === "bottom" ) {
19475                 basePosition.top += targetHeight;
19476         } else if ( options.at[1] === center ) {
19477                 basePosition.top += targetHeight / 2;
19478         }
19479
19480         basePosition.left += offset[ 0 ];
19481         basePosition.top += offset[ 1 ];
19482
19483         return this.each(function() {
19484                 var elem = $( this ),
19485                         elemWidth = elem.outerWidth(),
19486                         elemHeight = elem.outerHeight(),
19487                         marginLeft = parseInt( $.curCSS( this, "marginLeft", true ) ) || 0,
19488                         marginTop = parseInt( $.curCSS( this, "marginTop", true ) ) || 0,
19489                         collisionWidth = elemWidth + marginLeft +
19490                                 ( parseInt( $.curCSS( this, "marginRight", true ) ) || 0 ),
19491                         collisionHeight = elemHeight + marginTop +
19492                                 ( parseInt( $.curCSS( this, "marginBottom", true ) ) || 0 ),
19493                         position = $.extend( {}, basePosition ),
19494                         collisionPosition;
19495
19496                 if ( options.my[0] === "right" ) {
19497                         position.left -= elemWidth;
19498                 } else if ( options.my[0] === center ) {
19499                         position.left -= elemWidth / 2;
19500                 }
19501
19502                 if ( options.my[1] === "bottom" ) {
19503                         position.top -= elemHeight;
19504                 } else if ( options.my[1] === center ) {
19505                         position.top -= elemHeight / 2;
19506                 }
19507
19508                 // prevent fractions (see #5280)
19509                 position.left = Math.round( position.left );
19510                 position.top = Math.round( position.top );
19511
19512                 collisionPosition = {
19513                         left: position.left - marginLeft,
19514                         top: position.top - marginTop
19515                 };
19516
19517                 $.each( [ "left", "top" ], function( i, dir ) {
19518                         if ( $.ui.position[ collision[i] ] ) {
19519                                 $.ui.position[ collision[i] ][ dir ]( position, {
19520                                         targetWidth: targetWidth,
19521                                         targetHeight: targetHeight,
19522                                         elemWidth: elemWidth,
19523                                         elemHeight: elemHeight,
19524                                         collisionPosition: collisionPosition,
19525                                         collisionWidth: collisionWidth,
19526                                         collisionHeight: collisionHeight,
19527                                         offset: offset,
19528                                         my: options.my,
19529                                         at: options.at
19530                                 });
19531                         }
19532                 });
19533
19534                 if ( $.fn.bgiframe ) {
19535                         elem.bgiframe();
19536                 }
19537                 elem.offset( $.extend( position, { using: options.using } ) );
19538         });
19539 };
19540
19541 $.ui.position = {
19542         fit: {
19543                 left: function( position, data ) {
19544                         var win = $( window ),
19545                                 over = data.collisionPosition.left + data.collisionWidth - win.width() - win.scrollLeft();
19546                         position.left = over > 0 ? position.left - over : Math.max( position.left - data.collisionPosition.left, position.left );
19547                 },
19548                 top: function( position, data ) {
19549                         var win = $( window ),
19550                                 over = data.collisionPosition.top + data.collisionHeight - win.height() - win.scrollTop();
19551                         position.top = over > 0 ? position.top - over : Math.max( position.top - data.collisionPosition.top, position.top );
19552                 }
19553         },
19554
19555         flip: {
19556                 left: function( position, data ) {
19557                         if ( data.at[0] === center ) {
19558                                 return;
19559                         }
19560                         var win = $( window ),
19561                                 over = data.collisionPosition.left + data.collisionWidth - win.width() - win.scrollLeft(),
19562                                 myOffset = data.my[ 0 ] === "left" ?
19563                                         -data.elemWidth :
19564                                         data.my[ 0 ] === "right" ?
19565                                                 data.elemWidth :
19566                                                 0,
19567                                 atOffset = data.at[ 0 ] === "left" ?
19568                                         data.targetWidth :
19569                                         -data.targetWidth,
19570                                 offset = -2 * data.offset[ 0 ];
19571                         position.left += data.collisionPosition.left < 0 ?
19572                                 myOffset + atOffset + offset :
19573                                 over > 0 ?
19574                                         myOffset + atOffset + offset :
19575                                         0;
19576                 },
19577                 top: function( position, data ) {
19578                         if ( data.at[1] === center ) {
19579                                 return;
19580                         }
19581                         var win = $( window ),
19582                                 over = data.collisionPosition.top + data.collisionHeight - win.height() - win.scrollTop(),
19583                                 myOffset = data.my[ 1 ] === "top" ?
19584                                         -data.elemHeight :
19585                                         data.my[ 1 ] === "bottom" ?
19586                                                 data.elemHeight :
19587                                                 0,
19588                                 atOffset = data.at[ 1 ] === "top" ?
19589                                         data.targetHeight :
19590                                         -data.targetHeight,
19591                                 offset = -2 * data.offset[ 1 ];
19592                         position.top += data.collisionPosition.top < 0 ?
19593                                 myOffset + atOffset + offset :
19594                                 over > 0 ?
19595                                         myOffset + atOffset + offset :
19596                                         0;
19597                 }
19598         }
19599 };
19600
19601 // offset setter from jQuery 1.4
19602 if ( !$.offset.setOffset ) {
19603         $.offset.setOffset = function( elem, options ) {
19604                 // set position first, in-case top/left are set even on static elem
19605                 if ( /static/.test( $.curCSS( elem, "position" ) ) ) {
19606                         elem.style.position = "relative";
19607                 }
19608                 var curElem   = $( elem ),
19609                         curOffset = curElem.offset(),
19610                         curTop    = parseInt( $.curCSS( elem, "top",  true ), 10 ) || 0,
19611                         curLeft   = parseInt( $.curCSS( elem, "left", true ), 10)  || 0,
19612                         props     = {
19613                                 top:  (options.top  - curOffset.top)  + curTop,
19614                                 left: (options.left - curOffset.left) + curLeft
19615                         };
19616                 
19617                 if ( 'using' in options ) {
19618                         options.using.call( elem, props );
19619                 } else {
19620                         curElem.css( props );
19621                 }
19622         };
19623
19624         $.fn.offset = function( options ) {
19625                 var elem = this[ 0 ];
19626                 if ( !elem || !elem.ownerDocument ) { return null; }
19627                 if ( options ) { 
19628                         return this.each(function() {
19629                                 $.offset.setOffset( this, options );
19630                         });
19631                 }
19632                 return _offset.call( this );
19633         };
19634 }
19635
19636 }( jQuery ));
19637 /*
19638  * jQuery UI Progressbar 1.8.12
19639  *
19640  * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
19641  * Dual licensed under the MIT or GPL Version 2 licenses.
19642  * http://jquery.org/license
19643  *
19644  * http://docs.jquery.com/UI/Progressbar
19645  *
19646  * Depends:
19647  *   jquery.ui.core.js
19648  *   jquery.ui.widget.js
19649  */
19650 (function( $, undefined ) {
19651
19652 $.widget( "ui.progressbar", {
19653         options: {
19654                 value: 0,
19655                 max: 100
19656         },
19657
19658         min: 0,
19659
19660         _create: function() {
19661                 this.element
19662                         .addClass( "ui-progressbar ui-widget ui-widget-content ui-corner-all" )
19663                         .attr({
19664                                 role: "progressbar",
19665                                 "aria-valuemin": this.min,
19666                                 "aria-valuemax": this.options.max,
19667                                 "aria-valuenow": this._value()
19668                         });
19669
19670                 this.valueDiv = $( "<div class='ui-progressbar-value ui-widget-header ui-corner-left'></div>" )
19671                         .appendTo( this.element );
19672
19673                 this.oldValue = this._value();
19674                 this._refreshValue();
19675         },
19676
19677         destroy: function() {
19678                 this.element
19679                         .removeClass( "ui-progressbar ui-widget ui-widget-content ui-corner-all" )
19680                         .removeAttr( "role" )
19681                         .removeAttr( "aria-valuemin" )
19682                         .removeAttr( "aria-valuemax" )
19683                         .removeAttr( "aria-valuenow" );
19684
19685                 this.valueDiv.remove();
19686
19687                 $.Widget.prototype.destroy.apply( this, arguments );
19688         },
19689
19690         value: function( newValue ) {
19691                 if ( newValue === undefined ) {
19692                         return this._value();
19693                 }
19694
19695                 this._setOption( "value", newValue );
19696                 return this;
19697         },
19698
19699         _setOption: function( key, value ) {
19700                 if ( key === "value" ) {
19701                         this.options.value = value;
19702                         this._refreshValue();
19703                         if ( this._value() === this.options.max ) {
19704                                 this._trigger( "complete" );
19705                         }
19706                 }
19707
19708                 $.Widget.prototype._setOption.apply( this, arguments );
19709         },
19710
19711         _value: function() {
19712                 var val = this.options.value;
19713                 // normalize invalid value
19714                 if ( typeof val !== "number" ) {
19715                         val = 0;
19716                 }
19717                 return Math.min( this.options.max, Math.max( this.min, val ) );
19718         },
19719
19720         _percentage: function() {
19721                 return 100 * this._value() / this.options.max;
19722         },
19723
19724         _refreshValue: function() {
19725                 var value = this.value();
19726                 var percentage = this._percentage();
19727
19728                 if ( this.oldValue !== value ) {
19729                         this.oldValue = value;
19730                         this._trigger( "change" );
19731                 }
19732
19733                 this.valueDiv
19734                         .toggle( value > this.min )
19735                         .toggleClass( "ui-corner-right", value === this.options.max )
19736                         .width( percentage.toFixed(0) + "%" );
19737                 this.element.attr( "aria-valuenow", value );
19738         }
19739 });
19740
19741 $.extend( $.ui.progressbar, {
19742         version: "1.8.12"
19743 });
19744
19745 })( jQuery );
19746 /*
19747  * jQuery UI Slider 1.8.12
19748  *
19749  * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
19750  * Dual licensed under the MIT or GPL Version 2 licenses.
19751  * http://jquery.org/license
19752  *
19753  * http://docs.jquery.com/UI/Slider
19754  *
19755  * Depends:
19756  *      jquery.ui.core.js
19757  *      jquery.ui.mouse.js
19758  *      jquery.ui.widget.js
19759  */
19760 (function( $, undefined ) {
19761
19762 // number of pages in a slider
19763 // (how many times can you page up/down to go through the whole range)
19764 var numPages = 5;
19765
19766 $.widget( "ui.slider", $.ui.mouse, {
19767
19768         widgetEventPrefix: "slide",
19769
19770         options: {
19771                 animate: false,
19772                 distance: 0,
19773                 max: 100,
19774                 min: 0,
19775                 orientation: "horizontal",
19776                 range: false,
19777                 step: 1,
19778                 value: 0,
19779                 values: null
19780         },
19781
19782         _create: function() {
19783                 var self = this,
19784                         o = this.options;
19785
19786                 this._keySliding = false;
19787                 this._mouseSliding = false;
19788                 this._animateOff = true;
19789                 this._handleIndex = null;
19790                 this._detectOrientation();
19791                 this._mouseInit();
19792
19793                 this.element
19794                         .addClass( "ui-slider" +
19795                                 " ui-slider-" + this.orientation +
19796                                 " ui-widget" +
19797                                 " ui-widget-content" +
19798                                 " ui-corner-all" );
19799                 
19800                 if ( o.disabled ) {
19801                         this.element.addClass( "ui-slider-disabled ui-disabled" );
19802                 }
19803
19804                 this.range = $([]);
19805
19806                 if ( o.range ) {
19807                         if ( o.range === true ) {
19808                                 this.range = $( "<div></div>" );
19809                                 if ( !o.values ) {
19810                                         o.values = [ this._valueMin(), this._valueMin() ];
19811                                 }
19812                                 if ( o.values.length && o.values.length !== 2 ) {
19813                                         o.values = [ o.values[0], o.values[0] ];
19814                                 }
19815                         } else {
19816                                 this.range = $( "<div></div>" );
19817                         }
19818
19819                         this.range
19820                                 .appendTo( this.element )
19821                                 .addClass( "ui-slider-range" );
19822
19823                         if ( o.range === "min" || o.range === "max" ) {
19824                                 this.range.addClass( "ui-slider-range-" + o.range );
19825                         }
19826
19827                         // note: this isn't the most fittingly semantic framework class for this element,
19828                         // but worked best visually with a variety of themes
19829                         this.range.addClass( "ui-widget-header" );
19830                 }
19831
19832                 if ( $( ".ui-slider-handle", this.element ).length === 0 ) {
19833                         $( "<a href='#'></a>" )
19834                                 .appendTo( this.element )
19835                                 .addClass( "ui-slider-handle" );
19836                 }
19837
19838                 if ( o.values && o.values.length ) {
19839                         while ( $(".ui-slider-handle", this.element).length < o.values.length ) {
19840                                 $( "<a href='#'></a>" )
19841                                         .appendTo( this.element )
19842                                         .addClass( "ui-slider-handle" );
19843                         }
19844                 }
19845
19846                 this.handles = $( ".ui-slider-handle", this.element )
19847                         .addClass( "ui-state-default" +
19848                                 " ui-corner-all" );
19849
19850                 this.handle = this.handles.eq( 0 );
19851
19852                 this.handles.add( this.range ).filter( "a" )
19853                         .click(function( event ) {
19854                                 event.preventDefault();
19855                         })
19856                         .hover(function() {
19857                                 if ( !o.disabled ) {
19858                                         $( this ).addClass( "ui-state-hover" );
19859                                 }
19860                         }, function() {
19861                                 $( this ).removeClass( "ui-state-hover" );
19862                         })
19863                         .focus(function() {
19864                                 if ( !o.disabled ) {
19865                                         $( ".ui-slider .ui-state-focus" ).removeClass( "ui-state-focus" );
19866                                         $( this ).addClass( "ui-state-focus" );
19867                                 } else {
19868                                         $( this ).blur();
19869                                 }
19870                         })
19871                         .blur(function() {
19872                                 $( this ).removeClass( "ui-state-focus" );
19873                         });
19874
19875                 this.handles.each(function( i ) {
19876                         $( this ).data( "index.ui-slider-handle", i );
19877                 });
19878
19879                 this.handles
19880                         .keydown(function( event ) {
19881                                 var ret = true,
19882                                         index = $( this ).data( "index.ui-slider-handle" ),
19883                                         allowed,
19884                                         curVal,
19885                                         newVal,
19886                                         step;
19887         
19888                                 if ( self.options.disabled ) {
19889                                         return;
19890                                 }
19891         
19892                                 switch ( event.keyCode ) {
19893                                         case $.ui.keyCode.HOME:
19894                                         case $.ui.keyCode.END:
19895                                         case $.ui.keyCode.PAGE_UP:
19896                                         case $.ui.keyCode.PAGE_DOWN:
19897                                         case $.ui.keyCode.UP:
19898                                         case $.ui.keyCode.RIGHT:
19899                                         case $.ui.keyCode.DOWN:
19900                                         case $.ui.keyCode.LEFT:
19901                                                 ret = false;
19902                                                 if ( !self._keySliding ) {
19903                                                         self._keySliding = true;
19904                                                         $( this ).addClass( "ui-state-active" );
19905                                                         allowed = self._start( event, index );
19906                                                         if ( allowed === false ) {
19907                                                                 return;
19908                                                         }
19909                                                 }
19910                                                 break;
19911                                 }
19912         
19913                                 step = self.options.step;
19914                                 if ( self.options.values && self.options.values.length ) {
19915                                         curVal = newVal = self.values( index );
19916                                 } else {
19917                                         curVal = newVal = self.value();
19918                                 }
19919         
19920                                 switch ( event.keyCode ) {
19921                                         case $.ui.keyCode.HOME:
19922                                                 newVal = self._valueMin();
19923                                                 break;
19924                                         case $.ui.keyCode.END:
19925                                                 newVal = self._valueMax();
19926                                                 break;
19927                                         case $.ui.keyCode.PAGE_UP:
19928                                                 newVal = self._trimAlignValue( curVal + ( (self._valueMax() - self._valueMin()) / numPages ) );
19929                                                 break;
19930                                         case $.ui.keyCode.PAGE_DOWN:
19931                                                 newVal = self._trimAlignValue( curVal - ( (self._valueMax() - self._valueMin()) / numPages ) );
19932                                                 break;
19933                                         case $.ui.keyCode.UP:
19934                                         case $.ui.keyCode.RIGHT:
19935                                                 if ( curVal === self._valueMax() ) {
19936                                                         return;
19937                                                 }
19938                                                 newVal = self._trimAlignValue( curVal + step );
19939                                                 break;
19940                                         case $.ui.keyCode.DOWN:
19941                                         case $.ui.keyCode.LEFT:
19942                                                 if ( curVal === self._valueMin() ) {
19943                                                         return;
19944                                                 }
19945                                                 newVal = self._trimAlignValue( curVal - step );
19946                                                 break;
19947                                 }
19948         
19949                                 self._slide( event, index, newVal );
19950         
19951                                 return ret;
19952         
19953                         })
19954                         .keyup(function( event ) {
19955                                 var index = $( this ).data( "index.ui-slider-handle" );
19956         
19957                                 if ( self._keySliding ) {
19958                                         self._keySliding = false;
19959                                         self._stop( event, index );
19960                                         self._change( event, index );
19961                                         $( this ).removeClass( "ui-state-active" );
19962                                 }
19963         
19964                         });
19965
19966                 this._refreshValue();
19967
19968                 this._animateOff = false;
19969         },
19970
19971         destroy: function() {
19972                 this.handles.remove();
19973                 this.range.remove();
19974
19975                 this.element
19976                         .removeClass( "ui-slider" +
19977                                 " ui-slider-horizontal" +
19978                                 " ui-slider-vertical" +
19979                                 " ui-slider-disabled" +
19980                                 " ui-widget" +
19981                                 " ui-widget-content" +
19982                                 " ui-corner-all" )
19983                         .removeData( "slider" )
19984                         .unbind( ".slider" );
19985
19986                 this._mouseDestroy();
19987
19988                 return this;
19989         },
19990
19991         _mouseCapture: function( event ) {
19992                 var o = this.options,
19993                         position,
19994                         normValue,
19995                         distance,
19996                         closestHandle,
19997                         self,
19998                         index,
19999                         allowed,
20000                         offset,
20001                         mouseOverHandle;
20002
20003                 if ( o.disabled ) {
20004                         return false;
20005                 }
20006
20007                 this.elementSize = {
20008                         width: this.element.outerWidth(),
20009                         height: this.element.outerHeight()
20010                 };
20011                 this.elementOffset = this.element.offset();
20012
20013                 position = { x: event.pageX, y: event.pageY };
20014                 normValue = this._normValueFromMouse( position );
20015                 distance = this._valueMax() - this._valueMin() + 1;
20016                 self = this;
20017                 this.handles.each(function( i ) {
20018                         var thisDistance = Math.abs( normValue - self.values(i) );
20019                         if ( distance > thisDistance ) {
20020                                 distance = thisDistance;
20021                                 closestHandle = $( this );
20022                                 index = i;
20023                         }
20024                 });
20025
20026                 // workaround for bug #3736 (if both handles of a range are at 0,
20027                 // the first is always used as the one with least distance,
20028                 // and moving it is obviously prevented by preventing negative ranges)
20029                 if( o.range === true && this.values(1) === o.min ) {
20030                         index += 1;
20031                         closestHandle = $( this.handles[index] );
20032                 }
20033
20034                 allowed = this._start( event, index );
20035                 if ( allowed === false ) {
20036                         return false;
20037                 }
20038                 this._mouseSliding = true;
20039
20040                 self._handleIndex = index;
20041
20042                 closestHandle
20043                         .addClass( "ui-state-active" )
20044                         .focus();
20045                 
20046                 offset = closestHandle.offset();
20047                 mouseOverHandle = !$( event.target ).parents().andSelf().is( ".ui-slider-handle" );
20048                 this._clickOffset = mouseOverHandle ? { left: 0, top: 0 } : {
20049                         left: event.pageX - offset.left - ( closestHandle.width() / 2 ),
20050                         top: event.pageY - offset.top -
20051                                 ( closestHandle.height() / 2 ) -
20052                                 ( parseInt( closestHandle.css("borderTopWidth"), 10 ) || 0 ) -
20053                                 ( parseInt( closestHandle.css("borderBottomWidth"), 10 ) || 0) +
20054                                 ( parseInt( closestHandle.css("marginTop"), 10 ) || 0)
20055                 };
20056
20057                 if ( !this.handles.hasClass( "ui-state-hover" ) ) {
20058                         this._slide( event, index, normValue );
20059                 }
20060                 this._animateOff = true;
20061                 return true;
20062         },
20063
20064         _mouseStart: function( event ) {
20065                 return true;
20066         },
20067
20068         _mouseDrag: function( event ) {
20069                 var position = { x: event.pageX, y: event.pageY },
20070                         normValue = this._normValueFromMouse( position );
20071                 
20072                 this._slide( event, this._handleIndex, normValue );
20073
20074                 return false;
20075         },
20076
20077         _mouseStop: function( event ) {
20078                 this.handles.removeClass( "ui-state-active" );
20079                 this._mouseSliding = false;
20080
20081                 this._stop( event, this._handleIndex );
20082                 this._change( event, this._handleIndex );
20083
20084                 this._handleIndex = null;
20085                 this._clickOffset = null;
20086                 this._animateOff = false;
20087
20088                 return false;
20089         },
20090         
20091         _detectOrientation: function() {
20092                 this.orientation = ( this.options.orientation === "vertical" ) ? "vertical" : "horizontal";
20093         },
20094
20095         _normValueFromMouse: function( position ) {
20096                 var pixelTotal,
20097                         pixelMouse,
20098                         percentMouse,
20099                         valueTotal,
20100                         valueMouse;
20101
20102                 if ( this.orientation === "horizontal" ) {
20103                         pixelTotal = this.elementSize.width;
20104                         pixelMouse = position.x - this.elementOffset.left - ( this._clickOffset ? this._clickOffset.left : 0 );
20105                 } else {
20106                         pixelTotal = this.elementSize.height;
20107                         pixelMouse = position.y - this.elementOffset.top - ( this._clickOffset ? this._clickOffset.top : 0 );
20108                 }
20109
20110                 percentMouse = ( pixelMouse / pixelTotal );
20111                 if ( percentMouse > 1 ) {
20112                         percentMouse = 1;
20113                 }
20114                 if ( percentMouse < 0 ) {
20115                         percentMouse = 0;
20116                 }
20117                 if ( this.orientation === "vertical" ) {
20118                         percentMouse = 1 - percentMouse;
20119                 }
20120
20121                 valueTotal = this._valueMax() - this._valueMin();
20122                 valueMouse = this._valueMin() + percentMouse * valueTotal;
20123
20124                 return this._trimAlignValue( valueMouse );
20125         },
20126
20127         _start: function( event, index ) {
20128                 var uiHash = {
20129                         handle: this.handles[ index ],
20130                         value: this.value()
20131                 };
20132                 if ( this.options.values && this.options.values.length ) {
20133                         uiHash.value = this.values( index );
20134                         uiHash.values = this.values();
20135                 }
20136                 return this._trigger( "start", event, uiHash );
20137         },
20138
20139         _slide: function( event, index, newVal ) {
20140                 var otherVal,
20141                         newValues,
20142                         allowed;
20143
20144                 if ( this.options.values && this.options.values.length ) {
20145                         otherVal = this.values( index ? 0 : 1 );
20146
20147                         if ( ( this.options.values.length === 2 && this.options.range === true ) && 
20148                                         ( ( index === 0 && newVal > otherVal) || ( index === 1 && newVal < otherVal ) )
20149                                 ) {
20150                                 newVal = otherVal;
20151                         }
20152
20153                         if ( newVal !== this.values( index ) ) {
20154                                 newValues = this.values();
20155                                 newValues[ index ] = newVal;
20156                                 // A slide can be canceled by returning false from the slide callback
20157                                 allowed = this._trigger( "slide", event, {
20158                                         handle: this.handles[ index ],
20159                                         value: newVal,
20160                                         values: newValues
20161                                 } );
20162                                 otherVal = this.values( index ? 0 : 1 );
20163                                 if ( allowed !== false ) {
20164                                         this.values( index, newVal, true );
20165                                 }
20166                         }
20167                 } else {
20168                         if ( newVal !== this.value() ) {
20169                                 // A slide can be canceled by returning false from the slide callback
20170                                 allowed = this._trigger( "slide", event, {
20171                                         handle: this.handles[ index ],
20172                                         value: newVal
20173                                 } );
20174                                 if ( allowed !== false ) {
20175                                         this.value( newVal );
20176                                 }
20177                         }
20178                 }
20179         },
20180
20181         _stop: function( event, index ) {
20182                 var uiHash = {
20183                         handle: this.handles[ index ],
20184                         value: this.value()
20185                 };
20186                 if ( this.options.values && this.options.values.length ) {
20187                         uiHash.value = this.values( index );
20188                         uiHash.values = this.values();
20189                 }
20190
20191                 this._trigger( "stop", event, uiHash );
20192         },
20193
20194         _change: function( event, index ) {
20195                 if ( !this._keySliding && !this._mouseSliding ) {
20196                         var uiHash = {
20197                                 handle: this.handles[ index ],
20198                                 value: this.value()
20199                         };
20200                         if ( this.options.values && this.options.values.length ) {
20201                                 uiHash.value = this.values( index );
20202                                 uiHash.values = this.values();
20203                         }
20204
20205                         this._trigger( "change", event, uiHash );
20206                 }
20207         },
20208
20209         value: function( newValue ) {
20210                 if ( arguments.length ) {
20211                         this.options.value = this._trimAlignValue( newValue );
20212                         this._refreshValue();
20213                         this._change( null, 0 );
20214                         return;
20215                 }
20216
20217                 return this._value();
20218         },
20219
20220         values: function( index, newValue ) {
20221                 var vals,
20222                         newValues,
20223                         i;
20224
20225                 if ( arguments.length > 1 ) {
20226                         this.options.values[ index ] = this._trimAlignValue( newValue );
20227                         this._refreshValue();
20228                         this._change( null, index );
20229                         return;
20230                 }
20231
20232                 if ( arguments.length ) {
20233                         if ( $.isArray( arguments[ 0 ] ) ) {
20234                                 vals = this.options.values;
20235                                 newValues = arguments[ 0 ];
20236                                 for ( i = 0; i < vals.length; i += 1 ) {
20237                                         vals[ i ] = this._trimAlignValue( newValues[ i ] );
20238                                         this._change( null, i );
20239                                 }
20240                                 this._refreshValue();
20241                         } else {
20242                                 if ( this.options.values && this.options.values.length ) {
20243                                         return this._values( index );
20244                                 } else {
20245                                         return this.value();
20246                                 }
20247                         }
20248                 } else {
20249                         return this._values();
20250                 }
20251         },
20252
20253         _setOption: function( key, value ) {
20254                 var i,
20255                         valsLength = 0;
20256
20257                 if ( $.isArray( this.options.values ) ) {
20258                         valsLength = this.options.values.length;
20259                 }
20260
20261                 $.Widget.prototype._setOption.apply( this, arguments );
20262
20263                 switch ( key ) {
20264                         case "disabled":
20265                                 if ( value ) {
20266                                         this.handles.filter( ".ui-state-focus" ).blur();
20267                                         this.handles.removeClass( "ui-state-hover" );
20268                                         this.handles.attr( "disabled", "disabled" );
20269                                         this.element.addClass( "ui-disabled" );
20270                                 } else {
20271                                         this.handles.removeAttr( "disabled" );
20272                                         this.element.removeClass( "ui-disabled" );
20273                                 }
20274                                 break;
20275                         case "orientation":
20276                                 this._detectOrientation();
20277                                 this.element
20278                                         .removeClass( "ui-slider-horizontal ui-slider-vertical" )
20279                                         .addClass( "ui-slider-" + this.orientation );
20280                                 this._refreshValue();
20281                                 break;
20282                         case "value":
20283                                 this._animateOff = true;
20284                                 this._refreshValue();
20285                                 this._change( null, 0 );
20286                                 this._animateOff = false;
20287                                 break;
20288                         case "values":
20289                                 this._animateOff = true;
20290                                 this._refreshValue();
20291                                 for ( i = 0; i < valsLength; i += 1 ) {
20292                                         this._change( null, i );
20293                                 }
20294                                 this._animateOff = false;
20295                                 break;
20296                 }
20297         },
20298
20299         //internal value getter
20300         // _value() returns value trimmed by min and max, aligned by step
20301         _value: function() {
20302                 var val = this.options.value;
20303                 val = this._trimAlignValue( val );
20304
20305                 return val;
20306         },
20307
20308         //internal values getter
20309         // _values() returns array of values trimmed by min and max, aligned by step
20310         // _values( index ) returns single value trimmed by min and max, aligned by step
20311         _values: function( index ) {
20312                 var val,
20313                         vals,
20314                         i;
20315
20316                 if ( arguments.length ) {
20317                         val = this.options.values[ index ];
20318                         val = this._trimAlignValue( val );
20319
20320                         return val;
20321                 } else {
20322                         // .slice() creates a copy of the array
20323                         // this copy gets trimmed by min and max and then returned
20324                         vals = this.options.values.slice();
20325                         for ( i = 0; i < vals.length; i+= 1) {
20326                                 vals[ i ] = this._trimAlignValue( vals[ i ] );
20327                         }
20328
20329                         return vals;
20330                 }
20331         },
20332         
20333         // returns the step-aligned value that val is closest to, between (inclusive) min and max
20334         _trimAlignValue: function( val ) {
20335                 if ( val <= this._valueMin() ) {
20336                         return this._valueMin();
20337                 }
20338                 if ( val >= this._valueMax() ) {
20339                         return this._valueMax();
20340                 }
20341                 var step = ( this.options.step > 0 ) ? this.options.step : 1,
20342                         valModStep = (val - this._valueMin()) % step;
20343                         alignValue = val - valModStep;
20344
20345                 if ( Math.abs(valModStep) * 2 >= step ) {
20346                         alignValue += ( valModStep > 0 ) ? step : ( -step );
20347                 }
20348
20349                 // Since JavaScript has problems with large floats, round
20350                 // the final value to 5 digits after the decimal point (see #4124)
20351                 return parseFloat( alignValue.toFixed(5) );
20352         },
20353
20354         _valueMin: function() {
20355                 return this.options.min;
20356         },
20357
20358         _valueMax: function() {
20359                 return this.options.max;
20360         },
20361         
20362         _refreshValue: function() {
20363                 var oRange = this.options.range,
20364                         o = this.options,
20365                         self = this,
20366                         animate = ( !this._animateOff ) ? o.animate : false,
20367                         valPercent,
20368                         _set = {},
20369                         lastValPercent,
20370                         value,
20371                         valueMin,
20372                         valueMax;
20373
20374                 if ( this.options.values && this.options.values.length ) {
20375                         this.handles.each(function( i, j ) {
20376                                 valPercent = ( self.values(i) - self._valueMin() ) / ( self._valueMax() - self._valueMin() ) * 100;
20377                                 _set[ self.orientation === "horizontal" ? "left" : "bottom" ] = valPercent + "%";
20378                                 $( this ).stop( 1, 1 )[ animate ? "animate" : "css" ]( _set, o.animate );
20379                                 if ( self.options.range === true ) {
20380                                         if ( self.orientation === "horizontal" ) {
20381                                                 if ( i === 0 ) {
20382                                                         self.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { left: valPercent + "%" }, o.animate );
20383                                                 }
20384                                                 if ( i === 1 ) {
20385                                                         self.range[ animate ? "animate" : "css" ]( { width: ( valPercent - lastValPercent ) + "%" }, { queue: false, duration: o.animate } );
20386                                                 }
20387                                         } else {
20388                                                 if ( i === 0 ) {
20389                                                         self.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { bottom: ( valPercent ) + "%" }, o.animate );
20390                                                 }
20391                                                 if ( i === 1 ) {
20392                                                         self.range[ animate ? "animate" : "css" ]( { height: ( valPercent - lastValPercent ) + "%" }, { queue: false, duration: o.animate } );
20393                                                 }
20394                                         }
20395                                 }
20396                                 lastValPercent = valPercent;
20397                         });
20398                 } else {
20399                         value = this.value();
20400                         valueMin = this._valueMin();
20401                         valueMax = this._valueMax();
20402                         valPercent = ( valueMax !== valueMin ) ?
20403                                         ( value - valueMin ) / ( valueMax - valueMin ) * 100 :
20404                                         0;
20405                         _set[ self.orientation === "horizontal" ? "left" : "bottom" ] = valPercent + "%";
20406                         this.handle.stop( 1, 1 )[ animate ? "animate" : "css" ]( _set, o.animate );
20407
20408                         if ( oRange === "min" && this.orientation === "horizontal" ) {
20409                                 this.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { width: valPercent + "%" }, o.animate );
20410                         }
20411                         if ( oRange === "max" && this.orientation === "horizontal" ) {
20412                                 this.range[ animate ? "animate" : "css" ]( { width: ( 100 - valPercent ) + "%" }, { queue: false, duration: o.animate } );
20413                         }
20414                         if ( oRange === "min" && this.orientation === "vertical" ) {
20415                                 this.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { height: valPercent + "%" }, o.animate );
20416                         }
20417                         if ( oRange === "max" && this.orientation === "vertical" ) {
20418                                 this.range[ animate ? "animate" : "css" ]( { height: ( 100 - valPercent ) + "%" }, { queue: false, duration: o.animate } );
20419                         }
20420                 }
20421         }
20422
20423 });
20424
20425 $.extend( $.ui.slider, {
20426         version: "1.8.12"
20427 });
20428
20429 }(jQuery));
20430 /*
20431  * jQuery UI Tabs 1.8.12
20432  *
20433  * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
20434  * Dual licensed under the MIT or GPL Version 2 licenses.
20435  * http://jquery.org/license
20436  *
20437  * http://docs.jquery.com/UI/Tabs
20438  *
20439  * Depends:
20440  *      jquery.ui.core.js
20441  *      jquery.ui.widget.js
20442  */
20443 (function( $, undefined ) {
20444
20445 var tabId = 0,
20446         listId = 0;
20447
20448 function getNextTabId() {
20449         return ++tabId;
20450 }
20451
20452 function getNextListId() {
20453         return ++listId;
20454 }
20455
20456 $.widget( "ui.tabs", {
20457         options: {
20458                 add: null,
20459                 ajaxOptions: null,
20460                 cache: false,
20461                 cookie: null, // e.g. { expires: 7, path: '/', domain: 'jquery.com', secure: true }
20462                 collapsible: false,
20463                 disable: null,
20464                 disabled: [],
20465                 enable: null,
20466                 event: "click",
20467                 fx: null, // e.g. { height: 'toggle', opacity: 'toggle', duration: 200 }
20468                 idPrefix: "ui-tabs-",
20469                 load: null,
20470                 panelTemplate: "<div></div>",
20471                 remove: null,
20472                 select: null,
20473                 show: null,
20474                 spinner: "<em>Loading&#8230;</em>",
20475                 tabTemplate: "<li><a href='#{href}'><span>#{label}</span></a></li>"
20476         },
20477
20478         _create: function() {
20479                 this._tabify( true );
20480         },
20481
20482         _setOption: function( key, value ) {
20483                 if ( key == "selected" ) {
20484                         if (this.options.collapsible && value == this.options.selected ) {
20485                                 return;
20486                         }
20487                         this.select( value );
20488                 } else {
20489                         this.options[ key ] = value;
20490                         this._tabify();
20491                 }
20492         },
20493
20494         _tabId: function( a ) {
20495                 return a.title && a.title.replace( /\s/g, "_" ).replace( /[^\w\u00c0-\uFFFF-]/g, "" ) ||
20496                         this.options.idPrefix + getNextTabId();
20497         },
20498
20499         _sanitizeSelector: function( hash ) {
20500                 // we need this because an id may contain a ":"
20501                 return hash.replace( /:/g, "\\:" );
20502         },
20503
20504         _cookie: function() {
20505                 var cookie = this.cookie ||
20506                         ( this.cookie = this.options.cookie.name || "ui-tabs-" + getNextListId() );
20507                 return $.cookie.apply( null, [ cookie ].concat( $.makeArray( arguments ) ) );
20508         },
20509
20510         _ui: function( tab, panel ) {
20511                 return {
20512                         tab: tab,
20513                         panel: panel,
20514                         index: this.anchors.index( tab )
20515                 };
20516         },
20517
20518         _cleanup: function() {
20519                 // restore all former loading tabs labels
20520                 this.lis.filter( ".ui-state-processing" )
20521                         .removeClass( "ui-state-processing" )
20522                         .find( "span:data(label.tabs)" )
20523                                 .each(function() {
20524                                         var el = $( this );
20525                                         el.html( el.data( "label.tabs" ) ).removeData( "label.tabs" );
20526                                 });
20527         },
20528
20529         _tabify: function( init ) {
20530                 var self = this,
20531                         o = this.options,
20532                         fragmentId = /^#.+/; // Safari 2 reports '#' for an empty hash
20533
20534                 this.list = this.element.find( "ol,ul" ).eq( 0 );
20535                 this.lis = $( " > li:has(a[href])", this.list );
20536                 this.anchors = this.lis.map(function() {
20537                         return $( "a", this )[ 0 ];
20538                 });
20539                 this.panels = $( [] );
20540
20541                 this.anchors.each(function( i, a ) {
20542                         var href = $( a ).attr( "href" );
20543                         // For dynamically created HTML that contains a hash as href IE < 8 expands
20544                         // such href to the full page url with hash and then misinterprets tab as ajax.
20545                         // Same consideration applies for an added tab with a fragment identifier
20546                         // since a[href=#fragment-identifier] does unexpectedly not match.
20547                         // Thus normalize href attribute...
20548                         var hrefBase = href.split( "#" )[ 0 ],
20549                                 baseEl;
20550                         if ( hrefBase && ( hrefBase === location.toString().split( "#" )[ 0 ] ||
20551                                         ( baseEl = $( "base" )[ 0 ]) && hrefBase === baseEl.href ) ) {
20552                                 href = a.hash;
20553                                 a.href = href;
20554                         }
20555
20556                         // inline tab
20557                         if ( fragmentId.test( href ) ) {
20558                                 self.panels = self.panels.add( self.element.find( self._sanitizeSelector( href ) ) );
20559                         // remote tab
20560                         // prevent loading the page itself if href is just "#"
20561                         } else if ( href && href !== "#" ) {
20562                                 // required for restore on destroy
20563                                 $.data( a, "href.tabs", href );
20564
20565                                 // TODO until #3808 is fixed strip fragment identifier from url
20566                                 // (IE fails to load from such url)
20567                                 $.data( a, "load.tabs", href.replace( /#.*$/, "" ) );
20568
20569                                 var id = self._tabId( a );
20570                                 a.href = "#" + id;
20571                                 var $panel = self.element.find( "#" + id );
20572                                 if ( !$panel.length ) {
20573                                         $panel = $( o.panelTemplate )
20574                                                 .attr( "id", id )
20575                                                 .addClass( "ui-tabs-panel ui-widget-content ui-corner-bottom" )
20576                                                 .insertAfter( self.panels[ i - 1 ] || self.list );
20577                                         $panel.data( "destroy.tabs", true );
20578                                 }
20579                                 self.panels = self.panels.add( $panel );
20580                         // invalid tab href
20581                         } else {
20582                                 o.disabled.push( i );
20583                         }
20584                 });
20585
20586                 // initialization from scratch
20587                 if ( init ) {
20588                         // attach necessary classes for styling
20589                         this.element.addClass( "ui-tabs ui-widget ui-widget-content ui-corner-all" );
20590                         this.list.addClass( "ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all" );
20591                         this.lis.addClass( "ui-state-default ui-corner-top" );
20592                         this.panels.addClass( "ui-tabs-panel ui-widget-content ui-corner-bottom" );
20593
20594                         // Selected tab
20595                         // use "selected" option or try to retrieve:
20596                         // 1. from fragment identifier in url
20597                         // 2. from cookie
20598                         // 3. from selected class attribute on <li>
20599                         if ( o.selected === undefined ) {
20600                                 if ( location.hash ) {
20601                                         this.anchors.each(function( i, a ) {
20602                                                 if ( a.hash == location.hash ) {
20603                                                         o.selected = i;
20604                                                         return false;
20605                                                 }
20606                                         });
20607                                 }
20608                                 if ( typeof o.selected !== "number" && o.cookie ) {
20609                                         o.selected = parseInt( self._cookie(), 10 );
20610                                 }
20611                                 if ( typeof o.selected !== "number" && this.lis.filter( ".ui-tabs-selected" ).length ) {
20612                                         o.selected = this.lis.index( this.lis.filter( ".ui-tabs-selected" ) );
20613                                 }
20614                                 o.selected = o.selected || ( this.lis.length ? 0 : -1 );
20615                         } else if ( o.selected === null ) { // usage of null is deprecated, TODO remove in next release
20616                                 o.selected = -1;
20617                         }
20618
20619                         // sanity check - default to first tab...
20620                         o.selected = ( ( o.selected >= 0 && this.anchors[ o.selected ] ) || o.selected < 0 )
20621                                 ? o.selected
20622                                 : 0;
20623
20624                         // Take disabling tabs via class attribute from HTML
20625                         // into account and update option properly.
20626                         // A selected tab cannot become disabled.
20627                         o.disabled = $.unique( o.disabled.concat(
20628                                 $.map( this.lis.filter( ".ui-state-disabled" ), function( n, i ) {
20629                                         return self.lis.index( n );
20630                                 })
20631                         ) ).sort();
20632
20633                         if ( $.inArray( o.selected, o.disabled ) != -1 ) {
20634                                 o.disabled.splice( $.inArray( o.selected, o.disabled ), 1 );
20635                         }
20636
20637                         // highlight selected tab
20638                         this.panels.addClass( "ui-tabs-hide" );
20639                         this.lis.removeClass( "ui-tabs-selected ui-state-active" );
20640                         // check for length avoids error when initializing empty list
20641                         if ( o.selected >= 0 && this.anchors.length ) {
20642                                 self.element.find( self._sanitizeSelector( self.anchors[ o.selected ].hash ) ).removeClass( "ui-tabs-hide" );
20643                                 this.lis.eq( o.selected ).addClass( "ui-tabs-selected ui-state-active" );
20644
20645                                 // seems to be expected behavior that the show callback is fired
20646                                 self.element.queue( "tabs", function() {
20647                                         self._trigger( "show", null,
20648                                                 self._ui( self.anchors[ o.selected ], self.element.find( self._sanitizeSelector( self.anchors[ o.selected ].hash ) )[ 0 ] ) );
20649                                 });
20650
20651                                 this.load( o.selected );
20652                         }
20653
20654                         // clean up to avoid memory leaks in certain versions of IE 6
20655                         // TODO: namespace this event
20656                         $( window ).bind( "unload", function() {
20657                                 self.lis.add( self.anchors ).unbind( ".tabs" );
20658                                 self.lis = self.anchors = self.panels = null;
20659                         });
20660                 // update selected after add/remove
20661                 } else {
20662                         o.selected = this.lis.index( this.lis.filter( ".ui-tabs-selected" ) );
20663                 }
20664
20665                 // update collapsible
20666                 // TODO: use .toggleClass()
20667                 this.element[ o.collapsible ? "addClass" : "removeClass" ]( "ui-tabs-collapsible" );
20668
20669                 // set or update cookie after init and add/remove respectively
20670                 if ( o.cookie ) {
20671                         this._cookie( o.selected, o.cookie );
20672                 }
20673
20674                 // disable tabs
20675                 for ( var i = 0, li; ( li = this.lis[ i ] ); i++ ) {
20676                         $( li )[ $.inArray( i, o.disabled ) != -1 &&
20677                                 // TODO: use .toggleClass()
20678                                 !$( li ).hasClass( "ui-tabs-selected" ) ? "addClass" : "removeClass" ]( "ui-state-disabled" );
20679                 }
20680
20681                 // reset cache if switching from cached to not cached
20682                 if ( o.cache === false ) {
20683                         this.anchors.removeData( "cache.tabs" );
20684                 }
20685
20686                 // remove all handlers before, tabify may run on existing tabs after add or option change
20687                 this.lis.add( this.anchors ).unbind( ".tabs" );
20688
20689                 if ( o.event !== "mouseover" ) {
20690                         var addState = function( state, el ) {
20691                                 if ( el.is( ":not(.ui-state-disabled)" ) ) {
20692                                         el.addClass( "ui-state-" + state );
20693                                 }
20694                         };
20695                         var removeState = function( state, el ) {
20696                                 el.removeClass( "ui-state-" + state );
20697                         };
20698                         this.lis.bind( "mouseover.tabs" , function() {
20699                                 addState( "hover", $( this ) );
20700                         });
20701                         this.lis.bind( "mouseout.tabs", function() {
20702                                 removeState( "hover", $( this ) );
20703                         });
20704                         this.anchors.bind( "focus.tabs", function() {
20705                                 addState( "focus", $( this ).closest( "li" ) );
20706                         });
20707                         this.anchors.bind( "blur.tabs", function() {
20708                                 removeState( "focus", $( this ).closest( "li" ) );
20709                         });
20710                 }
20711
20712                 // set up animations
20713                 var hideFx, showFx;
20714                 if ( o.fx ) {
20715                         if ( $.isArray( o.fx ) ) {
20716                                 hideFx = o.fx[ 0 ];
20717                                 showFx = o.fx[ 1 ];
20718                         } else {
20719                                 hideFx = showFx = o.fx;
20720                         }
20721                 }
20722
20723                 // Reset certain styles left over from animation
20724                 // and prevent IE's ClearType bug...
20725                 function resetStyle( $el, fx ) {
20726                         $el.css( "display", "" );
20727                         if ( !$.support.opacity && fx.opacity ) {
20728                                 $el[ 0 ].style.removeAttribute( "filter" );
20729                         }
20730                 }
20731
20732                 // Show a tab...
20733                 var showTab = showFx
20734                         ? function( clicked, $show ) {
20735                                 $( clicked ).closest( "li" ).addClass( "ui-tabs-selected ui-state-active" );
20736                                 $show.hide().removeClass( "ui-tabs-hide" ) // avoid flicker that way
20737                                         .animate( showFx, showFx.duration || "normal", function() {
20738                                                 resetStyle( $show, showFx );
20739                                                 self._trigger( "show", null, self._ui( clicked, $show[ 0 ] ) );
20740                                         });
20741                         }
20742                         : function( clicked, $show ) {
20743                                 $( clicked ).closest( "li" ).addClass( "ui-tabs-selected ui-state-active" );
20744                                 $show.removeClass( "ui-tabs-hide" );
20745                                 self._trigger( "show", null, self._ui( clicked, $show[ 0 ] ) );
20746                         };
20747
20748                 // Hide a tab, $show is optional...
20749                 var hideTab = hideFx
20750                         ? function( clicked, $hide ) {
20751                                 $hide.animate( hideFx, hideFx.duration || "normal", function() {
20752                                         self.lis.removeClass( "ui-tabs-selected ui-state-active" );
20753                                         $hide.addClass( "ui-tabs-hide" );
20754                                         resetStyle( $hide, hideFx );
20755                                         self.element.dequeue( "tabs" );
20756                                 });
20757                         }
20758                         : function( clicked, $hide, $show ) {
20759                                 self.lis.removeClass( "ui-tabs-selected ui-state-active" );
20760                                 $hide.addClass( "ui-tabs-hide" );
20761                                 self.element.dequeue( "tabs" );
20762                         };
20763
20764                 // attach tab event handler, unbind to avoid duplicates from former tabifying...
20765                 this.anchors.bind( o.event + ".tabs", function() {
20766                         var el = this,
20767                                 $li = $(el).closest( "li" ),
20768                                 $hide = self.panels.filter( ":not(.ui-tabs-hide)" ),
20769                                 $show = self.element.find( self._sanitizeSelector( el.hash ) );
20770
20771                         // If tab is already selected and not collapsible or tab disabled or
20772                         // or is already loading or click callback returns false stop here.
20773                         // Check if click handler returns false last so that it is not executed
20774                         // for a disabled or loading tab!
20775                         if ( ( $li.hasClass( "ui-tabs-selected" ) && !o.collapsible) ||
20776                                 $li.hasClass( "ui-state-disabled" ) ||
20777                                 $li.hasClass( "ui-state-processing" ) ||
20778                                 self.panels.filter( ":animated" ).length ||
20779                                 self._trigger( "select", null, self._ui( this, $show[ 0 ] ) ) === false ) {
20780                                 this.blur();
20781                                 return false;
20782                         }
20783
20784                         o.selected = self.anchors.index( this );
20785
20786                         self.abort();
20787
20788                         // if tab may be closed
20789                         if ( o.collapsible ) {
20790                                 if ( $li.hasClass( "ui-tabs-selected" ) ) {
20791                                         o.selected = -1;
20792
20793                                         if ( o.cookie ) {
20794                                                 self._cookie( o.selected, o.cookie );
20795                                         }
20796
20797                                         self.element.queue( "tabs", function() {
20798                                                 hideTab( el, $hide );
20799                                         }).dequeue( "tabs" );
20800
20801                                         this.blur();
20802                                         return false;
20803                                 } else if ( !$hide.length ) {
20804                                         if ( o.cookie ) {
20805                                                 self._cookie( o.selected, o.cookie );
20806                                         }
20807
20808                                         self.element.queue( "tabs", function() {
20809                                                 showTab( el, $show );
20810                                         });
20811
20812                                         // TODO make passing in node possible, see also http://dev.jqueryui.com/ticket/3171
20813                                         self.load( self.anchors.index( this ) );
20814
20815                                         this.blur();
20816                                         return false;
20817                                 }
20818                         }
20819
20820                         if ( o.cookie ) {
20821                                 self._cookie( o.selected, o.cookie );
20822                         }
20823
20824                         // show new tab
20825                         if ( $show.length ) {
20826                                 if ( $hide.length ) {
20827                                         self.element.queue( "tabs", function() {
20828                                                 hideTab( el, $hide );
20829                                         });
20830                                 }
20831                                 self.element.queue( "tabs", function() {
20832                                         showTab( el, $show );
20833                                 });
20834
20835                                 self.load( self.anchors.index( this ) );
20836                         } else {
20837                                 throw "jQuery UI Tabs: Mismatching fragment identifier.";
20838                         }
20839
20840                         // Prevent IE from keeping other link focussed when using the back button
20841                         // and remove dotted border from clicked link. This is controlled via CSS
20842                         // in modern browsers; blur() removes focus from address bar in Firefox
20843                         // which can become a usability and annoying problem with tabs('rotate').
20844                         if ( $.browser.msie ) {
20845                                 this.blur();
20846                         }
20847                 });
20848
20849                 // disable click in any case
20850                 this.anchors.bind( "click.tabs", function(){
20851                         return false;
20852                 });
20853         },
20854
20855     _getIndex: function( index ) {
20856                 // meta-function to give users option to provide a href string instead of a numerical index.
20857                 // also sanitizes numerical indexes to valid values.
20858                 if ( typeof index == "string" ) {
20859                         index = this.anchors.index( this.anchors.filter( "[href$=" + index + "]" ) );
20860                 }
20861
20862                 return index;
20863         },
20864
20865         destroy: function() {
20866                 var o = this.options;
20867
20868                 this.abort();
20869
20870                 this.element
20871                         .unbind( ".tabs" )
20872                         .removeClass( "ui-tabs ui-widget ui-widget-content ui-corner-all ui-tabs-collapsible" )
20873                         .removeData( "tabs" );
20874
20875                 this.list.removeClass( "ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all" );
20876
20877                 this.anchors.each(function() {
20878                         var href = $.data( this, "href.tabs" );
20879                         if ( href ) {
20880                                 this.href = href;
20881                         }
20882                         var $this = $( this ).unbind( ".tabs" );
20883                         $.each( [ "href", "load", "cache" ], function( i, prefix ) {
20884                                 $this.removeData( prefix + ".tabs" );
20885                         });
20886                 });
20887
20888                 this.lis.unbind( ".tabs" ).add( this.panels ).each(function() {
20889                         if ( $.data( this, "destroy.tabs" ) ) {
20890                                 $( this ).remove();
20891                         } else {
20892                                 $( this ).removeClass([
20893                                         "ui-state-default",
20894                                         "ui-corner-top",
20895                                         "ui-tabs-selected",
20896                                         "ui-state-active",
20897                                         "ui-state-hover",
20898                                         "ui-state-focus",
20899                                         "ui-state-disabled",
20900                                         "ui-tabs-panel",
20901                                         "ui-widget-content",
20902                                         "ui-corner-bottom",
20903                                         "ui-tabs-hide"
20904                                 ].join( " " ) );
20905                         }
20906                 });
20907
20908                 if ( o.cookie ) {
20909                         this._cookie( null, o.cookie );
20910                 }
20911
20912                 return this;
20913         },
20914
20915         add: function( url, label, index ) {
20916                 if ( index === undefined ) {
20917                         index = this.anchors.length;
20918                 }
20919
20920                 var self = this,
20921                         o = this.options,
20922                         $li = $( o.tabTemplate.replace( /#\{href\}/g, url ).replace( /#\{label\}/g, label ) ),
20923                         id = !url.indexOf( "#" ) ? url.replace( "#", "" ) : this._tabId( $( "a", $li )[ 0 ] );
20924
20925                 $li.addClass( "ui-state-default ui-corner-top" ).data( "destroy.tabs", true );
20926
20927                 // try to find an existing element before creating a new one
20928                 var $panel = self.element.find( "#" + id );
20929                 if ( !$panel.length ) {
20930                         $panel = $( o.panelTemplate )
20931                                 .attr( "id", id )
20932                                 .data( "destroy.tabs", true );
20933                 }
20934                 $panel.addClass( "ui-tabs-panel ui-widget-content ui-corner-bottom ui-tabs-hide" );
20935
20936                 if ( index >= this.lis.length ) {
20937                         $li.appendTo( this.list );
20938                         $panel.appendTo( this.list[ 0 ].parentNode );
20939                 } else {
20940                         $li.insertBefore( this.lis[ index ] );
20941                         $panel.insertBefore( this.panels[ index ] );
20942                 }
20943
20944                 o.disabled = $.map( o.disabled, function( n, i ) {
20945                         return n >= index ? ++n : n;
20946                 });
20947
20948                 this._tabify();
20949
20950                 if ( this.anchors.length == 1 ) {
20951                         o.selected = 0;
20952                         $li.addClass( "ui-tabs-selected ui-state-active" );
20953                         $panel.removeClass( "ui-tabs-hide" );
20954                         this.element.queue( "tabs", function() {
20955                                 self._trigger( "show", null, self._ui( self.anchors[ 0 ], self.panels[ 0 ] ) );
20956                         });
20957
20958                         this.load( 0 );
20959                 }
20960
20961                 this._trigger( "add", null, this._ui( this.anchors[ index ], this.panels[ index ] ) );
20962                 return this;
20963         },
20964
20965         remove: function( index ) {
20966                 index = this._getIndex( index );
20967                 var o = this.options,
20968                         $li = this.lis.eq( index ).remove(),
20969                         $panel = this.panels.eq( index ).remove();
20970
20971                 // If selected tab was removed focus tab to the right or
20972                 // in case the last tab was removed the tab to the left.
20973                 if ( $li.hasClass( "ui-tabs-selected" ) && this.anchors.length > 1) {
20974                         this.select( index + ( index + 1 < this.anchors.length ? 1 : -1 ) );
20975                 }
20976
20977                 o.disabled = $.map(
20978                         $.grep( o.disabled, function(n, i) {
20979                                 return n != index;
20980                         }),
20981                         function( n, i ) {
20982                                 return n >= index ? --n : n;
20983                         });
20984
20985                 this._tabify();
20986
20987                 this._trigger( "remove", null, this._ui( $li.find( "a" )[ 0 ], $panel[ 0 ] ) );
20988                 return this;
20989         },
20990
20991         enable: function( index ) {
20992                 index = this._getIndex( index );
20993                 var o = this.options;
20994                 if ( $.inArray( index, o.disabled ) == -1 ) {
20995                         return;
20996                 }
20997
20998                 this.lis.eq( index ).removeClass( "ui-state-disabled" );
20999                 o.disabled = $.grep( o.disabled, function( n, i ) {
21000                         return n != index;
21001                 });
21002
21003                 this._trigger( "enable", null, this._ui( this.anchors[ index ], this.panels[ index ] ) );
21004                 return this;
21005         },
21006
21007         disable: function( index ) {
21008                 index = this._getIndex( index );
21009                 var self = this, o = this.options;
21010                 // cannot disable already selected tab
21011                 if ( index != o.selected ) {
21012                         this.lis.eq( index ).addClass( "ui-state-disabled" );
21013
21014                         o.disabled.push( index );
21015                         o.disabled.sort();
21016
21017                         this._trigger( "disable", null, this._ui( this.anchors[ index ], this.panels[ index ] ) );
21018                 }
21019
21020                 return this;
21021         },
21022
21023         select: function( index ) {
21024                 index = this._getIndex( index );
21025                 if ( index == -1 ) {
21026                         if ( this.options.collapsible && this.options.selected != -1 ) {
21027                                 index = this.options.selected;
21028                         } else {
21029                                 return this;
21030                         }
21031                 }
21032                 this.anchors.eq( index ).trigger( this.options.event + ".tabs" );
21033                 return this;
21034         },
21035
21036         load: function( index ) {
21037                 index = this._getIndex( index );
21038                 var self = this,
21039                         o = this.options,
21040                         a = this.anchors.eq( index )[ 0 ],
21041                         url = $.data( a, "load.tabs" );
21042
21043                 this.abort();
21044
21045                 // not remote or from cache
21046                 if ( !url || this.element.queue( "tabs" ).length !== 0 && $.data( a, "cache.tabs" ) ) {
21047                         this.element.dequeue( "tabs" );
21048                         return;
21049                 }
21050
21051                 // load remote from here on
21052                 this.lis.eq( index ).addClass( "ui-state-processing" );
21053
21054                 if ( o.spinner ) {
21055                         var span = $( "span", a );
21056                         span.data( "label.tabs", span.html() ).html( o.spinner );
21057                 }
21058
21059                 this.xhr = $.ajax( $.extend( {}, o.ajaxOptions, {
21060                         url: url,
21061                         success: function( r, s ) {
21062                                 self.element.find( self._sanitizeSelector( a.hash ) ).html( r );
21063
21064                                 // take care of tab labels
21065                                 self._cleanup();
21066
21067                                 if ( o.cache ) {
21068                                         $.data( a, "cache.tabs", true );
21069                                 }
21070
21071                                 self._trigger( "load", null, self._ui( self.anchors[ index ], self.panels[ index ] ) );
21072                                 try {
21073                                         o.ajaxOptions.success( r, s );
21074                                 }
21075                                 catch ( e ) {}
21076                         },
21077                         error: function( xhr, s, e ) {
21078                                 // take care of tab labels
21079                                 self._cleanup();
21080
21081                                 self._trigger( "load", null, self._ui( self.anchors[ index ], self.panels[ index ] ) );
21082                                 try {
21083                                         // Passing index avoid a race condition when this method is
21084                                         // called after the user has selected another tab.
21085                                         // Pass the anchor that initiated this request allows
21086                                         // loadError to manipulate the tab content panel via $(a.hash)
21087                                         o.ajaxOptions.error( xhr, s, index, a );
21088                                 }
21089                                 catch ( e ) {}
21090                         }
21091                 } ) );
21092
21093                 // last, so that load event is fired before show...
21094                 self.element.dequeue( "tabs" );
21095
21096                 return this;
21097         },
21098
21099         abort: function() {
21100                 // stop possibly running animations
21101                 this.element.queue( [] );
21102                 this.panels.stop( false, true );
21103
21104                 // "tabs" queue must not contain more than two elements,
21105                 // which are the callbacks for the latest clicked tab...
21106                 this.element.queue( "tabs", this.element.queue( "tabs" ).splice( -2, 2 ) );
21107
21108                 // terminate pending requests from other tabs
21109                 if ( this.xhr ) {
21110                         this.xhr.abort();
21111                         delete this.xhr;
21112                 }
21113
21114                 // take care of tab labels
21115                 this._cleanup();
21116                 return this;
21117         },
21118
21119         url: function( index, url ) {
21120                 this.anchors.eq( index ).removeData( "cache.tabs" ).data( "load.tabs", url );
21121                 return this;
21122         },
21123
21124         length: function() {
21125                 return this.anchors.length;
21126         }
21127 });
21128
21129 $.extend( $.ui.tabs, {
21130         version: "1.8.12"
21131 });
21132
21133 /*
21134  * Tabs Extensions
21135  */
21136
21137 /*
21138  * Rotate
21139  */
21140 $.extend( $.ui.tabs.prototype, {
21141         rotation: null,
21142         rotate: function( ms, continuing ) {
21143                 var self = this,
21144                         o = this.options;
21145
21146                 var rotate = self._rotate || ( self._rotate = function( e ) {
21147                         clearTimeout( self.rotation );
21148                         self.rotation = setTimeout(function() {
21149                                 var t = o.selected;
21150                                 self.select( ++t < self.anchors.length ? t : 0 );
21151                         }, ms );
21152                         
21153                         if ( e ) {
21154                                 e.stopPropagation();
21155                         }
21156                 });
21157
21158                 var stop = self._unrotate || ( self._unrotate = !continuing
21159                         ? function(e) {
21160                                 if (e.clientX) { // in case of a true click
21161                                         self.rotate(null);
21162                                 }
21163                         }
21164                         : function( e ) {
21165                                 t = o.selected;
21166                                 rotate();
21167                         });
21168
21169                 // start rotation
21170                 if ( ms ) {
21171                         this.element.bind( "tabsshow", rotate );
21172                         this.anchors.bind( o.event + ".tabs", stop );
21173                         rotate();
21174                 // stop rotation
21175                 } else {
21176                         clearTimeout( self.rotation );
21177                         this.element.unbind( "tabsshow", rotate );
21178                         this.anchors.unbind( o.event + ".tabs", stop );
21179                         delete this._rotate;
21180                         delete this._unrotate;
21181                 }
21182
21183                 return this;
21184         }
21185 });
21186
21187 })( jQuery );
21188 /*
21189  * jQuery Tooltip plugin 1.3
21190  *
21191  * http://bassistance.de/jquery-plugins/jquery-plugin-tooltip/
21192  * http://docs.jquery.com/Plugins/Tooltip
21193  *
21194  * Copyright (c) 2006 - 2008 Jörn Zaefferer
21195  *
21196  * $Id: jquery.tooltip.js 5741 2008-06-21 15:22:16Z joern.zaefferer $
21197  * 
21198  * Dual licensed under the MIT and GPL licenses:
21199  *   http://www.opensource.org/licenses/mit-license.php
21200  *   http://www.gnu.org/licenses/gpl.html
21201  */
21202  
21203 ;(function($) {
21204         
21205                 // the tooltip element
21206         var helper = {},
21207                 // the current tooltipped element
21208                 current,
21209                 // the title of the current element, used for restoring
21210                 title,
21211                 // timeout id for delayed tooltips
21212                 tID,
21213                 // IE 5.5 or 6
21214                 IE = $.browser.msie && /MSIE\s(5\.5|6\.)/.test(navigator.userAgent),
21215                 // flag for mouse tracking
21216                 track = false;
21217         
21218         $.tooltip = {
21219                 blocked: false,
21220                 defaults: {
21221                         delay: 200,
21222                         fade: false,
21223                         showURL: true,
21224                         extraClass: "",
21225                         top: 15,
21226                         left: 15,
21227                         id: "tooltip"
21228                 },
21229                 block: function() {
21230                         $.tooltip.blocked = !$.tooltip.blocked;
21231                 }
21232         };
21233         
21234         $.fn.extend({
21235                 tooltip: function(settings) {
21236                         settings = $.extend({}, $.tooltip.defaults, settings);
21237                         createHelper(settings);
21238                         return this.each(function() {
21239                                         $.data(this, "tooltip", settings);
21240                                         this.tOpacity = helper.parent.css("opacity");
21241                                         // copy tooltip into its own expando and remove the title
21242                                         this.tooltipText = this.title;
21243                                         $(this).removeAttr("title");
21244                                         // also remove alt attribute to prevent default tooltip in IE
21245                                         this.alt = "";
21246                                 })
21247                                 .mouseover(save)
21248                                 .mouseout(hide)
21249                                 .click(hide);
21250                 },
21251                 fixPNG: IE ? function() {
21252                         return this.each(function () {
21253                                 var image = $(this).css('backgroundImage');
21254                                 if (image.match(/^url\(["']?(.*\.png)["']?\)$/i)) {
21255                                         image = RegExp.$1;
21256                                         $(this).css({
21257                                                 'backgroundImage': 'none',
21258                                                 'filter': "progid:DXImageTransform.Microsoft.AlphaImageLoader(enabled=true, sizingMethod=crop, src='" + image + "')"
21259                                         }).each(function () {
21260                                                 var position = $(this).css('position');
21261                                                 if (position != 'absolute' && position != 'relative')
21262                                                         $(this).css('position', 'relative');
21263                                         });
21264                                 }
21265                         });
21266                 } : function() { return this; },
21267                 unfixPNG: IE ? function() {
21268                         return this.each(function () {
21269                                 $(this).css({'filter': '', backgroundImage: ''});
21270                         });
21271                 } : function() { return this; },
21272                 hideWhenEmpty: function() {
21273                         return this.each(function() {
21274                                 $(this)[ $(this).html() ? "show" : "hide" ]();
21275                         });
21276                 },
21277                 url: function() {
21278                         return this.attr('href') || this.attr('src');
21279                 }
21280         });
21281         
21282         function createHelper(settings) {
21283                 // there can be only one tooltip helper
21284                 if( helper.parent )
21285                         return;
21286                 // create the helper, h3 for title, div for url
21287                 helper.parent = $('<div id="' + settings.id + '"><h3></h3><div class="body"></div><div class="url"></div></div>')
21288                         // add to document
21289                         .appendTo(document.body)
21290                         // hide it at first
21291                         .hide();
21292                         
21293                 // apply bgiframe if available
21294                 if ( $.fn.bgiframe )
21295                         helper.parent.bgiframe();
21296                 
21297                 // save references to title and url elements
21298                 helper.title = $('h3', helper.parent);
21299                 helper.body = $('div.body', helper.parent);
21300                 helper.url = $('div.url', helper.parent);
21301         }
21302         
21303         function settings(element) {
21304                 return $.data(element, "tooltip");
21305         }
21306         
21307         // main event handler to start showing tooltips
21308         function handle(event) {
21309                 // show helper, either with timeout or on instant
21310                 if( settings(this).delay )
21311                         tID = setTimeout(show, settings(this).delay);
21312                 else
21313                         show();
21314                 
21315                 // if selected, update the helper position when the mouse moves
21316                 track = !!settings(this).track;
21317                 $(document.body).bind('mousemove', update);
21318                         
21319                 // update at least once
21320                 update(event);
21321         }
21322         
21323         // save elements title before the tooltip is displayed
21324         function save() {
21325                 // if this is the current source, or it has no title (occurs with click event), stop
21326                 if ( $.tooltip.blocked || this == current || (!this.tooltipText && !settings(this).bodyHandler) )
21327                         return;
21328
21329                 // save current
21330                 current = this;
21331                 title = this.tooltipText;
21332                 
21333                 if ( settings(this).bodyHandler ) {
21334                         helper.title.hide();
21335                         var bodyContent = settings(this).bodyHandler.call(this);
21336                         if (bodyContent.nodeType || bodyContent.jquery) {
21337                                 helper.body.empty().append(bodyContent)
21338                         } else {
21339                                 helper.body.html( bodyContent );
21340                         }
21341                         helper.body.show();
21342                 } else if ( settings(this).showBody ) {
21343                         var parts = title.split(settings(this).showBody);
21344                         helper.title.html(parts.shift()).show();
21345                         helper.body.empty();
21346                         for(var i = 0, part; (part = parts[i]); i++) {
21347                                 if(i > 0)
21348                                         helper.body.append("<br/>");
21349                                 helper.body.append(part);
21350                         }
21351                         helper.body.hideWhenEmpty();
21352                 } else {
21353                         helper.title.html(title).show();
21354                         helper.body.hide();
21355                 }
21356                 
21357                 // if element has href or src, add and show it, otherwise hide it
21358                 if( settings(this).showURL && $(this).url() )
21359                         helper.url.html( $(this).url().replace('http://', '') ).show();
21360                 else 
21361                         helper.url.hide();
21362                 
21363                 // add an optional class for this tip
21364                 helper.parent.addClass(settings(this).extraClass);
21365
21366                 // fix PNG background for IE
21367                 if (settings(this).fixPNG )
21368                         helper.parent.fixPNG();
21369                         
21370                 handle.apply(this, arguments);
21371         }
21372         
21373         // delete timeout and show helper
21374         function show() {
21375                 tID = null;
21376                 if ((!IE || !$.fn.bgiframe) && settings(current).fade) {
21377                         if (helper.parent.is(":animated"))
21378                                 helper.parent.stop().show().fadeTo(settings(current).fade, current.tOpacity);
21379                         else
21380                                 helper.parent.is(':visible') ? helper.parent.fadeTo(settings(current).fade, current.tOpacity) : helper.parent.fadeIn(settings(current).fade);
21381                 } else {
21382                         helper.parent.show();
21383                 }
21384                 update();
21385         }
21386         
21387         /**
21388          * callback for mousemove
21389          * updates the helper position
21390          * removes itself when no current element
21391          */
21392         function update(event)  {
21393                 if($.tooltip.blocked)
21394                         return;
21395                 
21396                 if (event && event.target.tagName == "OPTION") {
21397                         return;
21398                 }
21399                 
21400                 // stop updating when tracking is disabled and the tooltip is visible
21401                 if ( !track && helper.parent.is(":visible")) {
21402                         $(document.body).unbind('mousemove', update)
21403                 }
21404                 
21405                 // if no current element is available, remove this listener
21406                 if( current == null ) {
21407                         $(document.body).unbind('mousemove', update);
21408                         return; 
21409                 }
21410                 
21411                 // remove position helper classes
21412                 helper.parent.removeClass("viewport-right").removeClass("viewport-bottom");
21413                 
21414                 var left = helper.parent[0].offsetLeft;
21415                 var top = helper.parent[0].offsetTop;
21416                 if (event) {
21417                         // position the helper 15 pixel to bottom right, starting from mouse position
21418                         left = event.pageX + settings(current).left;
21419                         top = event.pageY + settings(current).top;
21420                         var right='auto';
21421                         if (settings(current).positionLeft) {
21422                                 right = $(window).width() - left;
21423                                 left = 'auto';
21424                         }
21425                         helper.parent.css({
21426                                 left: left,
21427                                 right: right,
21428                                 top: top
21429                         });
21430                 }
21431                 
21432                 var v = viewport(),
21433                         h = helper.parent[0];
21434                 // check horizontal position
21435                 if (v.x + v.cx < h.offsetLeft + h.offsetWidth) {
21436                         left -= h.offsetWidth + 20 + settings(current).left;
21437                         helper.parent.css({left: left + 'px'}).addClass("viewport-right");
21438                 }
21439                 // check vertical position
21440                 if (v.y + v.cy < h.offsetTop + h.offsetHeight) {
21441                         top -= h.offsetHeight + 20 + settings(current).top;
21442                         helper.parent.css({top: top + 'px'}).addClass("viewport-bottom");
21443                 }
21444         }
21445         
21446         function viewport() {
21447                 return {
21448                         x: $(window).scrollLeft(),
21449                         y: $(window).scrollTop(),
21450                         cx: $(window).width(),
21451                         cy: $(window).height()
21452                 };
21453         }
21454         
21455         // hide helper and restore added classes and the title
21456         function hide(event) {
21457                 if($.tooltip.blocked)
21458                         return;
21459                 // clear timeout if possible
21460                 if(tID)
21461                         clearTimeout(tID);
21462                 // no more current element
21463                 current = null;
21464                 
21465                 var tsettings = settings(this);
21466                 function complete() {
21467                         helper.parent.removeClass( tsettings.extraClass ).hide().css("opacity", "");
21468                 }
21469                 if ((!IE || !$.fn.bgiframe) && tsettings.fade) {
21470                         if (helper.parent.is(':animated'))
21471                                 helper.parent.stop().fadeTo(tsettings.fade, 0, complete);
21472                         else
21473                                 helper.parent.stop().fadeOut(tsettings.fade, complete);
21474                 } else
21475                         complete();
21476                 
21477                 if( settings(this).fixPNG )
21478                         helper.parent.unfixPNG();
21479         }
21480         
21481 })(jQuery);
21482 /*!
21483 Math.uuid.js (v1.4)
21484 http://www.broofa.com
21485 mailto:robert@broofa.com
21486
21487 Copyright (c) 2010 Robert Kieffer
21488 Dual licensed under the MIT and GPL licenses.
21489 */
21490
21491 /*
21492  * Generate a random uuid.
21493  *
21494  * USAGE: Math.uuid(length, radix)
21495  *   length - the desired number of characters
21496  *   radix  - the number of allowable values for each character.
21497  *
21498  * EXAMPLES:
21499  *   // No arguments  - returns RFC4122, version 4 ID
21500  *   >>> Math.uuid()
21501  *   "92329D39-6F5C-4520-ABFC-AAB64544E172"
21502  *
21503  *   // One argument - returns ID of the specified length
21504  *   >>> Math.uuid(15)     // 15 character ID (default base=62)
21505  *   "VcydxgltxrVZSTV"
21506  *
21507  *   // Two arguments - returns ID of the specified length, and radix. (Radix must be <= 62)
21508  *   >>> Math.uuid(8, 2)  // 8 character ID (base=2)
21509  *   "01001010"
21510  *   >>> Math.uuid(8, 10) // 8 character ID (base=10)
21511  *   "47473046"
21512  *   >>> Math.uuid(8, 16) // 8 character ID (base=16)
21513  *   "098F4D35"
21514  */
21515 (function() {
21516   // Private array of chars to use
21517   var CHARS = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'.split('');
21518
21519   Math.uuid = function (len, radix) {
21520     var chars = CHARS, uuid = [], i;
21521     radix = radix || chars.length;
21522
21523     if (len) {
21524       // Compact form
21525       for (i = 0; i < len; i++) uuid[i] = chars[0 | Math.random()*radix];
21526     } else {
21527       // rfc4122, version 4 form
21528       var r;
21529
21530       // rfc4122 requires these characters
21531       uuid[8] = uuid[13] = uuid[18] = uuid[23] = '-';
21532       uuid[14] = '4';
21533
21534       // Fill in random data.  At i==19 set the high bits of clock sequence as
21535       // per rfc4122, sec. 4.1.5
21536       for (i = 0; i < 36; i++) {
21537         if (!uuid[i]) {
21538           r = 0 | Math.random()*16;
21539           uuid[i] = chars[(i == 19) ? (r & 0x3) | 0x8 : r];
21540         }
21541       }
21542     }
21543
21544     return uuid.join('');
21545   };
21546
21547   // A more performant, but slightly bulkier, RFC4122v4 solution.  We boost performance
21548   // by minimizing calls to random()
21549   Math.uuidFast = function() {
21550     var chars = CHARS, uuid = new Array(36), rnd=0, r;
21551     for (var i = 0; i < 36; i++) {
21552       if (i==8 || i==13 ||  i==18 || i==23) {
21553         uuid[i] = '-';
21554       } else if (i==14) {
21555         uuid[i] = '4';
21556       } else {
21557         if (rnd <= 0x02) rnd = 0x2000000 + (Math.random()*0x1000000)|0;
21558         r = rnd & 0xf;
21559         rnd = rnd >> 4;
21560         uuid[i] = chars[(i == 19) ? (r & 0x3) | 0x8 : r];
21561       }
21562     }
21563     return uuid.join('');
21564   };
21565
21566   // A more compact, but less performant, RFC4122v4 solution:
21567   Math.uuidCompact = function() {
21568     return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
21569       var r = Math.random()*16|0, v = c == 'x' ? r : (r&0x3|0x8);
21570       return v.toString(16);
21571     });
21572   };
21573 })();
21574 // jXHR.js (JSON-P XHR)\r
21575 // v0.1 (c) Kyle Simpson\r
21576 // MIT License\r
21577 \r
21578 (function(global){\r
21579         var SETTIMEOUT = global.setTimeout, // for better compression\r
21580                 doc = global.document,\r
21581                 callback_counter = 0;\r
21582                 \r
21583         global.jXHR = function() {\r
21584                 var script_url,\r
21585                         script_loaded,\r
21586                         jsonp_callback,\r
21587                         scriptElem,\r
21588                         publicAPI = null;\r
21589                         \r
21590                 function removeScript() { try { scriptElem.parentNode.removeChild(scriptElem); } catch (err) { } }\r
21591                         \r
21592                 function reset() {\r
21593                         script_loaded = false;\r
21594                         script_url = "";\r
21595                         removeScript();\r
21596                         scriptElem = null;\r
21597                         fireReadyStateChange(0);\r
21598                 }\r
21599                 \r
21600                 function ThrowError(msg) {\r
21601                         try { publicAPI.onerror.call(publicAPI,msg,script_url); } catch (err) { throw new Error(msg); }\r
21602                 }\r
21603 \r
21604                 function handleScriptLoad() {\r
21605                         if ((this.readyState && this.readyState!=="complete" && this.readyState!=="loaded") || script_loaded) { return; }\r
21606                         this.onload = this.onreadystatechange = null; // prevent memory leak\r
21607                         script_loaded = true;\r
21608                         if (publicAPI.readyState !== 4) ThrowError("Script failed to load ["+script_url+"].");\r
21609                         removeScript();\r
21610                 }\r
21611                 \r
21612                 function fireReadyStateChange(rs,args) {\r
21613                         args = args || [];\r
21614                         publicAPI.readyState = rs;\r
21615                         if (typeof publicAPI.onreadystatechange === "function") publicAPI.onreadystatechange.apply(publicAPI,args);\r
21616                 }\r
21617                                 \r
21618                 publicAPI = {\r
21619                         onerror:null,\r
21620                         onreadystatechange:null,\r
21621                         readyState:0,\r
21622                         open:function(method,url){\r
21623                                 reset();\r
21624                                 internal_callback = "cb"+(callback_counter++);\r
21625                                 (function(icb){\r
21626                                         global.jXHR[icb] = function() {\r
21627                                                 try { fireReadyStateChange.call(publicAPI,4,arguments); } \r
21628                                                 catch(err) { \r
21629                                                         publicAPI.readyState = -1;\r
21630                                                         ThrowError("Script failed to run ["+script_url+"]."); \r
21631                                                 }\r
21632                                                 global.jXHR[icb] = null;\r
21633                                         };\r
21634                                 })(internal_callback);\r
21635                                 script_url = url.replace(/=\?/,"=jXHR."+internal_callback);\r
21636                                 fireReadyStateChange(1);\r
21637                         },\r
21638                         send:function(){\r
21639                                 SETTIMEOUT(function(){\r
21640                                         scriptElem = doc.createElement("script");\r
21641                                         scriptElem.setAttribute("type","text/javascript");\r
21642                                         scriptElem.onload = scriptElem.onreadystatechange = function(){handleScriptLoad.call(scriptElem);};\r
21643                                         scriptElem.setAttribute("src",script_url);\r
21644                                         doc.getElementsByTagName("head")[0].appendChild(scriptElem);\r
21645                                 },0);\r
21646                                 fireReadyStateChange(2);\r
21647                         },\r
21648                         setRequestHeader:function(){}, // noop\r
21649                         getResponseHeader:function(){return "";}, // basically noop\r
21650                         getAllResponseHeaders:function(){return [];} // ditto\r
21651                 };\r
21652 \r
21653                 reset();\r
21654                 \r
21655                 return publicAPI;\r
21656         };\r
21657 })(window);//////////////////////////////////////////////////////////////////////////////
21658 //                                                                          //
21659 // Wii Opera SDK - 3D Math Class v2.7.22 2008-12-14                         //
21660 // (c) 2007-2008 Daniel Gump. All Rights Reserved.                          //
21661 // http://wiioperasdk.com, http://hullbreachonline.com                      //
21662 // hullbreach@hullbreachonline.com                                          //
21663 //                                                                          //
21664 //  Wii is a trademark of Nintendo Co., Ltd.                                //
21665 //  Opera is a trademark of Opera, ASA.                                     //
21666 //  This software package is not associated with either company             //
21667 //  but was created to support users of both.  Its alternative name         //
21668 //  when supporting other products is the HULLBREACH SDK.                   //
21669 //                                                                          //
21670 //  Redistribution and use in source and binary forms, with or without      //
21671 //  modification, are permitted provided that the following conditions      //
21672 //  are met:                                                                //
21673 //    * Redistributions of source code must retain the above copyright      //
21674 //      notice, this list of conditions and the following disclaimer.       //
21675 //    * Redistributions in binary form must reproduce the above copyright   //
21676 //      notice, this list of conditions and the following disclaimer in     //
21677 //      the documentation and/or other materials provided with the          //
21678 //      distribution.                                                       //
21679 //    * Neither the names HULLBREACH ONLINE nor WII OPERA SDK nor the names //
21680 //      of its contributors may be used to endorse or promote products      //
21681 //      derived from this software without specific prior written           //
21682 //      permission.                                                         //
21683 //    * If the explicit purpose of the software is not to support the       //
21684 //      Nintendo Wii or the Opera Web browser, then the names of such must  //
21685 //      not be used in any derived product. The name shall be the           //
21686 //      HULLBREACH SDK with a reference link to http://hullbreachonline.    //
21687 //                                                                          //
21688 //  THIS SOFTWARE IS PROVIDED BY Daniel Gump ''AS IS'' AND ANY EXPRESS OR   //
21689 //  IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED          //
21690 //  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE  //
21691 //  DISCLAIMED. IN NO EVENT SHALL Daniel Gump BE LIABLE FOR ANY DIRECT,     //
21692 //  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES      //
21693 //  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR      //
21694 //  SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)      //
21695 //  HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,     //
21696 //  STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING   //
21697 //  IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE      //
21698 //  POSSIBILITY OF SUCH DAMAGE.                                             //
21699 //////////////////////////////////////////////////////////////////////////////
21700
21701 function ThreeD(){
21702         POLYMESH = new Array();
21703
21704         CENTERX = 400; CENTERY = 240;
21705         LIGHTX = -1000; LIGHTY = -1000; LIGHTZ = -1000;
21706         ORIGINX = 0; ORIGINY = 0; ORIGINZ = 0;
21707         ANGLEX = 0; ANGLEY = 0; ANGLEZ = 0;
21708 }
21709
21710 ThreeD.prototype.setPoints = function(Points){
21711         POLYMESH = [];
21712         for(var value=Points.length;--value>=0;) POLYMESH[value] = Points[value].slice();
21713 }
21714 ThreeD.prototype.loadMesh = function(array){
21715         if(POLYMESH = array.split(";")) for(i=POLYMESH.length;--i>=0;) POLYMESH[i] = POLYMESH[i].split(",");
21716 }
21717 ThreeD.prototype.getPoints = function(){ return POLYMESH; }
21718
21719 ThreeD.prototype.setCenter = function(x,y){ CENTERX = x|0; CENTERY = y|0; }
21720 ThreeD.prototype.setLight = function(x,y,z){ LIGHTX = x|0; LIGHTY = y|0; LIGHTZ = z|0; }
21721
21722 ThreeD.prototype.explode = function(z){
21723         var x1, y1, z1, x2, y2, z2;
21724         var normali, normalj, normalk, magNormal;
21725
21726         for(var value=POLYMESH.length;--value>=0;){
21727                 x1 = POLYMESH[value][3]-POLYMESH[value][0]; y1 = POLYMESH[value][4]-POLYMESH[value][1]; z1 = POLYMESH[value][5]-POLYMESH[value][2]; 
21728                 x2 = POLYMESH[value][6]-POLYMESH[value][0]; y2 = POLYMESH[value][7]-POLYMESH[value][1]; z2 = POLYMESH[value][8]-POLYMESH[value][2]; 
21729
21730                 normali = y2*z1-y1*z2; normalj = x1*z2-x2*z1; normalk = x2*y1-x1*y2;
21731                 magNormal = z/Math.sqrt(normali*normali+normalj*normalj+normalk*normalk);
21732
21733                 var movex = -normali*magNormal|0;
21734                 var movey = -normalj*magNormal|0;
21735                 var movez = -normalk*magNormal|0;
21736
21737                 POLYMESH[value][0] += movex; POLYMESH[value][1] += movey; POLYMESH[value][2] += movez;
21738                 POLYMESH[value][3] += movex; POLYMESH[value][4] += movey; POLYMESH[value][5] += movez;
21739                 POLYMESH[value][6] += movex; POLYMESH[value][7] += movey; POLYMESH[value][8] += movez;
21740         }
21741 }
21742 ThreeD.prototype.normalMap = function(normalMap){
21743         var x1, y1, z1, x2, y2, z2;
21744         var normali, normalj, normalk, magNormal;
21745
21746         for(var value=POLYMESH.length;--value>=0;){
21747                 x1 = POLYMESH[value][3]-POLYMESH[value][0]; y1 = POLYMESH[value][4]-POLYMESH[value][1]; z1 = POLYMESH[value][5]-POLYMESH[value][2]; 
21748                 x2 = POLYMESH[value][6]-POLYMESH[value][0]; y2 = POLYMESH[value][7]-POLYMESH[value][1]; z2 = POLYMESH[value][8]-POLYMESH[value][2]; 
21749
21750                 normali = y2*z1-y1*z2; normalj = x1*z2-x2*z1; normalk = x2*y1-x1*y2;
21751                 normal = 1/Math.sqrt(normali*normali+normalj*normalj+normalk*normalk);
21752                 
21753                 for(index2=0; index2<4; index2++){
21754                         for(index=0; index<=index2; index++){
21755                                 magNormal = normalMap[index][index2]*normal|0;
21756
21757                                 var movex = -normali*magNormal;
21758                                 var movey = -normalj*magNormal;
21759                                 var movez = -normalk*magNormal;
21760                                 
21761                                 POLYMESH[POLYMESH.length] = new Array(POLYMESH[value][0]+movex,POLYMESH[value][1]+movey,POLYMESH[value][2]+movez,
21762                                                         POLYMESH[value][3]+movex,POLYMESH[value][4]+movey,POLYMESH[value][7]+movez,
21763                                                         POLYMESH[value][6]+movex,POLYMESH[value][7]+movey,POLYMESH[value][8]+movez,
21764                                                         POLYMESH[value][9],POLYMESH[value][10],POLYMESH[value][11],
21765                                                         POLYMESH[value][12],POLYMESH[value][13], true, index, index2);
21766                         }
21767                 }
21768         }
21769 }
21770 ThreeD.prototype.move = function(x,y,z){
21771         for(var value=POLYMESH.length;--value>=0;)
21772                 for(var point=-1;++point<3;){
21773                         POLYMESH[value][point*3+2] += z;
21774                         POLYMESH[value][point*3+1] += y;
21775                         POLYMESH[value][point*3] += x;
21776                 }
21777 }
21778 ThreeD.prototype.rotate = function(anglex,angley,anglez){
21779         var cosx = Math.cos(anglex*0.01745329); var sinx = Math.sin(anglex*0.01745329);
21780         var cosy = Math.cos(angley*0.01745329); var siny = Math.sin(angley*0.01745329);
21781         var cosz = Math.cos(anglez*0.01745329); var sinz = Math.sin(anglez*0.01745329);
21782
21783         for(var value=POLYMESH.length;--value>=0;)
21784                 for(var point=-1;++point<3;){
21785                         var tempz = sinx*POLYMESH[value][point*3+1]+cosx*POLYMESH[value][point*3+2];
21786                         var tempy = cosx*POLYMESH[value][point*3+1]-sinx*POLYMESH[value][point*3+2];
21787                         var tempx = cosy*POLYMESH[value][point*3]+siny*tempz;
21788                         POLYMESH[value][point*3+2] = cosy*tempz-siny*POLYMESH[value][point*3];
21789                         POLYMESH[value][point*3+1] = sinz*tempx+cosz*tempy;
21790                         POLYMESH[value][point*3] = cosz*tempx-sinz*tempy;
21791                 }
21792 }
21793 ThreeD.prototype.scale = function(scalex,scaley,scalez){
21794         for(var value=POLYMESH.length;--value>=0;)
21795                 for(var point=-1;++point<3;){
21796                         POLYMESH[value][point*3+2] *= scalex;
21797                         POLYMESH[value][point*3+1] *= scaley;
21798                         POLYMESH[value][point*3] *= scalez;
21799                 }
21800 }
21801
21802 ThreeD.prototype.backface = function(){
21803         for(var value=POLYMESH.length, newvalue=0, TempPOLYMESH = [];--value>=0;)
21804                 if((POLYMESH[value][3]-POLYMESH[value][0])*(POLYMESH[value][7]-POLYMESH[value][1])-(POLYMESH[value][6]-POLYMESH[value][0])*(POLYMESH[value][4]-POLYMESH[value][1])>0){
21805                         TempPOLYMESH[newvalue++] = POLYMESH[value].slice();
21806                 }
21807         POLYMESH = TempPOLYMESH;
21808 }
21809 ThreeD.prototype.zSort = function(){ POLYMESH.sort(function(b,a){return b[2]+b[5]+b[8]-a[2]-a[5]-a[8]}); }
21810
21811 ThreeD.prototype.fade = function(bright){
21812         for(var value=POLYMESH.length;--value>=0;) POLYMESH[value][13] += bright;
21813 }
21814 ThreeD.prototype.shade = function(){
21815         var x1, y1, z1, x2, y2, z2;
21816         var normali, normalj, normalk, magNormal;
21817         var lighti, lightj, lightk, magLight;
21818
21819         for(var value=POLYMESH.length;--value>=0;){
21820                 x1 = POLYMESH[value][3]-POLYMESH[value][0]; y1 = POLYMESH[value][4]-POLYMESH[value][1]; z1 = POLYMESH[value][5]-POLYMESH[value][2]; 
21821                 x2 = POLYMESH[value][6]-POLYMESH[value][0]; y2 = POLYMESH[value][7]-POLYMESH[value][1]; z2 = POLYMESH[value][8]-POLYMESH[value][2]; 
21822
21823                 normali = y1*z2-y2*z1; normalj = x2*z1-x1*z2; normalk = x1*y2-x2*y1;
21824
21825                 lighti = LIGHTX-(POLYMESH[value][0]+POLYMESH[value][3]+POLYMESH[value][6])*0.33333333333333333;
21826                 lightj = LIGHTY-(POLYMESH[value][1]+POLYMESH[value][4]+POLYMESH[value][7])*0.33333333333333333;
21827                 lightk = LIGHTZ-(POLYMESH[value][2]+POLYMESH[value][5]+POLYMESH[value][8])*0.33333333333333333;
21828
21829                 POLYMESH[value][13] = 2*(normali*lighti + normalj*lightj + normalk*lightk)/Math.sqrt((normali*normali+normalj*normalj+normalk*normalk)*(lighti*lighti+lightj*lightj+lightk*lightk))-1;
21830         }
21831 }
21832 ThreeD.prototype.reColor = function(r,g,b){
21833         r=r>255?255:(r<0?0:r|0);
21834         g=g>255?255:(g<0?0:g|0);
21835         b=b>255?255:(b<0?0:b|0);
21836         for(var value=POLYMESH.length;--value>=0;){
21837                 POLYMESH[value][9]=r;
21838                 POLYMESH[value][10]=g;
21839                 POLYMESH[value][11]=b;
21840         }
21841 }
21842 ThreeD.prototype.shadow = function(){
21843         rayorigins = []; 
21844         raynormals = [];
21845         edge1 = [];
21846         edge2 = [];
21847
21848         for(var value=0, normali, normalj, normalk, magNormal;value<POLYMESH.length;value++){
21849                 edge1[value] = new Array(POLYMESH[value][3]-POLYMESH[value][0], POLYMESH[value][4]-POLYMESH[value][1], POLYMESH[value][5]-POLYMESH[value][2]);
21850                 edge2[value] = new Array(POLYMESH[value][6]-POLYMESH[value][0], POLYMESH[value][7]-POLYMESH[value][1], POLYMESH[value][8]-POLYMESH[value][2]);
21851
21852                 rayorigins[value] = new Array((POLYMESH[value][0]+POLYMESH[value][3]+POLYMESH[value][6])*0.33333333333333333, (POLYMESH[value][1]+POLYMESH[value][4]+POLYMESH[value][7])*0.33333333333333333, (POLYMESH[value][2]+POLYMESH[value][5]+POLYMESH[value][8])*0.33333333333333333);
21853
21854                 normali = LIGHTX-rayorigins[value][0];
21855                 normalj = LIGHTY-rayorigins[value][1];
21856                 normalk = LIGHTZ-rayorigins[value][2];
21857                 magNormal = 1/Math.sqrt(normali*normali+normalj*normalj+normalk*normalk);
21858                 raynormals[value] = new Array(normali*magNormal, normalj*magNormal, normalk*magNormal);
21859         }
21860
21861         for(var value=POLYMESH.length;--value>=0;){
21862                 for(var value2=POLYMESH.length;--value2>=0;){
21863                         if(value2!=value){
21864                                 var pvecti = raynormals[value][1]*edge2[value2][2]-edge2[value2][1]*raynormals[value][2];
21865                                 var pvectj = edge2[value2][0]*raynormals[value][2]-raynormals[value][0]*edge2[value2][2];
21866                                 var pvectk = raynormals[value][0]*edge2[value2][1]-edge2[value2][0]*raynormals[value][1];
21867
21868                                 if((det = edge1[value2][0]*pvecti+edge1[value2][1]*pvectj+edge1[value2][2]*pvectk)<0){
21869                                         det=1/det;
21870
21871                                         var tvecti = rayorigins[value][0]-POLYMESH[value2][0];
21872                                         var tvectj = rayorigins[value][1]-POLYMESH[value2][1];
21873                                         var tvectk = rayorigins[value][2]-POLYMESH[value2][2];
21874
21875                                         if((u = (pvecti*tvecti+pvectj*tvectj+pvectk*tvectk) * det)>=0 && u<=1){
21876                                                 if((v = (raynormals[value][0]*(tvectj*edge1[value2][2]-edge1[value2][1]*tvectk)+raynormals[value][1]*(edge1[value2][0]*tvectk-tvecti*edge1[value2][2])+raynormals[value][2]*(tvecti*edge1[value2][1]-edge1[value2][0]*tvectj)) * det)>=0 && u+v<=1){
21877                                                         POLYMESH[value][13] -=.5;
21878                                                         break;
21879                                                 }
21880                                         }
21881                                 }
21882                                 
21883                         }
21884                 }
21885         }
21886 }
21887
21888 ThreeD.prototype.getTranslation = function(){
21889         for(var value=POLYMESH.length,newvalue=0,TransPOLYMESH = [];--value>=0;){
21890                 var POLYMESH2=5000/(5000-POLYMESH[value][2]), POLYMESH5=5000/(5000-POLYMESH[value][5]), POLYMESH8=5000/(5000-POLYMESH[value][8]);
21891                 TransPOLYMESH[newvalue++] = new Array((CENTERX+POLYMESH[value][0]*POLYMESH2),(CENTERY+POLYMESH[value][1]*POLYMESH2),
21892                                                                         (CENTERX+POLYMESH[value][3]*POLYMESH5),(CENTERY+POLYMESH[value][4]*POLYMESH5),
21893                                                                         (CENTERX+POLYMESH[value][6]*POLYMESH8),(CENTERY+POLYMESH[value][7]*POLYMESH8),
21894                                                                         POLYMESH[value][9]|0,POLYMESH[value][10]|0,POLYMESH[value][11]|0,POLYMESH[value][12]|0,POLYMESH[value][13]);
21895         }
21896         return TransPOLYMESH;
21897 }
21898
21899 ThreeDee = new ThreeD();/**
21900  * @author mrdoob / http://mrdoob.com/
21901  */
21902
21903 var THREE = THREE || { REVISION: '51' };
21904
21905 if ( self.console === undefined ) {
21906
21907     self.console = {
21908
21909         info: function () {},
21910         log: function () {},
21911         debug: function () {},
21912         warn: function () {},
21913         error: function () {}
21914
21915     };
21916
21917 }
21918
21919 if ( self.Int32Array === undefined ) {
21920
21921     self.Int32Array = Array;
21922     self.Float32Array = Array;
21923
21924 }
21925
21926 // Shims for "startsWith", "endsWith", and "trim" for browsers where this is not yet implemented
21927 // not sure we should have this, or at least not have it here
21928
21929 // http://stackoverflow.com/questions/646628/javascript-startswith
21930 // http://stackoverflow.com/questions/498970/how-do-i-trim-a-string-in-javascript
21931 // http://wiki.ecmascript.org/doku.php?id=harmony%3astring_extras
21932
21933 if ( String.prototype.startsWith === undefined ) {
21934
21935     String.prototype.startsWith = function ( str ) {
21936
21937         return this.slice( 0, str.length ) === str;
21938
21939     };
21940
21941 }
21942
21943 if ( String.prototype.endsWith === undefined ) {
21944
21945     String.prototype.endsWith = function ( str ) {
21946
21947         var t = String( str );
21948         var index = this.lastIndexOf( t );
21949         return index >= 0 && index === this.length - t.length;
21950
21951     };
21952
21953 }
21954
21955 if ( ! String.prototype.trim === undefined ) {
21956
21957     String.prototype.trim = function () {
21958
21959         return this.replace( /^\s+|\s+$/g, '' );
21960
21961     };
21962
21963 }
21964
21965 // http://paulirish.com/2011/requestanimationframe-for-smart-animating/
21966 // http://my.opera.com/emoller/blog/2011/12/20/requestanimationframe-for-smart-er-animating
21967
21968 // requestAnimationFrame polyfill by Erik Möller
21969 // fixes from Paul Irish and Tino Zijdel
21970
21971 ( function () {
21972
21973     var lastTime = 0;
21974     var vendors = [ 'ms', 'moz', 'webkit', 'o' ];
21975
21976     for ( var x = 0; x < vendors.length && !window.requestAnimationFrame; ++ x ) {
21977
21978         window.requestAnimationFrame = window[ vendors[ x ] + 'RequestAnimationFrame' ];
21979         window.cancelAnimationFrame = window[ vendors[ x ] + 'CancelAnimationFrame' ] || window[ vendors[ x ] + 'CancelRequestAnimationFrame' ];
21980
21981     }
21982
21983     if ( window.requestAnimationFrame === undefined ) {
21984
21985         window.requestAnimationFrame = function ( callback, element ) {
21986
21987             var currTime = Date.now(), timeToCall = Math.max( 0, 16 - ( currTime - lastTime ) );
21988             var id = window.setTimeout( function() { callback( currTime + timeToCall ); }, timeToCall );
21989             lastTime = currTime + timeToCall;
21990             return id;
21991
21992         };
21993
21994     }
21995
21996
21997     if ( window.cancelAnimationFrame === undefined ) {
21998
21999         window.cancelAnimationFrame = function ( id ) { clearTimeout( id ); };
22000
22001     }
22002
22003 }() );
22004
22005
22006 // MATERIAL CONSTANTS
22007
22008 // side
22009
22010 THREE.FrontSide = 0;
22011 THREE.BackSide = 1;
22012 THREE.DoubleSide = 2;
22013
22014 // shading
22015
22016 THREE.NoShading = 0;
22017 THREE.FlatShading = 1;
22018 THREE.SmoothShading = 2;
22019
22020 // colors
22021
22022 THREE.NoColors = 0;
22023 THREE.FaceColors = 1;
22024 THREE.VertexColors = 2;
22025
22026 // blending modes
22027
22028 THREE.NoBlending = 0;
22029 THREE.NormalBlending = 1;
22030 THREE.AdditiveBlending = 2;
22031 THREE.SubtractiveBlending = 3;
22032 THREE.MultiplyBlending = 4;
22033 THREE.CustomBlending = 5;
22034
22035 // custom blending equations
22036 // (numbers start from 100 not to clash with other
22037 //  mappings to OpenGL constants defined in Texture.js)
22038
22039 THREE.AddEquation = 100;
22040 THREE.SubtractEquation = 101;
22041 THREE.ReverseSubtractEquation = 102;
22042
22043 // custom blending destination factors
22044
22045 THREE.ZeroFactor = 200;
22046 THREE.OneFactor = 201;
22047 THREE.SrcColorFactor = 202;
22048 THREE.OneMinusSrcColorFactor = 203;
22049 THREE.SrcAlphaFactor = 204;
22050 THREE.OneMinusSrcAlphaFactor = 205;
22051 THREE.DstAlphaFactor = 206;
22052 THREE.OneMinusDstAlphaFactor = 207;
22053
22054 // custom blending source factors
22055
22056 //THREE.ZeroFactor = 200;
22057 //THREE.OneFactor = 201;
22058 //THREE.SrcAlphaFactor = 204;
22059 //THREE.OneMinusSrcAlphaFactor = 205;
22060 //THREE.DstAlphaFactor = 206;
22061 //THREE.OneMinusDstAlphaFactor = 207;
22062 THREE.DstColorFactor = 208;
22063 THREE.OneMinusDstColorFactor = 209;
22064 THREE.SrcAlphaSaturateFactor = 210;
22065
22066
22067 // TEXTURE CONSTANTS
22068
22069 THREE.MultiplyOperation = 0;
22070 THREE.MixOperation = 1;
22071
22072 // Mapping modes
22073
22074 THREE.UVMapping = function () {};
22075
22076 THREE.CubeReflectionMapping = function () {};
22077 THREE.CubeRefractionMapping = function () {};
22078
22079 THREE.SphericalReflectionMapping = function () {};
22080 THREE.SphericalRefractionMapping = function () {};
22081
22082 // Wrapping modes
22083
22084 THREE.RepeatWrapping = 1000;
22085 THREE.ClampToEdgeWrapping = 1001;
22086 THREE.MirroredRepeatWrapping = 1002;
22087
22088 // Filters
22089
22090 THREE.NearestFilter = 1003;
22091 THREE.NearestMipMapNearestFilter = 1004;
22092 THREE.NearestMipMapLinearFilter = 1005;
22093 THREE.LinearFilter = 1006;
22094 THREE.LinearMipMapNearestFilter = 1007;
22095 THREE.LinearMipMapLinearFilter = 1008;
22096
22097 // Data types
22098
22099 THREE.UnsignedByteType = 1009;
22100 THREE.ByteType = 1010;
22101 THREE.ShortType = 1011;
22102 THREE.UnsignedShortType = 1012;
22103 THREE.IntType = 1013;
22104 THREE.UnsignedIntType = 1014;
22105 THREE.FloatType = 1015;
22106
22107 // Pixel types
22108
22109 //THREE.UnsignedByteType = 1009;
22110 THREE.UnsignedShort4444Type = 1016;
22111 THREE.UnsignedShort5551Type = 1017;
22112 THREE.UnsignedShort565Type = 1018;
22113
22114 // Pixel formats
22115
22116 THREE.AlphaFormat = 1019;
22117 THREE.RGBFormat = 1020;
22118 THREE.RGBAFormat = 1021;
22119 THREE.LuminanceFormat = 1022;
22120 THREE.LuminanceAlphaFormat = 1023;
22121
22122 // Compressed texture formats
22123
22124 THREE.RGB_S3TC_DXT1_Format = 2001;
22125 THREE.RGBA_S3TC_DXT1_Format = 2002;
22126 THREE.RGBA_S3TC_DXT3_Format = 2003;
22127 THREE.RGBA_S3TC_DXT5_Format = 2004;
22128
22129 /*
22130 // Potential future PVRTC compressed texture formats
22131 THREE.RGB_PVRTC_4BPPV1_Format = 2100;
22132 THREE.RGB_PVRTC_2BPPV1_Format = 2101;
22133 THREE.RGBA_PVRTC_4BPPV1_Format = 2102;
22134 THREE.RGBA_PVRTC_2BPPV1_Format = 2103;
22135 */
22136 /**
22137  * @author alteredq / http://alteredqualia.com/
22138  */
22139
22140 THREE.Clock = function ( autoStart ) {
22141
22142     this.autoStart = ( autoStart !== undefined ) ? autoStart : true;
22143
22144     this.startTime = 0;
22145     this.oldTime = 0;
22146     this.elapsedTime = 0;
22147
22148     this.running = false;
22149
22150 };
22151
22152 THREE.Clock.prototype.start = function () {
22153
22154     this.startTime = Date.now();
22155     this.oldTime = this.startTime;
22156
22157     this.running = true;
22158
22159 };
22160
22161 THREE.Clock.prototype.stop = function () {
22162
22163     this.getElapsedTime();
22164
22165     this.running = false;
22166
22167 };
22168
22169 THREE.Clock.prototype.getElapsedTime = function () {
22170
22171     this.elapsedTime += this.getDelta();
22172
22173     return this.elapsedTime;
22174
22175 };
22176
22177
22178 THREE.Clock.prototype.getDelta = function () {
22179
22180     var diff = 0;
22181
22182     if ( this.autoStart && ! this.running ) {
22183
22184         this.start();
22185
22186     }
22187
22188     if ( this.running ) {
22189
22190         var newTime = Date.now();
22191         diff = 0.001 * ( newTime - this.oldTime );
22192         this.oldTime = newTime;
22193
22194         this.elapsedTime += diff;
22195
22196     }
22197
22198     return diff;
22199
22200 };/**
22201  * @author mrdoob / http://mrdoob.com/
22202  */
22203
22204 THREE.Color = function ( hex ) {
22205
22206     if ( hex !== undefined ) this.setHex( hex );
22207
22208     return this;
22209
22210 };
22211
22212 THREE.Color.prototype = {
22213
22214     constructor: THREE.Color,
22215
22216     r: 1, g: 1, b: 1,
22217
22218     copy: function ( color ) {
22219
22220         this.r = color.r;
22221         this.g = color.g;
22222         this.b = color.b;
22223
22224         return this;
22225
22226     },
22227
22228     copyGammaToLinear: function ( color ) {
22229
22230         this.r = color.r * color.r;
22231         this.g = color.g * color.g;
22232         this.b = color.b * color.b;
22233
22234         return this;
22235
22236     },
22237
22238     copyLinearToGamma: function ( color ) {
22239
22240         this.r = Math.sqrt( color.r );
22241         this.g = Math.sqrt( color.g );
22242         this.b = Math.sqrt( color.b );
22243
22244         return this;
22245
22246     },
22247
22248     convertGammaToLinear: function () {
22249
22250         var r = this.r, g = this.g, b = this.b;
22251
22252         this.r = r * r;
22253         this.g = g * g;
22254         this.b = b * b;
22255
22256         return this;
22257
22258     },
22259
22260     convertLinearToGamma: function () {
22261
22262         this.r = Math.sqrt( this.r );
22263         this.g = Math.sqrt( this.g );
22264         this.b = Math.sqrt( this.b );
22265
22266         return this;
22267
22268     },
22269
22270     setRGB: function ( r, g, b ) {
22271
22272         this.r = r;
22273         this.g = g;
22274         this.b = b;
22275
22276         return this;
22277
22278     },
22279
22280     setHSV: function ( h, s, v ) {
22281
22282         // based on MochiKit implementation by Bob Ippolito
22283         // h,s,v ranges are < 0.0 - 1.0 >
22284
22285         var i, f, p, q, t;
22286
22287         if ( v === 0 ) {
22288
22289             this.r = this.g = this.b = 0;
22290
22291         } else {
22292
22293             i = Math.floor( h * 6 );
22294             f = ( h * 6 ) - i;
22295             p = v * ( 1 - s );
22296             q = v * ( 1 - ( s * f ) );
22297             t = v * ( 1 - ( s * ( 1 - f ) ) );
22298
22299             if ( i === 0 ) {
22300
22301                 this.r = v;
22302                 this.g = t;
22303                 this.b = p;
22304
22305             } else if ( i === 1 ) {
22306
22307                 this.r = q;
22308                 this.g = v;
22309                 this.b = p;
22310
22311             } else if ( i === 2 ) {
22312
22313                 this.r = p;
22314                 this.g = v;
22315                 this.b = t;
22316
22317             } else if ( i === 3 ) {
22318
22319                 this.r = p;
22320                 this.g = q;
22321                 this.b = v;
22322
22323             } else if ( i === 4 ) {
22324
22325                 this.r = t;
22326                 this.g = p;
22327                 this.b = v;
22328
22329             } else if ( i === 5 ) {
22330
22331                 this.r = v;
22332                 this.g = p;
22333                 this.b = q;
22334
22335             }
22336
22337         }
22338
22339         return this;
22340
22341     },
22342
22343     setHex: function ( hex ) {
22344
22345         hex = Math.floor( hex );
22346
22347         this.r = ( hex >> 16 & 255 ) / 255;
22348         this.g = ( hex >> 8 & 255 ) / 255;
22349         this.b = ( hex & 255 ) / 255;
22350
22351         return this;
22352
22353     },
22354
22355     lerpSelf: function ( color, alpha ) {
22356
22357         this.r += ( color.r - this.r ) * alpha;
22358         this.g += ( color.g - this.g ) * alpha;
22359         this.b += ( color.b - this.b ) * alpha;
22360
22361         return this;
22362
22363     },
22364
22365     getHex: function () {
22366
22367         return ( this.r * 255 ) << 16 ^ ( this.g * 255 ) << 8 ^ ( this.b * 255 ) << 0;
22368
22369     },
22370
22371     getContextStyle: function () {
22372
22373         return 'rgb(' + ( ( this.r * 255 ) | 0 )  + ',' + ( ( this.g * 255 ) | 0 ) + ',' + ( ( this.b * 255 ) | 0 ) + ')';
22374
22375     },
22376
22377     clone: function () {
22378
22379         return new THREE.Color().setRGB( this.r, this.g, this.b );
22380
22381     }
22382
22383 };
22384 /**
22385  * @author mrdoob / http://mrdoob.com/
22386  * @author philogb / http://blog.thejit.org/
22387  * @author egraether / http://egraether.com/
22388  * @author zz85 / http://www.lab4games.net/zz85/blog
22389  */
22390
22391 THREE.Vector2 = function ( x, y ) {
22392
22393     this.x = x || 0;
22394     this.y = y || 0;
22395
22396 };
22397
22398 THREE.Vector2.prototype = {
22399
22400     constructor: THREE.Vector2,
22401
22402     set: function ( x, y ) {
22403
22404         this.x = x;
22405         this.y = y;
22406
22407         return this;
22408
22409     },
22410
22411     copy: function ( v ) {
22412
22413         this.x = v.x;
22414         this.y = v.y;
22415
22416         return this;
22417
22418     },
22419
22420     add: function ( a, b ) {
22421
22422         this.x = a.x + b.x;
22423         this.y = a.y + b.y;
22424
22425         return this;
22426
22427     },
22428
22429     addSelf: function ( v ) {
22430
22431         this.x += v.x;
22432         this.y += v.y;
22433
22434         return this;
22435
22436     },
22437
22438     sub: function ( a, b ) {
22439
22440         this.x = a.x - b.x;
22441         this.y = a.y - b.y;
22442
22443         return this;
22444
22445     },
22446
22447     subSelf: function ( v ) {
22448
22449         this.x -= v.x;
22450         this.y -= v.y;
22451
22452         return this;
22453
22454     },
22455
22456     multiplyScalar: function ( s ) {
22457
22458         this.x *= s;
22459         this.y *= s;
22460
22461         return this;
22462
22463     },
22464
22465     divideScalar: function ( s ) {
22466
22467         if ( s ) {
22468
22469             this.x /= s;
22470             this.y /= s;
22471
22472         } else {
22473
22474             this.set( 0, 0 );
22475
22476         }
22477
22478         return this;
22479
22480     },
22481
22482     negate: function() {
22483
22484         return this.multiplyScalar( - 1 );
22485
22486     },
22487
22488     dot: function ( v ) {
22489
22490         return this.x * v.x + this.y * v.y;
22491
22492     },
22493
22494     lengthSq: function () {
22495
22496         return this.x * this.x + this.y * this.y;
22497
22498     },
22499
22500     length: function () {
22501
22502         return Math.sqrt( this.lengthSq() );
22503
22504     },
22505
22506     normalize: function () {
22507
22508         return this.divideScalar( this.length() );
22509
22510     },
22511
22512     distanceTo: function ( v ) {
22513
22514         return Math.sqrt( this.distanceToSquared( v ) );
22515
22516     },
22517
22518     distanceToSquared: function ( v ) {
22519
22520         var dx = this.x - v.x, dy = this.y - v.y;
22521         return dx * dx + dy * dy;
22522
22523     },
22524
22525     setLength: function ( l ) {
22526
22527         return this.normalize().multiplyScalar( l );
22528
22529     },
22530
22531     lerpSelf: function ( v, alpha ) {
22532
22533         this.x += ( v.x - this.x ) * alpha;
22534         this.y += ( v.y - this.y ) * alpha;
22535
22536         return this;
22537
22538     },
22539
22540     equals: function( v ) {
22541
22542         return ( ( v.x === this.x ) && ( v.y === this.y ) );
22543
22544     },
22545
22546     isZero: function () {
22547
22548         return ( this.lengthSq() < 0.0001 /* almostZero */ );
22549
22550     },
22551
22552     clone: function () {
22553
22554         return new THREE.Vector2( this.x, this.y );
22555
22556     }
22557
22558 };
22559 /**
22560  * @author mrdoob / http://mrdoob.com/
22561  * @author kile / http://kile.stravaganza.org/
22562  * @author philogb / http://blog.thejit.org/
22563  * @author mikael emtinger / http://gomo.se/
22564  * @author egraether / http://egraether.com/
22565  * @author WestLangley / http://github.com/WestLangley
22566  */
22567
22568 THREE.Vector3 = function ( x, y, z ) {
22569
22570     this.x = x || 0;
22571     this.y = y || 0;
22572     this.z = z || 0;
22573
22574 };
22575
22576
22577 THREE.Vector3.prototype = {
22578
22579     constructor: THREE.Vector3,
22580
22581     set: function ( x, y, z ) {
22582
22583         this.x = x;
22584         this.y = y;
22585         this.z = z;
22586
22587         return this;
22588
22589     },
22590
22591     setX: function ( x ) {
22592
22593         this.x = x;
22594
22595         return this;
22596
22597     },
22598
22599     setY: function ( y ) {
22600
22601         this.y = y;
22602
22603         return this;
22604
22605     },
22606
22607     setZ: function ( z ) {
22608
22609         this.z = z;
22610
22611         return this;
22612
22613     },
22614
22615     copy: function ( v ) {
22616
22617         this.x = v.x;
22618         this.y = v.y;
22619         this.z = v.z;
22620
22621         return this;
22622
22623     },
22624
22625     add: function ( a, b ) {
22626
22627         this.x = a.x + b.x;
22628         this.y = a.y + b.y;
22629         this.z = a.z + b.z;
22630
22631         return this;
22632
22633     },
22634
22635     addSelf: function ( v ) {
22636
22637         this.x += v.x;
22638         this.y += v.y;
22639         this.z += v.z;
22640
22641         return this;
22642
22643     },
22644
22645     addScalar: function ( s ) {
22646
22647         this.x += s;
22648         this.y += s;
22649         this.z += s;
22650
22651         return this;
22652
22653     },
22654
22655     sub: function ( a, b ) {
22656
22657         this.x = a.x - b.x;
22658         this.y = a.y - b.y;
22659         this.z = a.z - b.z;
22660
22661         return this;
22662
22663     },
22664
22665     subSelf: function ( v ) {
22666
22667         this.x -= v.x;
22668         this.y -= v.y;
22669         this.z -= v.z;
22670
22671         return this;
22672
22673     },
22674
22675     multiply: function ( a, b ) {
22676
22677         this.x = a.x * b.x;
22678         this.y = a.y * b.y;
22679         this.z = a.z * b.z;
22680
22681         return this;
22682
22683     },
22684
22685     multiplySelf: function ( v ) {
22686
22687         this.x *= v.x;
22688         this.y *= v.y;
22689         this.z *= v.z;
22690
22691         return this;
22692
22693     },
22694
22695     multiplyScalar: function ( s ) {
22696
22697         this.x *= s;
22698         this.y *= s;
22699         this.z *= s;
22700
22701         return this;
22702
22703     },
22704
22705     divideSelf: function ( v ) {
22706
22707         this.x /= v.x;
22708         this.y /= v.y;
22709         this.z /= v.z;
22710
22711         return this;
22712
22713     },
22714
22715     divideScalar: function ( s ) {
22716
22717         if ( s ) {
22718
22719             this.x /= s;
22720             this.y /= s;
22721             this.z /= s;
22722
22723         } else {
22724
22725             this.x = 0;
22726             this.y = 0;
22727             this.z = 0;
22728
22729         }
22730
22731         return this;
22732
22733     },
22734
22735
22736     negate: function() {
22737
22738         return this.multiplyScalar( - 1 );
22739
22740     },
22741
22742     dot: function ( v ) {
22743
22744         return this.x * v.x + this.y * v.y + this.z * v.z;
22745
22746     },
22747
22748     lengthSq: function () {
22749
22750         return this.x * this.x + this.y * this.y + this.z * this.z;
22751
22752     },
22753
22754     length: function () {
22755
22756         return Math.sqrt( this.lengthSq() );
22757
22758     },
22759
22760     lengthManhattan: function () {
22761
22762         return Math.abs( this.x ) + Math.abs( this.y ) + Math.abs( this.z );
22763
22764     },
22765
22766     normalize: function () {
22767
22768         return this.divideScalar( this.length() );
22769
22770     },
22771
22772     setLength: function ( l ) {
22773
22774         return this.normalize().multiplyScalar( l );
22775
22776     },
22777
22778     lerpSelf: function ( v, alpha ) {
22779
22780         this.x += ( v.x - this.x ) * alpha;
22781         this.y += ( v.y - this.y ) * alpha;
22782         this.z += ( v.z - this.z ) * alpha;
22783
22784         return this;
22785
22786     },
22787
22788     cross: function ( a, b ) {
22789
22790         this.x = a.y * b.z - a.z * b.y;
22791         this.y = a.z * b.x - a.x * b.z;
22792         this.z = a.x * b.y - a.y * b.x;
22793
22794         return this;
22795
22796     },
22797
22798     crossSelf: function ( v ) {
22799
22800         var x = this.x, y = this.y, z = this.z;
22801
22802         this.x = y * v.z - z * v.y;
22803         this.y = z * v.x - x * v.z;
22804         this.z = x * v.y - y * v.x;
22805
22806         return this;
22807
22808     },
22809
22810     distanceTo: function ( v ) {
22811
22812         return Math.sqrt( this.distanceToSquared( v ) );
22813
22814     },
22815
22816     distanceToSquared: function ( v ) {
22817
22818         return new THREE.Vector3().sub( this, v ).lengthSq();
22819
22820     },
22821
22822     getPositionFromMatrix: function ( m ) {
22823
22824         this.x = m.elements[12];
22825         this.y = m.elements[13];
22826         this.z = m.elements[14];
22827
22828         return this;
22829
22830     },
22831
22832     setEulerFromRotationMatrix: function ( m, order ) {
22833
22834         // assumes the upper 3x3 of m is a pure rotation matrix (i.e, unscaled)
22835
22836         // clamp, to handle numerical problems
22837
22838         function clamp( x ) {
22839
22840             return Math.min( Math.max( x, -1 ), 1 );
22841
22842         }
22843
22844         var te = m.elements;
22845         var m11 = te[0], m12 = te[4], m13 = te[8];
22846         var m21 = te[1], m22 = te[5], m23 = te[9];
22847         var m31 = te[2], m32 = te[6], m33 = te[10];
22848
22849         if ( order === undefined || order === 'XYZ' ) {
22850
22851             this.y = Math.asin( clamp( m13 ) );
22852
22853             if ( Math.abs( m13 ) < 0.99999 ) {
22854
22855                 this.x = Math.atan2( - m23, m33 );
22856                 this.z = Math.atan2( - m12, m11 );
22857
22858             } else {
22859
22860                 this.x = Math.atan2( m32, m22 );
22861                 this.z = 0;
22862
22863             }
22864
22865         } else if ( order === 'YXZ' ) {
22866
22867             this.x = Math.asin( - clamp( m23 ) );
22868
22869             if ( Math.abs( m23 ) < 0.99999 ) {
22870
22871                 this.y = Math.atan2( m13, m33 );
22872                 this.z = Math.atan2( m21, m22 );
22873
22874             } else {
22875
22876                 this.y = Math.atan2( - m31, m11 );
22877                 this.z = 0;
22878
22879             }
22880
22881         } else if ( order === 'ZXY' ) {
22882
22883             this.x = Math.asin( clamp( m32 ) );
22884
22885             if ( Math.abs( m32 ) < 0.99999 ) {
22886
22887                 this.y = Math.atan2( - m31, m33 );
22888                 this.z = Math.atan2( - m12, m22 );
22889
22890             } else {
22891
22892                 this.y = 0;
22893                 this.z = Math.atan2( m21, m11 );
22894
22895             }
22896
22897         } else if ( order === 'ZYX' ) {
22898
22899             this.y = Math.asin( - clamp( m31 ) );
22900
22901             if ( Math.abs( m31 ) < 0.99999 ) {
22902
22903                 this.x = Math.atan2( m32, m33 );
22904                 this.z = Math.atan2( m21, m11 );
22905
22906             } else {
22907
22908                 this.x = 0;
22909                 this.z = Math.atan2( - m12, m22 );
22910
22911             }
22912
22913         } else if ( order === 'YZX' ) {
22914
22915             this.z = Math.asin( clamp( m21 ) );
22916
22917             if ( Math.abs( m21 ) < 0.99999 ) {
22918
22919                 this.x = Math.atan2( - m23, m22 );
22920                 this.y = Math.atan2( - m31, m11 );
22921
22922             } else {
22923
22924                 this.x = 0;
22925                 this.y = Math.atan2( m13, m33 );
22926
22927             }
22928
22929         } else if ( order === 'XZY' ) {
22930
22931             this.z = Math.asin( - clamp( m12 ) );
22932
22933             if ( Math.abs( m12 ) < 0.99999 ) {
22934
22935                 this.x = Math.atan2( m32, m22 );
22936                 this.y = Math.atan2( m13, m11 );
22937
22938             } else {
22939
22940                 this.x = Math.atan2( - m23, m33 );
22941                 this.y = 0;
22942
22943             }
22944
22945         }
22946
22947         return this;
22948
22949     },
22950
22951     setEulerFromQuaternion: function ( q, order ) {
22952
22953         // q is assumed to be normalized
22954
22955         // clamp, to handle numerical problems
22956
22957         function clamp( x ) {
22958
22959             return Math.min( Math.max( x, -1 ), 1 );
22960
22961         }
22962
22963         // http://www.mathworks.com/matlabcentral/fileexchange/20696-function-to-convert-between-dcm-euler-angles-quaternions-and-euler-vectors/content/SpinCalc.m
22964
22965         var sqx = q.x * q.x;
22966         var sqy = q.y * q.y;
22967         var sqz = q.z * q.z;
22968         var sqw = q.w * q.w;
22969
22970         if ( order === undefined || order === 'XYZ' ) {
22971
22972             this.x = Math.atan2( 2 * ( q.x * q.w - q.y * q.z ), ( sqw - sqx - sqy + sqz ) );
22973             this.y = Math.asin(  clamp( 2 * ( q.x * q.z + q.y * q.w ) ) );
22974             this.z = Math.atan2( 2 * ( q.z * q.w - q.x * q.y ), ( sqw + sqx - sqy - sqz ) );
22975
22976         } else if ( order ===  'YXZ' ) {
22977
22978             this.x = Math.asin(  clamp( 2 * ( q.x * q.w - q.y * q.z ) ) );
22979             this.y = Math.atan2( 2 * ( q.x * q.z + q.y * q.w ), ( sqw - sqx - sqy + sqz ) );
22980             this.z = Math.atan2( 2 * ( q.x * q.y + q.z * q.w ), ( sqw - sqx + sqy - sqz ) );
22981
22982         } else if ( order === 'ZXY' ) {
22983
22984             this.x = Math.asin(  clamp( 2 * ( q.x * q.w + q.y * q.z ) ) );
22985             this.y = Math.atan2( 2 * ( q.y * q.w - q.z * q.x ), ( sqw - sqx - sqy + sqz ) );
22986             this.z = Math.atan2( 2 * ( q.z * q.w - q.x * q.y ), ( sqw - sqx + sqy - sqz ) );
22987
22988         } else if ( order === 'ZYX' ) {
22989
22990             this.x = Math.atan2( 2 * ( q.x * q.w + q.z * q.y ), ( sqw - sqx - sqy + sqz ) );
22991             this.y = Math.asin(  clamp( 2 * ( q.y * q.w - q.x * q.z ) ) );
22992             this.z = Math.atan2( 2 * ( q.x * q.y + q.z * q.w ), ( sqw + sqx - sqy - sqz ) );
22993
22994         } else if ( order === 'YZX' ) {
22995
22996             this.x = Math.atan2( 2 * ( q.x * q.w - q.z * q.y ), ( sqw - sqx + sqy - sqz ) );
22997             this.y = Math.atan2( 2 * ( q.y * q.w - q.x * q.z ), ( sqw + sqx - sqy - sqz ) );
22998             this.z = Math.asin(  clamp( 2 * ( q.x * q.y + q.z * q.w ) ) );
22999
23000         } else if ( order === 'XZY' ) {
23001
23002             this.x = Math.atan2( 2 * ( q.x * q.w + q.y * q.z ), ( sqw - sqx + sqy - sqz ) );
23003             this.y = Math.atan2( 2 * ( q.x * q.z + q.y * q.w ), ( sqw + sqx - sqy - sqz ) );
23004             this.z = Math.asin(  clamp( 2 * ( q.z * q.w - q.x * q.y ) ) );
23005
23006         }
23007
23008         return this;
23009
23010     },
23011
23012     getScaleFromMatrix: function ( m ) {
23013
23014         var sx = this.set( m.elements[0], m.elements[1], m.elements[2] ).length();
23015         var sy = this.set( m.elements[4], m.elements[5], m.elements[6] ).length();
23016         var sz = this.set( m.elements[8], m.elements[9], m.elements[10] ).length();
23017
23018         this.x = sx;
23019         this.y = sy;
23020         this.z = sz;
23021
23022         return this;
23023     },
23024
23025     equals: function ( v ) {
23026
23027         return ( ( v.x === this.x ) && ( v.y === this.y ) && ( v.z === this.z ) );
23028
23029     },
23030
23031     isZero: function () {
23032
23033         return ( this.lengthSq() < 0.0001 /* almostZero */ );
23034
23035     },
23036
23037     clone: function () {
23038
23039         return new THREE.Vector3( this.x, this.y, this.z );
23040
23041     }
23042
23043 };
23044
23045 /**
23046  * @author supereggbert / http://www.paulbrunt.co.uk/
23047  * @author philogb / http://blog.thejit.org/
23048  * @author mikael emtinger / http://gomo.se/
23049  * @author egraether / http://egraether.com/
23050  * @author WestLangley / http://github.com/WestLangley
23051  */
23052
23053 THREE.Vector4 = function ( x, y, z, w ) {
23054
23055     this.x = x || 0;
23056     this.y = y || 0;
23057     this.z = z || 0;
23058     this.w = ( w !== undefined ) ? w : 1;
23059
23060 };
23061
23062 THREE.Vector4.prototype = {
23063
23064     constructor: THREE.Vector4,
23065
23066     set: function ( x, y, z, w ) {
23067
23068         this.x = x;
23069         this.y = y;
23070         this.z = z;
23071         this.w = w;
23072
23073         return this;
23074
23075     },
23076
23077     copy: function ( v ) {
23078
23079         this.x = v.x;
23080         this.y = v.y;
23081         this.z = v.z;
23082         this.w = ( v.w !== undefined ) ? v.w : 1;
23083
23084         return this;
23085
23086     },
23087
23088     add: function ( a, b ) {
23089
23090         this.x = a.x + b.x;
23091         this.y = a.y + b.y;
23092         this.z = a.z + b.z;
23093         this.w = a.w + b.w;
23094
23095         return this;
23096
23097     },
23098
23099     addSelf: function ( v ) {
23100
23101         this.x += v.x;
23102         this.y += v.y;
23103         this.z += v.z;
23104         this.w += v.w;
23105
23106         return this;
23107
23108     },
23109
23110     sub: function ( a, b ) {
23111
23112         this.x = a.x - b.x;
23113         this.y = a.y - b.y;
23114         this.z = a.z - b.z;
23115         this.w = a.w - b.w;
23116
23117         return this;
23118
23119     },
23120
23121     subSelf: function ( v ) {
23122
23123         this.x -= v.x;
23124         this.y -= v.y;
23125         this.z -= v.z;
23126         this.w -= v.w;
23127
23128         return this;
23129
23130     },
23131
23132     multiplyScalar: function ( s ) {
23133
23134         this.x *= s;
23135         this.y *= s;
23136         this.z *= s;
23137         this.w *= s;
23138
23139         return this;
23140
23141     },
23142
23143     divideScalar: function ( s ) {
23144
23145         if ( s ) {
23146
23147             this.x /= s;
23148             this.y /= s;
23149             this.z /= s;
23150             this.w /= s;
23151
23152         } else {
23153
23154             this.x = 0;
23155             this.y = 0;
23156             this.z = 0;
23157             this.w = 1;
23158
23159         }
23160
23161         return this;
23162
23163     },
23164
23165
23166     negate: function() {
23167
23168         return this.multiplyScalar( -1 );
23169
23170     },
23171
23172     dot: function ( v ) {
23173
23174         return this.x * v.x + this.y * v.y + this.z * v.z + this.w * v.w;
23175
23176     },
23177
23178     lengthSq: function () {
23179
23180         return this.dot( this );
23181
23182     },
23183
23184     length: function () {
23185
23186         return Math.sqrt( this.lengthSq() );
23187
23188     },
23189
23190     lengthManhattan: function () {
23191
23192         return Math.abs( this.x ) + Math.abs( this.y ) + Math.abs( this.z ) + Math.abs( this.w );
23193
23194     },
23195
23196     normalize: function () {
23197
23198         return this.divideScalar( this.length() );
23199
23200     },
23201
23202     setLength: function ( l ) {
23203
23204         return this.normalize().multiplyScalar( l );
23205
23206     },
23207
23208     lerpSelf: function ( v, alpha ) {
23209
23210         this.x += ( v.x - this.x ) * alpha;
23211         this.y += ( v.y - this.y ) * alpha;
23212         this.z += ( v.z - this.z ) * alpha;
23213         this.w += ( v.w - this.w ) * alpha;
23214
23215         return this;
23216
23217     },
23218
23219     clone: function () {
23220
23221         return new THREE.Vector4( this.x, this.y, this.z, this.w );
23222
23223     },
23224
23225     setAxisAngleFromQuaternion: function ( q ) {
23226
23227         // http://www.euclideanspace.com/maths/geometry/rotations/conversions/quaternionToAngle/index.htm
23228
23229         // q is assumed to be normalized
23230
23231         this.w = 2 * Math.acos( q.w );
23232
23233         var s = Math.sqrt( 1 - q.w * q.w );
23234
23235         if ( s < 0.0001 ) {
23236
23237              this.x = 1;
23238              this.y = 0;
23239              this.z = 0;
23240
23241         } else {
23242
23243              this.x = q.x / s;
23244              this.y = q.y / s;
23245              this.z = q.z / s;
23246
23247         }
23248
23249         return this;
23250
23251     },
23252
23253     setAxisAngleFromRotationMatrix: function ( m ) {
23254
23255         // http://www.euclideanspace.com/maths/geometry/rotations/conversions/matrixToAngle/index.htm
23256
23257         // assumes the upper 3x3 of m is a pure rotation matrix (i.e, unscaled)
23258
23259         var angle, x, y, z,        // variables for result
23260             epsilon = 0.01,        // margin to allow for rounding errors
23261             epsilon2 = 0.1,        // margin to distinguish between 0 and 180 degrees
23262
23263             te = m.elements,
23264
23265             m11 = te[0], m12 = te[4], m13 = te[8],
23266             m21 = te[1], m22 = te[5], m23 = te[9],
23267             m31 = te[2], m32 = te[6], m33 = te[10];
23268
23269         if ( ( Math.abs( m12 - m21 ) < epsilon )
23270           && ( Math.abs( m13 - m31 ) < epsilon )
23271           && ( Math.abs( m23 - m32 ) < epsilon ) ) {
23272
23273             // singularity found
23274             // first check for identity matrix which must have +1 for all terms
23275             // in leading diagonal and zero in other terms
23276
23277             if ( ( Math.abs( m12 + m21 ) < epsilon2 )
23278               && ( Math.abs( m13 + m31 ) < epsilon2 )
23279               && ( Math.abs( m23 + m32 ) < epsilon2 )
23280               && ( Math.abs( m11 + m22 + m33 - 3 ) < epsilon2 ) ) {
23281
23282                 // this singularity is identity matrix so angle = 0
23283
23284                 this.set( 1, 0, 0, 0 );
23285
23286                 return this; // zero angle, arbitrary axis
23287
23288             }
23289
23290             // otherwise this singularity is angle = 180
23291
23292             angle = Math.PI;
23293
23294             var xx = ( m11 + 1 ) / 2;
23295             var yy = ( m22 + 1 ) / 2;
23296             var zz = ( m33 + 1 ) / 2;
23297             var xy = ( m12 + m21 ) / 4;
23298             var xz = ( m13 + m31 ) / 4;
23299             var yz = ( m23 + m32 ) / 4;
23300
23301             if ( ( xx > yy ) && ( xx > zz ) ) { // m11 is the largest diagonal term
23302
23303                 if ( xx < epsilon ) {
23304
23305                     x = 0;
23306                     y = 0.707106781;
23307                     z = 0.707106781;
23308
23309                 } else {
23310
23311                     x = Math.sqrt( xx );
23312                     y = xy / x;
23313                     z = xz / x;
23314
23315                 }
23316
23317             } else if ( yy > zz ) { // m22 is the largest diagonal term
23318
23319                 if ( yy < epsilon ) {
23320
23321                     x = 0.707106781;
23322                     y = 0;
23323                     z = 0.707106781;
23324
23325                 } else {
23326
23327                     y = Math.sqrt( yy );
23328                     x = xy / y;
23329                     z = yz / y;
23330
23331                 }
23332
23333             } else { // m33 is the largest diagonal term so base result on this
23334
23335                 if ( zz < epsilon ) {
23336
23337                     x = 0.707106781;
23338                     y = 0.707106781;
23339                     z = 0;
23340
23341                 } else {
23342
23343                     z = Math.sqrt( zz );
23344                     x = xz / z;
23345                     y = yz / z;
23346
23347                 }
23348
23349             }
23350
23351             this.set( x, y, z, angle );
23352
23353             return this; // return 180 deg rotation
23354
23355         }
23356
23357         // as we have reached here there are no singularities so we can handle normally
23358
23359         var s = Math.sqrt( ( m32 - m23 ) * ( m32 - m23 )
23360                          + ( m13 - m31 ) * ( m13 - m31 )
23361                          + ( m21 - m12 ) * ( m21 - m12 ) ); // used to normalize
23362
23363         if ( Math.abs( s ) < 0.001 ) s = 1;
23364
23365         // prevent divide by zero, should not happen if matrix is orthogonal and should be
23366         // caught by singularity test above, but I've left it in just in case
23367
23368         this.x = ( m32 - m23 ) / s;
23369         this.y = ( m13 - m31 ) / s;
23370         this.z = ( m21 - m12 ) / s;
23371         this.w = Math.acos( ( m11 + m22 + m33 - 1 ) / 2 );
23372
23373         return this;
23374
23375     }
23376
23377 };
23378 /**
23379  * @author alteredq / http://alteredqualia.com/
23380  */
23381
23382 THREE.Matrix3 = function () {
23383
23384     this.elements = new Float32Array(9);
23385
23386 };
23387
23388 THREE.Matrix3.prototype = {
23389
23390     constructor: THREE.Matrix3,
23391
23392     getInverse: function ( matrix ) {
23393
23394         // input: THREE.Matrix4
23395         // ( based on http://code.google.com/p/webgl-mjs/ )
23396
23397         var me = matrix.elements;
23398
23399         var a11 =   me[10] * me[5] - me[6] * me[9];
23400         var a21 = - me[10] * me[1] + me[2] * me[9];
23401         var a31 =   me[6] * me[1] - me[2] * me[5];
23402         var a12 = - me[10] * me[4] + me[6] * me[8];
23403         var a22 =   me[10] * me[0] - me[2] * me[8];
23404         var a32 = - me[6] * me[0] + me[2] * me[4];
23405         var a13 =   me[9] * me[4] - me[5] * me[8];
23406         var a23 = - me[9] * me[0] + me[1] * me[8];
23407         var a33 =   me[5] * me[0] - me[1] * me[4];
23408
23409         var det = me[0] * a11 + me[1] * a12 + me[2] * a13;
23410
23411         // no inverse
23412
23413         if ( det === 0 ) {
23414
23415             console.warn( "Matrix3.getInverse(): determinant == 0" );
23416
23417         }
23418
23419         var idet = 1.0 / det;
23420
23421         var m = this.elements;
23422
23423         m[ 0 ] = idet * a11; m[ 1 ] = idet * a21; m[ 2 ] = idet * a31;
23424         m[ 3 ] = idet * a12; m[ 4 ] = idet * a22; m[ 5 ] = idet * a32;
23425         m[ 6 ] = idet * a13; m[ 7 ] = idet * a23; m[ 8 ] = idet * a33;
23426
23427         return this;
23428
23429     },
23430
23431
23432     transpose: function () {
23433
23434         var tmp, m = this.elements;
23435
23436         tmp = m[1]; m[1] = m[3]; m[3] = tmp;
23437         tmp = m[2]; m[2] = m[6]; m[6] = tmp;
23438         tmp = m[5]; m[5] = m[7]; m[7] = tmp;
23439
23440         return this;
23441
23442     },
23443
23444
23445     transposeIntoArray: function ( r ) {
23446
23447         var m = this.m;
23448
23449         r[ 0 ] = m[ 0 ];
23450         r[ 1 ] = m[ 3 ];
23451         r[ 2 ] = m[ 6 ];
23452         r[ 3 ] = m[ 1 ];
23453         r[ 4 ] = m[ 4 ];
23454         r[ 5 ] = m[ 7 ];
23455         r[ 6 ] = m[ 2 ];
23456         r[ 7 ] = m[ 5 ];
23457         r[ 8 ] = m[ 8 ];
23458
23459         return this;
23460
23461     }
23462
23463 };
23464 /**
23465  * @author mrdoob / http://mrdoob.com/
23466  * @author supereggbert / http://www.paulbrunt.co.uk/
23467  * @author philogb / http://blog.thejit.org/
23468  * @author jordi_ros / http://plattsoft.com
23469  * @author D1plo1d / http://github.com/D1plo1d
23470  * @author alteredq / http://alteredqualia.com/
23471  * @author mikael emtinger / http://gomo.se/
23472  * @author timknip / http://www.floorplanner.com/
23473  */
23474
23475
23476 THREE.Matrix4 = function ( n11, n12, n13, n14, n21, n22, n23, n24, n31, n32, n33, n34, n41, n42, n43, n44 ) {
23477
23478     this.elements = new Float32Array( 16 );
23479
23480     this.set(
23481
23482         ( n11 !== undefined ) ? n11 : 1, n12 || 0, n13 || 0, n14 || 0,
23483         n21 || 0, ( n22 !== undefined ) ? n22 : 1, n23 || 0, n24 || 0,
23484         n31 || 0, n32 || 0, ( n33 !== undefined ) ? n33 : 1, n34 || 0,
23485         n41 || 0, n42 || 0, n43 || 0, ( n44 !== undefined ) ? n44 : 1
23486
23487     );
23488
23489 };
23490
23491 THREE.Matrix4.prototype = {
23492
23493     constructor: THREE.Matrix4,
23494
23495     set: function ( n11, n12, n13, n14, n21, n22, n23, n24, n31, n32, n33, n34, n41, n42, n43, n44 ) {
23496
23497         var te = this.elements;
23498
23499         te[0] = n11; te[4] = n12; te[8] = n13; te[12] = n14;
23500         te[1] = n21; te[5] = n22; te[9] = n23; te[13] = n24;
23501         te[2] = n31; te[6] = n32; te[10] = n33; te[14] = n34;
23502         te[3] = n41; te[7] = n42; te[11] = n43; te[15] = n44;
23503
23504         return this;
23505
23506     },
23507
23508     identity: function () {
23509
23510         this.set(
23511
23512             1, 0, 0, 0,
23513             0, 1, 0, 0,
23514             0, 0, 1, 0,
23515             0, 0, 0, 1
23516
23517         );
23518
23519         return this;
23520
23521     },
23522
23523     copy: function ( m ) {
23524
23525         var me = m.elements;
23526
23527         this.set(
23528
23529             me[0], me[4], me[8], me[12],
23530             me[1], me[5], me[9], me[13],
23531             me[2], me[6], me[10], me[14],
23532             me[3], me[7], me[11], me[15]
23533
23534         );
23535
23536         return this;
23537
23538     },
23539
23540     lookAt: function ( eye, target, up ) {
23541
23542         var te = this.elements;
23543
23544         var x = THREE.Matrix4.__v1;
23545         var y = THREE.Matrix4.__v2;
23546         var z = THREE.Matrix4.__v3;
23547
23548         z.sub( eye, target ).normalize();
23549
23550         if ( z.length() === 0 ) {
23551
23552             z.z = 1;
23553
23554         }
23555
23556         x.cross( up, z ).normalize();
23557
23558         if ( x.length() === 0 ) {
23559
23560             z.x += 0.0001;
23561             x.cross( up, z ).normalize();
23562
23563         }
23564
23565         y.cross( z, x );
23566
23567
23568         te[0] = x.x; te[4] = y.x; te[8] = z.x;
23569         te[1] = x.y; te[5] = y.y; te[9] = z.y;
23570         te[2] = x.z; te[6] = y.z; te[10] = z.z;
23571
23572         return this;
23573
23574     },
23575
23576     multiply: function ( a, b ) {
23577
23578         var ae = a.elements;
23579         var be = b.elements;
23580         var te = this.elements;
23581
23582         var a11 = ae[0], a12 = ae[4], a13 = ae[8], a14 = ae[12];
23583         var a21 = ae[1], a22 = ae[5], a23 = ae[9], a24 = ae[13];
23584         var a31 = ae[2], a32 = ae[6], a33 = ae[10], a34 = ae[14];
23585         var a41 = ae[3], a42 = ae[7], a43 = ae[11], a44 = ae[15];
23586
23587         var b11 = be[0], b12 = be[4], b13 = be[8], b14 = be[12];
23588         var b21 = be[1], b22 = be[5], b23 = be[9], b24 = be[13];
23589         var b31 = be[2], b32 = be[6], b33 = be[10], b34 = be[14];
23590         var b41 = be[3], b42 = be[7], b43 = be[11], b44 = be[15];
23591
23592         te[0] = a11 * b11 + a12 * b21 + a13 * b31 + a14 * b41;
23593         te[4] = a11 * b12 + a12 * b22 + a13 * b32 + a14 * b42;
23594         te[8] = a11 * b13 + a12 * b23 + a13 * b33 + a14 * b43;
23595         te[12] = a11 * b14 + a12 * b24 + a13 * b34 + a14 * b44;
23596
23597         te[1] = a21 * b11 + a22 * b21 + a23 * b31 + a24 * b41;
23598         te[5] = a21 * b12 + a22 * b22 + a23 * b32 + a24 * b42;
23599         te[9] = a21 * b13 + a22 * b23 + a23 * b33 + a24 * b43;
23600         te[13] = a21 * b14 + a22 * b24 + a23 * b34 + a24 * b44;
23601
23602         te[2] = a31 * b11 + a32 * b21 + a33 * b31 + a34 * b41;
23603         te[6] = a31 * b12 + a32 * b22 + a33 * b32 + a34 * b42;
23604         te[10] = a31 * b13 + a32 * b23 + a33 * b33 + a34 * b43;
23605         te[14] = a31 * b14 + a32 * b24 + a33 * b34 + a34 * b44;
23606
23607         te[3] = a41 * b11 + a42 * b21 + a43 * b31 + a44 * b41;
23608         te[7] = a41 * b12 + a42 * b22 + a43 * b32 + a44 * b42;
23609         te[11] = a41 * b13 + a42 * b23 + a43 * b33 + a44 * b43;
23610         te[15] = a41 * b14 + a42 * b24 + a43 * b34 + a44 * b44;
23611
23612         return this;
23613
23614     },
23615
23616     multiplySelf: function ( m ) {
23617
23618         return this.multiply( this, m );
23619
23620     },
23621
23622     multiplyToArray: function ( a, b, r ) {
23623
23624         var te = this.elements;
23625
23626         this.multiply( a, b );
23627
23628         r[ 0 ] = te[0]; r[ 1 ] = te[1]; r[ 2 ] = te[2]; r[ 3 ] = te[3];
23629         r[ 4 ] = te[4]; r[ 5 ] = te[5]; r[ 6 ] = te[6]; r[ 7 ] = te[7];
23630         r[ 8 ]  = te[8]; r[ 9 ]  = te[9]; r[ 10 ] = te[10]; r[ 11 ] = te[11];
23631         r[ 12 ] = te[12]; r[ 13 ] = te[13]; r[ 14 ] = te[14]; r[ 15 ] = te[15];
23632
23633         return this;
23634
23635     },
23636
23637     multiplyScalar: function ( s ) {
23638
23639         var te = this.elements;
23640
23641         te[0] *= s; te[4] *= s; te[8] *= s; te[12] *= s;
23642         te[1] *= s; te[5] *= s; te[9] *= s; te[13] *= s;
23643         te[2] *= s; te[6] *= s; te[10] *= s; te[14] *= s;
23644         te[3] *= s; te[7] *= s; te[11] *= s; te[15] *= s;
23645
23646         return this;
23647
23648     },
23649
23650     multiplyVector3: function ( v ) {
23651
23652         var te = this.elements;
23653
23654         var vx = v.x, vy = v.y, vz = v.z;
23655         var d = 1 / ( te[3] * vx + te[7] * vy + te[11] * vz + te[15] );
23656
23657         v.x = ( te[0] * vx + te[4] * vy + te[8] * vz + te[12] ) * d;
23658         v.y = ( te[1] * vx + te[5] * vy + te[9] * vz + te[13] ) * d;
23659         v.z = ( te[2] * vx + te[6] * vy + te[10] * vz + te[14] ) * d;
23660
23661         return v;
23662
23663     },
23664
23665     multiplyVector4: function ( v ) {
23666
23667         var te = this.elements;
23668         var vx = v.x, vy = v.y, vz = v.z, vw = v.w;
23669
23670         v.x = te[0] * vx + te[4] * vy + te[8] * vz + te[12] * vw;
23671         v.y = te[1] * vx + te[5] * vy + te[9] * vz + te[13] * vw;
23672         v.z = te[2] * vx + te[6] * vy + te[10] * vz + te[14] * vw;
23673         v.w = te[3] * vx + te[7] * vy + te[11] * vz + te[15] * vw;
23674
23675         return v;
23676
23677     },
23678
23679     multiplyVector3Array: function ( a ) {
23680
23681         var tmp = THREE.Matrix4.__v1;
23682
23683         for ( var i = 0, il = a.length; i < il; i += 3 ) {
23684
23685             tmp.x = a[ i ];
23686             tmp.y = a[ i + 1 ];
23687             tmp.z = a[ i + 2 ];
23688
23689             this.multiplyVector3( tmp );
23690
23691             a[ i ]     = tmp.x;
23692             a[ i + 1 ] = tmp.y;
23693             a[ i + 2 ] = tmp.z;
23694
23695         }
23696
23697         return a;
23698
23699     },
23700
23701     rotateAxis: function ( v ) {
23702
23703         var te = this.elements;
23704         var vx = v.x, vy = v.y, vz = v.z;
23705
23706         v.x = vx * te[0] + vy * te[4] + vz * te[8];
23707         v.y = vx * te[1] + vy * te[5] + vz * te[9];
23708         v.z = vx * te[2] + vy * te[6] + vz * te[10];
23709
23710         v.normalize();
23711
23712         return v;
23713
23714     },
23715
23716     crossVector: function ( a ) {
23717
23718         var te = this.elements;
23719         var v = new THREE.Vector4();
23720
23721         v.x = te[0] * a.x + te[4] * a.y + te[8] * a.z + te[12] * a.w;
23722         v.y = te[1] * a.x + te[5] * a.y + te[9] * a.z + te[13] * a.w;
23723         v.z = te[2] * a.x + te[6] * a.y + te[10] * a.z + te[14] * a.w;
23724
23725         v.w = ( a.w ) ? te[3] * a.x + te[7] * a.y + te[11] * a.z + te[15] * a.w : 1;
23726
23727         return v;
23728
23729     },
23730
23731     determinant: function () {
23732
23733         var te = this.elements;
23734
23735         var n11 = te[0], n12 = te[4], n13 = te[8], n14 = te[12];
23736         var n21 = te[1], n22 = te[5], n23 = te[9], n24 = te[13];
23737         var n31 = te[2], n32 = te[6], n33 = te[10], n34 = te[14];
23738         var n41 = te[3], n42 = te[7], n43 = te[11], n44 = te[15];
23739
23740         //TODO: make this more efficient
23741         //( based on http://www.euclideanspace.com/maths/algebra/matrix/functions/inverse/fourD/index.htm )
23742
23743         return (
23744             n14 * n23 * n32 * n41-
23745             n13 * n24 * n32 * n41-
23746             n14 * n22 * n33 * n41+
23747             n12 * n24 * n33 * n41+
23748
23749             n13 * n22 * n34 * n41-
23750             n12 * n23 * n34 * n41-
23751             n14 * n23 * n31 * n42+
23752             n13 * n24 * n31 * n42+
23753
23754             n14 * n21 * n33 * n42-
23755             n11 * n24 * n33 * n42-
23756             n13 * n21 * n34 * n42+
23757             n11 * n23 * n34 * n42+
23758
23759             n14 * n22 * n31 * n43-
23760             n12 * n24 * n31 * n43-
23761             n14 * n21 * n32 * n43+
23762             n11 * n24 * n32 * n43+
23763
23764             n12 * n21 * n34 * n43-
23765             n11 * n22 * n34 * n43-
23766             n13 * n22 * n31 * n44+
23767             n12 * n23 * n31 * n44+
23768
23769             n13 * n21 * n32 * n44-
23770             n11 * n23 * n32 * n44-
23771             n12 * n21 * n33 * n44+
23772             n11 * n22 * n33 * n44
23773         );
23774
23775     },
23776
23777     transpose: function () {
23778
23779         var te = this.elements;
23780         var tmp;
23781
23782         tmp = te[1]; te[1] = te[4]; te[4] = tmp;
23783         tmp = te[2]; te[2] = te[8]; te[8] = tmp;
23784         tmp = te[6]; te[6] = te[9]; te[9] = tmp;
23785
23786         tmp = te[3]; te[3] = te[12]; te[12] = tmp;
23787         tmp = te[7]; te[7] = te[13]; te[13] = tmp;
23788         tmp = te[11]; te[11] = te[14]; te[14] = tmp;
23789
23790         return this;
23791
23792     },
23793
23794     flattenToArray: function ( flat ) {
23795
23796         var te = this.elements;
23797         flat[ 0 ] = te[0]; flat[ 1 ] = te[1]; flat[ 2 ] = te[2]; flat[ 3 ] = te[3];
23798         flat[ 4 ] = te[4]; flat[ 5 ] = te[5]; flat[ 6 ] = te[6]; flat[ 7 ] = te[7];
23799         flat[ 8 ]  = te[8]; flat[ 9 ]  = te[9]; flat[ 10 ] = te[10]; flat[ 11 ] = te[11];
23800         flat[ 12 ] = te[12]; flat[ 13 ] = te[13]; flat[ 14 ] = te[14]; flat[ 15 ] = te[15];
23801
23802         return flat;
23803
23804     },
23805
23806     flattenToArrayOffset: function( flat, offset ) {
23807
23808         var te = this.elements;
23809         flat[ offset ] = te[0];
23810         flat[ offset + 1 ] = te[1];
23811         flat[ offset + 2 ] = te[2];
23812         flat[ offset + 3 ] = te[3];
23813
23814         flat[ offset + 4 ] = te[4];
23815         flat[ offset + 5 ] = te[5];
23816         flat[ offset + 6 ] = te[6];
23817         flat[ offset + 7 ] = te[7];
23818
23819         flat[ offset + 8 ]  = te[8];
23820         flat[ offset + 9 ]  = te[9];
23821         flat[ offset + 10 ] = te[10];
23822         flat[ offset + 11 ] = te[11];
23823
23824         flat[ offset + 12 ] = te[12];
23825         flat[ offset + 13 ] = te[13];
23826         flat[ offset + 14 ] = te[14];
23827         flat[ offset + 15 ] = te[15];
23828
23829         return flat;
23830
23831     },
23832
23833     getPosition: function () {
23834
23835         var te = this.elements;
23836         return THREE.Matrix4.__v1.set( te[12], te[13], te[14] );
23837
23838     },
23839
23840     setPosition: function ( v ) {
23841
23842         var te = this.elements;
23843
23844         te[12] = v.x;
23845         te[13] = v.y;
23846         te[14] = v.z;
23847
23848         return this;
23849
23850     },
23851
23852     getColumnX: function () {
23853
23854         var te = this.elements;
23855         return THREE.Matrix4.__v1.set( te[0], te[1], te[2] );
23856
23857     },
23858
23859     getColumnY: function () {
23860
23861         var te = this.elements;
23862         return THREE.Matrix4.__v1.set( te[4], te[5], te[6] );
23863
23864     },
23865
23866     getColumnZ: function() {
23867
23868         var te = this.elements;
23869         return THREE.Matrix4.__v1.set( te[8], te[9], te[10] );
23870
23871     },
23872
23873     getInverse: function ( m ) {
23874
23875         // based on http://www.euclideanspace.com/maths/algebra/matrix/functions/inverse/fourD/index.htm
23876         var te = this.elements;
23877         var me = m.elements;
23878
23879         var n11 = me[0], n12 = me[4], n13 = me[8], n14 = me[12];
23880         var n21 = me[1], n22 = me[5], n23 = me[9], n24 = me[13];
23881         var n31 = me[2], n32 = me[6], n33 = me[10], n34 = me[14];
23882         var n41 = me[3], n42 = me[7], n43 = me[11], n44 = me[15];
23883
23884         te[0] = n23*n34*n42 - n24*n33*n42 + n24*n32*n43 - n22*n34*n43 - n23*n32*n44 + n22*n33*n44;
23885         te[4] = n14*n33*n42 - n13*n34*n42 - n14*n32*n43 + n12*n34*n43 + n13*n32*n44 - n12*n33*n44;
23886         te[8] = n13*n24*n42 - n14*n23*n42 + n14*n22*n43 - n12*n24*n43 - n13*n22*n44 + n12*n23*n44;
23887         te[12] = n14*n23*n32 - n13*n24*n32 - n14*n22*n33 + n12*n24*n33 + n13*n22*n34 - n12*n23*n34;
23888         te[1] = n24*n33*n41 - n23*n34*n41 - n24*n31*n43 + n21*n34*n43 + n23*n31*n44 - n21*n33*n44;
23889         te[5] = n13*n34*n41 - n14*n33*n41 + n14*n31*n43 - n11*n34*n43 - n13*n31*n44 + n11*n33*n44;
23890         te[9] = n14*n23*n41 - n13*n24*n41 - n14*n21*n43 + n11*n24*n43 + n13*n21*n44 - n11*n23*n44;
23891         te[13] = n13*n24*n31 - n14*n23*n31 + n14*n21*n33 - n11*n24*n33 - n13*n21*n34 + n11*n23*n34;
23892         te[2] = n22*n34*n41 - n24*n32*n41 + n24*n31*n42 - n21*n34*n42 - n22*n31*n44 + n21*n32*n44;
23893         te[6] = n14*n32*n41 - n12*n34*n41 - n14*n31*n42 + n11*n34*n42 + n12*n31*n44 - n11*n32*n44;
23894         te[10] = n12*n24*n41 - n14*n22*n41 + n14*n21*n42 - n11*n24*n42 - n12*n21*n44 + n11*n22*n44;
23895         te[14] = n14*n22*n31 - n12*n24*n31 - n14*n21*n32 + n11*n24*n32 + n12*n21*n34 - n11*n22*n34;
23896         te[3] = n23*n32*n41 - n22*n33*n41 - n23*n31*n42 + n21*n33*n42 + n22*n31*n43 - n21*n32*n43;
23897         te[7] = n12*n33*n41 - n13*n32*n41 + n13*n31*n42 - n11*n33*n42 - n12*n31*n43 + n11*n32*n43;
23898         te[11] = n13*n22*n41 - n12*n23*n41 - n13*n21*n42 + n11*n23*n42 + n12*n21*n43 - n11*n22*n43;
23899         te[15] = n12*n23*n31 - n13*n22*n31 + n13*n21*n32 - n11*n23*n32 - n12*n21*n33 + n11*n22*n33;
23900         this.multiplyScalar( 1 / m.determinant() );
23901
23902         return this;
23903
23904     },
23905
23906     setRotationFromEuler: function ( v, order ) {
23907
23908         var te = this.elements;
23909
23910         var x = v.x, y = v.y, z = v.z;
23911         var a = Math.cos( x ), b = Math.sin( x );
23912         var c = Math.cos( y ), d = Math.sin( y );
23913         var e = Math.cos( z ), f = Math.sin( z );
23914
23915         if ( order === undefined || order === 'XYZ' ) {
23916
23917             var ae = a * e, af = a * f, be = b * e, bf = b * f;
23918
23919             te[0] = c * e;
23920             te[4] = - c * f;
23921             te[8] = d;
23922
23923             te[1] = af + be * d;
23924             te[5] = ae - bf * d;
23925             te[9] = - b * c;
23926
23927             te[2] = bf - ae * d;
23928             te[6] = be + af * d;
23929             te[10] = a * c;
23930
23931         } else if ( order === 'YXZ' ) {
23932
23933             var ce = c * e, cf = c * f, de = d * e, df = d * f;
23934
23935             te[0] = ce + df * b;
23936             te[4] = de * b - cf;
23937             te[8] = a * d;
23938
23939             te[1] = a * f;
23940             te[5] = a * e;
23941             te[9] = - b;
23942
23943             te[2] = cf * b - de;
23944             te[6] = df + ce * b;
23945             te[10] = a * c;
23946
23947         } else if ( order === 'ZXY' ) {
23948
23949             var ce = c * e, cf = c * f, de = d * e, df = d * f;
23950
23951             te[0] = ce - df * b;
23952             te[4] = - a * f;
23953             te[8] = de + cf * b;
23954
23955             te[1] = cf + de * b;
23956             te[5] = a * e;
23957             te[9] = df - ce * b;
23958
23959             te[2] = - a * d;
23960             te[6] = b;
23961             te[10] = a * c;
23962
23963         } else if ( order === 'ZYX' ) {
23964
23965             var ae = a * e, af = a * f, be = b * e, bf = b * f;
23966
23967             te[0] = c * e;
23968             te[4] = be * d - af;
23969             te[8] = ae * d + bf;
23970
23971             te[1] = c * f;
23972             te[5] = bf * d + ae;
23973             te[9] = af * d - be;
23974
23975             te[2] = - d;
23976             te[6] = b * c;
23977             te[10] = a * c;
23978
23979         } else if ( order === 'YZX' ) {
23980
23981             var ac = a * c, ad = a * d, bc = b * c, bd = b * d;
23982
23983             te[0] = c * e;
23984             te[4] = bd - ac * f;
23985             te[8] = bc * f + ad;
23986
23987             te[1] = f;
23988             te[5] = a * e;
23989             te[9] = - b * e;
23990
23991             te[2] = - d * e;
23992             te[6] = ad * f + bc;
23993             te[10] = ac - bd * f;
23994
23995         } else if ( order === 'XZY' ) {
23996
23997             var ac = a * c, ad = a * d, bc = b * c, bd = b * d;
23998
23999             te[0] = c * e;
24000             te[4] = - f;
24001             te[8] = d * e;
24002
24003             te[1] = ac * f + bd;
24004             te[5] = a * e;
24005             te[9] = ad * f - bc;
24006
24007             te[2] = bc * f - ad;
24008             te[6] = b * e;
24009             te[10] = bd * f + ac;
24010
24011         }
24012
24013         return this;
24014
24015     },
24016
24017
24018     setRotationFromQuaternion: function ( q ) {
24019
24020         var te = this.elements;
24021
24022         var x = q.x, y = q.y, z = q.z, w = q.w;
24023         var x2 = x + x, y2 = y + y, z2 = z + z;
24024         var xx = x * x2, xy = x * y2, xz = x * z2;
24025         var yy = y * y2, yz = y * z2, zz = z * z2;
24026         var wx = w * x2, wy = w * y2, wz = w * z2;
24027
24028         te[0] = 1 - ( yy + zz );
24029         te[4] = xy - wz;
24030         te[8] = xz + wy;
24031
24032         te[1] = xy + wz;
24033         te[5] = 1 - ( xx + zz );
24034         te[9] = yz - wx;
24035
24036         te[2] = xz - wy;
24037         te[6] = yz + wx;
24038         te[10] = 1 - ( xx + yy );
24039
24040         return this;
24041
24042     },
24043
24044     compose: function ( translation, rotation, scale ) {
24045
24046         var te = this.elements;
24047         var mRotation = THREE.Matrix4.__m1;
24048         var mScale = THREE.Matrix4.__m2;
24049
24050         mRotation.identity();
24051         mRotation.setRotationFromQuaternion( rotation );
24052
24053         mScale.makeScale( scale.x, scale.y, scale.z );
24054
24055         this.multiply( mRotation, mScale );
24056
24057         te[12] = translation.x;
24058         te[13] = translation.y;
24059         te[14] = translation.z;
24060
24061         return this;
24062
24063     },
24064
24065     decompose: function ( translation, rotation, scale ) {
24066
24067         var te = this.elements;
24068
24069         // grab the axis vectors
24070         var x = THREE.Matrix4.__v1;
24071         var y = THREE.Matrix4.__v2;
24072         var z = THREE.Matrix4.__v3;
24073
24074         x.set( te[0], te[1], te[2] );
24075         y.set( te[4], te[5], te[6] );
24076         z.set( te[8], te[9], te[10] );
24077
24078         translation = ( translation instanceof THREE.Vector3 ) ? translation : new THREE.Vector3();
24079         rotation = ( rotation instanceof THREE.Quaternion ) ? rotation : new THREE.Quaternion();
24080         scale = ( scale instanceof THREE.Vector3 ) ? scale : new THREE.Vector3();
24081
24082         scale.x = x.length();
24083         scale.y = y.length();
24084         scale.z = z.length();
24085
24086         translation.x = te[12];
24087         translation.y = te[13];
24088         translation.z = te[14];
24089
24090         // scale the rotation part
24091
24092         var matrix = THREE.Matrix4.__m1;
24093
24094         matrix.copy( this );
24095
24096         matrix.elements[0] /= scale.x;
24097         matrix.elements[1] /= scale.x;
24098         matrix.elements[2] /= scale.x;
24099
24100         matrix.elements[4] /= scale.y;
24101         matrix.elements[5] /= scale.y;
24102         matrix.elements[6] /= scale.y;
24103
24104         matrix.elements[8] /= scale.z;
24105         matrix.elements[9] /= scale.z;
24106         matrix.elements[10] /= scale.z;
24107
24108         rotation.setFromRotationMatrix( matrix );
24109
24110         return [ translation, rotation, scale ];
24111
24112     },
24113
24114     extractPosition: function ( m ) {
24115
24116         var te = this.elements;
24117         var me = m.elements;
24118
24119         te[12] = me[12];
24120         te[13] = me[13];
24121         te[14] = me[14];
24122
24123         return this;
24124
24125     },
24126
24127     extractRotation: function ( m ) {
24128
24129         var te = this.elements;
24130         var me = m.elements;
24131
24132         var vector = THREE.Matrix4.__v1;
24133
24134         var scaleX = 1 / vector.set( me[0], me[1], me[2] ).length();
24135         var scaleY = 1 / vector.set( me[4], me[5], me[6] ).length();
24136         var scaleZ = 1 / vector.set( me[8], me[9], me[10] ).length();
24137
24138         te[0] = me[0] * scaleX;
24139         te[1] = me[1] * scaleX;
24140         te[2] = me[2] * scaleX;
24141
24142         te[4] = me[4] * scaleY;
24143         te[5] = me[5] * scaleY;
24144         te[6] = me[6] * scaleY;
24145
24146         te[8] = me[8] * scaleZ;
24147         te[9] = me[9] * scaleZ;
24148         te[10] = me[10] * scaleZ;
24149
24150         return this;
24151
24152     },
24153
24154     //
24155
24156     translate: function ( v ) {
24157
24158         var te = this.elements;
24159         var x = v.x, y = v.y, z = v.z;
24160
24161         te[12] = te[0] * x + te[4] * y + te[8] * z + te[12];
24162         te[13] = te[1] * x + te[5] * y + te[9] * z + te[13];
24163         te[14] = te[2] * x + te[6] * y + te[10] * z + te[14];
24164         te[15] = te[3] * x + te[7] * y + te[11] * z + te[15];
24165
24166         return this;
24167
24168     },
24169
24170     rotateX: function ( angle ) {
24171
24172         var te = this.elements;
24173         var m12 = te[4];
24174         var m22 = te[5];
24175         var m32 = te[6];
24176         var m42 = te[7];
24177         var m13 = te[8];
24178         var m23 = te[9];
24179         var m33 = te[10];
24180         var m43 = te[11];
24181         var c = Math.cos( angle );
24182         var s = Math.sin( angle );
24183
24184         te[4] = c * m12 + s * m13;
24185         te[5] = c * m22 + s * m23;
24186         te[6] = c * m32 + s * m33;
24187         te[7] = c * m42 + s * m43;
24188
24189         te[8] = c * m13 - s * m12;
24190         te[9] = c * m23 - s * m22;
24191         te[10] = c * m33 - s * m32;
24192         te[11] = c * m43 - s * m42;
24193
24194         return this;
24195
24196     },
24197
24198     rotateY: function ( angle ) {
24199
24200         var te = this.elements;
24201         var m11 = te[0];
24202         var m21 = te[1];
24203         var m31 = te[2];
24204         var m41 = te[3];
24205         var m13 = te[8];
24206         var m23 = te[9];
24207         var m33 = te[10];
24208         var m43 = te[11];
24209         var c = Math.cos( angle );
24210         var s = Math.sin( angle );
24211
24212         te[0] = c * m11 - s * m13;
24213         te[1] = c * m21 - s * m23;
24214         te[2] = c * m31 - s * m33;
24215         te[3] = c * m41 - s * m43;
24216
24217         te[8] = c * m13 + s * m11;
24218         te[9] = c * m23 + s * m21;
24219         te[10] = c * m33 + s * m31;
24220         te[11] = c * m43 + s * m41;
24221
24222         return this;
24223
24224     },
24225
24226     rotateZ: function ( angle ) {
24227
24228         var te = this.elements;
24229         var m11 = te[0];
24230         var m21 = te[1];
24231         var m31 = te[2];
24232         var m41 = te[3];
24233         var m12 = te[4];
24234         var m22 = te[5];
24235         var m32 = te[6];
24236         var m42 = te[7];
24237         var c = Math.cos( angle );
24238         var s = Math.sin( angle );
24239
24240         te[0] = c * m11 + s * m12;
24241         te[1] = c * m21 + s * m22;
24242         te[2] = c * m31 + s * m32;
24243         te[3] = c * m41 + s * m42;
24244
24245         te[4] = c * m12 - s * m11;
24246         te[5] = c * m22 - s * m21;
24247         te[6] = c * m32 - s * m31;
24248         te[7] = c * m42 - s * m41;
24249
24250         return this;
24251
24252     },
24253
24254     rotateByAxis: function ( axis, angle ) {
24255
24256         var te = this.elements;
24257
24258         // optimize by checking axis
24259
24260         if ( axis.x === 1 && axis.y === 0 && axis.z === 0 ) {
24261
24262             return this.rotateX( angle );
24263
24264         } else if ( axis.x === 0 && axis.y === 1 && axis.z === 0 ) {
24265
24266             return this.rotateY( angle );
24267
24268         } else if ( axis.x === 0 && axis.y === 0 && axis.z === 1 ) {
24269
24270             return this.rotateZ( angle );
24271
24272         }
24273
24274         var x = axis.x, y = axis.y, z = axis.z;
24275         var n = Math.sqrt(x * x + y * y + z * z);
24276
24277         x /= n;
24278         y /= n;
24279         z /= n;
24280
24281         var xx = x * x, yy = y * y, zz = z * z;
24282         var c = Math.cos( angle );
24283         var s = Math.sin( angle );
24284         var oneMinusCosine = 1 - c;
24285         var xy = x * y * oneMinusCosine;
24286         var xz = x * z * oneMinusCosine;
24287         var yz = y * z * oneMinusCosine;
24288         var xs = x * s;
24289         var ys = y * s;
24290         var zs = z * s;
24291
24292         var r11 = xx + (1 - xx) * c;
24293         var r21 = xy + zs;
24294         var r31 = xz - ys;
24295         var r12 = xy - zs;
24296         var r22 = yy + (1 - yy) * c;
24297         var r32 = yz + xs;
24298         var r13 = xz + ys;
24299         var r23 = yz - xs;
24300         var r33 = zz + (1 - zz) * c;
24301
24302         var m11 = te[0], m21 = te[1], m31 = te[2], m41 = te[3];
24303         var m12 = te[4], m22 = te[5], m32 = te[6], m42 = te[7];
24304         var m13 = te[8], m23 = te[9], m33 = te[10], m43 = te[11];
24305         var m14 = te[12], m24 = te[13], m34 = te[14], m44 = te[15];
24306
24307         te[0] = r11 * m11 + r21 * m12 + r31 * m13;
24308         te[1] = r11 * m21 + r21 * m22 + r31 * m23;
24309         te[2] = r11 * m31 + r21 * m32 + r31 * m33;
24310         te[3] = r11 * m41 + r21 * m42 + r31 * m43;
24311
24312         te[4] = r12 * m11 + r22 * m12 + r32 * m13;
24313         te[5] = r12 * m21 + r22 * m22 + r32 * m23;
24314         te[6] = r12 * m31 + r22 * m32 + r32 * m33;
24315         te[7] = r12 * m41 + r22 * m42 + r32 * m43;
24316
24317         te[8] = r13 * m11 + r23 * m12 + r33 * m13;
24318         te[9] = r13 * m21 + r23 * m22 + r33 * m23;
24319         te[10] = r13 * m31 + r23 * m32 + r33 * m33;
24320         te[11] = r13 * m41 + r23 * m42 + r33 * m43;
24321
24322         return this;
24323
24324     },
24325
24326     scale: function ( v ) {
24327
24328         var te = this.elements;
24329         var x = v.x, y = v.y, z = v.z;
24330
24331         te[0] *= x; te[4] *= y; te[8] *= z;
24332         te[1] *= x; te[5] *= y; te[9] *= z;
24333         te[2] *= x; te[6] *= y; te[10] *= z;
24334         te[3] *= x; te[7] *= y; te[11] *= z;
24335
24336         return this;
24337
24338     },
24339
24340     getMaxScaleOnAxis: function () {
24341
24342         var te = this.elements;
24343
24344         var scaleXSq =  te[0] * te[0] + te[1] * te[1] + te[2] * te[2];
24345         var scaleYSq =  te[4] * te[4] + te[5] * te[5] + te[6] * te[6];
24346         var scaleZSq =  te[8] * te[8] + te[9] * te[9] + te[10] * te[10];
24347
24348         return Math.sqrt( Math.max( scaleXSq, Math.max( scaleYSq, scaleZSq ) ) );
24349
24350     },
24351
24352     //
24353
24354     makeTranslation: function ( x, y, z ) {
24355
24356         this.set(
24357
24358             1, 0, 0, x,
24359             0, 1, 0, y,
24360             0, 0, 1, z,
24361             0, 0, 0, 1
24362
24363         );
24364
24365         return this;
24366
24367     },
24368
24369     makeRotationX: function ( theta ) {
24370
24371         var c = Math.cos( theta ), s = Math.sin( theta );
24372
24373         this.set(
24374
24375             1, 0,  0, 0,
24376             0, c, -s, 0,
24377             0, s,  c, 0,
24378             0, 0,  0, 1
24379
24380         );
24381
24382         return this;
24383
24384     },
24385
24386     makeRotationY: function ( theta ) {
24387
24388         var c = Math.cos( theta ), s = Math.sin( theta );
24389
24390         this.set(
24391
24392              c, 0, s, 0,
24393              0, 1, 0, 0,
24394             -s, 0, c, 0,
24395              0, 0, 0, 1
24396
24397         );
24398
24399         return this;
24400
24401     },
24402
24403     makeRotationZ: function ( theta ) {
24404
24405         var c = Math.cos( theta ), s = Math.sin( theta );
24406
24407         this.set(
24408
24409             c, -s, 0, 0,
24410             s,  c, 0, 0,
24411             0,  0, 1, 0,
24412             0,  0, 0, 1
24413
24414         );
24415
24416         return this;
24417
24418     },
24419
24420     makeRotationAxis: function ( axis, angle ) {
24421
24422         // Based on http://www.gamedev.net/reference/articles/article1199.asp
24423
24424         var c = Math.cos( angle );
24425         var s = Math.sin( angle );
24426         var t = 1 - c;
24427         var x = axis.x, y = axis.y, z = axis.z;
24428         var tx = t * x, ty = t * y;
24429
24430         this.set(
24431
24432             tx * x + c, tx * y - s * z, tx * z + s * y, 0,
24433             tx * y + s * z, ty * y + c, ty * z - s * x, 0,
24434             tx * z - s * y, ty * z + s * x, t * z * z + c, 0,
24435             0, 0, 0, 1
24436
24437         );
24438
24439          return this;
24440
24441     },
24442
24443     makeScale: function ( x, y, z ) {
24444
24445         this.set(
24446
24447             x, 0, 0, 0,
24448             0, y, 0, 0,
24449             0, 0, z, 0,
24450             0, 0, 0, 1
24451
24452         );
24453
24454         return this;
24455
24456     },
24457
24458     makeFrustum: function ( left, right, bottom, top, near, far ) {
24459
24460         var te = this.elements;
24461         var x = 2 * near / ( right - left );
24462         var y = 2 * near / ( top - bottom );
24463
24464         var a = ( right + left ) / ( right - left );
24465         var b = ( top + bottom ) / ( top - bottom );
24466         var c = - ( far + near ) / ( far - near );
24467         var d = - 2 * far * near / ( far - near );
24468
24469         te[0] = x;  te[4] = 0;  te[8] = a;   te[12] = 0;
24470         te[1] = 0;  te[5] = y;  te[9] = b;   te[13] = 0;
24471         te[2] = 0;  te[6] = 0;  te[10] = c;   te[14] = d;
24472         te[3] = 0;  te[7] = 0;  te[11] = - 1; te[15] = 0;
24473
24474         return this;
24475
24476     },
24477
24478     makePerspective: function ( fov, aspect, near, far ) {
24479
24480         var ymax = near * Math.tan( fov * Math.PI / 360 );
24481         var ymin = - ymax;
24482         var xmin = ymin * aspect;
24483         var xmax = ymax * aspect;
24484
24485         return this.makeFrustum( xmin, xmax, ymin, ymax, near, far );
24486
24487     },
24488
24489     makeOrthographic: function ( left, right, top, bottom, near, far ) {
24490
24491         var te = this.elements;
24492         var w = right - left;
24493         var h = top - bottom;
24494         var p = far - near;
24495
24496         var x = ( right + left ) / w;
24497         var y = ( top + bottom ) / h;
24498         var z = ( far + near ) / p;
24499
24500         te[0] = 2 / w; te[4] = 0;     te[8] = 0;      te[12] = -x;
24501         te[1] = 0;     te[5] = 2 / h; te[9] = 0;      te[13] = -y;
24502         te[2] = 0;     te[6] = 0;     te[10] = -2 / p; te[14] = -z;
24503         te[3] = 0;     te[7] = 0;     te[11] = 0;      te[15] = 1;
24504
24505         return this;
24506
24507     },
24508
24509
24510     clone: function () {
24511
24512         var te = this.elements;
24513
24514         return new THREE.Matrix4(
24515
24516             te[0], te[4], te[8], te[12],
24517             te[1], te[5], te[9], te[13],
24518             te[2], te[6], te[10], te[14],
24519             te[3], te[7], te[11], te[15]
24520
24521         );
24522
24523     }
24524
24525 };
24526
24527 THREE.Matrix4.__v1 = new THREE.Vector3();
24528 THREE.Matrix4.__v2 = new THREE.Vector3();
24529 THREE.Matrix4.__v3 = new THREE.Vector3();
24530
24531 THREE.Matrix4.__m1 = new THREE.Matrix4();
24532 THREE.Matrix4.__m2 = new THREE.Matrix4();
24533 /**
24534  * https://github.com/mrdoob/eventtarget.js/
24535  */
24536
24537 THREE.EventTarget = function () {
24538
24539     var listeners = {};
24540
24541     this.addEventListener = function ( type, listener ) {
24542
24543         if ( listeners[ type ] === undefined ) {
24544
24545             listeners[ type ] = [];
24546
24547         }
24548
24549         if ( listeners[ type ].indexOf( listener ) === - 1 ) {
24550
24551             listeners[ type ].push( listener );
24552
24553         }
24554
24555     };
24556
24557     this.dispatchEvent = function ( event ) {
24558
24559         for ( var listener in listeners[ event.type ] ) {
24560
24561             listeners[ event.type ][ listener ]( event );
24562
24563         }
24564
24565     };
24566
24567     this.removeEventListener = function ( type, listener ) {
24568
24569         var index = listeners[ type ].indexOf( listener );
24570
24571         if ( index !== - 1 ) {
24572
24573             listeners[ type ].splice( index, 1 );
24574
24575         }
24576
24577     };
24578
24579 };
24580 /**
24581  * @author mrdoob / http://mrdoob.com/
24582  * @author alteredq / http://alteredqualia.com/
24583  */
24584
24585 THREE.Frustum = function ( ) {
24586
24587     this.planes = [
24588
24589         new THREE.Vector4(),
24590         new THREE.Vector4(),
24591         new THREE.Vector4(),
24592         new THREE.Vector4(),
24593         new THREE.Vector4(),
24594         new THREE.Vector4()
24595
24596     ];
24597
24598 };
24599
24600 THREE.Frustum.prototype.setFromMatrix = function ( m ) {
24601
24602     var plane;
24603     var planes = this.planes;
24604
24605     var me = m.elements;
24606     var me0 = me[0], me1 = me[1], me2 = me[2], me3 = me[3];
24607     var me4 = me[4], me5 = me[5], me6 = me[6], me7 = me[7];
24608     var me8 = me[8], me9 = me[9], me10 = me[10], me11 = me[11];
24609     var me12 = me[12], me13 = me[13], me14 = me[14], me15 = me[15];
24610
24611     planes[ 0 ].set( me3 - me0, me7 - me4, me11 - me8, me15 - me12 );
24612     planes[ 1 ].set( me3 + me0, me7 + me4, me11 + me8, me15 + me12 );
24613     planes[ 2 ].set( me3 + me1, me7 + me5, me11 + me9, me15 + me13 );
24614     planes[ 3 ].set( me3 - me1, me7 - me5, me11 - me9, me15 - me13 );
24615     planes[ 4 ].set( me3 - me2, me7 - me6, me11 - me10, me15 - me14 );
24616     planes[ 5 ].set( me3 + me2, me7 + me6, me11 + me10, me15 + me14 );
24617
24618     for ( var i = 0; i < 6; i ++ ) {
24619
24620         plane = planes[ i ];
24621         plane.divideScalar( Math.sqrt( plane.x * plane.x + plane.y * plane.y + plane.z * plane.z ) );
24622
24623     }
24624
24625 };
24626
24627 THREE.Frustum.prototype.contains = function ( object ) {
24628
24629     var distance = 0.0;
24630     var planes = this.planes;
24631     var matrix = object.matrixWorld;
24632     var me = matrix.elements;
24633     var radius = - object.geometry.boundingSphere.radius * matrix.getMaxScaleOnAxis();
24634
24635     for ( var i = 0; i < 6; i ++ ) {
24636
24637         distance = planes[ i ].x * me[12] + planes[ i ].y * me[13] + planes[ i ].z * me[14] + planes[ i ].w;
24638         if ( distance <= radius ) return false;
24639
24640     }
24641
24642     return true;
24643
24644 };
24645
24646 THREE.Frustum.__v1 = new THREE.Vector3();
24647 /**
24648  * @author mrdoob / http://mrdoob.com/
24649  */
24650
24651 ( function ( THREE ) {
24652
24653     THREE.Ray = function ( origin, direction, near, far ) {
24654
24655         this.origin = origin || new THREE.Vector3();
24656         this.direction = direction || new THREE.Vector3();
24657         this.near = near || 0;
24658         this.far = far || Infinity;
24659
24660     };
24661
24662     var originCopy = new THREE.Vector3();
24663
24664     var localOriginCopy = new THREE.Vector3();
24665     var localDirectionCopy = new THREE.Vector3();
24666
24667     var vector = new THREE.Vector3();
24668     var normal = new THREE.Vector3();
24669     var intersectPoint = new THREE.Vector3();
24670
24671     var inverseMatrix = new THREE.Matrix4();
24672
24673     var descSort = function ( a, b ) {
24674
24675         return a.distance - b.distance;
24676
24677     };
24678
24679     var v0 = new THREE.Vector3(), v1 = new THREE.Vector3(), v2 = new THREE.Vector3();
24680
24681     var distanceFromIntersection = function ( origin, direction, position ) {
24682
24683         v0.sub( position, origin );
24684
24685         var dot = v0.dot( direction );
24686
24687         var intersect = v1.add( origin, v2.copy( direction ).multiplyScalar( dot ) );
24688         var distance = position.distanceTo( intersect );
24689
24690         return distance;
24691
24692     };
24693
24694     // http://www.blackpawn.com/texts/pointinpoly/default.html
24695
24696     var pointInFace3 = function ( p, a, b, c ) {
24697
24698         v0.sub( c, a );
24699         v1.sub( b, a );
24700         v2.sub( p, a );
24701
24702         var dot00 = v0.dot( v0 );
24703         var dot01 = v0.dot( v1 );
24704         var dot02 = v0.dot( v2 );
24705         var dot11 = v1.dot( v1 );
24706         var dot12 = v1.dot( v2 );
24707
24708         var invDenom = 1 / ( dot00 * dot11 - dot01 * dot01 );
24709         var u = ( dot11 * dot02 - dot01 * dot12 ) * invDenom;
24710         var v = ( dot00 * dot12 - dot01 * dot02 ) * invDenom;
24711
24712         return ( u >= 0 ) && ( v >= 0 ) && ( u + v < 1 );
24713
24714     };
24715
24716     var intersectObject = function ( object, ray, intersects ) {
24717
24718         var distance,intersect;
24719
24720         if ( object instanceof THREE.Particle ) {
24721
24722             distance = distanceFromIntersection( ray.origin, ray.direction, object.matrixWorld.getPosition() );
24723
24724             if ( distance > object.scale.x ) {
24725
24726                 return intersects;
24727
24728             }
24729
24730             intersect = {
24731
24732                 distance: distance,
24733                 point: object.position,
24734                 face: null,
24735                 object: object
24736
24737             };
24738
24739             intersects.push( intersect );
24740
24741         } else if ( object instanceof THREE.Mesh ) {
24742
24743             // Checking boundingSphere
24744
24745             var scaledRadius = object.geometry.boundingSphere.radius * object.matrixWorld.getMaxScaleOnAxis();
24746
24747             // Checking distance to ray
24748
24749             distance = distanceFromIntersection( ray.origin, ray.direction, object.matrixWorld.getPosition() );
24750
24751             if ( distance > scaledRadius) {
24752
24753                 return intersects;
24754
24755             }
24756
24757             // Checking faces
24758
24759             var f, fl, face, dot, scalar,
24760             geometry = object.geometry,
24761             vertices = geometry.vertices,
24762             objMatrix, geometryMaterials,
24763             isFaceMaterial, material, side, point;
24764
24765             geometryMaterials = object.geometry.materials;
24766             isFaceMaterial = object.material instanceof THREE.MeshFaceMaterial;
24767             side = object.material.side;
24768
24769             var a, b, c, d;
24770             var precision = ray.precision;
24771
24772             object.matrixRotationWorld.extractRotation( object.matrixWorld );
24773
24774             originCopy.copy( ray.origin );
24775
24776             objMatrix = object.matrixWorld;
24777             inverseMatrix.getInverse( objMatrix );
24778
24779             localOriginCopy.copy( originCopy );
24780             inverseMatrix.multiplyVector3( localOriginCopy );
24781
24782             localDirectionCopy.copy( ray.direction );
24783             inverseMatrix.rotateAxis( localDirectionCopy ).normalize();
24784
24785             for ( f = 0, fl = geometry.faces.length; f < fl; f ++ ) {
24786
24787                 face = geometry.faces[ f ];
24788
24789                 material = isFaceMaterial === true ? geometryMaterials[ face.materialIndex ] : object.material;
24790                 if ( material === undefined ) continue;
24791                 side = material.side;
24792
24793                 vector.sub( face.centroid, localOriginCopy );
24794                 normal = face.normal;
24795                 dot = localDirectionCopy.dot( normal );
24796
24797                 // bail if ray and plane are parallel
24798
24799                 if ( Math.abs( dot ) < precision ) continue;
24800
24801                 // calc distance to plane
24802
24803                 scalar = normal.dot( vector ) / dot;
24804
24805                 // if negative distance, then plane is behind ray
24806
24807                 if ( scalar < 0 ) continue;
24808
24809                 if ( side === THREE.DoubleSide || ( side === THREE.FrontSide ? dot < 0 : dot > 0 ) ) {
24810
24811                     intersectPoint.add( localOriginCopy, localDirectionCopy.multiplyScalar( scalar ) );
24812
24813                     if ( face instanceof THREE.Face3 ) {
24814
24815                         a = vertices[ face.a ];
24816                         b = vertices[ face.b ];
24817                         c = vertices[ face.c ];
24818
24819                         if ( pointInFace3( intersectPoint, a, b, c ) ) {
24820
24821                             point = object.matrixWorld.multiplyVector3( intersectPoint.clone() );
24822                             distance = originCopy.distanceTo( point );
24823
24824                             if ( distance < ray.near || distance > ray.far ) continue;
24825
24826                             intersect = {
24827
24828                                 distance: distance,
24829                                 point: point,
24830                                 face: face,
24831                                 faceIndex: f,
24832                                 object: object
24833
24834                             };
24835
24836                             intersects.push( intersect );
24837
24838                         }
24839
24840                     } else if ( face instanceof THREE.Face4 ) {
24841
24842                         a = vertices[ face.a ];
24843                         b = vertices[ face.b ];
24844                         c = vertices[ face.c ];
24845                         d = vertices[ face.d ];
24846
24847                         if ( pointInFace3( intersectPoint, a, b, d ) || pointInFace3( intersectPoint, b, c, d ) ) {
24848
24849                             point = object.matrixWorld.multiplyVector3( intersectPoint.clone() );
24850                             distance = originCopy.distanceTo( point );
24851
24852                             if ( distance < ray.near || distance > ray.far ) continue;
24853
24854                             intersect = {
24855
24856                                 distance: distance,
24857                                 point: point,
24858                                 face: face,
24859                                 faceIndex: f,
24860                                 object: object
24861
24862                             };
24863
24864                             intersects.push( intersect );
24865
24866                         }
24867
24868                     }
24869
24870                 }
24871
24872             }
24873
24874         }
24875
24876     };
24877
24878     var intersectDescendants = function ( object, ray, intersects ) {
24879
24880         var descendants = object.getDescendants();
24881
24882         for ( var i = 0, l = descendants.length; i < l; i ++ ) {
24883
24884             intersectObject( descendants[ i ], ray, intersects );
24885
24886         }
24887     };
24888
24889     //
24890
24891     THREE.Ray.prototype.precision = 0.0001;
24892
24893     THREE.Ray.prototype.set = function ( origin, direction ) {
24894
24895         this.origin = origin;
24896         this.direction = direction;
24897
24898     };
24899
24900     THREE.Ray.prototype.intersectObject = function ( object, recursive ) {
24901
24902         var intersects = [];
24903
24904         if ( recursive === true ) {
24905
24906             intersectDescendants( object, this, intersects );
24907
24908         }
24909
24910         intersectObject( object, this, intersects );
24911
24912         intersects.sort( descSort );
24913
24914         return intersects;
24915
24916     };
24917
24918     THREE.Ray.prototype.intersectObjects = function ( objects, recursive ) {
24919
24920         var intersects = [];
24921
24922         for ( var i = 0, l = objects.length; i < l; i ++ ) {
24923
24924             intersectObject( objects[ i ], this, intersects );
24925
24926             if ( recursive === true ) {
24927
24928                 intersectDescendants( objects[ i ], this, intersects );
24929
24930             }
24931         }
24932
24933         intersects.sort( descSort );
24934
24935         return intersects;
24936
24937     };
24938
24939 }( THREE ) );
24940 /**
24941  * @author mrdoob / http://mrdoob.com/
24942  */
24943
24944 THREE.Rectangle = function () {
24945
24946     var _left = 0;
24947     var _top = 0;
24948     var _right = 0;
24949     var _bottom = 0;
24950     var _width = 0;
24951     var _height = 0;
24952     var _isEmpty = true;
24953
24954     function resize() {
24955
24956         _width = _right - _left;
24957         _height = _bottom - _top;
24958
24959     }
24960
24961     this.getX = function () {
24962
24963         return _left;
24964
24965     };
24966
24967     this.getY = function () {
24968
24969         return _top;
24970
24971     };
24972
24973     this.getWidth = function () {
24974
24975         return _width;
24976
24977     };
24978
24979     this.getHeight = function () {
24980
24981         return _height;
24982
24983     };
24984
24985     this.getLeft = function() {
24986
24987         return _left;
24988
24989     };
24990
24991     this.getTop = function() {
24992
24993         return _top;
24994
24995     };
24996
24997     this.getRight = function() {
24998
24999         return _right;
25000
25001     };
25002
25003     this.getBottom = function() {
25004
25005         return _bottom;
25006
25007     };
25008
25009     this.set = function ( left, top, right, bottom ) {
25010
25011         _isEmpty = false;
25012
25013         _left = left; _top = top;
25014         _right = right; _bottom = bottom;
25015
25016         resize();
25017
25018     };
25019
25020     this.addPoint = function ( x, y ) {
25021
25022         if ( _isEmpty === true ) {
25023
25024             _isEmpty = false;
25025             _left = x; _top = y;
25026             _right = x; _bottom = y;
25027
25028             resize();
25029
25030         } else {
25031
25032             _left = _left < x ? _left : x; // Math.min( _left, x );
25033             _top = _top < y ? _top : y; // Math.min( _top, y );
25034             _right = _right > x ? _right : x; // Math.max( _right, x );
25035             _bottom = _bottom > y ? _bottom : y; // Math.max( _bottom, y );
25036
25037             resize();
25038         }
25039
25040     };
25041
25042     this.add3Points = function ( x1, y1, x2, y2, x3, y3 ) {
25043
25044         if ( _isEmpty === true ) {
25045
25046             _isEmpty = false;
25047             _left = x1 < x2 ? ( x1 < x3 ? x1 : x3 ) : ( x2 < x3 ? x2 : x3 );
25048             _top = y1 < y2 ? ( y1 < y3 ? y1 : y3 ) : ( y2 < y3 ? y2 : y3 );
25049             _right = x1 > x2 ? ( x1 > x3 ? x1 : x3 ) : ( x2 > x3 ? x2 : x3 );
25050             _bottom = y1 > y2 ? ( y1 > y3 ? y1 : y3 ) : ( y2 > y3 ? y2 : y3 );
25051
25052             resize();
25053
25054         } else {
25055
25056             _left = x1 < x2 ? ( x1 < x3 ? ( x1 < _left ? x1 : _left ) : ( x3 < _left ? x3 : _left ) ) : ( x2 < x3 ? ( x2 < _left ? x2 : _left ) : ( x3 < _left ? x3 : _left ) );
25057             _top = y1 < y2 ? ( y1 < y3 ? ( y1 < _top ? y1 : _top ) : ( y3 < _top ? y3 : _top ) ) : ( y2 < y3 ? ( y2 < _top ? y2 : _top ) : ( y3 < _top ? y3 : _top ) );
25058             _right = x1 > x2 ? ( x1 > x3 ? ( x1 > _right ? x1 : _right ) : ( x3 > _right ? x3 : _right ) ) : ( x2 > x3 ? ( x2 > _right ? x2 : _right ) : ( x3 > _right ? x3 : _right ) );
25059             _bottom = y1 > y2 ? ( y1 > y3 ? ( y1 > _bottom ? y1 : _bottom ) : ( y3 > _bottom ? y3 : _bottom ) ) : ( y2 > y3 ? ( y2 > _bottom ? y2 : _bottom ) : ( y3 > _bottom ? y3 : _bottom ) );
25060
25061             resize();
25062
25063         };
25064
25065     };
25066
25067     this.addRectangle = function ( r ) {
25068
25069         if ( _isEmpty === true ) {
25070
25071             _isEmpty = false;
25072             _left = r.getLeft(); _top = r.getTop();
25073             _right = r.getRight(); _bottom = r.getBottom();
25074
25075             resize();
25076
25077         } else {
25078
25079             _left = _left < r.getLeft() ? _left : r.getLeft(); // Math.min(_left, r.getLeft() );
25080             _top = _top < r.getTop() ? _top : r.getTop(); // Math.min(_top, r.getTop() );
25081             _right = _right > r.getRight() ? _right : r.getRight(); // Math.max(_right, r.getRight() );
25082             _bottom = _bottom > r.getBottom() ? _bottom : r.getBottom(); // Math.max(_bottom, r.getBottom() );
25083
25084             resize();
25085
25086         }
25087
25088     };
25089
25090     this.inflate = function ( v ) {
25091
25092         _left -= v; _top -= v;
25093         _right += v; _bottom += v;
25094
25095         resize();
25096
25097     };
25098
25099     this.minSelf = function ( r ) {
25100
25101         _left = _left > r.getLeft() ? _left : r.getLeft(); // Math.max( _left, r.getLeft() );
25102         _top = _top > r.getTop() ? _top : r.getTop(); // Math.max( _top, r.getTop() );
25103         _right = _right < r.getRight() ? _right : r.getRight(); // Math.min( _right, r.getRight() );
25104         _bottom = _bottom < r.getBottom() ? _bottom : r.getBottom(); // Math.min( _bottom, r.getBottom() );
25105
25106         resize();
25107
25108     };
25109
25110     this.intersects = function ( r ) {
25111
25112         // http://gamemath.com/2011/09/detecting-whether-two-boxes-overlap/
25113
25114         if ( _right < r.getLeft() ) return false;
25115         if ( _left > r.getRight() ) return false;
25116         if ( _bottom < r.getTop() ) return false;
25117         if ( _top > r.getBottom() ) return false;
25118
25119         return true;
25120
25121     };
25122
25123     this.empty = function () {
25124
25125         _isEmpty = true;
25126
25127         _left = 0; _top = 0;
25128         _right = 0; _bottom = 0;
25129
25130         resize();
25131
25132     };
25133
25134     this.isEmpty = function () {
25135
25136         return _isEmpty;
25137
25138     };
25139
25140 };
25141 /**
25142  * @author alteredq / http://alteredqualia.com/
25143  */
25144
25145 THREE.Math = {
25146
25147     // Clamp value to range <a, b>
25148
25149     clamp: function ( x, a, b ) {
25150
25151         return ( x < a ) ? a : ( ( x > b ) ? b : x );
25152
25153     },
25154
25155     // Clamp value to range <a, inf)
25156
25157     clampBottom: function ( x, a ) {
25158
25159         return x < a ? a : x;
25160
25161     },
25162
25163     // Linear mapping from range <a1, a2> to range <b1, b2>
25164
25165     mapLinear: function ( x, a1, a2, b1, b2 ) {
25166
25167         return b1 + ( x - a1 ) * ( b2 - b1 ) / ( a2 - a1 );
25168
25169     },
25170
25171     // Random float from <0, 1> with 16 bits of randomness
25172     // (standard Math.random() creates repetitive patterns when applied over larger space)
25173
25174     random16: function () {
25175
25176         return ( 65280 * Math.random() + 255 * Math.random() ) / 65535;
25177
25178     },
25179
25180     // Random integer from <low, high> interval
25181
25182     randInt: function ( low, high ) {
25183
25184         return low + Math.floor( Math.random() * ( high - low + 1 ) );
25185
25186     },
25187
25188     // Random float from <low, high> interval
25189
25190     randFloat: function ( low, high ) {
25191
25192         return low + Math.random() * ( high - low );
25193
25194     },
25195
25196     // Random float from <-range/2, range/2> interval
25197
25198     randFloatSpread: function ( range ) {
25199
25200         return range * ( 0.5 - Math.random() );
25201
25202     },
25203
25204     sign: function ( x ) {
25205
25206         return ( x < 0 ) ? -1 : ( ( x > 0 ) ? 1 : 0 );
25207
25208     }
25209
25210 };
25211 /**
25212  * @author mrdoob / http://mrdoob.com/
25213  * @author mikael emtinger / http://gomo.se/
25214  * @author alteredq / http://alteredqualia.com/
25215  */
25216
25217 THREE.Object3D = function () {
25218
25219     this.id = THREE.Object3DCount ++;
25220
25221     this.name = '';
25222     this.properties = {};
25223
25224     this.parent = undefined;
25225     this.children = [];
25226
25227     this.up = new THREE.Vector3( 0, 1, 0 );
25228
25229     this.position = new THREE.Vector3();
25230     this.rotation = new THREE.Vector3();
25231     this.eulerOrder = 'XYZ';
25232     this.scale = new THREE.Vector3( 1, 1, 1 );
25233
25234     this.renderDepth = null;
25235
25236     this.rotationAutoUpdate = true;
25237
25238     this.matrix = new THREE.Matrix4();
25239     this.matrixWorld = new THREE.Matrix4();
25240     this.matrixRotationWorld = new THREE.Matrix4();
25241
25242     this.matrixAutoUpdate = true;
25243     this.matrixWorldNeedsUpdate = true;
25244
25245     this.quaternion = new THREE.Quaternion();
25246     this.useQuaternion = false;
25247
25248     this.boundRadius = 0.0;
25249     this.boundRadiusScale = 1.0;
25250
25251     this.visible = true;
25252
25253     this.castShadow = false;
25254     this.receiveShadow = false;
25255
25256     this.frustumCulled = true;
25257
25258     this._vector = new THREE.Vector3();
25259
25260 };
25261
25262
25263 THREE.Object3D.prototype = {
25264
25265     constructor: THREE.Object3D,
25266
25267     applyMatrix: function ( matrix ) {
25268
25269         this.matrix.multiply( matrix, this.matrix );
25270
25271         this.scale.getScaleFromMatrix( this.matrix );
25272
25273         var mat = new THREE.Matrix4().extractRotation( this.matrix );
25274         this.rotation.setEulerFromRotationMatrix( mat, this.eulerOrder );
25275
25276         this.position.getPositionFromMatrix( this.matrix );
25277
25278     },
25279
25280     translate: function ( distance, axis ) {
25281
25282         this.matrix.rotateAxis( axis );
25283         this.position.addSelf( axis.multiplyScalar( distance ) );
25284
25285     },
25286
25287     translateX: function ( distance ) {
25288
25289         this.translate( distance, this._vector.set( 1, 0, 0 ) );
25290
25291     },
25292
25293     translateY: function ( distance ) {
25294
25295         this.translate( distance, this._vector.set( 0, 1, 0 ) );
25296
25297     },
25298
25299     translateZ: function ( distance ) {
25300
25301         this.translate( distance, this._vector.set( 0, 0, 1 ) );
25302
25303     },
25304
25305     localToWorld: function ( vector ) {
25306
25307         return this.matrixWorld.multiplyVector3( vector );
25308
25309     },
25310
25311     worldToLocal: function ( vector ) {
25312
25313         return THREE.Object3D.__m1.getInverse( this.matrixWorld ).multiplyVector3( vector );
25314
25315     },
25316
25317     lookAt: function ( vector ) {
25318
25319         // TODO: Add hierarchy support.
25320
25321         this.matrix.lookAt( vector, this.position, this.up );
25322
25323         if ( this.rotationAutoUpdate ) {
25324
25325             this.rotation.setEulerFromRotationMatrix( this.matrix, this.eulerOrder );
25326
25327         }
25328
25329     },
25330
25331     add: function ( object ) {
25332
25333         if ( object === this ) {
25334
25335             console.warn( 'THREE.Object3D.add: An object can\'t be added as a child of itself.' );
25336             return;
25337
25338         }
25339
25340         if ( object instanceof THREE.Object3D ) {
25341
25342             if ( object.parent !== undefined ) {
25343
25344                 object.parent.remove( object );
25345
25346             }
25347
25348             object.parent = this;
25349             this.children.push( object );
25350
25351             // add to scene
25352
25353             var scene = this;
25354
25355             while ( scene.parent !== undefined ) {
25356
25357                 scene = scene.parent;
25358
25359             }
25360
25361             if ( scene !== undefined && scene instanceof THREE.Scene )  {
25362
25363                 scene.__addObject( object );
25364
25365             }
25366
25367         }
25368
25369     },
25370
25371     remove: function ( object ) {
25372
25373         var index = this.children.indexOf( object );
25374
25375         if ( index !== - 1 ) {
25376
25377             object.parent = undefined;
25378             this.children.splice( index, 1 );
25379
25380             // remove from scene
25381
25382             var scene = this;
25383
25384             while ( scene.parent !== undefined ) {
25385
25386                 scene = scene.parent;
25387
25388             }
25389
25390             if ( scene !== undefined && scene instanceof THREE.Scene ) {
25391
25392                 scene.__removeObject( object );
25393
25394             }
25395
25396         }
25397
25398     },
25399
25400     getChildByName: function ( name, recursive ) {
25401
25402         var c, cl, child;
25403
25404         for ( c = 0, cl = this.children.length; c < cl; c ++ ) {
25405
25406             child = this.children[ c ];
25407
25408             if ( child.name === name ) {
25409
25410                 return child;
25411
25412             }
25413
25414             if ( recursive ) {
25415
25416                 child = child.getChildByName( name, recursive );
25417
25418                 if ( child !== undefined ) {
25419
25420                     return child;
25421
25422                 }
25423
25424             }
25425
25426         }
25427
25428         return undefined;
25429
25430     },
25431
25432     getDescendants: function ( array ) {
25433
25434         if ( array === undefined ) array = [];
25435
25436         Array.prototype.push.apply( array, this.children );
25437
25438         for ( var i = 0, l = this.children.length; i < l; i ++ ) {
25439
25440             this.children[ i ].getDescendants( array );
25441
25442         };
25443
25444         return array;
25445
25446     },
25447
25448     updateMatrix: function () {
25449
25450         this.matrix.setPosition( this.position );
25451
25452         if ( this.useQuaternion === false )  {
25453
25454             this.matrix.setRotationFromEuler( this.rotation, this.eulerOrder );
25455
25456         } else {
25457
25458             this.matrix.setRotationFromQuaternion( this.quaternion );
25459
25460         }
25461
25462         if ( this.scale.x !== 1 || this.scale.y !== 1 || this.scale.z !== 1 ) {
25463
25464             this.matrix.scale( this.scale );
25465             this.boundRadiusScale = Math.max( this.scale.x, Math.max( this.scale.y, this.scale.z ) );
25466
25467         }
25468
25469         this.matrixWorldNeedsUpdate = true;
25470
25471     },
25472
25473     updateMatrixWorld: function ( force ) {
25474
25475         if ( this.matrixAutoUpdate === true ) this.updateMatrix();
25476
25477         if ( this.matrixWorldNeedsUpdate === true || force === true ) {
25478
25479             if ( this.parent === undefined ) {
25480
25481                 this.matrixWorld.copy( this.matrix );
25482
25483             } else {
25484
25485                 this.matrixWorld.multiply( this.parent.matrixWorld, this.matrix );
25486
25487             }
25488
25489             this.matrixWorldNeedsUpdate = false;
25490
25491             force = true;
25492
25493         }
25494
25495         // update children
25496
25497         for ( var i = 0, l = this.children.length; i < l; i ++ ) {
25498
25499             this.children[ i ].updateMatrixWorld( force );
25500
25501         }
25502
25503     },
25504
25505     clone: function () {
25506
25507         // TODO
25508
25509     }
25510
25511 };
25512
25513 THREE.Object3D.__m1 = new THREE.Matrix4();
25514
25515 THREE.Object3DCount = 0;
25516 /**
25517  * @author mrdoob / http://mrdoob.com/
25518  * @author supereggbert / http://www.paulbrunt.co.uk/
25519  * @author julianwa / https://github.com/julianwa
25520  */
25521
25522 THREE.Projector = function() {
25523
25524     var _object, _objectCount, _objectPool = [], _objectPoolLength = 0,
25525     _vertex, _vertexCount, _vertexPool = [], _vertexPoolLength = 0,
25526     _face, _face3Count, _face3Pool = [], _face3PoolLength = 0,
25527     _face4Count, _face4Pool = [], _face4PoolLength = 0,
25528     _line, _lineCount, _linePool = [], _linePoolLength = 0,
25529     _particle, _particleCount, _particlePool = [], _particlePoolLength = 0,
25530
25531     _renderData = { objects: [], sprites: [], lights: [], elements: [] },
25532
25533     _vector3 = new THREE.Vector3(),
25534     _vector4 = new THREE.Vector4(),
25535
25536     _viewProjectionMatrix = new THREE.Matrix4(),
25537     _modelViewProjectionMatrix = new THREE.Matrix4(),
25538
25539     _frustum = new THREE.Frustum(),
25540
25541     _clippedVertex1PositionScreen = new THREE.Vector4(),
25542     _clippedVertex2PositionScreen = new THREE.Vector4(),
25543
25544     _face3VertexNormals;
25545
25546     this.projectVector = function ( vector, camera ) {
25547
25548         camera.matrixWorldInverse.getInverse( camera.matrixWorld );
25549
25550         _viewProjectionMatrix.multiply( camera.projectionMatrix, camera.matrixWorldInverse );
25551         _viewProjectionMatrix.multiplyVector3( vector );
25552
25553         return vector;
25554
25555     };
25556
25557     this.unprojectVector = function ( vector, camera ) {
25558
25559         camera.projectionMatrixInverse.getInverse( camera.projectionMatrix );
25560
25561         _viewProjectionMatrix.multiply( camera.matrixWorld, camera.projectionMatrixInverse );
25562         _viewProjectionMatrix.multiplyVector3( vector );
25563
25564         return vector;
25565
25566     };
25567
25568     this.pickingRay = function ( vector, camera ) {
25569
25570         var end, ray, t;
25571
25572         // set two vectors with opposing z values
25573         vector.z = -1.0;
25574         end = new THREE.Vector3( vector.x, vector.y, 1.0 );
25575
25576         this.unprojectVector( vector, camera );
25577         this.unprojectVector( end, camera );
25578
25579         // find direction from vector to end
25580         end.subSelf( vector ).normalize();
25581
25582         return new THREE.Ray( vector, end );
25583
25584     };
25585
25586     var projectGraph = function ( root, sortObjects ) {
25587
25588         _objectCount = 0;
25589
25590         _renderData.objects.length = 0;
25591         _renderData.sprites.length = 0;
25592         _renderData.lights.length = 0;
25593
25594         var projectObject = function ( parent ) {
25595
25596             for ( var c = 0, cl = parent.children.length; c < cl; c ++ ) {
25597
25598                 var object = parent.children[ c ];
25599
25600                 if ( object.visible === false ) continue;
25601
25602                 if ( object instanceof THREE.Light ) {
25603
25604                     _renderData.lights.push( object );
25605
25606                 } else if ( object instanceof THREE.Mesh || object instanceof THREE.Line ) {
25607
25608                     if ( object.frustumCulled === false || _frustum.contains( object ) === true ) {
25609
25610                         _object = getNextObjectInPool();
25611                         _object.object = object;
25612
25613                         if ( object.renderDepth !== null ) {
25614
25615                             _object.z = object.renderDepth;
25616
25617                         } else {
25618
25619                             _vector3.copy( object.matrixWorld.getPosition() );
25620                             _viewProjectionMatrix.multiplyVector3( _vector3 );
25621                             _object.z = _vector3.z;
25622
25623                         }
25624
25625                         _renderData.objects.push( _object );
25626
25627                     }
25628
25629                 } else if ( object instanceof THREE.Sprite || object instanceof THREE.Particle ) {
25630
25631                     _object = getNextObjectInPool();
25632                     _object.object = object;
25633
25634                     // TODO: Find an elegant and performant solution and remove this dupe code.
25635
25636                     if ( object.renderDepth !== null ) {
25637
25638                         _object.z = object.renderDepth;
25639
25640                     } else {
25641
25642                         _vector3.copy( object.matrixWorld.getPosition() );
25643                         _viewProjectionMatrix.multiplyVector3( _vector3 );
25644                         _object.z = _vector3.z;
25645
25646                     }
25647
25648                     _renderData.sprites.push( _object );
25649
25650                 } else {
25651
25652                     _object = getNextObjectInPool();
25653                     _object.object = object;
25654
25655                     if ( object.renderDepth !== null ) {
25656
25657                         _object.z = object.renderDepth;
25658
25659                     } else {
25660
25661                         _vector3.copy( object.matrixWorld.getPosition() );
25662                         _viewProjectionMatrix.multiplyVector3( _vector3 );
25663                         _object.z = _vector3.z;
25664
25665                     }
25666
25667                     _renderData.objects.push( _object );
25668
25669                 }
25670
25671                 projectObject( object );
25672
25673             }
25674
25675         };
25676
25677         projectObject( root );
25678
25679         if ( sortObjects === true ) _renderData.objects.sort( painterSort );
25680
25681         return _renderData;
25682
25683     };
25684
25685     this.projectScene = function ( scene, camera, sortObjects, sortElements ) {
25686
25687         var near = camera.near, far = camera.far, visible = false,
25688         o, ol, v, vl, f, fl, n, nl, c, cl, u, ul, object,
25689         modelMatrix, rotationMatrix,
25690         geometry, geometryMaterials, vertices, vertex, vertexPositionScreen,
25691         faces, face, faceVertexNormals, normal, faceVertexUvs, uvs,
25692         v1, v2, v3, v4, isFaceMaterial, material, side;
25693
25694         _face3Count = 0;
25695         _face4Count = 0;
25696         _lineCount = 0;
25697         _particleCount = 0;
25698
25699         _renderData.elements.length = 0;
25700
25701         scene.updateMatrixWorld();
25702
25703         if ( camera.parent === undefined ) camera.updateMatrixWorld();
25704
25705         camera.matrixWorldInverse.getInverse( camera.matrixWorld );
25706
25707         _viewProjectionMatrix.multiply( camera.projectionMatrix, camera.matrixWorldInverse );
25708
25709         _frustum.setFromMatrix( _viewProjectionMatrix );
25710
25711         _renderData = projectGraph( scene, sortObjects );
25712
25713         for ( o = 0, ol = _renderData.objects.length; o < ol; o++ ) {
25714
25715             object = _renderData.objects[ o ].object;
25716
25717             modelMatrix = object.matrixWorld;
25718
25719             _vertexCount = 0;
25720
25721             if ( object instanceof THREE.Mesh ) {
25722
25723                 geometry = object.geometry;
25724                 geometryMaterials = object.geometry.materials;
25725                 vertices = geometry.vertices;
25726                 faces = geometry.faces;
25727                 faceVertexUvs = geometry.faceVertexUvs;
25728
25729                 rotationMatrix = object.matrixRotationWorld.extractRotation( modelMatrix );
25730
25731                 isFaceMaterial = object.material instanceof THREE.MeshFaceMaterial;
25732                 side = object.material.side;
25733
25734                 for ( v = 0, vl = vertices.length; v < vl; v ++ ) {
25735
25736                     _vertex = getNextVertexInPool();
25737                     _vertex.positionWorld.copy( vertices[ v ] );
25738
25739                     modelMatrix.multiplyVector3( _vertex.positionWorld );
25740
25741                     _vertex.positionScreen.copy( _vertex.positionWorld );
25742                     _viewProjectionMatrix.multiplyVector4( _vertex.positionScreen );
25743
25744                     _vertex.positionScreen.x /= _vertex.positionScreen.w;
25745                     _vertex.positionScreen.y /= _vertex.positionScreen.w;
25746
25747                     _vertex.visible = _vertex.positionScreen.z > near && _vertex.positionScreen.z < far;
25748
25749                 }
25750
25751                 for ( f = 0, fl = faces.length; f < fl; f ++ ) {
25752
25753                     face = faces[ f ];
25754
25755                     material = isFaceMaterial === true ? geometryMaterials[ face.materialIndex ] : object.material;
25756
25757                     if ( material === undefined ) continue;
25758
25759                     side = material.side;
25760
25761                     if ( face instanceof THREE.Face3 ) {
25762
25763                         v1 = _vertexPool[ face.a ];
25764                         v2 = _vertexPool[ face.b ];
25765                         v3 = _vertexPool[ face.c ];
25766
25767                         if ( v1.visible === true && v2.visible === true && v3.visible === true ) {
25768
25769                             visible = ( ( v3.positionScreen.x - v1.positionScreen.x ) * ( v2.positionScreen.y - v1.positionScreen.y ) -
25770                                 ( v3.positionScreen.y - v1.positionScreen.y ) * ( v2.positionScreen.x - v1.positionScreen.x ) ) < 0;
25771
25772                             if ( side === THREE.DoubleSide || visible === ( side === THREE.FrontSide ) ) {
25773
25774                                 _face = getNextFace3InPool();
25775
25776                                 _face.v1.copy( v1 );
25777                                 _face.v2.copy( v2 );
25778                                 _face.v3.copy( v3 );
25779
25780                             } else {
25781
25782                                 continue;
25783
25784                             }
25785
25786                         } else {
25787
25788                             continue;
25789
25790                         }
25791
25792                     } else if ( face instanceof THREE.Face4 ) {
25793
25794                         v1 = _vertexPool[ face.a ];
25795                         v2 = _vertexPool[ face.b ];
25796                         v3 = _vertexPool[ face.c ];
25797                         v4 = _vertexPool[ face.d ];
25798
25799                         if ( v1.visible === true && v2.visible === true && v3.visible === true && v4.visible === true ) {
25800
25801                             visible = ( v4.positionScreen.x - v1.positionScreen.x ) * ( v2.positionScreen.y - v1.positionScreen.y ) -
25802                                 ( v4.positionScreen.y - v1.positionScreen.y ) * ( v2.positionScreen.x - v1.positionScreen.x ) < 0 ||
25803                                 ( v2.positionScreen.x - v3.positionScreen.x ) * ( v4.positionScreen.y - v3.positionScreen.y ) -
25804                                 ( v2.positionScreen.y - v3.positionScreen.y ) * ( v4.positionScreen.x - v3.positionScreen.x ) < 0;
25805
25806
25807                             if ( side === THREE.DoubleSide || visible === ( side === THREE.FrontSide ) ) {
25808
25809                                 _face = getNextFace4InPool();
25810
25811                                 _face.v1.copy( v1 );
25812                                 _face.v2.copy( v2 );
25813                                 _face.v3.copy( v3 );
25814                                 _face.v4.copy( v4 );
25815
25816                             } else {
25817
25818                                 continue;
25819
25820                             }
25821
25822                         } else {
25823
25824                             continue;
25825
25826                         }
25827
25828                     }
25829
25830                     _face.normalWorld.copy( face.normal );
25831
25832                     if ( visible === false && ( side === THREE.BackSide || side === THREE.DoubleSide ) ) _face.normalWorld.negate();
25833                     rotationMatrix.multiplyVector3( _face.normalWorld );
25834
25835                     _face.centroidWorld.copy( face.centroid );
25836                     modelMatrix.multiplyVector3( _face.centroidWorld );
25837
25838                     _face.centroidScreen.copy( _face.centroidWorld );
25839                     _viewProjectionMatrix.multiplyVector3( _face.centroidScreen );
25840
25841                     faceVertexNormals = face.vertexNormals;
25842
25843                     for ( n = 0, nl = faceVertexNormals.length; n < nl; n ++ ) {
25844
25845                         normal = _face.vertexNormalsWorld[ n ];
25846                         normal.copy( faceVertexNormals[ n ] );
25847
25848                         if ( visible === false && ( side === THREE.BackSide || side === THREE.DoubleSide ) ) normal.negate();
25849
25850                         rotationMatrix.multiplyVector3( normal );
25851
25852                     }
25853
25854                     _face.vertexNormalsLength = faceVertexNormals.length;
25855
25856                     for ( c = 0, cl = faceVertexUvs.length; c < cl; c ++ ) {
25857
25858                         uvs = faceVertexUvs[ c ][ f ];
25859
25860                         if ( uvs === undefined ) continue;
25861
25862                         for ( u = 0, ul = uvs.length; u < ul; u ++ ) {
25863
25864                             _face.uvs[ c ][ u ] = uvs[ u ];
25865
25866                         }
25867
25868                     }
25869
25870                     _face.material = material;
25871
25872                     _face.z = _face.centroidScreen.z;
25873
25874                     _renderData.elements.push( _face );
25875
25876                 }
25877
25878             } else if ( object instanceof THREE.Line ) {
25879
25880                 _modelViewProjectionMatrix.multiply( _viewProjectionMatrix, modelMatrix );
25881
25882                 vertices = object.geometry.vertices;
25883
25884                 v1 = getNextVertexInPool();
25885                 v1.positionScreen.copy( vertices[ 0 ] );
25886                 _modelViewProjectionMatrix.multiplyVector4( v1.positionScreen );
25887
25888                 // Handle LineStrip and LinePieces
25889                 var step = object.type === THREE.LinePieces ? 2 : 1;
25890
25891                 for ( v = 1, vl = vertices.length; v < vl; v ++ ) {
25892
25893                     v1 = getNextVertexInPool();
25894                     v1.positionScreen.copy( vertices[ v ] );
25895                     _modelViewProjectionMatrix.multiplyVector4( v1.positionScreen );
25896
25897                     if ( ( v + 1 ) % step > 0 ) continue;
25898
25899                     v2 = _vertexPool[ _vertexCount - 2 ];
25900
25901                     _clippedVertex1PositionScreen.copy( v1.positionScreen );
25902                     _clippedVertex2PositionScreen.copy( v2.positionScreen );
25903
25904                     if ( clipLine( _clippedVertex1PositionScreen, _clippedVertex2PositionScreen ) === true ) {
25905
25906                         // Perform the perspective divide
25907                         _clippedVertex1PositionScreen.multiplyScalar( 1 / _clippedVertex1PositionScreen.w );
25908                         _clippedVertex2PositionScreen.multiplyScalar( 1 / _clippedVertex2PositionScreen.w );
25909
25910                         _line = getNextLineInPool();
25911                         _line.v1.positionScreen.copy( _clippedVertex1PositionScreen );
25912                         _line.v2.positionScreen.copy( _clippedVertex2PositionScreen );
25913
25914                         _line.z = Math.max( _clippedVertex1PositionScreen.z, _clippedVertex2PositionScreen.z );
25915
25916                         _line.material = object.material;
25917
25918                         _renderData.elements.push( _line );
25919
25920                     }
25921
25922                 }
25923
25924             }
25925
25926         }
25927
25928         for ( o = 0, ol = _renderData.sprites.length; o < ol; o++ ) {
25929
25930             object = _renderData.sprites[ o ].object;
25931
25932             modelMatrix = object.matrixWorld;
25933
25934             if ( object instanceof THREE.Particle ) {
25935
25936                 _vector4.set( modelMatrix.elements[12], modelMatrix.elements[13], modelMatrix.elements[14], 1 );
25937                 _viewProjectionMatrix.multiplyVector4( _vector4 );
25938
25939                 _vector4.z /= _vector4.w;
25940
25941                 if ( _vector4.z > 0 && _vector4.z < 1 ) {
25942
25943                     _particle = getNextParticleInPool();
25944                     _particle.object = object;
25945                     _particle.x = _vector4.x / _vector4.w;
25946                     _particle.y = _vector4.y / _vector4.w;
25947                     _particle.z = _vector4.z;
25948
25949                     _particle.rotation = object.rotation.z;
25950
25951                     _particle.scale.x = object.scale.x * Math.abs( _particle.x - ( _vector4.x + camera.projectionMatrix.elements[0] ) / ( _vector4.w + camera.projectionMatrix.elements[12] ) );
25952                     _particle.scale.y = object.scale.y * Math.abs( _particle.y - ( _vector4.y + camera.projectionMatrix.elements[5] ) / ( _vector4.w + camera.projectionMatrix.elements[13] ) );
25953
25954                     _particle.material = object.material;
25955
25956                     _renderData.elements.push( _particle );
25957
25958                 }
25959
25960             }
25961
25962         }
25963
25964         if ( sortElements === true ) _renderData.elements.sort( painterSort );
25965
25966         return _renderData;
25967
25968     };
25969
25970     // Pools
25971
25972     function getNextObjectInPool() {
25973
25974         if ( _objectCount === _objectPoolLength ) {
25975
25976             var object = new THREE.RenderableObject();
25977             _objectPool.push( object );
25978             _objectPoolLength ++;
25979             _objectCount ++;
25980             return object;
25981
25982         }
25983
25984         return _objectPool[ _objectCount ++ ];
25985
25986     }
25987
25988     function getNextVertexInPool() {
25989
25990         if ( _vertexCount === _vertexPoolLength ) {
25991
25992             var vertex = new THREE.RenderableVertex();
25993             _vertexPool.push( vertex );
25994             _vertexPoolLength ++;
25995             _vertexCount ++;
25996             return vertex;
25997
25998         }
25999
26000         return _vertexPool[ _vertexCount ++ ];
26001
26002     }
26003
26004     function getNextFace3InPool() {
26005
26006         if ( _face3Count === _face3PoolLength ) {
26007
26008             var face = new THREE.RenderableFace3();
26009             _face3Pool.push( face );
26010             _face3PoolLength ++;
26011             _face3Count ++;
26012             return face;
26013
26014         }
26015
26016         return _face3Pool[ _face3Count ++ ];
26017
26018
26019     }
26020
26021     function getNextFace4InPool() {
26022
26023         if ( _face4Count === _face4PoolLength ) {
26024
26025             var face = new THREE.RenderableFace4();
26026             _face4Pool.push( face );
26027             _face4PoolLength ++;
26028             _face4Count ++;
26029             return face;
26030
26031         }
26032
26033         return _face4Pool[ _face4Count ++ ];
26034
26035     }
26036
26037     function getNextLineInPool() {
26038
26039         if ( _lineCount === _linePoolLength ) {
26040
26041             var line = new THREE.RenderableLine();
26042             _linePool.push( line );
26043             _linePoolLength ++;
26044             _lineCount ++
26045             return line;
26046
26047         }
26048
26049         return _linePool[ _lineCount ++ ];
26050
26051     }
26052
26053     function getNextParticleInPool() {
26054
26055         if ( _particleCount === _particlePoolLength ) {
26056
26057             var particle = new THREE.RenderableParticle();
26058             _particlePool.push( particle );
26059             _particlePoolLength ++;
26060             _particleCount ++
26061             return particle;
26062
26063         }
26064
26065         return _particlePool[ _particleCount ++ ];
26066
26067     }
26068
26069     //
26070
26071     function painterSort( a, b ) {
26072
26073         return b.z - a.z;
26074
26075     }
26076
26077     function clipLine( s1, s2 ) {
26078
26079         var alpha1 = 0, alpha2 = 1,
26080
26081         // Calculate the boundary coordinate of each vertex for the near and far clip planes,
26082         // Z = -1 and Z = +1, respectively.
26083         bc1near =  s1.z + s1.w,
26084         bc2near =  s2.z + s2.w,
26085         bc1far =  - s1.z + s1.w,
26086         bc2far =  - s2.z + s2.w;
26087
26088         if ( bc1near >= 0 && bc2near >= 0 && bc1far >= 0 && bc2far >= 0 ) {
26089
26090             // Both vertices lie entirely within all clip planes.
26091             return true;
26092
26093         } else if ( ( bc1near < 0 && bc2near < 0) || (bc1far < 0 && bc2far < 0 ) ) {
26094
26095             // Both vertices lie entirely outside one of the clip planes.
26096             return false;
26097
26098         } else {
26099
26100             // The line segment spans at least one clip plane.
26101
26102             if ( bc1near < 0 ) {
26103
26104                 // v1 lies outside the near plane, v2 inside
26105                 alpha1 = Math.max( alpha1, bc1near / ( bc1near - bc2near ) );
26106
26107             } else if ( bc2near < 0 ) {
26108
26109                 // v2 lies outside the near plane, v1 inside
26110                 alpha2 = Math.min( alpha2, bc1near / ( bc1near - bc2near ) );
26111
26112             }
26113
26114             if ( bc1far < 0 ) {
26115
26116                 // v1 lies outside the far plane, v2 inside
26117                 alpha1 = Math.max( alpha1, bc1far / ( bc1far - bc2far ) );
26118
26119             } else if ( bc2far < 0 ) {
26120
26121                 // v2 lies outside the far plane, v2 inside
26122                 alpha2 = Math.min( alpha2, bc1far / ( bc1far - bc2far ) );
26123
26124             }
26125
26126             if ( alpha2 < alpha1 ) {
26127
26128                 // The line segment spans two boundaries, but is outside both of them.
26129                 // (This can't happen when we're only clipping against just near/far but good
26130                 //  to leave the check here for future usage if other clip planes are added.)
26131                 return false;
26132
26133             } else {
26134
26135                 // Update the s1 and s2 vertices to match the clipped line segment.
26136                 s1.lerpSelf( s2, alpha1 );
26137                 s2.lerpSelf( s1, 1 - alpha2 );
26138
26139                 return true;
26140
26141             }
26142
26143         }
26144
26145     }
26146
26147 };
26148 /**
26149  * @author mikael emtinger / http://gomo.se/
26150  * @author alteredq / http://alteredqualia.com/
26151  * @author WestLangley / http://github.com/WestLangley
26152  */
26153
26154 THREE.Quaternion = function( x, y, z, w ) {
26155
26156     this.x = x || 0;
26157     this.y = y || 0;
26158     this.z = z || 0;
26159     this.w = ( w !== undefined ) ? w : 1;
26160
26161 };
26162
26163 THREE.Quaternion.prototype = {
26164
26165     constructor: THREE.Quaternion,
26166
26167     set: function ( x, y, z, w ) {
26168
26169         this.x = x;
26170         this.y = y;
26171         this.z = z;
26172         this.w = w;
26173
26174         return this;
26175
26176     },
26177
26178     copy: function ( q ) {
26179
26180         this.x = q.x;
26181         this.y = q.y;
26182         this.z = q.z;
26183         this.w = q.w;
26184
26185         return this;
26186
26187     },
26188
26189     setFromEuler: function ( v, order ) {
26190
26191         // http://www.mathworks.com/matlabcentral/fileexchange/
26192         //     20696-function-to-convert-between-dcm-euler-angles-quaternions-and-euler-vectors/
26193         //    content/SpinCalc.m
26194
26195         var c1 = Math.cos( v.x / 2 );
26196         var c2 = Math.cos( v.y / 2 );
26197         var c3 = Math.cos( v.z / 2 );
26198         var s1 = Math.sin( v.x / 2 );
26199         var s2 = Math.sin( v.y / 2 );
26200         var s3 = Math.sin( v.z / 2 );
26201
26202         if ( order === undefined || order === 'XYZ' ) {
26203
26204             this.x = s1 * c2 * c3 + c1 * s2 * s3;
26205             this.y = c1 * s2 * c3 - s1 * c2 * s3;
26206             this.z = c1 * c2 * s3 + s1 * s2 * c3;
26207             this.w = c1 * c2 * c3 - s1 * s2 * s3;
26208
26209         } else if ( order === 'YXZ' ) {
26210
26211             this.x = s1 * c2 * c3 + c1 * s2 * s3;
26212             this.y = c1 * s2 * c3 - s1 * c2 * s3;
26213             this.z = c1 * c2 * s3 - s1 * s2 * c3;
26214             this.w = c1 * c2 * c3 + s1 * s2 * s3;
26215
26216         } else if ( order === 'ZXY' ) {
26217
26218             this.x = s1 * c2 * c3 - c1 * s2 * s3;
26219             this.y = c1 * s2 * c3 + s1 * c2 * s3;
26220             this.z = c1 * c2 * s3 + s1 * s2 * c3;
26221             this.w = c1 * c2 * c3 - s1 * s2 * s3;
26222
26223         } else if ( order === 'ZYX' ) {
26224
26225             this.x = s1 * c2 * c3 - c1 * s2 * s3;
26226             this.y = c1 * s2 * c3 + s1 * c2 * s3;
26227             this.z = c1 * c2 * s3 - s1 * s2 * c3;
26228             this.w = c1 * c2 * c3 + s1 * s2 * s3;
26229
26230         } else if ( order === 'YZX' ) {
26231
26232             this.x = s1 * c2 * c3 + c1 * s2 * s3;
26233             this.y = c1 * s2 * c3 + s1 * c2 * s3;
26234             this.z = c1 * c2 * s3 - s1 * s2 * c3;
26235             this.w = c1 * c2 * c3 - s1 * s2 * s3;
26236
26237         } else if ( order === 'XZY' ) {
26238
26239             this.x = s1 * c2 * c3 - c1 * s2 * s3;
26240             this.y = c1 * s2 * c3 - s1 * c2 * s3;
26241             this.z = c1 * c2 * s3 + s1 * s2 * c3;
26242             this.w = c1 * c2 * c3 + s1 * s2 * s3;
26243
26244         }
26245
26246         return this;
26247
26248     },
26249
26250     setFromAxisAngle: function ( axis, angle ) {
26251
26252         // from http://www.euclideanspace.com/maths/geometry/rotations/conversions/angleToQuaternion/index.htm
26253         // axis have to be normalized
26254
26255         var halfAngle = angle / 2,
26256             s = Math.sin( halfAngle );
26257
26258         this.x = axis.x * s;
26259         this.y = axis.y * s;
26260         this.z = axis.z * s;
26261         this.w = Math.cos( halfAngle );
26262
26263         return this;
26264
26265     },
26266
26267     setFromRotationMatrix: function ( m ) {
26268
26269         // http://www.euclideanspace.com/maths/geometry/rotations/conversions/matrixToQuaternion/index.htm
26270
26271         // assumes the upper 3x3 of m is a pure rotation matrix (i.e, unscaled)
26272
26273         var te = m.elements,
26274
26275             m11 = te[0], m12 = te[4], m13 = te[8],
26276             m21 = te[1], m22 = te[5], m23 = te[9],
26277             m31 = te[2], m32 = te[6], m33 = te[10],
26278
26279             trace = m11 + m22 + m33,
26280             s;
26281
26282         if( trace > 0 ) {
26283
26284             s = 0.5 / Math.sqrt( trace + 1.0 );
26285
26286             this.w = 0.25 / s;
26287             this.x = ( m32 - m23 ) * s;
26288             this.y = ( m13 - m31 ) * s;
26289             this.z = ( m21 - m12 ) * s;
26290
26291         } else if ( m11 > m22 && m11 > m33 ) {
26292
26293             s = 2.0 * Math.sqrt( 1.0 + m11 - m22 - m33 );
26294
26295             this.w = (m32 - m23 ) / s;
26296             this.x = 0.25 * s;
26297             this.y = (m12 + m21 ) / s;
26298             this.z = (m13 + m31 ) / s;
26299
26300         } else if (m22 > m33) {
26301
26302             s = 2.0 * Math.sqrt( 1.0 + m22 - m11 - m33 );
26303
26304             this.w = (m13 - m31 ) / s;
26305             this.x = (m12 + m21 ) / s;
26306             this.y = 0.25 * s;
26307             this.z = (m23 + m32 ) / s;
26308
26309         } else {
26310
26311             s = 2.0 * Math.sqrt( 1.0 + m33 - m11 - m22 );
26312
26313             this.w = ( m21 - m12 ) / s;
26314             this.x = ( m13 + m31 ) / s;
26315             this.y = ( m23 + m32 ) / s;
26316             this.z = 0.25 * s;
26317
26318         }
26319
26320         return this;
26321
26322     },
26323
26324     calculateW : function () {
26325
26326         this.w = - Math.sqrt( Math.abs( 1.0 - this.x * this.x - this.y * this.y - this.z * this.z ) );
26327
26328         return this;
26329
26330     },
26331
26332     inverse: function () {
26333
26334         this.x *= -1;
26335         this.y *= -1;
26336         this.z *= -1;
26337
26338         return this;
26339
26340     },
26341
26342     length: function () {
26343
26344         return Math.sqrt( this.x * this.x + this.y * this.y + this.z * this.z + this.w * this.w );
26345
26346     },
26347
26348     normalize: function () {
26349
26350         var l = Math.sqrt( this.x * this.x + this.y * this.y + this.z * this.z + this.w * this.w );
26351
26352         if ( l === 0 ) {
26353
26354             this.x = 0;
26355             this.y = 0;
26356             this.z = 0;
26357             this.w = 0;
26358
26359         } else {
26360
26361             l = 1 / l;
26362
26363             this.x = this.x * l;
26364             this.y = this.y * l;
26365             this.z = this.z * l;
26366             this.w = this.w * l;
26367
26368         }
26369
26370         return this;
26371
26372     },
26373
26374     multiply: function ( a, b ) {
26375
26376         // from http://www.euclideanspace.com/maths/algebra/realNormedAlgebra/quaternions/code/index.htm
26377         var qax = a.x, qay = a.y, qaz = a.z, qaw = a.w,
26378         qbx = b.x, qby = b.y, qbz = b.z, qbw = b.w;
26379
26380         this.x =  qax * qbw + qay * qbz - qaz * qby + qaw * qbx;
26381         this.y = -qax * qbz + qay * qbw + qaz * qbx + qaw * qby;
26382         this.z =  qax * qby - qay * qbx + qaz * qbw + qaw * qbz;
26383         this.w = -qax * qbx - qay * qby - qaz * qbz + qaw * qbw;
26384
26385         return this;
26386
26387     },
26388
26389     multiplySelf: function ( b ) {
26390
26391         var qax = this.x, qay = this.y, qaz = this.z, qaw = this.w,
26392         qbx = b.x, qby = b.y, qbz = b.z, qbw = b.w;
26393
26394         this.x = qax * qbw + qaw * qbx + qay * qbz - qaz * qby;
26395         this.y = qay * qbw + qaw * qby + qaz * qbx - qax * qbz;
26396         this.z = qaz * qbw + qaw * qbz + qax * qby - qay * qbx;
26397         this.w = qaw * qbw - qax * qbx - qay * qby - qaz * qbz;
26398
26399         return this;
26400
26401     },
26402
26403     multiplyVector3: function ( vector, dest ) {
26404
26405         if ( !dest ) { dest = vector; }
26406
26407         var x    = vector.x,  y  = vector.y,  z  = vector.z,
26408             qx   = this.x, qy = this.y, qz = this.z, qw = this.w;
26409
26410         // calculate quat * vector
26411
26412         var ix =  qw * x + qy * z - qz * y,
26413             iy =  qw * y + qz * x - qx * z,
26414             iz =  qw * z + qx * y - qy * x,
26415             iw = -qx * x - qy * y - qz * z;
26416
26417         // calculate result * inverse quat
26418
26419         dest.x = ix * qw + iw * -qx + iy * -qz - iz * -qy;
26420         dest.y = iy * qw + iw * -qy + iz * -qx - ix * -qz;
26421         dest.z = iz * qw + iw * -qz + ix * -qy - iy * -qx;
26422
26423         return dest;
26424
26425     },
26426
26427     slerpSelf: function ( qb, t ) {
26428
26429         var x = this.x, y = this.y, z = this.z, w = this.w;
26430
26431         // http://www.euclideanspace.com/maths/algebra/realNormedAlgebra/quaternions/slerp/
26432
26433         var cosHalfTheta = w * qb.w + x * qb.x + y * qb.y + z * qb.z;
26434
26435         if ( cosHalfTheta < 0 ) {
26436
26437             this.w = -qb.w;
26438             this.x = -qb.x;
26439             this.y = -qb.y;
26440             this.z = -qb.z;
26441
26442             cosHalfTheta = -cosHalfTheta;
26443
26444         } else {
26445
26446             this.copy( qb );
26447
26448         }
26449
26450         if ( cosHalfTheta >= 1.0 ) {
26451
26452             this.w = w;
26453             this.x = x;
26454             this.y = y;
26455             this.z = z;
26456
26457             return this;
26458
26459         }
26460
26461         var halfTheta = Math.acos( cosHalfTheta );
26462         var sinHalfTheta = Math.sqrt( 1.0 - cosHalfTheta * cosHalfTheta );
26463
26464         if ( Math.abs( sinHalfTheta ) < 0.001 ) {
26465
26466             this.w = 0.5 * ( w + this.w );
26467             this.x = 0.5 * ( x + this.x );
26468             this.y = 0.5 * ( y + this.y );
26469             this.z = 0.5 * ( z + this.z );
26470
26471             return this;
26472
26473         }
26474
26475         var ratioA = Math.sin( ( 1 - t ) * halfTheta ) / sinHalfTheta,
26476         ratioB = Math.sin( t * halfTheta ) / sinHalfTheta;
26477
26478         this.w = ( w * ratioA + this.w * ratioB );
26479         this.x = ( x * ratioA + this.x * ratioB );
26480         this.y = ( y * ratioA + this.y * ratioB );
26481         this.z = ( z * ratioA + this.z * ratioB );
26482
26483         return this;
26484
26485     },
26486
26487     clone: function () {
26488
26489         return new THREE.Quaternion( this.x, this.y, this.z, this.w );
26490
26491     }
26492
26493 }
26494
26495 THREE.Quaternion.slerp = function ( qa, qb, qm, t ) {
26496
26497     // http://www.euclideanspace.com/maths/algebra/realNormedAlgebra/quaternions/slerp/
26498
26499     var cosHalfTheta = qa.w * qb.w + qa.x * qb.x + qa.y * qb.y + qa.z * qb.z;
26500
26501     if ( cosHalfTheta < 0 ) {
26502
26503         qm.w = -qb.w;
26504         qm.x = -qb.x;
26505         qm.y = -qb.y;
26506         qm.z = -qb.z;
26507
26508         cosHalfTheta = -cosHalfTheta;
26509
26510     } else {
26511
26512         qm.copy( qb );
26513
26514     }
26515
26516     if ( Math.abs( cosHalfTheta ) >= 1.0 ) {
26517
26518         qm.w = qa.w;
26519         qm.x = qa.x;
26520         qm.y = qa.y;
26521         qm.z = qa.z;
26522
26523         return qm;
26524
26525     }
26526
26527     var halfTheta = Math.acos( cosHalfTheta );
26528     var sinHalfTheta = Math.sqrt( 1.0 - cosHalfTheta * cosHalfTheta );
26529
26530     if ( Math.abs( sinHalfTheta ) < 0.001 ) {
26531
26532         qm.w = 0.5 * ( qa.w + qm.w );
26533         qm.x = 0.5 * ( qa.x + qm.x );
26534         qm.y = 0.5 * ( qa.y + qm.y );
26535         qm.z = 0.5 * ( qa.z + qm.z );
26536
26537         return qm;
26538
26539     }
26540
26541     var ratioA = Math.sin( ( 1 - t ) * halfTheta ) / sinHalfTheta;
26542     var ratioB = Math.sin( t * halfTheta ) / sinHalfTheta;
26543
26544     qm.w = ( qa.w * ratioA + qm.w * ratioB );
26545     qm.x = ( qa.x * ratioA + qm.x * ratioB );
26546     qm.y = ( qa.y * ratioA + qm.y * ratioB );
26547     qm.z = ( qa.z * ratioA + qm.z * ratioB );
26548
26549     return qm;
26550
26551 }
26552 /**
26553  * @author mrdoob / http://mrdoob.com/
26554  */
26555
26556 THREE.Vertex = function ( v ) {
26557
26558     console.warn( 'THREE.Vertex has been DEPRECATED. Use THREE.Vector3 instead.')
26559     return v;
26560
26561 };
26562 /**
26563  * @author mrdoob / http://mrdoob.com/
26564  * @author alteredq / http://alteredqualia.com/
26565  */
26566
26567 THREE.Face3 = function ( a, b, c, normal, color, materialIndex ) {
26568
26569     this.a = a;
26570     this.b = b;
26571     this.c = c;
26572
26573     this.normal = normal instanceof THREE.Vector3 ? normal : new THREE.Vector3();
26574     this.vertexNormals = normal instanceof Array ? normal : [ ];
26575
26576     this.color = color instanceof THREE.Color ? color : new THREE.Color();
26577     this.vertexColors = color instanceof Array ? color : [];
26578
26579     this.vertexTangents = [];
26580
26581     this.materialIndex = materialIndex;
26582
26583     this.centroid = new THREE.Vector3();
26584
26585 };
26586
26587 THREE.Face3.prototype = {
26588
26589     constructor: THREE.Face3,
26590
26591     clone: function () {
26592
26593         var face = new THREE.Face3( this.a, this.b, this.c );
26594
26595         face.normal.copy( this.normal );
26596         face.color.copy( this.color );
26597         face.centroid.copy( this.centroid );
26598
26599         face.materialIndex = this.materialIndex;
26600
26601         var i, il;
26602         for ( i = 0, il = this.vertexNormals.length; i < il; i ++ ) face.vertexNormals[ i ] = this.vertexNormals[ i ].clone();
26603         for ( i = 0, il = this.vertexColors.length; i < il; i ++ ) face.vertexColors[ i ] = this.vertexColors[ i ].clone();
26604         for ( i = 0, il = this.vertexTangents.length; i < il; i ++ ) face.vertexTangents[ i ] = this.vertexTangents[ i ].clone();
26605
26606         return face;
26607
26608     }
26609
26610 };
26611 /**
26612  * @author mrdoob / http://mrdoob.com/
26613  * @author alteredq / http://alteredqualia.com/
26614  */
26615
26616 THREE.Face4 = function ( a, b, c, d, normal, color, materialIndex ) {
26617
26618     this.a = a;
26619     this.b = b;
26620     this.c = c;
26621     this.d = d;
26622
26623     this.normal = normal instanceof THREE.Vector3 ? normal : new THREE.Vector3();
26624     this.vertexNormals = normal instanceof Array ? normal : [ ];
26625
26626     this.color = color instanceof THREE.Color ? color : new THREE.Color();
26627     this.vertexColors = color instanceof Array ? color : [];
26628
26629     this.vertexTangents = [];
26630
26631     this.materialIndex = materialIndex;
26632
26633     this.centroid = new THREE.Vector3();
26634
26635 };
26636
26637 THREE.Face4.prototype = {
26638
26639     constructor: THREE.Face4,
26640
26641     clone: function () {
26642
26643         var face = new THREE.Face4( this.a, this.b, this.c, this.d );
26644
26645         face.normal.copy( this.normal );
26646         face.color.copy( this.color );
26647         face.centroid.copy( this.centroid );
26648
26649         face.materialIndex = this.materialIndex;
26650
26651         var i, il;
26652         for ( i = 0, il = this.vertexNormals.length; i < il; i ++ ) face.vertexNormals[ i ] = this.vertexNormals[ i ].clone();
26653         for ( i = 0, il = this.vertexColors.length; i < il; i ++ ) face.vertexColors[ i ] = this.vertexColors[ i ].clone();
26654         for ( i = 0, il = this.vertexTangents.length; i < il; i ++ ) face.vertexTangents[ i ] = this.vertexTangents[ i ].clone();
26655
26656         return face;
26657
26658     }
26659
26660 };
26661 /**
26662  * @author mrdoob / http://mrdoob.com/
26663  */
26664
26665 THREE.UV = function ( u, v ) {
26666
26667     this.u = u || 0;
26668     this.v = v || 0;
26669
26670 };
26671
26672 THREE.UV.prototype = {
26673
26674     constructor: THREE.UV,
26675
26676     set: function ( u, v ) {
26677
26678         this.u = u;
26679         this.v = v;
26680
26681         return this;
26682
26683     },
26684
26685     copy: function ( uv ) {
26686
26687         this.u = uv.u;
26688         this.v = uv.v;
26689
26690         return this;
26691
26692     },
26693
26694     lerpSelf: function ( uv, alpha ) {
26695
26696         this.u += ( uv.u - this.u ) * alpha;
26697         this.v += ( uv.v - this.v ) * alpha;
26698
26699         return this;
26700
26701     },
26702
26703     clone: function () {
26704
26705         return new THREE.UV( this.u, this.v );
26706
26707     }
26708
26709 };
26710 /**
26711  * @author mrdoob / http://mrdoob.com/
26712  * @author kile / http://kile.stravaganza.org/
26713  * @author alteredq / http://alteredqualia.com/
26714  * @author mikael emtinger / http://gomo.se/
26715  * @author zz85 / http://www.lab4games.net/zz85/blog
26716  */
26717
26718 THREE.Geometry = function () {
26719
26720     this.id = THREE.GeometryCount ++;
26721
26722     this.name = '';
26723
26724     this.vertices = [];
26725     this.colors = []; // one-to-one vertex colors, used in ParticleSystem, Line and Ribbon
26726
26727     this.materials = [];
26728
26729     this.faces = [];
26730
26731     this.faceUvs = [[]];
26732     this.faceVertexUvs = [[]];
26733
26734     this.morphTargets = [];
26735     this.morphColors = [];
26736     this.morphNormals = [];
26737
26738     this.skinWeights = [];
26739     this.skinIndices = [];
26740
26741     this.boundingBox = null;
26742     this.boundingSphere = null;
26743
26744     this.hasTangents = false;
26745
26746     this.dynamic = true; // the intermediate typearrays will be deleted when set to false
26747
26748 };
26749
26750 THREE.Geometry.prototype = {
26751
26752     constructor : THREE.Geometry,
26753
26754     applyMatrix: function ( matrix ) {
26755
26756         var matrixRotation = new THREE.Matrix4();
26757         matrixRotation.extractRotation( matrix );
26758
26759         for ( var i = 0, il = this.vertices.length; i < il; i ++ ) {
26760
26761             var vertex = this.vertices[ i ];
26762
26763             matrix.multiplyVector3( vertex );
26764
26765         }
26766
26767         for ( var i = 0, il = this.faces.length; i < il; i ++ ) {
26768
26769             var face = this.faces[ i ];
26770
26771             matrixRotation.multiplyVector3( face.normal );
26772
26773             for ( var j = 0, jl = face.vertexNormals.length; j < jl; j ++ ) {
26774
26775                 matrixRotation.multiplyVector3( face.vertexNormals[ j ] );
26776
26777             }
26778
26779             matrix.multiplyVector3( face.centroid );
26780
26781         }
26782
26783     },
26784
26785     computeCentroids: function () {
26786
26787         var f, fl, face;
26788
26789         for ( f = 0, fl = this.faces.length; f < fl; f ++ ) {
26790
26791             face = this.faces[ f ];
26792             face.centroid.set( 0, 0, 0 );
26793
26794             if ( face instanceof THREE.Face3 ) {
26795
26796                 face.centroid.addSelf( this.vertices[ face.a ] );
26797                 face.centroid.addSelf( this.vertices[ face.b ] );
26798                 face.centroid.addSelf( this.vertices[ face.c ] );
26799                 face.centroid.divideScalar( 3 );
26800
26801             } else if ( face instanceof THREE.Face4 ) {
26802
26803                 face.centroid.addSelf( this.vertices[ face.a ] );
26804                 face.centroid.addSelf( this.vertices[ face.b ] );
26805                 face.centroid.addSelf( this.vertices[ face.c ] );
26806                 face.centroid.addSelf( this.vertices[ face.d ] );
26807                 face.centroid.divideScalar( 4 );
26808
26809             }
26810
26811         }
26812
26813     },
26814
26815     computeFaceNormals: function () {
26816
26817         var n, nl, v, vl, vertex, f, fl, face, vA, vB, vC,
26818         cb = new THREE.Vector3(), ab = new THREE.Vector3();
26819
26820         for ( f = 0, fl = this.faces.length; f < fl; f ++ ) {
26821
26822             face = this.faces[ f ];
26823
26824             vA = this.vertices[ face.a ];
26825             vB = this.vertices[ face.b ];
26826             vC = this.vertices[ face.c ];
26827
26828             cb.sub( vC, vB );
26829             ab.sub( vA, vB );
26830             cb.crossSelf( ab );
26831
26832             if ( !cb.isZero() ) {
26833
26834                 cb.normalize();
26835
26836             }
26837
26838             face.normal.copy( cb );
26839
26840         }
26841
26842     },
26843
26844     computeVertexNormals: function () {
26845
26846         var v, vl, f, fl, face, vertices;
26847
26848         // create internal buffers for reuse when calling this method repeatedly
26849         // (otherwise memory allocation / deallocation every frame is big resource hog)
26850
26851         if ( this.__tmpVertices === undefined ) {
26852
26853             this.__tmpVertices = new Array( this.vertices.length );
26854             vertices = this.__tmpVertices;
26855
26856             for ( v = 0, vl = this.vertices.length; v < vl; v ++ ) {
26857
26858                 vertices[ v ] = new THREE.Vector3();
26859
26860             }
26861
26862             for ( f = 0, fl = this.faces.length; f < fl; f ++ ) {
26863
26864                 face = this.faces[ f ];
26865
26866                 if ( face instanceof THREE.Face3 ) {
26867
26868                     face.vertexNormals = [ new THREE.Vector3(), new THREE.Vector3(), new THREE.Vector3() ];
26869
26870                 } else if ( face instanceof THREE.Face4 ) {
26871
26872                     face.vertexNormals = [ new THREE.Vector3(), new THREE.Vector3(), new THREE.Vector3(), new THREE.Vector3() ];
26873
26874                 }
26875
26876             }
26877
26878         } else {
26879
26880             vertices = this.__tmpVertices;
26881
26882             for ( v = 0, vl = this.vertices.length; v < vl; v ++ ) {
26883
26884                 vertices[ v ].set( 0, 0, 0 );
26885
26886             }
26887
26888         }
26889
26890         for ( f = 0, fl = this.faces.length; f < fl; f ++ ) {
26891
26892             face = this.faces[ f ];
26893
26894             if ( face instanceof THREE.Face3 ) {
26895
26896                 vertices[ face.a ].addSelf( face.normal );
26897                 vertices[ face.b ].addSelf( face.normal );
26898                 vertices[ face.c ].addSelf( face.normal );
26899
26900             } else if ( face instanceof THREE.Face4 ) {
26901
26902                 vertices[ face.a ].addSelf( face.normal );
26903                 vertices[ face.b ].addSelf( face.normal );
26904                 vertices[ face.c ].addSelf( face.normal );
26905                 vertices[ face.d ].addSelf( face.normal );
26906
26907             }
26908
26909         }
26910
26911         for ( v = 0, vl = this.vertices.length; v < vl; v ++ ) {
26912
26913             vertices[ v ].normalize();
26914
26915         }
26916
26917         for ( f = 0, fl = this.faces.length; f < fl; f ++ ) {
26918
26919             face = this.faces[ f ];
26920
26921             if ( face instanceof THREE.Face3 ) {
26922
26923                 face.vertexNormals[ 0 ].copy( vertices[ face.a ] );
26924                 face.vertexNormals[ 1 ].copy( vertices[ face.b ] );
26925                 face.vertexNormals[ 2 ].copy( vertices[ face.c ] );
26926
26927             } else if ( face instanceof THREE.Face4 ) {
26928
26929                 face.vertexNormals[ 0 ].copy( vertices[ face.a ] );
26930                 face.vertexNormals[ 1 ].copy( vertices[ face.b ] );
26931                 face.vertexNormals[ 2 ].copy( vertices[ face.c ] );
26932                 face.vertexNormals[ 3 ].copy( vertices[ face.d ] );
26933
26934             }
26935
26936         }
26937
26938     },
26939
26940     computeMorphNormals: function () {
26941
26942         var i, il, f, fl, face;
26943
26944         // save original normals
26945         // - create temp variables on first access
26946         //   otherwise just copy (for faster repeated calls)
26947
26948         for ( f = 0, fl = this.faces.length; f < fl; f ++ ) {
26949
26950             face = this.faces[ f ];
26951
26952             if ( ! face.__originalFaceNormal ) {
26953
26954                 face.__originalFaceNormal = face.normal.clone();
26955
26956             } else {
26957
26958                 face.__originalFaceNormal.copy( face.normal );
26959
26960             }
26961
26962             if ( ! face.__originalVertexNormals ) face.__originalVertexNormals = [];
26963
26964             for ( i = 0, il = face.vertexNormals.length; i < il; i ++ ) {
26965
26966                 if ( ! face.__originalVertexNormals[ i ] ) {
26967
26968                     face.__originalVertexNormals[ i ] = face.vertexNormals[ i ].clone();
26969
26970                 } else {
26971
26972                     face.__originalVertexNormals[ i ].copy( face.vertexNormals[ i ] );
26973
26974                 }
26975
26976             }
26977
26978         }
26979
26980         // use temp geometry to compute face and vertex normals for each morph
26981
26982         var tmpGeo = new THREE.Geometry();
26983         tmpGeo.faces = this.faces;
26984
26985         for ( i = 0, il = this.morphTargets.length; i < il; i ++ ) {
26986
26987             // create on first access
26988
26989             if ( ! this.morphNormals[ i ] ) {
26990
26991                 this.morphNormals[ i ] = {};
26992                 this.morphNormals[ i ].faceNormals = [];
26993                 this.morphNormals[ i ].vertexNormals = [];
26994
26995                 var dstNormalsFace = this.morphNormals[ i ].faceNormals;
26996                 var dstNormalsVertex = this.morphNormals[ i ].vertexNormals;
26997
26998                 var faceNormal, vertexNormals;
26999
27000                 for ( f = 0, fl = this.faces.length; f < fl; f ++ ) {
27001
27002                     face = this.faces[ f ];
27003
27004                     faceNormal = new THREE.Vector3();
27005
27006                     if ( face instanceof THREE.Face3 ) {
27007
27008                         vertexNormals = { a: new THREE.Vector3(), b: new THREE.Vector3(), c: new THREE.Vector3() };
27009
27010                     } else {
27011
27012                         vertexNormals = { a: new THREE.Vector3(), b: new THREE.Vector3(), c: new THREE.Vector3(), d: new THREE.Vector3() };
27013
27014                     }
27015
27016                     dstNormalsFace.push( faceNormal );
27017                     dstNormalsVertex.push( vertexNormals );
27018
27019                 }
27020
27021             }
27022
27023             var morphNormals = this.morphNormals[ i ];
27024
27025             // set vertices to morph target
27026
27027             tmpGeo.vertices = this.morphTargets[ i ].vertices;
27028
27029             // compute morph normals
27030
27031             tmpGeo.computeFaceNormals();
27032             tmpGeo.computeVertexNormals();
27033
27034             // store morph normals
27035
27036             var faceNormal, vertexNormals;
27037
27038             for ( f = 0, fl = this.faces.length; f < fl; f ++ ) {
27039
27040                 face = this.faces[ f ];
27041
27042                 faceNormal = morphNormals.faceNormals[ f ];
27043                 vertexNormals = morphNormals.vertexNormals[ f ];
27044
27045                 faceNormal.copy( face.normal );
27046
27047                 if ( face instanceof THREE.Face3 ) {
27048
27049                     vertexNormals.a.copy( face.vertexNormals[ 0 ] );
27050                     vertexNormals.b.copy( face.vertexNormals[ 1 ] );
27051                     vertexNormals.c.copy( face.vertexNormals[ 2 ] );
27052
27053                 } else {
27054
27055                     vertexNormals.a.copy( face.vertexNormals[ 0 ] );
27056                     vertexNormals.b.copy( face.vertexNormals[ 1 ] );
27057                     vertexNormals.c.copy( face.vertexNormals[ 2 ] );
27058                     vertexNormals.d.copy( face.vertexNormals[ 3 ] );
27059
27060                 }
27061
27062             }
27063
27064         }
27065
27066         // restore original normals
27067
27068         for ( f = 0, fl = this.faces.length; f < fl; f ++ ) {
27069
27070             face = this.faces[ f ];
27071
27072             face.normal = face.__originalFaceNormal;
27073             face.vertexNormals = face.__originalVertexNormals;
27074
27075         }
27076
27077     },
27078
27079     computeTangents: function () {
27080
27081         // based on http://www.terathon.com/code/tangent.html
27082         // tangents go to vertices
27083
27084         var f, fl, v, vl, i, il, vertexIndex,
27085             face, uv, vA, vB, vC, uvA, uvB, uvC,
27086             x1, x2, y1, y2, z1, z2,
27087             s1, s2, t1, t2, r, t, test,
27088             tan1 = [], tan2 = [],
27089             sdir = new THREE.Vector3(), tdir = new THREE.Vector3(),
27090             tmp = new THREE.Vector3(), tmp2 = new THREE.Vector3(),
27091             n = new THREE.Vector3(), w;
27092
27093         for ( v = 0, vl = this.vertices.length; v < vl; v ++ ) {
27094
27095             tan1[ v ] = new THREE.Vector3();
27096             tan2[ v ] = new THREE.Vector3();
27097
27098         }
27099
27100         function handleTriangle( context, a, b, c, ua, ub, uc ) {
27101
27102             vA = context.vertices[ a ];
27103             vB = context.vertices[ b ];
27104             vC = context.vertices[ c ];
27105
27106             uvA = uv[ ua ];
27107             uvB = uv[ ub ];
27108             uvC = uv[ uc ];
27109
27110             x1 = vB.x - vA.x;
27111             x2 = vC.x - vA.x;
27112             y1 = vB.y - vA.y;
27113             y2 = vC.y - vA.y;
27114             z1 = vB.z - vA.z;
27115             z2 = vC.z - vA.z;
27116
27117             s1 = uvB.u - uvA.u;
27118             s2 = uvC.u - uvA.u;
27119             t1 = uvB.v - uvA.v;
27120             t2 = uvC.v - uvA.v;
27121
27122             r = 1.0 / ( s1 * t2 - s2 * t1 );
27123             sdir.set( ( t2 * x1 - t1 * x2 ) * r,
27124                       ( t2 * y1 - t1 * y2 ) * r,
27125                       ( t2 * z1 - t1 * z2 ) * r );
27126             tdir.set( ( s1 * x2 - s2 * x1 ) * r,
27127                       ( s1 * y2 - s2 * y1 ) * r,
27128                       ( s1 * z2 - s2 * z1 ) * r );
27129
27130             tan1[ a ].addSelf( sdir );
27131             tan1[ b ].addSelf( sdir );
27132             tan1[ c ].addSelf( sdir );
27133
27134             tan2[ a ].addSelf( tdir );
27135             tan2[ b ].addSelf( tdir );
27136             tan2[ c ].addSelf( tdir );
27137
27138         }
27139
27140         for ( f = 0, fl = this.faces.length; f < fl; f ++ ) {
27141
27142             face = this.faces[ f ];
27143             uv = this.faceVertexUvs[ 0 ][ f ]; // use UV layer 0 for tangents
27144
27145             if ( face instanceof THREE.Face3 ) {
27146
27147                 handleTriangle( this, face.a, face.b, face.c, 0, 1, 2 );
27148
27149             } else if ( face instanceof THREE.Face4 ) {
27150
27151                 handleTriangle( this, face.a, face.b, face.d, 0, 1, 3 );
27152                 handleTriangle( this, face.b, face.c, face.d, 1, 2, 3 );
27153
27154             }
27155
27156         }
27157
27158         var faceIndex = [ 'a', 'b', 'c', 'd' ];
27159
27160         for ( f = 0, fl = this.faces.length; f < fl; f ++ ) {
27161
27162             face = this.faces[ f ];
27163
27164             for ( i = 0; i < face.vertexNormals.length; i++ ) {
27165
27166                 n.copy( face.vertexNormals[ i ] );
27167
27168                 vertexIndex = face[ faceIndex[ i ] ];
27169
27170                 t = tan1[ vertexIndex ];
27171
27172                 // Gram-Schmidt orthogonalize
27173
27174                 tmp.copy( t );
27175                 tmp.subSelf( n.multiplyScalar( n.dot( t ) ) ).normalize();
27176
27177                 // Calculate handedness
27178
27179                 tmp2.cross( face.vertexNormals[ i ], t );
27180                 test = tmp2.dot( tan2[ vertexIndex ] );
27181                 w = (test < 0.0) ? -1.0 : 1.0;
27182
27183                 face.vertexTangents[ i ] = new THREE.Vector4( tmp.x, tmp.y, tmp.z, w );
27184
27185             }
27186
27187         }
27188
27189         this.hasTangents = true;
27190
27191     },
27192
27193     computeBoundingBox: function () {
27194
27195         if ( ! this.boundingBox ) {
27196
27197             this.boundingBox = { min: new THREE.Vector3(), max: new THREE.Vector3() };
27198
27199         }
27200
27201         if ( this.vertices.length > 0 ) {
27202
27203             var position, firstPosition = this.vertices[ 0 ];
27204
27205             this.boundingBox.min.copy( firstPosition );
27206             this.boundingBox.max.copy( firstPosition );
27207
27208             var min = this.boundingBox.min,
27209                 max = this.boundingBox.max;
27210
27211             for ( var v = 1, vl = this.vertices.length; v < vl; v ++ ) {
27212
27213                 position = this.vertices[ v ];
27214
27215                 if ( position.x < min.x ) {
27216
27217                     min.x = position.x;
27218
27219                 } else if ( position.x > max.x ) {
27220
27221                     max.x = position.x;
27222
27223                 }
27224
27225                 if ( position.y < min.y ) {
27226
27227                     min.y = position.y;
27228
27229                 } else if ( position.y > max.y ) {
27230
27231                     max.y = position.y;
27232
27233                 }
27234
27235                 if ( position.z < min.z ) {
27236
27237                     min.z = position.z;
27238
27239                 } else if ( position.z > max.z ) {
27240
27241                     max.z = position.z;
27242
27243                 }
27244
27245             }
27246
27247         } else {
27248
27249             this.boundingBox.min.set( 0, 0, 0 );
27250             this.boundingBox.max.set( 0, 0, 0 );
27251
27252         }
27253
27254     },
27255
27256     computeBoundingSphere: function () {
27257
27258         var maxRadiusSq = 0;
27259
27260         if ( this.boundingSphere === null ) this.boundingSphere = { radius: 0 };
27261
27262         for ( var i = 0, l = this.vertices.length; i < l; i ++ ) {
27263
27264             var radiusSq = this.vertices[ i ].lengthSq();
27265             if ( radiusSq > maxRadiusSq ) maxRadiusSq = radiusSq;
27266
27267         }
27268
27269         this.boundingSphere.radius = Math.sqrt( maxRadiusSq );
27270
27271     },
27272
27273     /*
27274      * Checks for duplicate vertices with hashmap.
27275      * Duplicated vertices are removed
27276      * and faces' vertices are updated.
27277      */
27278
27279     mergeVertices: function () {
27280
27281         var verticesMap = {}; // Hashmap for looking up vertice by position coordinates (and making sure they are unique)
27282         var unique = [], changes = [];
27283
27284         var v, key;
27285         var precisionPoints = 4; // number of decimal points, eg. 4 for epsilon of 0.0001
27286         var precision = Math.pow( 10, precisionPoints );
27287         var i,il, face;
27288         var abcd = 'abcd', o, k, j, jl, u;
27289
27290         for ( i = 0, il = this.vertices.length; i < il; i ++ ) {
27291
27292             v = this.vertices[ i ];
27293             key = [ Math.round( v.x * precision ), Math.round( v.y * precision ), Math.round( v.z * precision ) ].join( '_' );
27294
27295             if ( verticesMap[ key ] === undefined ) {
27296
27297                 verticesMap[ key ] = i;
27298                 unique.push( this.vertices[ i ] );
27299                 changes[ i ] = unique.length - 1;
27300
27301             } else {
27302
27303                 //console.log('Duplicate vertex found. ', i, ' could be using ', verticesMap[key]);
27304                 changes[ i ] = changes[ verticesMap[ key ] ];
27305
27306             }
27307
27308         };
27309
27310
27311         // Start to patch face indices
27312
27313         for( i = 0, il = this.faces.length; i < il; i ++ ) {
27314
27315             face = this.faces[ i ];
27316
27317             if ( face instanceof THREE.Face3 ) {
27318
27319                 face.a = changes[ face.a ];
27320                 face.b = changes[ face.b ];
27321                 face.c = changes[ face.c ];
27322
27323             } else if ( face instanceof THREE.Face4 ) {
27324
27325                 face.a = changes[ face.a ];
27326                 face.b = changes[ face.b ];
27327                 face.c = changes[ face.c ];
27328                 face.d = changes[ face.d ];
27329
27330                 // check dups in (a, b, c, d) and convert to -> face3
27331
27332                 o = [ face.a, face.b, face.c, face.d ];
27333
27334                 for ( k = 3; k > 0; k -- ) {
27335
27336                     if ( o.indexOf( face[ abcd[ k ] ] ) !== k ) {
27337
27338                         // console.log('faces', face.a, face.b, face.c, face.d, 'dup at', k);
27339
27340                         o.splice( k, 1 );
27341
27342                         this.faces[ i ] = new THREE.Face3( o[0], o[1], o[2], face.normal, face.color, face.materialIndex );
27343
27344                         for ( j = 0, jl = this.faceVertexUvs.length; j < jl; j ++ ) {
27345
27346                             u = this.faceVertexUvs[ j ][ i ];
27347                             if ( u ) u.splice( k, 1 );
27348
27349                         }
27350
27351                         this.faces[ i ].vertexColors = face.vertexColors;
27352
27353                         break;
27354                     }
27355
27356                 }
27357
27358             }
27359
27360         }
27361
27362         // Use unique set of vertices
27363
27364         var diff = this.vertices.length - unique.length;
27365         this.vertices = unique;
27366         return diff;
27367
27368     },
27369
27370     clone: function () {
27371
27372         // TODO
27373
27374     }
27375
27376 };
27377
27378 THREE.GeometryCount = 0;
27379 /**
27380  * @author alteredq / http://alteredqualia.com/
27381  */
27382
27383 THREE.BufferGeometry = function () {
27384
27385     this.id = THREE.GeometryCount ++;
27386
27387     // attributes
27388
27389     this.attributes = {};
27390
27391     // attributes typed arrays are kept only if dynamic flag is set
27392
27393     this.dynamic = false;
27394
27395     // boundings
27396
27397     this.boundingBox = null;
27398     this.boundingSphere = null;
27399
27400     this.hasTangents = false;
27401
27402     // for compatibility
27403
27404     this.morphTargets = [];
27405
27406 };
27407
27408 THREE.BufferGeometry.prototype = {
27409
27410     constructor : THREE.BufferGeometry,
27411
27412     applyMatrix: function ( matrix ) {
27413
27414         var positionArray;
27415         var normalArray;
27416
27417         if ( this.attributes[ "position" ] ) positionArray = this.attributes[ "position" ].array;
27418         if ( this.attributes[ "normal" ] ) normalArray = this.attributes[ "normal" ].array;
27419
27420         if ( positionArray !== undefined ) {
27421
27422             matrix.multiplyVector3Array( positionArray );
27423             this.verticesNeedUpdate = true;
27424
27425         }
27426
27427         if ( normalArray !== undefined ) {
27428
27429             var matrixRotation = new THREE.Matrix4();
27430             matrixRotation.extractRotation( matrix );
27431
27432             matrixRotation.multiplyVector3Array( normalArray );
27433             this.normalsNeedUpdate = true;
27434
27435         }
27436
27437     },
27438
27439     computeBoundingBox: function () {
27440
27441         if ( ! this.boundingBox ) {
27442
27443             this.boundingBox = {
27444
27445                 min: new THREE.Vector3( Infinity, Infinity, Infinity ),
27446                 max: new THREE.Vector3( -Infinity, -Infinity, -Infinity )
27447
27448             };
27449
27450         }
27451
27452         var positions = this.attributes[ "position" ].array;
27453
27454         if ( positions ) {
27455
27456             var bb = this.boundingBox;
27457             var x, y, z;
27458
27459             for ( var i = 0, il = positions.length; i < il; i += 3 ) {
27460
27461                 x = positions[ i ];
27462                 y = positions[ i + 1 ];
27463                 z = positions[ i + 2 ];
27464
27465                 // bounding box
27466
27467                 if ( x < bb.min.x ) {
27468
27469                     bb.min.x = x;
27470
27471                 } else if ( x > bb.max.x ) {
27472
27473                     bb.max.x = x;
27474
27475                 }
27476
27477                 if ( y < bb.min.y ) {
27478
27479                     bb.min.y = y;
27480
27481                 } else if ( y > bb.max.y ) {
27482
27483                     bb.max.y = y;
27484
27485                 }
27486
27487                 if ( z < bb.min.z ) {
27488
27489                     bb.min.z = z;
27490
27491                 } else if ( z > bb.max.z ) {
27492
27493                     bb.max.z = z;
27494
27495                 }
27496
27497             }
27498
27499         }
27500
27501         if ( positions === undefined || positions.length === 0 ) {
27502
27503             this.boundingBox.min.set( 0, 0, 0 );
27504             this.boundingBox.max.set( 0, 0, 0 );
27505
27506         }
27507
27508     },
27509
27510     computeBoundingSphere: function () {
27511
27512         if ( ! this.boundingSphere ) this.boundingSphere = { radius: 0 };
27513
27514         var positions = this.attributes[ "position" ].array;
27515
27516         if ( positions ) {
27517
27518             var radiusSq, maxRadiusSq = 0;
27519             var x, y, z;
27520
27521             for ( var i = 0, il = positions.length; i < il; i += 3 ) {
27522
27523                 x = positions[ i ];
27524                 y = positions[ i + 1 ];
27525                 z = positions[ i + 2 ];
27526
27527                 radiusSq =  x * x + y * y + z * z;
27528                 if ( radiusSq > maxRadiusSq ) maxRadiusSq = radiusSq;
27529
27530             }
27531
27532             this.boundingSphere.radius = Math.sqrt( maxRadiusSq );
27533
27534         }
27535
27536     },
27537
27538     computeVertexNormals: function () {
27539
27540         if ( this.attributes[ "position" ] && this.attributes[ "index" ] ) {
27541
27542             var i, il;
27543             var j, jl;
27544
27545             var nVertexElements = this.attributes[ "position" ].array.length;
27546
27547             if ( this.attributes[ "normal" ] === undefined ) {
27548
27549                 this.attributes[ "normal" ] = {
27550
27551                     itemSize: 3,
27552                     array: new Float32Array( nVertexElements ),
27553                     numItems: nVertexElements
27554
27555                 };
27556
27557             } else {
27558
27559                 // reset existing normals to zero
27560
27561                 for ( i = 0, il = this.attributes[ "normal" ].array.length; i < il; i ++ ) {
27562
27563                     this.attributes[ "normal" ].array[ i ] = 0;
27564
27565                 }
27566
27567             }
27568
27569             var offsets = this.offsets;
27570
27571             var indices = this.attributes[ "index" ].array;
27572             var positions = this.attributes[ "position" ].array;
27573             var normals = this.attributes[ "normal" ].array;
27574
27575             var vA, vB, vC, x, y, z,
27576
27577             pA = new THREE.Vector3(),
27578             pB = new THREE.Vector3(),
27579             pC = new THREE.Vector3(),
27580
27581             cb = new THREE.Vector3(),
27582             ab = new THREE.Vector3();
27583
27584             for ( j = 0, jl = offsets.length; j < jl; ++ j ) {
27585
27586                 var start = offsets[ j ].start;
27587                 var count = offsets[ j ].count;
27588                 var index = offsets[ j ].index;
27589
27590                 for ( i = start, il = start + count; i < il; i += 3 ) {
27591
27592                     vA = index + indices[ i ];
27593                     vB = index + indices[ i + 1 ];
27594                     vC = index + indices[ i + 2 ];
27595
27596                     x = positions[ vA * 3 ];
27597                     y = positions[ vA * 3 + 1 ];
27598                     z = positions[ vA * 3 + 2 ];
27599                     pA.set( x, y, z );
27600
27601                     x = positions[ vB * 3 ];
27602                     y = positions[ vB * 3 + 1 ];
27603                     z = positions[ vB * 3 + 2 ];
27604                     pB.set( x, y, z );
27605
27606                     x = positions[ vC * 3 ];
27607                     y = positions[ vC * 3 + 1 ];
27608                     z = positions[ vC * 3 + 2 ];
27609                     pC.set( x, y, z );
27610
27611                     cb.sub( pC, pB );
27612                     ab.sub( pA, pB );
27613                     cb.crossSelf( ab );
27614
27615                     normals[ vA * 3 ] += cb.x;
27616                     normals[ vA * 3 + 1 ] += cb.y;
27617                     normals[ vA * 3 + 2 ] += cb.z;
27618
27619                     normals[ vB * 3 ] += cb.x;
27620                     normals[ vB * 3 + 1 ] += cb.y;
27621                     normals[ vB * 3 + 2 ] += cb.z;
27622
27623                     normals[ vC * 3 ] += cb.x;
27624                     normals[ vC * 3 + 1 ] += cb.y;
27625                     normals[ vC * 3 + 2 ] += cb.z;
27626
27627                 }
27628
27629             }
27630
27631             // normalize normals
27632
27633             for ( i = 0, il = normals.length; i < il; i += 3 ) {
27634
27635                 x = normals[ i ];
27636                 y = normals[ i + 1 ];
27637                 z = normals[ i + 2 ];
27638
27639                 var n = 1.0 / Math.sqrt( x * x + y * y + z * z );
27640
27641                 normals[ i ] *= n;
27642                 normals[ i + 1 ] *= n;
27643                 normals[ i + 2 ] *= n;
27644
27645             }
27646
27647             this.normalsNeedUpdate = true;
27648
27649         }
27650
27651     },
27652
27653     computeTangents: function () {
27654
27655         // based on http://www.terathon.com/code/tangent.html
27656         // (per vertex tangents)
27657
27658         if ( this.attributes[ "index" ] === undefined ||
27659              this.attributes[ "position" ] === undefined ||
27660              this.attributes[ "normal" ] === undefined ||
27661              this.attributes[ "uv" ] === undefined ) {
27662
27663             console.warn( "Missing required attributes (index, position, normal or uv) in BufferGeometry.computeTangents()" );
27664             return;
27665
27666         }
27667
27668         var indices = this.attributes[ "index" ].array;
27669         var positions = this.attributes[ "position" ].array;
27670         var normals = this.attributes[ "normal" ].array;
27671         var uvs = this.attributes[ "uv" ].array;
27672
27673         var nVertices = positions.length / 3;
27674
27675         if ( this.attributes[ "tangent" ] === undefined ) {
27676
27677             var nTangentElements = 4 * nVertices;
27678
27679             this.attributes[ "tangent" ] = {
27680
27681                 itemSize: 4,
27682                 array: new Float32Array( nTangentElements ),
27683                 numItems: nTangentElements
27684
27685             };
27686
27687         }
27688
27689         var tangents = this.attributes[ "tangent" ].array;
27690
27691         var tan1 = [], tan2 = [];
27692
27693         for ( var k = 0; k < nVertices; k ++ ) {
27694
27695             tan1[ k ] = new THREE.Vector3();
27696             tan2[ k ] = new THREE.Vector3();
27697
27698         }
27699
27700         var xA, yA, zA,
27701             xB, yB, zB,
27702             xC, yC, zC,
27703
27704             uA, vA,
27705             uB, vB,
27706             uC, vC,
27707
27708             x1, x2, y1, y2, z1, z2,
27709             s1, s2, t1, t2, r;
27710
27711         var sdir = new THREE.Vector3(), tdir = new THREE.Vector3();
27712
27713         function handleTriangle( a, b, c ) {
27714
27715             xA = positions[ a * 3 ];
27716             yA = positions[ a * 3 + 1 ];
27717             zA = positions[ a * 3 + 2 ];
27718
27719             xB = positions[ b * 3 ];
27720             yB = positions[ b * 3 + 1 ];
27721             zB = positions[ b * 3 + 2 ];
27722
27723             xC = positions[ c * 3 ];
27724             yC = positions[ c * 3 + 1 ];
27725             zC = positions[ c * 3 + 2 ];
27726
27727             uA = uvs[ a * 2 ];
27728             vA = uvs[ a * 2 + 1 ];
27729
27730             uB = uvs[ b * 2 ];
27731             vB = uvs[ b * 2 + 1 ];
27732
27733             uC = uvs[ c * 2 ];
27734             vC = uvs[ c * 2 + 1 ];
27735
27736             x1 = xB - xA;
27737             x2 = xC - xA;
27738
27739             y1 = yB - yA;
27740             y2 = yC - yA;
27741
27742             z1 = zB - zA;
27743             z2 = zC - zA;
27744
27745             s1 = uB - uA;
27746             s2 = uC - uA;
27747
27748             t1 = vB - vA;
27749             t2 = vC - vA;
27750
27751             r = 1.0 / ( s1 * t2 - s2 * t1 );
27752
27753             sdir.set(
27754                 ( t2 * x1 - t1 * x2 ) * r,
27755                 ( t2 * y1 - t1 * y2 ) * r,
27756                 ( t2 * z1 - t1 * z2 ) * r
27757             );
27758
27759             tdir.set(
27760                 ( s1 * x2 - s2 * x1 ) * r,
27761                 ( s1 * y2 - s2 * y1 ) * r,
27762                 ( s1 * z2 - s2 * z1 ) * r
27763             );
27764
27765             tan1[ a ].addSelf( sdir );
27766             tan1[ b ].addSelf( sdir );
27767             tan1[ c ].addSelf( sdir );
27768
27769             tan2[ a ].addSelf( tdir );
27770             tan2[ b ].addSelf( tdir );
27771             tan2[ c ].addSelf( tdir );
27772
27773         }
27774
27775         var i, il;
27776         var j, jl;
27777         var iA, iB, iC;
27778
27779         var offsets = this.offsets;
27780
27781         for ( j = 0, jl = offsets.length; j < jl; ++ j ) {
27782
27783             var start = offsets[ j ].start;
27784             var count = offsets[ j ].count;
27785             var index = offsets[ j ].index;
27786
27787             for ( i = start, il = start + count; i < il; i += 3 ) {
27788
27789                 iA = index + indices[ i ];
27790                 iB = index + indices[ i + 1 ];
27791                 iC = index + indices[ i + 2 ];
27792
27793                 handleTriangle( iA, iB, iC );
27794
27795             }
27796
27797         }
27798
27799         var tmp = new THREE.Vector3(), tmp2 = new THREE.Vector3();
27800         var n = new THREE.Vector3(), n2 = new THREE.Vector3();
27801         var w, t, test;
27802         var nx, ny, nz;
27803
27804         function handleVertex( v ) {
27805
27806             n.x = normals[ v * 3 ];
27807             n.y = normals[ v * 3 + 1 ];
27808             n.z = normals[ v * 3 + 2 ];
27809
27810             n2.copy( n );
27811
27812             t = tan1[ v ];
27813
27814             // Gram-Schmidt orthogonalize
27815
27816             tmp.copy( t );
27817             tmp.subSelf( n.multiplyScalar( n.dot( t ) ) ).normalize();
27818
27819             // Calculate handedness
27820
27821             tmp2.cross( n2, t );
27822             test = tmp2.dot( tan2[ v ] );
27823             w = ( test < 0.0 ) ? -1.0 : 1.0;
27824
27825             tangents[ v * 4 ]       = tmp.x;
27826             tangents[ v * 4 + 1 ] = tmp.y;
27827             tangents[ v * 4 + 2 ] = tmp.z;
27828             tangents[ v * 4 + 3 ] = w;
27829
27830         }
27831
27832         for ( j = 0, jl = offsets.length; j < jl; ++ j ) {
27833
27834             var start = offsets[ j ].start;
27835             var count = offsets[ j ].count;
27836             var index = offsets[ j ].index;
27837
27838             for ( i = start, il = start + count; i < il; i += 3 ) {
27839
27840                 iA = index + indices[ i ];
27841                 iB = index + indices[ i + 1 ];
27842                 iC = index + indices[ i + 2 ];
27843
27844                 handleVertex( iA );
27845                 handleVertex( iB );
27846                 handleVertex( iC );
27847
27848             }
27849
27850         }
27851
27852         this.hasTangents = true;
27853         this.tangentsNeedUpdate = true;
27854
27855     }
27856
27857 };
27858
27859 /**
27860  * Spline from Tween.js, slightly optimized (and trashed)
27861  * http://sole.github.com/tween.js/examples/05_spline.html
27862  *
27863  * @author mrdoob / http://mrdoob.com/
27864  * @author alteredq / http://alteredqualia.com/
27865  */
27866
27867 THREE.Spline = function ( points ) {
27868
27869     this.points = points;
27870
27871     var c = [], v3 = { x: 0, y: 0, z: 0 },
27872     point, intPoint, weight, w2, w3,
27873     pa, pb, pc, pd;
27874
27875     this.initFromArray = function( a ) {
27876
27877         this.points = [];
27878
27879         for ( var i = 0; i < a.length; i++ ) {
27880
27881             this.points[ i ] = { x: a[ i ][ 0 ], y: a[ i ][ 1 ], z: a[ i ][ 2 ] };
27882
27883         }
27884
27885     };
27886
27887     this.getPoint = function ( k ) {
27888
27889         point = ( this.points.length - 1 ) * k;
27890         intPoint = Math.floor( point );
27891         weight = point - intPoint;
27892
27893         c[ 0 ] = intPoint === 0 ? intPoint : intPoint - 1;
27894         c[ 1 ] = intPoint;
27895         c[ 2 ] = intPoint  > this.points.length - 2 ? this.points.length - 1 : intPoint + 1;
27896         c[ 3 ] = intPoint  > this.points.length - 3 ? this.points.length - 1 : intPoint + 2;
27897
27898         pa = this.points[ c[ 0 ] ];
27899         pb = this.points[ c[ 1 ] ];
27900         pc = this.points[ c[ 2 ] ];
27901         pd = this.points[ c[ 3 ] ];
27902
27903         w2 = weight * weight;
27904         w3 = weight * w2;
27905
27906         v3.x = interpolate( pa.x, pb.x, pc.x, pd.x, weight, w2, w3 );
27907         v3.y = interpolate( pa.y, pb.y, pc.y, pd.y, weight, w2, w3 );
27908         v3.z = interpolate( pa.z, pb.z, pc.z, pd.z, weight, w2, w3 );
27909
27910         return v3;
27911
27912     };
27913
27914     this.getControlPointsArray = function () {
27915
27916         var i, p, l = this.points.length,
27917             coords = [];
27918
27919         for ( i = 0; i < l; i ++ ) {
27920
27921             p = this.points[ i ];
27922             coords[ i ] = [ p.x, p.y, p.z ];
27923
27924         }
27925
27926         return coords;
27927
27928     };
27929
27930     // approximate length by summing linear segments
27931
27932     this.getLength = function ( nSubDivisions ) {
27933
27934         var i, index, nSamples, position,
27935             point = 0, intPoint = 0, oldIntPoint = 0,
27936             oldPosition = new THREE.Vector3(),
27937             tmpVec = new THREE.Vector3(),
27938             chunkLengths = [],
27939             totalLength = 0;
27940
27941         // first point has 0 length
27942
27943         chunkLengths[ 0 ] = 0;
27944
27945         if ( !nSubDivisions ) nSubDivisions = 100;
27946
27947         nSamples = this.points.length * nSubDivisions;
27948
27949         oldPosition.copy( this.points[ 0 ] );
27950
27951         for ( i = 1; i < nSamples; i ++ ) {
27952
27953             index = i / nSamples;
27954
27955             position = this.getPoint( index );
27956             tmpVec.copy( position );
27957
27958             totalLength += tmpVec.distanceTo( oldPosition );
27959
27960             oldPosition.copy( position );
27961
27962             point = ( this.points.length - 1 ) * index;
27963             intPoint = Math.floor( point );
27964
27965             if ( intPoint != oldIntPoint ) {
27966
27967                 chunkLengths[ intPoint ] = totalLength;
27968                 oldIntPoint = intPoint;
27969
27970             }
27971
27972         }
27973
27974         // last point ends with total length
27975
27976         chunkLengths[ chunkLengths.length ] = totalLength;
27977
27978         return { chunks: chunkLengths, total: totalLength };
27979
27980     };
27981
27982     this.reparametrizeByArcLength = function ( samplingCoef ) {
27983
27984         var i, j,
27985             index, indexCurrent, indexNext,
27986             linearDistance, realDistance,
27987             sampling, position,
27988             newpoints = [],
27989             tmpVec = new THREE.Vector3(),
27990             sl = this.getLength();
27991
27992         newpoints.push( tmpVec.copy( this.points[ 0 ] ).clone() );
27993
27994         for ( i = 1; i < this.points.length; i++ ) {
27995
27996             //tmpVec.copy( this.points[ i - 1 ] );
27997             //linearDistance = tmpVec.distanceTo( this.points[ i ] );
27998
27999             realDistance = sl.chunks[ i ] - sl.chunks[ i - 1 ];
28000
28001             sampling = Math.ceil( samplingCoef * realDistance / sl.total );
28002
28003             indexCurrent = ( i - 1 ) / ( this.points.length - 1 );
28004             indexNext = i / ( this.points.length - 1 );
28005
28006             for ( j = 1; j < sampling - 1; j++ ) {
28007
28008                 index = indexCurrent + j * ( 1 / sampling ) * ( indexNext - indexCurrent );
28009
28010                 position = this.getPoint( index );
28011                 newpoints.push( tmpVec.copy( position ).clone() );
28012
28013             }
28014
28015             newpoints.push( tmpVec.copy( this.points[ i ] ).clone() );
28016
28017         }
28018
28019         this.points = newpoints;
28020
28021     };
28022
28023     // Catmull-Rom
28024
28025     function interpolate( p0, p1, p2, p3, t, t2, t3 ) {
28026
28027         var v0 = ( p2 - p0 ) * 0.5,
28028             v1 = ( p3 - p1 ) * 0.5;
28029
28030         return ( 2 * ( p1 - p2 ) + v0 + v1 ) * t3 + ( - 3 * ( p1 - p2 ) - 2 * v0 - v1 ) * t2 + v0 * t + p1;
28031
28032     };
28033
28034 };
28035 /**
28036  * @author mrdoob / http://mrdoob.com/
28037  * @author mikael emtinger / http://gomo.se/
28038  */
28039
28040 THREE.Camera = function () {
28041
28042     THREE.Object3D.call( this );
28043
28044     this.matrixWorldInverse = new THREE.Matrix4();
28045
28046     this.projectionMatrix = new THREE.Matrix4();
28047     this.projectionMatrixInverse = new THREE.Matrix4();
28048
28049 };
28050
28051 THREE.Camera.prototype = Object.create( THREE.Object3D.prototype );
28052
28053 THREE.Camera.prototype.lookAt = function ( vector ) {
28054
28055     // TODO: Add hierarchy support.
28056
28057     this.matrix.lookAt( this.position, vector, this.up );
28058
28059     if ( this.rotationAutoUpdate === true ) {
28060
28061         this.rotation.setEulerFromRotationMatrix( this.matrix, this.eulerOrder );
28062
28063     }
28064
28065 };
28066 /**
28067  * @author alteredq / http://alteredqualia.com/
28068  */
28069
28070 THREE.OrthographicCamera = function ( left, right, top, bottom, near, far ) {
28071
28072     THREE.Camera.call( this );
28073
28074     this.left = left;
28075     this.right = right;
28076     this.top = top;
28077     this.bottom = bottom;
28078
28079     this.near = ( near !== undefined ) ? near : 0.1;
28080     this.far = ( far !== undefined ) ? far : 2000;
28081
28082     this.updateProjectionMatrix();
28083
28084 };
28085
28086 THREE.OrthographicCamera.prototype = Object.create( THREE.Camera.prototype );
28087
28088 THREE.OrthographicCamera.prototype.updateProjectionMatrix = function () {
28089
28090     this.projectionMatrix.makeOrthographic( this.left, this.right, this.top, this.bottom, this.near, this.far );
28091
28092 };
28093 /**
28094  * @author mrdoob / http://mrdoob.com/
28095  * @author greggman / http://games.greggman.com/
28096  * @author zz85 / http://www.lab4games.net/zz85/blog
28097  */
28098
28099 THREE.PerspectiveCamera = function ( fov, aspect, near, far ) {
28100
28101     THREE.Camera.call( this );
28102
28103     this.fov = fov !== undefined ? fov : 50;
28104     this.aspect = aspect !== undefined ? aspect : 1;
28105     this.near = near !== undefined ? near : 0.1;
28106     this.far = far !== undefined ? far : 2000;
28107
28108     this.updateProjectionMatrix();
28109
28110 };
28111
28112 THREE.PerspectiveCamera.prototype = Object.create( THREE.Camera.prototype );
28113
28114
28115 /**
28116  * Uses Focal Length (in mm) to estimate and set FOV
28117  * 35mm (fullframe) camera is used if frame size is not specified;
28118  * Formula based on http://www.bobatkins.com/photography/technical/field_of_view.html
28119  */
28120
28121 THREE.PerspectiveCamera.prototype.setLens = function ( focalLength, frameHeight ) {
28122
28123     if ( frameHeight === undefined ) frameHeight = 24;
28124
28125     this.fov = 2 * Math.atan( frameHeight / ( focalLength * 2 ) ) * ( 180 / Math.PI );
28126     this.updateProjectionMatrix();
28127
28128 }
28129
28130
28131 /**
28132  * Sets an offset in a larger frustum. This is useful for multi-window or
28133  * multi-monitor/multi-machine setups.
28134  *
28135  * For example, if you have 3x2 monitors and each monitor is 1920x1080 and
28136  * the monitors are in grid like this
28137  *
28138  *   +---+---+---+
28139  *   | A | B | C |
28140  *   +---+---+---+
28141  *   | D | E | F |
28142  *   +---+---+---+
28143  *
28144  * then for each monitor you would call it like this
28145  *
28146  *   var w = 1920;
28147  *   var h = 1080;
28148  *   var fullWidth = w * 3;
28149  *   var fullHeight = h * 2;
28150  *
28151  *   --A--
28152  *   camera.setOffset( fullWidth, fullHeight, w * 0, h * 0, w, h );
28153  *   --B--
28154  *   camera.setOffset( fullWidth, fullHeight, w * 1, h * 0, w, h );
28155  *   --C--
28156  *   camera.setOffset( fullWidth, fullHeight, w * 2, h * 0, w, h );
28157  *   --D--
28158  *   camera.setOffset( fullWidth, fullHeight, w * 0, h * 1, w, h );
28159  *   --E--
28160  *   camera.setOffset( fullWidth, fullHeight, w * 1, h * 1, w, h );
28161  *   --F--
28162  *   camera.setOffset( fullWidth, fullHeight, w * 2, h * 1, w, h );
28163  *
28164  *   Note there is no reason monitors have to be the same size or in a grid.
28165  */
28166
28167 THREE.PerspectiveCamera.prototype.setViewOffset = function ( fullWidth, fullHeight, x, y, width, height ) {
28168
28169     this.fullWidth = fullWidth;
28170     this.fullHeight = fullHeight;
28171     this.x = x;
28172     this.y = y;
28173     this.width = width;
28174     this.height = height;
28175
28176     this.updateProjectionMatrix();
28177
28178 };
28179
28180
28181 THREE.PerspectiveCamera.prototype.updateProjectionMatrix = function () {
28182
28183     if ( this.fullWidth ) {
28184
28185         var aspect = this.fullWidth / this.fullHeight;
28186         var top = Math.tan( this.fov * Math.PI / 360 ) * this.near;
28187         var bottom = -top;
28188         var left = aspect * bottom;
28189         var right = aspect * top;
28190         var width = Math.abs( right - left );
28191         var height = Math.abs( top - bottom );
28192
28193         this.projectionMatrix.makeFrustum(
28194             left + this.x * width / this.fullWidth,
28195             left + ( this.x + this.width ) * width / this.fullWidth,
28196             top - ( this.y + this.height ) * height / this.fullHeight,
28197             top - this.y * height / this.fullHeight,
28198             this.near,
28199             this.far
28200         );
28201
28202     } else {
28203
28204         this.projectionMatrix.makePerspective( this.fov, this.aspect, this.near, this.far );
28205
28206     }
28207
28208 };
28209 /**
28210  * @author mrdoob / http://mrdoob.com/
28211  * @author alteredq / http://alteredqualia.com/
28212  */
28213
28214 THREE.Light = function ( hex ) {
28215
28216     THREE.Object3D.call( this );
28217
28218     this.color = new THREE.Color( hex );
28219
28220 };
28221
28222 THREE.Light.prototype = Object.create( THREE.Object3D.prototype );
28223 /**
28224  * @author mrdoob / http://mrdoob.com/
28225  */
28226
28227 THREE.AmbientLight = function ( hex ) {
28228
28229     THREE.Light.call( this, hex );
28230
28231 };
28232
28233 THREE.AmbientLight.prototype = Object.create( THREE.Light.prototype );
28234 /**
28235  * @author mrdoob / http://mrdoob.com/
28236  * @author alteredq / http://alteredqualia.com/
28237  */
28238
28239 THREE.DirectionalLight = function ( hex, intensity, distance ) {
28240
28241     THREE.Light.call( this, hex );
28242
28243     this.position = new THREE.Vector3( 0, 1, 0 );
28244     this.target = new THREE.Object3D();
28245
28246     this.intensity = ( intensity !== undefined ) ? intensity : 1;
28247     this.distance = ( distance !== undefined ) ? distance : 0;
28248
28249     this.castShadow = false;
28250     this.onlyShadow = false;
28251
28252     //
28253
28254     this.shadowCameraNear = 50;
28255     this.shadowCameraFar = 5000;
28256
28257     this.shadowCameraLeft = -500;
28258     this.shadowCameraRight = 500;
28259     this.shadowCameraTop = 500;
28260     this.shadowCameraBottom = -500;
28261
28262     this.shadowCameraVisible = false;
28263
28264     this.shadowBias = 0;
28265     this.shadowDarkness = 0.5;
28266
28267     this.shadowMapWidth = 512;
28268     this.shadowMapHeight = 512;
28269
28270     //
28271
28272     this.shadowCascade = false;
28273
28274     this.shadowCascadeOffset = new THREE.Vector3( 0, 0, -1000 );
28275     this.shadowCascadeCount = 2;
28276
28277     this.shadowCascadeBias = [ 0, 0, 0 ];
28278     this.shadowCascadeWidth = [ 512, 512, 512 ];
28279     this.shadowCascadeHeight = [ 512, 512, 512 ];
28280
28281     this.shadowCascadeNearZ = [ -1.000, 0.990, 0.998 ];
28282     this.shadowCascadeFarZ  = [  0.990, 0.998, 1.000 ];
28283
28284     this.shadowCascadeArray = [];
28285
28286     //
28287
28288     this.shadowMap = null;
28289     this.shadowMapSize = null;
28290     this.shadowCamera = null;
28291     this.shadowMatrix = null;
28292
28293 };
28294
28295 THREE.DirectionalLight.prototype = Object.create( THREE.Light.prototype );
28296 /**
28297  * @author alteredq / http://alteredqualia.com/
28298  */
28299
28300 THREE.HemisphereLight = function ( skyColorHex, groundColorHex, intensity ) {
28301
28302     THREE.Light.call( this, skyColorHex );
28303
28304     this.groundColor = new THREE.Color( groundColorHex );
28305
28306     this.position = new THREE.Vector3( 0, 100, 0 );
28307
28308     this.intensity = ( intensity !== undefined ) ? intensity : 1;
28309
28310 };
28311
28312 THREE.HemisphereLight.prototype = Object.create( THREE.Light.prototype );
28313 /**
28314  * @author mrdoob / http://mrdoob.com/
28315  */
28316
28317 THREE.PointLight = function ( hex, intensity, distance ) {
28318
28319     THREE.Light.call( this, hex );
28320
28321     this.position = new THREE.Vector3( 0, 0, 0 );
28322     this.intensity = ( intensity !== undefined ) ? intensity : 1;
28323     this.distance = ( distance !== undefined ) ? distance : 0;
28324
28325 };
28326
28327 THREE.PointLight.prototype = Object.create( THREE.Light.prototype );
28328 /**
28329  * @author alteredq / http://alteredqualia.com/
28330  */
28331
28332 THREE.SpotLight = function ( hex, intensity, distance, angle, exponent ) {
28333
28334     THREE.Light.call( this, hex );
28335
28336     this.position = new THREE.Vector3( 0, 1, 0 );
28337     this.target = new THREE.Object3D();
28338
28339     this.intensity = ( intensity !== undefined ) ? intensity : 1;
28340     this.distance = ( distance !== undefined ) ? distance : 0;
28341     this.angle = ( angle !== undefined ) ? angle : Math.PI / 2;
28342     this.exponent = ( exponent !== undefined ) ? exponent : 10;
28343
28344     this.castShadow = false;
28345     this.onlyShadow = false;
28346
28347     //
28348
28349     this.shadowCameraNear = 50;
28350     this.shadowCameraFar = 5000;
28351     this.shadowCameraFov = 50;
28352
28353     this.shadowCameraVisible = false;
28354
28355     this.shadowBias = 0;
28356     this.shadowDarkness = 0.5;
28357
28358     this.shadowMapWidth = 512;
28359     this.shadowMapHeight = 512;
28360
28361     //
28362
28363     this.shadowMap = null;
28364     this.shadowMapSize = null;
28365     this.shadowCamera = null;
28366     this.shadowMatrix = null;
28367
28368 };
28369
28370 THREE.SpotLight.prototype = Object.create( THREE.Light.prototype );
28371 /**
28372  * @author alteredq / http://alteredqualia.com/
28373  */
28374
28375 THREE.Loader = function ( showStatus ) {
28376
28377     this.showStatus = showStatus;
28378     this.statusDomElement = showStatus ? THREE.Loader.prototype.addStatusElement() : null;
28379
28380     this.onLoadStart = function () {};
28381     this.onLoadProgress = function () {};
28382     this.onLoadComplete = function () {};
28383
28384 };
28385
28386 THREE.Loader.prototype = {
28387
28388     constructor: THREE.Loader,
28389
28390     crossOrigin: 'anonymous',
28391
28392     addStatusElement: function () {
28393
28394         var e = document.createElement( "div" );
28395
28396         e.style.position = "absolute";
28397         e.style.right = "0px";
28398         e.style.top = "0px";
28399         e.style.fontSize = "0.8em";
28400         e.style.textAlign = "left";
28401         e.style.background = "rgba(0,0,0,0.25)";
28402         e.style.color = "#fff";
28403         e.style.width = "120px";
28404         e.style.padding = "0.5em 0.5em 0.5em 0.5em";
28405         e.style.zIndex = 1000;
28406
28407         e.innerHTML = "Loading ...";
28408
28409         return e;
28410
28411     },
28412
28413     updateProgress: function ( progress ) {
28414
28415         var message = "Loaded ";
28416
28417         if ( progress.total ) {
28418
28419             message += ( 100 * progress.loaded / progress.total ).toFixed(0) + "%";
28420
28421
28422         } else {
28423
28424             message += ( progress.loaded / 1000 ).toFixed(2) + " KB";
28425
28426         }
28427
28428         this.statusDomElement.innerHTML = message;
28429
28430     },
28431
28432     extractUrlBase: function ( url ) {
28433
28434         var parts = url.split( '/' );
28435         parts.pop();
28436         return ( parts.length < 1 ? '.' : parts.join( '/' ) ) + '/';
28437
28438     },
28439
28440     initMaterials: function ( scope, materials, texturePath ) {
28441
28442         scope.materials = [];
28443
28444         for ( var i = 0; i < materials.length; ++ i ) {
28445
28446             scope.materials[ i ] = THREE.Loader.prototype.createMaterial( materials[ i ], texturePath );
28447
28448         }
28449
28450     },
28451
28452     hasNormals: function ( scope ) {
28453
28454         var m, i, il = scope.materials.length;
28455
28456         for( i = 0; i < il; i ++ ) {
28457
28458             m = scope.materials[ i ];
28459
28460             if ( m instanceof THREE.ShaderMaterial ) return true;
28461
28462         }
28463
28464         return false;
28465
28466     },
28467
28468     createMaterial: function ( m, texturePath ) {
28469
28470         var _this = this;
28471
28472         function is_pow2( n ) {
28473
28474             var l = Math.log( n ) / Math.LN2;
28475             return Math.floor( l ) == l;
28476
28477         }
28478
28479         function nearest_pow2( n ) {
28480
28481             var l = Math.log( n ) / Math.LN2;
28482             return Math.pow( 2, Math.round(  l ) );
28483
28484         }
28485
28486         function load_image( where, url ) {
28487
28488             var image = new Image();
28489
28490             image.onload = function () {
28491
28492                 if ( !is_pow2( this.width ) || !is_pow2( this.height ) ) {
28493
28494                     var width = nearest_pow2( this.width );
28495                     var height = nearest_pow2( this.height );
28496
28497                     where.image.width = width;
28498                     where.image.height = height;
28499                     where.image.getContext( '2d' ).drawImage( this, 0, 0, width, height );
28500
28501                 } else {
28502
28503                     where.image = this;
28504
28505                 }
28506
28507                 where.needsUpdate = true;
28508
28509             };
28510
28511             image.crossOrigin = _this.crossOrigin;
28512             image.src = url;
28513
28514         }
28515
28516         function create_texture( where, name, sourceFile, repeat, offset, wrap, anisotropy ) {
28517
28518             var isCompressed = sourceFile.toLowerCase().endsWith( ".dds" );
28519             var fullPath = texturePath + "/" + sourceFile;
28520
28521             if ( isCompressed ) {
28522
28523                 var texture = THREE.ImageUtils.loadCompressedTexture( fullPath );
28524
28525                 where[ name ] = texture;
28526
28527             } else {
28528
28529                 var texture = document.createElement( 'canvas' );
28530
28531                 where[ name ] = new THREE.Texture( texture );
28532
28533             }
28534
28535             where[ name ].sourceFile = sourceFile;
28536
28537             if( repeat ) {
28538
28539                 where[ name ].repeat.set( repeat[ 0 ], repeat[ 1 ] );
28540
28541                 if ( repeat[ 0 ] !== 1 ) where[ name ].wrapS = THREE.RepeatWrapping;
28542                 if ( repeat[ 1 ] !== 1 ) where[ name ].wrapT = THREE.RepeatWrapping;
28543
28544             }
28545
28546             if ( offset ) {
28547
28548                 where[ name ].offset.set( offset[ 0 ], offset[ 1 ] );
28549
28550             }
28551
28552             if ( wrap ) {
28553
28554                 var wrapMap = {
28555                     "repeat": THREE.RepeatWrapping,
28556                     "mirror": THREE.MirroredRepeatWrapping
28557                 }
28558
28559                 if ( wrapMap[ wrap[ 0 ] ] !== undefined ) where[ name ].wrapS = wrapMap[ wrap[ 0 ] ];
28560                 if ( wrapMap[ wrap[ 1 ] ] !== undefined ) where[ name ].wrapT = wrapMap[ wrap[ 1 ] ];
28561
28562             }
28563
28564             if ( anisotropy ) {
28565
28566                 where[ name ].anisotropy = anisotropy;
28567
28568             }
28569
28570             if ( ! isCompressed ) {
28571
28572                 load_image( where[ name ], fullPath );
28573
28574             }
28575
28576         }
28577
28578         function rgb2hex( rgb ) {
28579
28580             return ( rgb[ 0 ] * 255 << 16 ) + ( rgb[ 1 ] * 255 << 8 ) + rgb[ 2 ] * 255;
28581
28582         }
28583
28584         // defaults
28585
28586         var mtype = "MeshLambertMaterial";
28587         var mpars = { color: 0xeeeeee, opacity: 1.0, map: null, lightMap: null, normalMap: null, bumpMap: null, wireframe: false };
28588
28589         // parameters from model file
28590
28591         if ( m.shading ) {
28592
28593             var shading = m.shading.toLowerCase();
28594
28595             if ( shading === "phong" ) mtype = "MeshPhongMaterial";
28596             else if ( shading === "basic" ) mtype = "MeshBasicMaterial";
28597
28598         }
28599
28600         if ( m.blending !== undefined && THREE[ m.blending ] !== undefined ) {
28601
28602             mpars.blending = THREE[ m.blending ];
28603
28604         }
28605
28606         if ( m.transparent !== undefined || m.opacity < 1.0 ) {
28607
28608             mpars.transparent = m.transparent;
28609
28610         }
28611
28612         if ( m.depthTest !== undefined ) {
28613
28614             mpars.depthTest = m.depthTest;
28615
28616         }
28617
28618         if ( m.depthWrite !== undefined ) {
28619
28620             mpars.depthWrite = m.depthWrite;
28621
28622         }
28623
28624         if ( m.visible !== undefined ) {
28625
28626             mpars.visible = m.visible;
28627
28628         }
28629
28630         if ( m.flipSided !== undefined ) {
28631
28632             mpars.side = THREE.BackSide;
28633
28634         }
28635
28636         if ( m.doubleSided !== undefined ) {
28637
28638             mpars.side = THREE.DoubleSide;
28639
28640         }
28641
28642         if ( m.wireframe !== undefined ) {
28643
28644             mpars.wireframe = m.wireframe;
28645
28646         }
28647
28648         if ( m.vertexColors !== undefined ) {
28649
28650             if ( m.vertexColors === "face" ) {
28651
28652                 mpars.vertexColors = THREE.FaceColors;
28653
28654             } else if ( m.vertexColors ) {
28655
28656                 mpars.vertexColors = THREE.VertexColors;
28657
28658             }
28659
28660         }
28661
28662         // colors
28663
28664         if ( m.colorDiffuse ) {
28665
28666             mpars.color = rgb2hex( m.colorDiffuse );
28667
28668         } else if ( m.DbgColor ) {
28669
28670             mpars.color = m.DbgColor;
28671
28672         }
28673
28674         if ( m.colorSpecular ) {
28675
28676             mpars.specular = rgb2hex( m.colorSpecular );
28677
28678         }
28679
28680         if ( m.colorAmbient ) {
28681
28682             mpars.ambient = rgb2hex( m.colorAmbient );
28683
28684         }
28685
28686         // modifiers
28687
28688         if ( m.transparency ) {
28689
28690             mpars.opacity = m.transparency;
28691
28692         }
28693
28694         if ( m.specularCoef ) {
28695
28696             mpars.shininess = m.specularCoef;
28697
28698         }
28699
28700         // textures
28701
28702         if ( m.mapDiffuse && texturePath ) {
28703
28704             create_texture( mpars, "map", m.mapDiffuse, m.mapDiffuseRepeat, m.mapDiffuseOffset, m.mapDiffuseWrap, m.mapDiffuseAnisotropy );
28705
28706         }
28707
28708         if ( m.mapLight && texturePath ) {
28709
28710             create_texture( mpars, "lightMap", m.mapLight, m.mapLightRepeat, m.mapLightOffset, m.mapLightWrap, m.mapLightAnisotropy );
28711
28712         }
28713
28714         if ( m.mapBump && texturePath ) {
28715
28716             create_texture( mpars, "bumpMap", m.mapBump, m.mapBumpRepeat, m.mapBumpOffset, m.mapBumpWrap, m.mapBumpAnisotropy );
28717
28718         }
28719
28720         if ( m.mapNormal && texturePath ) {
28721
28722             create_texture( mpars, "normalMap", m.mapNormal, m.mapNormalRepeat, m.mapNormalOffset, m.mapNormalWrap, m.mapNormalAnisotropy );
28723
28724         }
28725
28726         if ( m.mapSpecular && texturePath ) {
28727
28728             create_texture( mpars, "specularMap", m.mapSpecular, m.mapSpecularRepeat, m.mapSpecularOffset, m.mapSpecularWrap, m.mapSpecularAnisotropy );
28729
28730         }
28731
28732         //
28733
28734         if ( m.mapBumpScale ) {
28735
28736             mpars.bumpScale = m.mapBumpScale;
28737
28738         }
28739
28740         // special case for normal mapped material
28741
28742         if ( m.mapNormal ) {
28743
28744             var shader = THREE.ShaderUtils.lib[ "normal" ];
28745             var uniforms = THREE.UniformsUtils.clone( shader.uniforms );
28746
28747             uniforms[ "tNormal" ].value = mpars.normalMap;
28748
28749             if ( m.mapNormalFactor ) {
28750
28751                 uniforms[ "uNormalScale" ].value.set( m.mapNormalFactor, m.mapNormalFactor );
28752
28753             }
28754
28755             if ( mpars.map ) {
28756
28757                 uniforms[ "tDiffuse" ].value = mpars.map;
28758                 uniforms[ "enableDiffuse" ].value = true;
28759
28760             }
28761
28762             if ( mpars.specularMap ) {
28763
28764                 uniforms[ "tSpecular" ].value = mpars.specularMap;
28765                 uniforms[ "enableSpecular" ].value = true;
28766
28767             }
28768
28769             if ( mpars.lightMap ) {
28770
28771                 uniforms[ "tAO" ].value = mpars.lightMap;
28772                 uniforms[ "enableAO" ].value = true;
28773
28774             }
28775
28776             // for the moment don't handle displacement texture
28777
28778             uniforms[ "uDiffuseColor" ].value.setHex( mpars.color );
28779             uniforms[ "uSpecularColor" ].value.setHex( mpars.specular );
28780             uniforms[ "uAmbientColor" ].value.setHex( mpars.ambient );
28781
28782             uniforms[ "uShininess" ].value = mpars.shininess;
28783
28784             if ( mpars.opacity !== undefined ) {
28785
28786                 uniforms[ "uOpacity" ].value = mpars.opacity;
28787
28788             }
28789
28790             var parameters = { fragmentShader: shader.fragmentShader, vertexShader: shader.vertexShader, uniforms: uniforms, lights: true, fog: true };
28791             var material = new THREE.ShaderMaterial( parameters );
28792
28793         } else {
28794
28795             var material = new THREE[ mtype ]( mpars );
28796
28797         }
28798
28799         if ( m.DbgName !== undefined ) material.name = m.DbgName;
28800
28801         return material;
28802
28803     }
28804
28805 };
28806 /**
28807  * @author alteredq / http://alteredqualia.com/
28808  */
28809
28810 THREE.BinaryLoader = function ( showStatus ) {
28811
28812     THREE.Loader.call( this, showStatus );
28813
28814 };
28815
28816 THREE.BinaryLoader.prototype = Object.create( THREE.Loader.prototype );
28817
28818 // Load models generated by slim OBJ converter with BINARY option (converter_obj_three_slim.py -t binary)
28819 //  - binary models consist of two files: JS and BIN
28820 //  - parameters
28821 //        - url (required)
28822 //        - callback (required)
28823 //        - texturePath (optional: if not specified, textures will be assumed to be in the same folder as JS model file)
28824 //        - binaryPath (optional: if not specified, binary file will be assumed to be in the same folder as JS model file)
28825
28826 THREE.BinaryLoader.prototype.load = function( url, callback, texturePath, binaryPath ) {
28827
28828     texturePath = texturePath ? texturePath : this.extractUrlBase( url );
28829     binaryPath = binaryPath ? binaryPath : this.extractUrlBase( url );
28830
28831     var callbackProgress = this.showProgress ? THREE.Loader.prototype.updateProgress : null;
28832
28833     this.onLoadStart();
28834
28835     // #1 load JS part via web worker
28836
28837     this.loadAjaxJSON( this, url, callback, texturePath, binaryPath, callbackProgress );
28838
28839 };
28840
28841 THREE.BinaryLoader.prototype.loadAjaxJSON = function ( context, url, callback, texturePath, binaryPath, callbackProgress ) {
28842
28843     var xhr = new XMLHttpRequest();
28844
28845     xhr.onreadystatechange = function () {
28846
28847         if ( xhr.readyState == 4 ) {
28848
28849             if ( xhr.status == 200 || xhr.status == 0 ) {
28850
28851                 var json = JSON.parse( xhr.responseText );
28852                 context.loadAjaxBuffers( json, callback, binaryPath, texturePath, callbackProgress );
28853
28854             } else {
28855
28856                 console.error( "THREE.BinaryLoader: Couldn't load [" + url + "] [" + xhr.status + "]" );
28857
28858             }
28859
28860         }
28861
28862     };
28863
28864     xhr.open( "GET", url, true );
28865     xhr.send( null );
28866
28867 };
28868
28869 THREE.BinaryLoader.prototype.loadAjaxBuffers = function ( json, callback, binaryPath, texturePath, callbackProgress ) {
28870
28871     var xhr = new XMLHttpRequest(),
28872         url = binaryPath + "/" + json.buffers;
28873
28874     var length = 0;
28875
28876     xhr.onreadystatechange = function () {
28877
28878         if ( xhr.readyState == 4 ) {
28879
28880             if ( xhr.status == 200 || xhr.status == 0 ) {
28881
28882                 var buffer = xhr.response;
28883                 if ( buffer === undefined ) buffer = ( new Uint8Array( xhr.responseBody ) ).buffer; // IEWEBGL needs this
28884                 THREE.BinaryLoader.prototype.createBinModel( buffer, callback, texturePath, json.materials );
28885
28886             } else {
28887
28888                 console.error( "THREE.BinaryLoader: Couldn't load [" + url + "] [" + xhr.status + "]" );
28889
28890             }
28891
28892         } else if ( xhr.readyState == 3 ) {
28893
28894             if ( callbackProgress ) {
28895
28896                 if ( length == 0 ) {
28897
28898                     length = xhr.getResponseHeader( "Content-Length" );
28899
28900                 }
28901
28902                 callbackProgress( { total: length, loaded: xhr.responseText.length } );
28903
28904             }
28905
28906         } else if ( xhr.readyState == 2 ) {
28907
28908             length = xhr.getResponseHeader( "Content-Length" );
28909
28910         }
28911
28912     };
28913
28914     xhr.open( "GET", url, true );
28915     xhr.responseType = "arraybuffer";
28916     xhr.send( null );
28917
28918 };
28919
28920 // Binary AJAX parser
28921
28922 THREE.BinaryLoader.prototype.createBinModel = function ( data, callback, texturePath, materials ) {
28923
28924     var Model = function ( texturePath ) {
28925
28926         var scope = this,
28927             currentOffset = 0,
28928             md,
28929             normals = [],
28930             uvs = [],
28931             start_tri_flat, start_tri_smooth, start_tri_flat_uv, start_tri_smooth_uv,
28932             start_quad_flat, start_quad_smooth, start_quad_flat_uv, start_quad_smooth_uv,
28933             tri_size, quad_size,
28934             len_tri_flat, len_tri_smooth, len_tri_flat_uv, len_tri_smooth_uv,
28935             len_quad_flat, len_quad_smooth, len_quad_flat_uv, len_quad_smooth_uv;
28936
28937
28938         THREE.Geometry.call( this );
28939
28940         THREE.Loader.prototype.initMaterials( scope, materials, texturePath );
28941
28942         md = parseMetaData( data, currentOffset );
28943
28944         currentOffset += md.header_bytes;
28945 /*
28946         md.vertex_index_bytes = Uint32Array.BYTES_PER_ELEMENT;
28947         md.material_index_bytes = Uint16Array.BYTES_PER_ELEMENT;
28948         md.normal_index_bytes = Uint32Array.BYTES_PER_ELEMENT;
28949         md.uv_index_bytes = Uint32Array.BYTES_PER_ELEMENT;
28950 */
28951         // buffers sizes
28952
28953         tri_size =  md.vertex_index_bytes * 3 + md.material_index_bytes;
28954         quad_size = md.vertex_index_bytes * 4 + md.material_index_bytes;
28955
28956         len_tri_flat      = md.ntri_flat      * ( tri_size );
28957         len_tri_smooth    = md.ntri_smooth    * ( tri_size + md.normal_index_bytes * 3 );
28958         len_tri_flat_uv   = md.ntri_flat_uv   * ( tri_size + md.uv_index_bytes * 3 );
28959         len_tri_smooth_uv = md.ntri_smooth_uv * ( tri_size + md.normal_index_bytes * 3 + md.uv_index_bytes * 3 );
28960
28961         len_quad_flat      = md.nquad_flat      * ( quad_size );
28962         len_quad_smooth    = md.nquad_smooth    * ( quad_size + md.normal_index_bytes * 4 );
28963         len_quad_flat_uv   = md.nquad_flat_uv   * ( quad_size + md.uv_index_bytes * 4 );
28964         len_quad_smooth_uv = md.nquad_smooth_uv * ( quad_size + md.normal_index_bytes * 4 + md.uv_index_bytes * 4 );
28965
28966         // read buffers
28967
28968         currentOffset += init_vertices( currentOffset );
28969
28970         currentOffset += init_normals( currentOffset );
28971         currentOffset += handlePadding( md.nnormals * 3 );
28972
28973         currentOffset += init_uvs( currentOffset );
28974
28975         start_tri_flat         = currentOffset;
28976         start_tri_smooth    = start_tri_flat    + len_tri_flat    + handlePadding( md.ntri_flat * 2 );
28977         start_tri_flat_uv   = start_tri_smooth  + len_tri_smooth  + handlePadding( md.ntri_smooth * 2 );
28978         start_tri_smooth_uv = start_tri_flat_uv + len_tri_flat_uv + handlePadding( md.ntri_flat_uv * 2 );
28979
28980         start_quad_flat     = start_tri_smooth_uv + len_tri_smooth_uv  + handlePadding( md.ntri_smooth_uv * 2 );
28981         start_quad_smooth   = start_quad_flat     + len_quad_flat       + handlePadding( md.nquad_flat * 2 );
28982         start_quad_flat_uv  = start_quad_smooth   + len_quad_smooth    + handlePadding( md.nquad_smooth * 2 );
28983         start_quad_smooth_uv= start_quad_flat_uv  + len_quad_flat_uv   + handlePadding( md.nquad_flat_uv * 2 );
28984
28985         // have to first process faces with uvs
28986         // so that face and uv indices match
28987
28988         init_triangles_flat_uv( start_tri_flat_uv );
28989         init_triangles_smooth_uv( start_tri_smooth_uv );
28990
28991         init_quads_flat_uv( start_quad_flat_uv );
28992         init_quads_smooth_uv( start_quad_smooth_uv );
28993
28994         // now we can process untextured faces
28995
28996         init_triangles_flat( start_tri_flat );
28997         init_triangles_smooth( start_tri_smooth );
28998
28999         init_quads_flat( start_quad_flat );
29000         init_quads_smooth( start_quad_smooth );
29001
29002         this.computeCentroids();
29003         this.computeFaceNormals();
29004
29005         if ( THREE.Loader.prototype.hasNormals( this ) ) this.computeTangents();
29006
29007         function handlePadding( n ) {
29008
29009             return ( n % 4 ) ? ( 4 - n % 4 ) : 0;
29010
29011         };
29012
29013         function parseMetaData( data, offset ) {
29014
29015             var metaData = {
29016
29017                 'signature'               :parseString( data, offset,  12 ),
29018                 'header_bytes'            :parseUChar8( data, offset + 12 ),
29019
29020                 'vertex_coordinate_bytes' :parseUChar8( data, offset + 13 ),
29021                 'normal_coordinate_bytes' :parseUChar8( data, offset + 14 ),
29022                 'uv_coordinate_bytes'     :parseUChar8( data, offset + 15 ),
29023
29024                 'vertex_index_bytes'      :parseUChar8( data, offset + 16 ),
29025                 'normal_index_bytes'      :parseUChar8( data, offset + 17 ),
29026                 'uv_index_bytes'          :parseUChar8( data, offset + 18 ),
29027                 'material_index_bytes'    :parseUChar8( data, offset + 19 ),
29028
29029                 'nvertices'    :parseUInt32( data, offset + 20 ),
29030                 'nnormals'     :parseUInt32( data, offset + 20 + 4*1 ),
29031                 'nuvs'         :parseUInt32( data, offset + 20 + 4*2 ),
29032
29033                 'ntri_flat'      :parseUInt32( data, offset + 20 + 4*3 ),
29034                 'ntri_smooth'    :parseUInt32( data, offset + 20 + 4*4 ),
29035                 'ntri_flat_uv'   :parseUInt32( data, offset + 20 + 4*5 ),
29036                 'ntri_smooth_uv' :parseUInt32( data, offset + 20 + 4*6 ),
29037
29038                 'nquad_flat'      :parseUInt32( data, offset + 20 + 4*7 ),
29039                 'nquad_smooth'    :parseUInt32( data, offset + 20 + 4*8 ),
29040                 'nquad_flat_uv'   :parseUInt32( data, offset + 20 + 4*9 ),
29041                 'nquad_smooth_uv' :parseUInt32( data, offset + 20 + 4*10 )
29042
29043             };
29044 /*
29045             console.log( "signature: " + metaData.signature );
29046
29047             console.log( "header_bytes: " + metaData.header_bytes );
29048             console.log( "vertex_coordinate_bytes: " + metaData.vertex_coordinate_bytes );
29049             console.log( "normal_coordinate_bytes: " + metaData.normal_coordinate_bytes );
29050             console.log( "uv_coordinate_bytes: " + metaData.uv_coordinate_bytes );
29051
29052             console.log( "vertex_index_bytes: " + metaData.vertex_index_bytes );
29053             console.log( "normal_index_bytes: " + metaData.normal_index_bytes );
29054             console.log( "uv_index_bytes: " + metaData.uv_index_bytes );
29055             console.log( "material_index_bytes: " + metaData.material_index_bytes );
29056
29057             console.log( "nvertices: " + metaData.nvertices );
29058             console.log( "nnormals: " + metaData.nnormals );
29059             console.log( "nuvs: " + metaData.nuvs );
29060
29061             console.log( "ntri_flat: " + metaData.ntri_flat );
29062             console.log( "ntri_smooth: " + metaData.ntri_smooth );
29063             console.log( "ntri_flat_uv: " + metaData.ntri_flat_uv );
29064             console.log( "ntri_smooth_uv: " + metaData.ntri_smooth_uv );
29065
29066             console.log( "nquad_flat: " + metaData.nquad_flat );
29067             console.log( "nquad_smooth: " + metaData.nquad_smooth );
29068             console.log( "nquad_flat_uv: " + metaData.nquad_flat_uv );
29069             console.log( "nquad_smooth_uv: " + metaData.nquad_smooth_uv );
29070
29071             var total = metaData.header_bytes
29072                       + metaData.nvertices * metaData.vertex_coordinate_bytes * 3
29073                       + metaData.nnormals * metaData.normal_coordinate_bytes * 3
29074                       + metaData.nuvs * metaData.uv_coordinate_bytes * 2
29075                       + metaData.ntri_flat * ( metaData.vertex_index_bytes*3 + metaData.material_index_bytes )
29076                       + metaData.ntri_smooth * ( metaData.vertex_index_bytes*3 + metaData.material_index_bytes + metaData.normal_index_bytes*3 )
29077                       + metaData.ntri_flat_uv * ( metaData.vertex_index_bytes*3 + metaData.material_index_bytes + metaData.uv_index_bytes*3 )
29078                       + metaData.ntri_smooth_uv * ( metaData.vertex_index_bytes*3 + metaData.material_index_bytes + metaData.normal_index_bytes*3 + metaData.uv_index_bytes*3 )
29079                       + metaData.nquad_flat * ( metaData.vertex_index_bytes*4 + metaData.material_index_bytes )
29080                       + metaData.nquad_smooth * ( metaData.vertex_index_bytes*4 + metaData.material_index_bytes + metaData.normal_index_bytes*4 )
29081                       + metaData.nquad_flat_uv * ( metaData.vertex_index_bytes*4 + metaData.material_index_bytes + metaData.uv_index_bytes*4 )
29082                       + metaData.nquad_smooth_uv * ( metaData.vertex_index_bytes*4 + metaData.material_index_bytes + metaData.normal_index_bytes*4 + metaData.uv_index_bytes*4 );
29083             console.log( "total bytes: " + total );
29084 */
29085
29086             return metaData;
29087
29088         };
29089
29090         function parseString( data, offset, length ) {
29091
29092             var charArray = new Uint8Array( data, offset, length );
29093
29094             var text = "";
29095
29096             for ( var i = 0; i < length; i ++ ) {
29097
29098                 text += String.fromCharCode( charArray[ offset + i ] );
29099
29100             }
29101
29102             return text;
29103
29104         };
29105
29106         function parseUChar8( data, offset ) {
29107
29108             var charArray = new Uint8Array( data, offset, 1 );
29109
29110             return charArray[ 0 ];
29111
29112         };
29113
29114         function parseUInt32( data, offset ) {
29115
29116             var intArray = new Uint32Array( data, offset, 1 );
29117
29118             return intArray[ 0 ];
29119
29120         };
29121
29122         function init_vertices( start ) {
29123
29124             var nElements = md.nvertices;
29125
29126             var coordArray = new Float32Array( data, start, nElements * 3 );
29127
29128             var i, x, y, z;
29129
29130             for( i = 0; i < nElements; i ++ ) {
29131
29132                 x = coordArray[ i * 3 ];
29133                 y = coordArray[ i * 3 + 1 ];
29134                 z = coordArray[ i * 3 + 2 ];
29135
29136                 vertex( scope, x, y, z );
29137
29138             }
29139
29140             return nElements * 3 * Float32Array.BYTES_PER_ELEMENT;
29141
29142         };
29143
29144         function init_normals( start ) {
29145
29146             var nElements = md.nnormals;
29147
29148             if ( nElements ) {
29149
29150                 var normalArray = new Int8Array( data, start, nElements * 3 );
29151
29152                 var i, x, y, z;
29153
29154                 for( i = 0; i < nElements; i ++ ) {
29155
29156                     x = normalArray[ i * 3 ];
29157                     y = normalArray[ i * 3 + 1 ];
29158                     z = normalArray[ i * 3 + 2 ];
29159
29160                     normals.push( x/127, y/127, z/127 );
29161
29162                 }
29163
29164             }
29165
29166             return nElements * 3 * Int8Array.BYTES_PER_ELEMENT;
29167
29168         };
29169
29170         function init_uvs( start ) {
29171
29172             var nElements = md.nuvs;
29173
29174             if ( nElements ) {
29175
29176                 var uvArray = new Float32Array( data, start, nElements * 2 );
29177
29178                 var i, u, v;
29179
29180                 for( i = 0; i < nElements; i ++ ) {
29181
29182                     u = uvArray[ i * 2 ];
29183                     v = uvArray[ i * 2 + 1 ];
29184
29185                     uvs.push( u, v );
29186
29187                 }
29188
29189             }
29190
29191             return nElements * 2 * Float32Array.BYTES_PER_ELEMENT;
29192
29193         };
29194
29195         function init_uvs3( nElements, offset ) {
29196
29197             var i, uva, uvb, uvc, u1, u2, u3, v1, v2, v3;
29198
29199             var uvIndexBuffer = new Uint32Array( data, offset, 3 * nElements );
29200
29201             for( i = 0; i < nElements; i ++ ) {
29202
29203                 uva = uvIndexBuffer[ i * 3 ];
29204                 uvb = uvIndexBuffer[ i * 3 + 1 ];
29205                 uvc = uvIndexBuffer[ i * 3 + 2 ];
29206
29207                 u1 = uvs[ uva*2 ];
29208                 v1 = uvs[ uva*2 + 1 ];
29209
29210                 u2 = uvs[ uvb*2 ];
29211                 v2 = uvs[ uvb*2 + 1 ];
29212
29213                 u3 = uvs[ uvc*2 ];
29214                 v3 = uvs[ uvc*2 + 1 ];
29215
29216                 uv3( scope.faceVertexUvs[ 0 ], u1, v1, u2, v2, u3, v3 );
29217
29218             }
29219
29220         };
29221
29222         function init_uvs4( nElements, offset ) {
29223
29224             var i, uva, uvb, uvc, uvd, u1, u2, u3, u4, v1, v2, v3, v4;
29225
29226             var uvIndexBuffer = new Uint32Array( data, offset, 4 * nElements );
29227
29228             for( i = 0; i < nElements; i ++ ) {
29229
29230                 uva = uvIndexBuffer[ i * 4 ];
29231                 uvb = uvIndexBuffer[ i * 4 + 1 ];
29232                 uvc = uvIndexBuffer[ i * 4 + 2 ];
29233                 uvd = uvIndexBuffer[ i * 4 + 3 ];
29234
29235                 u1 = uvs[ uva*2 ];
29236                 v1 = uvs[ uva*2 + 1 ];
29237
29238                 u2 = uvs[ uvb*2 ];
29239                 v2 = uvs[ uvb*2 + 1 ];
29240
29241                 u3 = uvs[ uvc*2 ];
29242                 v3 = uvs[ uvc*2 + 1 ];
29243
29244                 u4 = uvs[ uvd*2 ];
29245                 v4 = uvs[ uvd*2 + 1 ];
29246
29247                 uv4( scope.faceVertexUvs[ 0 ], u1, v1, u2, v2, u3, v3, u4, v4 );
29248
29249             }
29250
29251         };
29252
29253         function init_faces3_flat( nElements, offsetVertices, offsetMaterials ) {
29254
29255             var i, a, b, c, m;
29256
29257             var vertexIndexBuffer = new Uint32Array( data, offsetVertices, 3 * nElements );
29258             var materialIndexBuffer = new Uint16Array( data, offsetMaterials, nElements );
29259
29260             for( i = 0; i < nElements; i ++ ) {
29261
29262                 a = vertexIndexBuffer[ i * 3 ];
29263                 b = vertexIndexBuffer[ i * 3 + 1 ];
29264                 c = vertexIndexBuffer[ i * 3 + 2 ];
29265
29266                 m = materialIndexBuffer[ i ];
29267
29268                 f3( scope, a, b, c, m );
29269
29270             }
29271
29272         };
29273
29274         function init_faces4_flat( nElements, offsetVertices, offsetMaterials ) {
29275
29276             var i, a, b, c, d, m;
29277
29278             var vertexIndexBuffer = new Uint32Array( data, offsetVertices, 4 * nElements );
29279             var materialIndexBuffer = new Uint16Array( data, offsetMaterials, nElements );
29280
29281             for( i = 0; i < nElements; i ++ ) {
29282
29283                 a = vertexIndexBuffer[ i * 4 ];
29284                 b = vertexIndexBuffer[ i * 4 + 1 ];
29285                 c = vertexIndexBuffer[ i * 4 + 2 ];
29286                 d = vertexIndexBuffer[ i * 4 + 3 ];
29287
29288                 m = materialIndexBuffer[ i ];
29289
29290                 f4( scope, a, b, c, d, m );
29291
29292             }
29293
29294         };
29295
29296         function init_faces3_smooth( nElements, offsetVertices, offsetNormals, offsetMaterials ) {
29297
29298             var i, a, b, c, m;
29299             var na, nb, nc;
29300
29301             var vertexIndexBuffer = new Uint32Array( data, offsetVertices, 3 * nElements );
29302             var normalIndexBuffer = new Uint32Array( data, offsetNormals, 3 * nElements );
29303             var materialIndexBuffer = new Uint16Array( data, offsetMaterials, nElements );
29304
29305             for( i = 0; i < nElements; i ++ ) {
29306
29307                 a = vertexIndexBuffer[ i * 3 ];
29308                 b = vertexIndexBuffer[ i * 3 + 1 ];
29309                 c = vertexIndexBuffer[ i * 3 + 2 ];
29310
29311                 na = normalIndexBuffer[ i * 3 ];
29312                 nb = normalIndexBuffer[ i * 3 + 1 ];
29313                 nc = normalIndexBuffer[ i * 3 + 2 ];
29314
29315                 m = materialIndexBuffer[ i ];
29316
29317                 f3n( scope, normals, a, b, c, m, na, nb, nc );
29318
29319             }
29320
29321         };
29322
29323         function init_faces4_smooth( nElements, offsetVertices, offsetNormals, offsetMaterials ) {
29324
29325             var i, a, b, c, d, m;
29326             var na, nb, nc, nd;
29327
29328             var vertexIndexBuffer = new Uint32Array( data, offsetVertices, 4 * nElements );
29329             var normalIndexBuffer = new Uint32Array( data, offsetNormals, 4 * nElements );
29330             var materialIndexBuffer = new Uint16Array( data, offsetMaterials, nElements );
29331
29332             for( i = 0; i < nElements; i ++ ) {
29333
29334                 a = vertexIndexBuffer[ i * 4 ];
29335                 b = vertexIndexBuffer[ i * 4 + 1 ];
29336                 c = vertexIndexBuffer[ i * 4 + 2 ];
29337                 d = vertexIndexBuffer[ i * 4 + 3 ];
29338
29339                 na = normalIndexBuffer[ i * 4 ];
29340                 nb = normalIndexBuffer[ i * 4 + 1 ];
29341                 nc = normalIndexBuffer[ i * 4 + 2 ];
29342                 nd = normalIndexBuffer[ i * 4 + 3 ];
29343
29344                 m = materialIndexBuffer[ i ];
29345
29346                 f4n( scope, normals, a, b, c, d, m, na, nb, nc, nd );
29347
29348             }
29349
29350         };
29351
29352         function init_triangles_flat( start ) {
29353
29354             var nElements = md.ntri_flat;
29355
29356             if ( nElements ) {
29357
29358                 var offsetMaterials = start + nElements * Uint32Array.BYTES_PER_ELEMENT * 3;
29359                 init_faces3_flat( nElements, start, offsetMaterials );
29360
29361             }
29362
29363         };
29364
29365         function init_triangles_flat_uv( start ) {
29366
29367             var nElements = md.ntri_flat_uv;
29368
29369             if ( nElements ) {
29370
29371                 var offsetUvs = start + nElements * Uint32Array.BYTES_PER_ELEMENT * 3;
29372                 var offsetMaterials = offsetUvs + nElements * Uint32Array.BYTES_PER_ELEMENT * 3;
29373
29374                 init_faces3_flat( nElements, start, offsetMaterials );
29375                 init_uvs3( nElements, offsetUvs );
29376
29377             }
29378
29379         };
29380
29381         function init_triangles_smooth( start ) {
29382
29383             var nElements = md.ntri_smooth;
29384
29385             if ( nElements ) {
29386
29387                 var offsetNormals = start + nElements * Uint32Array.BYTES_PER_ELEMENT * 3;
29388                 var offsetMaterials = offsetNormals + nElements * Uint32Array.BYTES_PER_ELEMENT * 3;
29389
29390                 init_faces3_smooth( nElements, start, offsetNormals, offsetMaterials );
29391
29392             }
29393
29394         };
29395
29396         function init_triangles_smooth_uv( start ) {
29397
29398             var nElements = md.ntri_smooth_uv;
29399
29400             if ( nElements ) {
29401
29402                 var offsetNormals = start + nElements * Uint32Array.BYTES_PER_ELEMENT * 3;
29403                 var offsetUvs = offsetNormals + nElements * Uint32Array.BYTES_PER_ELEMENT * 3;
29404                 var offsetMaterials = offsetUvs + nElements * Uint32Array.BYTES_PER_ELEMENT * 3;
29405
29406                 init_faces3_smooth( nElements, start, offsetNormals, offsetMaterials );
29407                 init_uvs3( nElements, offsetUvs );
29408
29409             }
29410
29411         };
29412
29413         function init_quads_flat( start ) {
29414
29415             var nElements = md.nquad_flat;
29416
29417             if ( nElements ) {
29418
29419                 var offsetMaterials = start + nElements * Uint32Array.BYTES_PER_ELEMENT * 4;
29420                 init_faces4_flat( nElements, start, offsetMaterials );
29421
29422             }
29423
29424         };
29425
29426         function init_quads_flat_uv( start ) {
29427
29428             var nElements = md.nquad_flat_uv;
29429
29430             if ( nElements ) {
29431
29432                 var offsetUvs = start + nElements * Uint32Array.BYTES_PER_ELEMENT * 4;
29433                 var offsetMaterials = offsetUvs + nElements * Uint32Array.BYTES_PER_ELEMENT * 4;
29434
29435                 init_faces4_flat( nElements, start, offsetMaterials );
29436                 init_uvs4( nElements, offsetUvs );
29437
29438             }
29439
29440         };
29441
29442         function init_quads_smooth( start ) {
29443
29444             var nElements = md.nquad_smooth;
29445
29446             if ( nElements ) {
29447
29448                 var offsetNormals = start + nElements * Uint32Array.BYTES_PER_ELEMENT * 4;
29449                 var offsetMaterials = offsetNormals + nElements * Uint32Array.BYTES_PER_ELEMENT * 4;
29450
29451                 init_faces4_smooth( nElements, start, offsetNormals, offsetMaterials );
29452
29453             }
29454
29455         };
29456
29457         function init_quads_smooth_uv( start ) {
29458
29459             var nElements = md.nquad_smooth_uv;
29460
29461             if ( nElements ) {
29462
29463                 var offsetNormals = start + nElements * Uint32Array.BYTES_PER_ELEMENT * 4;
29464                 var offsetUvs = offsetNormals + nElements * Uint32Array.BYTES_PER_ELEMENT * 4;
29465                 var offsetMaterials = offsetUvs + nElements * Uint32Array.BYTES_PER_ELEMENT * 4;
29466
29467                 init_faces4_smooth( nElements, start, offsetNormals, offsetMaterials );
29468                 init_uvs4( nElements, offsetUvs );
29469
29470             }
29471
29472         };
29473
29474     };
29475
29476     function vertex ( scope, x, y, z ) {
29477
29478         scope.vertices.push( new THREE.Vector3( x, y, z ) );
29479
29480     };
29481
29482     function f3 ( scope, a, b, c, mi ) {
29483
29484         scope.faces.push( new THREE.Face3( a, b, c, null, null, mi ) );
29485
29486     };
29487
29488     function f4 ( scope, a, b, c, d, mi ) {
29489
29490         scope.faces.push( new THREE.Face4( a, b, c, d, null, null, mi ) );
29491
29492     };
29493
29494     function f3n ( scope, normals, a, b, c, mi, na, nb, nc ) {
29495
29496         var nax = normals[ na*3     ],
29497             nay = normals[ na*3 + 1 ],
29498             naz = normals[ na*3 + 2 ],
29499
29500             nbx = normals[ nb*3     ],
29501             nby = normals[ nb*3 + 1 ],
29502             nbz = normals[ nb*3 + 2 ],
29503
29504             ncx = normals[ nc*3     ],
29505             ncy = normals[ nc*3 + 1 ],
29506             ncz = normals[ nc*3 + 2 ];
29507
29508         scope.faces.push( new THREE.Face3( a, b, c,
29509                           [new THREE.Vector3( nax, nay, naz ),
29510                            new THREE.Vector3( nbx, nby, nbz ),
29511                            new THREE.Vector3( ncx, ncy, ncz )],
29512                           null,
29513                           mi ) );
29514
29515     };
29516
29517     function f4n ( scope, normals, a, b, c, d, mi, na, nb, nc, nd ) {
29518
29519         var nax = normals[ na*3     ],
29520             nay = normals[ na*3 + 1 ],
29521             naz = normals[ na*3 + 2 ],
29522
29523             nbx = normals[ nb*3     ],
29524             nby = normals[ nb*3 + 1 ],
29525             nbz = normals[ nb*3 + 2 ],
29526
29527             ncx = normals[ nc*3     ],
29528             ncy = normals[ nc*3 + 1 ],
29529             ncz = normals[ nc*3 + 2 ],
29530
29531             ndx = normals[ nd*3     ],
29532             ndy = normals[ nd*3 + 1 ],
29533             ndz = normals[ nd*3 + 2 ];
29534
29535         scope.faces.push( new THREE.Face4( a, b, c, d,
29536                           [new THREE.Vector3( nax, nay, naz ),
29537                            new THREE.Vector3( nbx, nby, nbz ),
29538                            new THREE.Vector3( ncx, ncy, ncz ),
29539                            new THREE.Vector3( ndx, ndy, ndz )],
29540                           null,
29541                           mi ) );
29542
29543     };
29544
29545     function uv3 ( where, u1, v1, u2, v2, u3, v3 ) {
29546
29547         var uv = [];
29548         uv.push( new THREE.UV( u1, v1 ) );
29549         uv.push( new THREE.UV( u2, v2 ) );
29550         uv.push( new THREE.UV( u3, v3 ) );
29551         where.push( uv );
29552
29553     };
29554
29555     function uv4 ( where, u1, v1, u2, v2, u3, v3, u4, v4 ) {
29556
29557         var uv = [];
29558         uv.push( new THREE.UV( u1, v1 ) );
29559         uv.push( new THREE.UV( u2, v2 ) );
29560         uv.push( new THREE.UV( u3, v3 ) );
29561         uv.push( new THREE.UV( u4, v4 ) );
29562         where.push( uv );
29563
29564     };
29565
29566     Model.prototype = Object.create( THREE.Geometry.prototype );
29567
29568     callback( new Model( texturePath ) );
29569
29570 };
29571 /**
29572  * @author mrdoob / http://mrdoob.com/
29573  */
29574
29575 THREE.ImageLoader = function () {
29576
29577     THREE.EventTarget.call( this );
29578
29579     this.crossOrigin = null;
29580
29581 };
29582
29583 THREE.ImageLoader.prototype = {
29584
29585     constructor: THREE.ImageLoader,
29586
29587     load: function ( url, image ) {
29588
29589         var scope = this;
29590
29591         if ( image === undefined ) image = new Image();
29592
29593         image.addEventListener( 'load', function () {
29594
29595             scope.dispatchEvent( { type: 'load', content: image } );
29596
29597         }, false );
29598
29599         image.addEventListener( 'error', function () {
29600
29601             scope.dispatchEvent( { type: 'error', message: 'Couldn\'t load URL [' + url + ']' } );
29602
29603         }, false );
29604
29605         if ( scope.crossOrigin ) image.crossOrigin = scope.crossOrigin;
29606
29607         image.src = url;
29608
29609     }
29610
29611 }
29612 /**
29613  * @author mrdoob / http://mrdoob.com/
29614  * @author alteredq / http://alteredqualia.com/
29615  */
29616
29617 THREE.JSONLoader = function ( showStatus ) {
29618
29619     THREE.Loader.call( this, showStatus );
29620
29621 };
29622
29623 THREE.JSONLoader.prototype = Object.create( THREE.Loader.prototype );
29624
29625 THREE.JSONLoader.prototype.load = function ( url, callback, texturePath ) {
29626
29627     var scope = this;
29628
29629     texturePath = texturePath ? texturePath : this.extractUrlBase( url );
29630
29631     this.onLoadStart();
29632     this.loadAjaxJSON( this, url, callback, texturePath );
29633
29634 };
29635
29636 THREE.JSONLoader.prototype.loadAjaxJSON = function ( context, url, callback, texturePath, callbackProgress ) {
29637
29638     var xhr = new XMLHttpRequest();
29639
29640     var length = 0;
29641
29642     xhr.onreadystatechange = function () {
29643
29644         if ( xhr.readyState === xhr.DONE ) {
29645
29646             if ( xhr.status === 200 || xhr.status === 0 ) {
29647
29648                 if ( xhr.responseText ) {
29649
29650                     var json = JSON.parse( xhr.responseText );
29651                     context.createModel( json, callback, texturePath );
29652
29653                 } else {
29654
29655                     console.warn( "THREE.JSONLoader: [" + url + "] seems to be unreachable or file there is empty" );
29656
29657                 }
29658
29659                 // in context of more complex asset initialization
29660                 // do not block on single failed file
29661                 // maybe should go even one more level up
29662
29663                 context.onLoadComplete();
29664
29665             } else {
29666
29667                 console.error( "THREE.JSONLoader: Couldn't load [" + url + "] [" + xhr.status + "]" );
29668
29669             }
29670
29671         } else if ( xhr.readyState === xhr.LOADING ) {
29672
29673             if ( callbackProgress ) {
29674
29675                 if ( length === 0 ) {
29676
29677                     length = xhr.getResponseHeader( "Content-Length" );
29678
29679                 }
29680
29681                 callbackProgress( { total: length, loaded: xhr.responseText.length } );
29682
29683             }
29684
29685         } else if ( xhr.readyState === xhr.HEADERS_RECEIVED ) {
29686
29687             length = xhr.getResponseHeader( "Content-Length" );
29688
29689         }
29690
29691     };
29692
29693     xhr.open( "GET", url, true );
29694     xhr.send( null );
29695
29696 };
29697
29698 THREE.JSONLoader.prototype.createModel = function ( json, callback, texturePath ) {
29699
29700     var scope = this,
29701     geometry = new THREE.Geometry(),
29702     scale = ( json.scale !== undefined ) ? 1.0 / json.scale : 1.0;
29703
29704     this.initMaterials( geometry, json.materials, texturePath );
29705
29706     parseModel( scale );
29707
29708     parseSkin();
29709     parseMorphing( scale );
29710
29711     geometry.computeCentroids();
29712     geometry.computeFaceNormals();
29713
29714     if ( this.hasNormals( geometry ) ) geometry.computeTangents();
29715
29716
29717     function parseModel( scale ) {
29718
29719         function isBitSet( value, position ) {
29720
29721             return value & ( 1 << position );
29722
29723         }
29724
29725         var i, j, fi,
29726
29727         offset, zLength, nVertices,
29728
29729         colorIndex, normalIndex, uvIndex, materialIndex,
29730
29731         type,
29732         isQuad,
29733         hasMaterial,
29734         hasFaceUv, hasFaceVertexUv,
29735         hasFaceNormal, hasFaceVertexNormal,
29736         hasFaceColor, hasFaceVertexColor,
29737
29738         vertex, face, color, normal,
29739
29740         uvLayer, uvs, u, v,
29741
29742         faces = json.faces,
29743         vertices = json.vertices,
29744         normals = json.normals,
29745         colors = json.colors,
29746
29747         nUvLayers = 0;
29748
29749         // disregard empty arrays
29750
29751         for ( i = 0; i < json.uvs.length; i++ ) {
29752
29753             if ( json.uvs[ i ].length ) nUvLayers ++;
29754
29755         }
29756
29757         for ( i = 0; i < nUvLayers; i++ ) {
29758
29759             geometry.faceUvs[ i ] = [];
29760             geometry.faceVertexUvs[ i ] = [];
29761
29762         }
29763
29764         offset = 0;
29765         zLength = vertices.length;
29766
29767         while ( offset < zLength ) {
29768
29769             vertex = new THREE.Vector3();
29770
29771             vertex.x = vertices[ offset ++ ] * scale;
29772             vertex.y = vertices[ offset ++ ] * scale;
29773             vertex.z = vertices[ offset ++ ] * scale;
29774
29775             geometry.vertices.push( vertex );
29776
29777         }
29778
29779         offset = 0;
29780         zLength = faces.length;
29781
29782         while ( offset < zLength ) {
29783
29784             type = faces[ offset ++ ];
29785
29786
29787             isQuad              = isBitSet( type, 0 );
29788             hasMaterial         = isBitSet( type, 1 );
29789             hasFaceUv           = isBitSet( type, 2 );
29790             hasFaceVertexUv     = isBitSet( type, 3 );
29791             hasFaceNormal       = isBitSet( type, 4 );
29792             hasFaceVertexNormal = isBitSet( type, 5 );
29793             hasFaceColor        = isBitSet( type, 6 );
29794             hasFaceVertexColor  = isBitSet( type, 7 );
29795
29796             //console.log("type", type, "bits", isQuad, hasMaterial, hasFaceUv, hasFaceVertexUv, hasFaceNormal, hasFaceVertexNormal, hasFaceColor, hasFaceVertexColor);
29797
29798             if ( isQuad ) {
29799
29800                 face = new THREE.Face4();
29801
29802                 face.a = faces[ offset ++ ];
29803                 face.b = faces[ offset ++ ];
29804                 face.c = faces[ offset ++ ];
29805                 face.d = faces[ offset ++ ];
29806
29807                 nVertices = 4;
29808
29809             } else {
29810
29811                 face = new THREE.Face3();
29812
29813                 face.a = faces[ offset ++ ];
29814                 face.b = faces[ offset ++ ];
29815                 face.c = faces[ offset ++ ];
29816
29817                 nVertices = 3;
29818
29819             }
29820
29821             if ( hasMaterial ) {
29822
29823                 materialIndex = faces[ offset ++ ];
29824                 face.materialIndex = materialIndex;
29825
29826             }
29827
29828             // to get face <=> uv index correspondence
29829
29830             fi = geometry.faces.length;
29831
29832             if ( hasFaceUv ) {
29833
29834                 for ( i = 0; i < nUvLayers; i++ ) {
29835
29836                     uvLayer = json.uvs[ i ];
29837
29838                     uvIndex = faces[ offset ++ ];
29839
29840                     u = uvLayer[ uvIndex * 2 ];
29841                     v = uvLayer[ uvIndex * 2 + 1 ];
29842
29843                     geometry.faceUvs[ i ][ fi ] = new THREE.UV( u, v );
29844
29845                 }
29846
29847             }
29848
29849             if ( hasFaceVertexUv ) {
29850
29851                 for ( i = 0; i < nUvLayers; i++ ) {
29852
29853                     uvLayer = json.uvs[ i ];
29854
29855                     uvs = [];
29856
29857                     for ( j = 0; j < nVertices; j ++ ) {
29858
29859                         uvIndex = faces[ offset ++ ];
29860
29861                         u = uvLayer[ uvIndex * 2 ];
29862                         v = uvLayer[ uvIndex * 2 + 1 ];
29863
29864                         uvs[ j ] = new THREE.UV( u, v );
29865
29866                     }
29867
29868                     geometry.faceVertexUvs[ i ][ fi ] = uvs;
29869
29870                 }
29871
29872             }
29873
29874             if ( hasFaceNormal ) {
29875
29876                 normalIndex = faces[ offset ++ ] * 3;
29877
29878                 normal = new THREE.Vector3();
29879
29880                 normal.x = normals[ normalIndex ++ ];
29881                 normal.y = normals[ normalIndex ++ ];
29882                 normal.z = normals[ normalIndex ];
29883
29884                 face.normal = normal;
29885
29886             }
29887
29888             if ( hasFaceVertexNormal ) {
29889
29890                 for ( i = 0; i < nVertices; i++ ) {
29891
29892                     normalIndex = faces[ offset ++ ] * 3;
29893
29894                     normal = new THREE.Vector3();
29895
29896                     normal.x = normals[ normalIndex ++ ];
29897                     normal.y = normals[ normalIndex ++ ];
29898                     normal.z = normals[ normalIndex ];
29899
29900                     face.vertexNormals.push( normal );
29901
29902                 }
29903
29904             }
29905
29906
29907             if ( hasFaceColor ) {
29908
29909                 colorIndex = faces[ offset ++ ];
29910
29911                 color = new THREE.Color( colors[ colorIndex ] );
29912                 face.color = color;
29913
29914             }
29915
29916
29917             if ( hasFaceVertexColor ) {
29918
29919                 for ( i = 0; i < nVertices; i++ ) {
29920
29921                     colorIndex = faces[ offset ++ ];
29922
29923                     color = new THREE.Color( colors[ colorIndex ] );
29924                     face.vertexColors.push( color );
29925
29926                 }
29927
29928             }
29929
29930             geometry.faces.push( face );
29931
29932         }
29933
29934     };
29935
29936     function parseSkin() {
29937
29938         var i, l, x, y, z, w, a, b, c, d;
29939
29940         if ( json.skinWeights ) {
29941
29942             for ( i = 0, l = json.skinWeights.length; i < l; i += 2 ) {
29943
29944                 x = json.skinWeights[ i     ];
29945                 y = json.skinWeights[ i + 1 ];
29946                 z = 0;
29947                 w = 0;
29948
29949                 geometry.skinWeights.push( new THREE.Vector4( x, y, z, w ) );
29950
29951             }
29952
29953         }
29954
29955         if ( json.skinIndices ) {
29956
29957             for ( i = 0, l = json.skinIndices.length; i < l; i += 2 ) {
29958
29959                 a = json.skinIndices[ i     ];
29960                 b = json.skinIndices[ i + 1 ];
29961                 c = 0;
29962                 d = 0;
29963
29964                 geometry.skinIndices.push( new THREE.Vector4( a, b, c, d ) );
29965
29966             }
29967
29968         }
29969
29970         geometry.bones = json.bones;
29971         geometry.animation = json.animation;
29972
29973     };
29974
29975     function parseMorphing( scale ) {
29976
29977         if ( json.morphTargets !== undefined ) {
29978
29979             var i, l, v, vl, dstVertices, srcVertices;
29980
29981             for ( i = 0, l = json.morphTargets.length; i < l; i ++ ) {
29982
29983                 geometry.morphTargets[ i ] = {};
29984                 geometry.morphTargets[ i ].name = json.morphTargets[ i ].name;
29985                 geometry.morphTargets[ i ].vertices = [];
29986
29987                 dstVertices = geometry.morphTargets[ i ].vertices;
29988                 srcVertices = json.morphTargets [ i ].vertices;
29989
29990                 for( v = 0, vl = srcVertices.length; v < vl; v += 3 ) {
29991
29992                     var vertex = new THREE.Vector3();
29993                     vertex.x = srcVertices[ v ] * scale;
29994                     vertex.y = srcVertices[ v + 1 ] * scale;
29995                     vertex.z = srcVertices[ v + 2 ] * scale;
29996
29997                     dstVertices.push( vertex );
29998
29999                 }
30000
30001             }
30002
30003         }
30004
30005         if ( json.morphColors !== undefined ) {
30006
30007             var i, l, c, cl, dstColors, srcColors, color;
30008
30009             for ( i = 0, l = json.morphColors.length; i < l; i++ ) {
30010
30011                 geometry.morphColors[ i ] = {};
30012                 geometry.morphColors[ i ].name = json.morphColors[ i ].name;
30013                 geometry.morphColors[ i ].colors = [];
30014
30015                 dstColors = geometry.morphColors[ i ].colors;
30016                 srcColors = json.morphColors [ i ].colors;
30017
30018                 for ( c = 0, cl = srcColors.length; c < cl; c += 3 ) {
30019
30020                     color = new THREE.Color( 0xffaa00 );
30021                     color.setRGB( srcColors[ c ], srcColors[ c + 1 ], srcColors[ c + 2 ] );
30022                     dstColors.push( color );
30023
30024                 }
30025
30026             }
30027
30028         }
30029
30030     };
30031
30032     callback( geometry );
30033
30034 };
30035 /**
30036  * @author mrdoob / http://mrdoob.com/
30037  */
30038
30039 THREE.LoadingMonitor = function () {
30040
30041     THREE.EventTarget.call( this );
30042
30043     var scope = this;
30044
30045     var loaded = 0;
30046     var total = 0;
30047
30048     var onLoad = function ( event ) {
30049
30050         loaded ++;
30051
30052         scope.dispatchEvent( { type: 'progress', loaded: loaded, total: total } );
30053
30054         if ( loaded === total ) {
30055
30056             scope.dispatchEvent( { type: 'load' } );
30057
30058         }
30059
30060     };
30061
30062     this.add = function ( loader ) {
30063
30064         total ++;
30065
30066         loader.addEventListener( 'load', onLoad, false );
30067
30068     };
30069
30070 };
30071 /**
30072  * @author mrdoob / http://mrdoob.com/
30073  * @author alteredq / http://alteredqualia.com/
30074  */
30075
30076 THREE.GeometryLoader = function () {
30077
30078     THREE.EventTarget.call( this );
30079
30080     this.crossOrigin = null;
30081     this.path = null;
30082
30083
30084 };
30085
30086 THREE.GeometryLoader.prototype = {
30087
30088     constructor: THREE.GeometryLoader,
30089
30090     load: function ( url ) {
30091
30092         var scope = this;
30093         var geometry = null;
30094
30095         if ( scope.path === null ) {
30096
30097             var parts = url.split( '/' ); parts.pop();
30098             scope.path = ( parts.length < 1 ? '.' : parts.join( '/' ) );
30099
30100         }
30101
30102         //
30103
30104         var xhr = new XMLHttpRequest();
30105
30106         xhr.addEventListener( 'load', function ( event ) {
30107
30108             if ( event.target.responseText ) {
30109
30110                 geometry = scope.parse( JSON.parse( event.target.responseText ), monitor );
30111
30112             } else {
30113
30114                 scope.dispatchEvent( { type: 'error', message: 'Invalid file [' + url + ']' } );
30115
30116             }
30117
30118         }, false );
30119
30120         xhr.addEventListener( 'error', function () {
30121
30122             scope.dispatchEvent( { type: 'error', message: 'Couldn\'t load URL [' + url + ']' } );
30123
30124         }, false );
30125
30126         xhr.open( 'GET', url, true );
30127         xhr.send( null );
30128
30129         //
30130
30131         var monitor = new THREE.LoadingMonitor();
30132
30133         monitor.addEventListener( 'load', function ( event ) {
30134
30135             scope.dispatchEvent( { type: 'load', content: geometry } );
30136
30137         } );
30138
30139         monitor.add( xhr );
30140
30141     },
30142
30143     parse: function ( data, monitor ) {
30144
30145         var scope = this;
30146         var geometry = new THREE.Geometry();
30147
30148         var scale = ( data.scale !== undefined ) ? 1 / data.scale : 1;
30149
30150         // materials
30151
30152         if ( data.materials ) {
30153
30154             geometry.materials = [];
30155
30156             for ( var i = 0; i < data.materials.length; ++ i ) {
30157
30158                 var m = data.materials[ i ];
30159
30160                 function isPow2( n ) {
30161
30162                     var l = Math.log( n ) / Math.LN2;
30163                     return Math.floor( l ) == l;
30164
30165                 }
30166
30167                 function nearestPow2( n ) {
30168
30169                     var l = Math.log( n ) / Math.LN2;
30170                     return Math.pow( 2, Math.round(  l ) );
30171
30172                 }
30173
30174                 function createTexture( where, name, sourceFile, repeat, offset, wrap ) {
30175
30176                     where[ name ] = new THREE.Texture();
30177                     where[ name ].sourceFile = sourceFile;
30178
30179                     if ( repeat ) {
30180
30181                         where[ name ].repeat.set( repeat[ 0 ], repeat[ 1 ] );
30182
30183                         if ( repeat[ 0 ] !== 1 ) where[ name ].wrapS = THREE.RepeatWrapping;
30184                         if ( repeat[ 1 ] !== 1 ) where[ name ].wrapT = THREE.RepeatWrapping;
30185
30186                     }
30187
30188                     if ( offset ) {
30189
30190                         where[ name ].offset.set( offset[ 0 ], offset[ 1 ] );
30191
30192                     }
30193
30194                     if ( wrap ) {
30195
30196                         var wrapMap = {
30197
30198                             "repeat": THREE.RepeatWrapping,
30199                             "mirror": THREE.MirroredRepeatWrapping
30200
30201                         }
30202
30203                         if ( wrapMap[ wrap[ 0 ] ] !== undefined ) where[ name ].wrapS = wrapMap[ wrap[ 0 ] ];
30204                         if ( wrapMap[ wrap[ 1 ] ] !== undefined ) where[ name ].wrapT = wrapMap[ wrap[ 1 ] ];
30205
30206                     }
30207
30208                     // load image
30209
30210                     var texture = where[ name ];
30211
30212                     var loader = new THREE.ImageLoader();
30213                     loader.addEventListener( 'load', function ( event ) {
30214
30215                         var image = event.content;
30216
30217                         if ( !isPow2( image.width ) || !isPow2( image.height ) ) {
30218
30219                             var width = nearestPow2( image.width );
30220                             var height = nearestPow2( image.height );
30221
30222                             texture.image = document.createElement( 'canvas' );
30223                             texture.image.width = width;
30224                             texture.image.height = height;
30225                             texture.image.getContext( '2d' ).drawImage( image, 0, 0, width, height );
30226
30227                         } else {
30228
30229                             texture.image = image;
30230
30231                         }
30232
30233                         texture.needsUpdate = true;
30234
30235                     } );
30236                     loader.crossOrigin = scope.crossOrigin;
30237                     loader.load( scope.path + '/' + sourceFile );
30238
30239                     if ( monitor ) monitor.add( loader );
30240
30241                 }
30242
30243                 function rgb2hex( rgb ) {
30244
30245                     return ( rgb[ 0 ] * 255 << 16 ) + ( rgb[ 1 ] * 255 << 8 ) + rgb[ 2 ] * 255;
30246
30247                 }
30248
30249                 // defaults
30250
30251                 var mtype = "MeshLambertMaterial";
30252                 var mpars = { color: 0xeeeeee, opacity: 1.0, map: null, lightMap: null, normalMap: null, bumpMap: null, wireframe: false };
30253
30254                 // parameters from model file
30255
30256                 if ( m.shading ) {
30257
30258                     var shading = m.shading.toLowerCase();
30259
30260                     if ( shading === "phong" ) mtype = "MeshPhongMaterial";
30261                     else if ( shading === "basic" ) mtype = "MeshBasicMaterial";
30262
30263                 }
30264
30265                 if ( m.blending !== undefined && THREE[ m.blending ] !== undefined ) {
30266
30267                     mpars.blending = THREE[ m.blending ];
30268
30269                 }
30270
30271                 if ( m.transparent !== undefined || m.opacity < 1.0 ) {
30272
30273                     mpars.transparent = m.transparent;
30274
30275                 }
30276
30277                 if ( m.depthTest !== undefined ) {
30278
30279                     mpars.depthTest = m.depthTest;
30280
30281                 }
30282
30283                 if ( m.depthWrite !== undefined ) {
30284
30285                     mpars.depthWrite = m.depthWrite;
30286
30287                 }
30288
30289                 if ( m.vertexColors !== undefined ) {
30290
30291                     if ( m.vertexColors == "face" ) {
30292
30293                         mpars.vertexColors = THREE.FaceColors;
30294
30295                     } else if ( m.vertexColors ) {
30296
30297                         mpars.vertexColors = THREE.VertexColors;
30298
30299                     }
30300
30301                 }
30302
30303                 // colors
30304
30305                 if ( m.colorDiffuse ) {
30306
30307                     mpars.color = rgb2hex( m.colorDiffuse );
30308
30309                 } else if ( m.DbgColor ) {
30310
30311                     mpars.color = m.DbgColor;
30312
30313                 }
30314
30315                 if ( m.colorSpecular ) {
30316
30317                     mpars.specular = rgb2hex( m.colorSpecular );
30318
30319                 }
30320
30321                 if ( m.colorAmbient ) {
30322
30323                     mpars.ambient = rgb2hex( m.colorAmbient );
30324
30325                 }
30326
30327                 // modifiers
30328
30329                 if ( m.transparency ) {
30330
30331                     mpars.opacity = m.transparency;
30332
30333                 }
30334
30335                 if ( m.specularCoef ) {
30336
30337                     mpars.shininess = m.specularCoef;
30338
30339                 }
30340
30341                 if ( m.visible !== undefined ) {
30342
30343                     mpars.visible = m.visible;
30344
30345                 }
30346
30347                 if ( m.flipSided !== undefined ) {
30348
30349                     mpars.side = THREE.BackSide;
30350
30351                 }
30352
30353                 if ( m.doubleSided !== undefined ) {
30354
30355                     mpars.side = THREE.DoubleSide;
30356
30357                 }
30358
30359                 if ( m.wireframe !== undefined ) {
30360
30361                     mpars.wireframe = m.wireframe;
30362
30363                 }
30364
30365                 // textures
30366
30367                 if ( m.mapDiffuse ) {
30368
30369                     createTexture( mpars, "map", m.mapDiffuse, m.mapDiffuseRepeat, m.mapDiffuseOffset, m.mapDiffuseWrap );
30370
30371                 }
30372
30373                 if ( m.mapLight ) {
30374
30375                     createTexture( mpars, "lightMap", m.mapLight, m.mapLightRepeat, m.mapLightOffset, m.mapLightWrap );
30376
30377                 }
30378
30379                 if ( m.mapBump ) {
30380
30381                     createTexture( mpars, "bumpMap", m.mapBump, m.mapBumpRepeat, m.mapBumpOffset, m.mapBumpWrap );
30382
30383                 }
30384
30385                 if ( m.mapNormal ) {
30386
30387                     createTexture( mpars, "normalMap", m.mapNormal, m.mapNormalRepeat, m.mapNormalOffset, m.mapNormalWrap );
30388
30389                 }
30390
30391                 if ( m.mapSpecular ) {
30392
30393                     createTexture( mpars, "specularMap", m.mapSpecular, m.mapSpecularRepeat, m.mapSpecularOffset, m.mapSpecularWrap );
30394
30395                 }
30396
30397                 // special case for normal mapped material
30398
30399                 if ( m.mapNormal ) {
30400
30401                     var shader = THREE.ShaderUtils.lib[ "normal" ];
30402                     var uniforms = THREE.UniformsUtils.clone( shader.uniforms );
30403
30404                     uniforms[ "tNormal" ].value = mpars.normalMap;
30405
30406                     if ( m.mapNormalFactor ) {
30407
30408                         uniforms[ "uNormalScale" ].value.set( m.mapNormalFactor, m.mapNormalFactor );
30409
30410                     }
30411
30412                     if ( mpars.map ) {
30413
30414                         uniforms[ "tDiffuse" ].value = mpars.map;
30415                         uniforms[ "enableDiffuse" ].value = true;
30416
30417                     }
30418
30419                     if ( mpars.specularMap ) {
30420
30421                         uniforms[ "tSpecular" ].value = mpars.specularMap;
30422                         uniforms[ "enableSpecular" ].value = true;
30423
30424                     }
30425
30426                     if ( mpars.lightMap ) {
30427
30428                         uniforms[ "tAO" ].value = mpars.lightMap;
30429                         uniforms[ "enableAO" ].value = true;
30430
30431                     }
30432
30433                     // for the moment don't handle displacement texture
30434
30435                     uniforms[ "uDiffuseColor" ].value.setHex( mpars.color );
30436                     uniforms[ "uSpecularColor" ].value.setHex( mpars.specular );
30437                     uniforms[ "uAmbientColor" ].value.setHex( mpars.ambient );
30438
30439                     uniforms[ "uShininess" ].value = mpars.shininess;
30440
30441                     if ( mpars.opacity !== undefined ) {
30442
30443                         uniforms[ "uOpacity" ].value = mpars.opacity;
30444
30445                     }
30446
30447                     var parameters = { fragmentShader: shader.fragmentShader, vertexShader: shader.vertexShader, uniforms: uniforms, lights: true, fog: true };
30448                     var material = new THREE.ShaderMaterial( parameters );
30449
30450                 } else {
30451
30452                     var material = new THREE[ mtype ]( mpars );
30453
30454                 }
30455
30456                 if ( m.DbgName !== undefined ) material.name = m.DbgName;
30457
30458                 geometry.materials[ i ] = material;
30459
30460             }
30461
30462         }
30463
30464         // geometry
30465
30466         function isBitSet( value, position ) {
30467
30468             return value & ( 1 << position );
30469
30470         }
30471
30472         var faces = data.faces;
30473         var vertices = data.vertices;
30474         var normals = data.normals;
30475         var colors = data.colors;
30476         var nUvLayers = 0;
30477
30478         // disregard empty arrays
30479
30480         if ( data.uvs ) {
30481
30482             for ( var i = 0; i < data.uvs.length; i ++ ) {
30483
30484                 if ( data.uvs[ i ].length ) nUvLayers ++;
30485
30486             }
30487
30488         }
30489
30490         for ( var i = 0; i < nUvLayers; i ++ ) {
30491
30492             geometry.faceUvs[ i ] = [];
30493             geometry.faceVertexUvs[ i ] = [];
30494
30495         }
30496
30497         var offset = 0;
30498         var zLength = vertices.length;
30499
30500         while ( offset < zLength ) {
30501
30502             var vertex = new THREE.Vector3();
30503
30504             vertex.x = vertices[ offset ++ ] * scale;
30505             vertex.y = vertices[ offset ++ ] * scale;
30506             vertex.z = vertices[ offset ++ ] * scale;
30507
30508             geometry.vertices.push( vertex );
30509
30510         }
30511
30512         offset = 0;
30513         zLength = faces.length;
30514
30515         while ( offset < zLength ) {
30516
30517             var type = faces[ offset ++ ];
30518
30519             var isQuad = isBitSet( type, 0 );
30520
30521             var hasMaterial = isBitSet( type, 1 );
30522             var hasFaceUv = isBitSet( type, 2 );
30523             var hasFaceVertexUv = isBitSet( type, 3 );
30524             var hasFaceNormal = isBitSet( type, 4 );
30525             var hasFaceVertexNormal = isBitSet( type, 5 );
30526             var hasFaceColor = isBitSet( type, 6 );
30527             var hasFaceVertexColor = isBitSet( type, 7 );
30528
30529             // console.log("type", type, "bits", isQuad, hasMaterial, hasFaceUv, hasFaceVertexUv, hasFaceNormal, hasFaceVertexNormal, hasFaceColor, hasFaceVertexColor);
30530
30531             if ( isQuad ) {
30532
30533                 var face = new THREE.Face4();
30534
30535                 face.a = faces[ offset ++ ];
30536                 face.b = faces[ offset ++ ];
30537                 face.c = faces[ offset ++ ];
30538                 face.d = faces[ offset ++ ];
30539
30540                 var nVertices = 4;
30541
30542             } else {
30543
30544                 var face = new THREE.Face3();
30545
30546                 face.a = faces[ offset ++ ];
30547                 face.b = faces[ offset ++ ];
30548                 face.c = faces[ offset ++ ];
30549
30550                 var nVertices = 3;
30551
30552             }
30553
30554             if ( hasMaterial ) {
30555
30556                 var materialIndex = faces[ offset ++ ];
30557                 face.materialIndex = materialIndex;
30558
30559             }
30560
30561             // to get face <=> uv index correspondence
30562
30563             var fi = geometry.faces.length;
30564
30565             if ( hasFaceUv ) {
30566
30567                 for ( var i = 0; i < nUvLayers; i ++ ) {
30568
30569                     var uvLayer = data.uvs[ i ];
30570
30571                     var uvIndex = faces[ offset ++ ];
30572
30573                     var u = uvLayer[ uvIndex * 2 ];
30574                     var v = uvLayer[ uvIndex * 2 + 1 ];
30575
30576                     geometry.faceUvs[ i ][ fi ] = new THREE.UV( u, v );
30577
30578                 }
30579
30580             }
30581
30582             if ( hasFaceVertexUv ) {
30583
30584                 for ( var i = 0; i < nUvLayers; i ++ ) {
30585
30586                     var uvLayer = data.uvs[ i ];
30587
30588                     var uvs = [];
30589
30590                     for ( var j = 0; j < nVertices; j ++ ) {
30591
30592                         var uvIndex = faces[ offset ++ ];
30593
30594                         var u = uvLayer[ uvIndex * 2 ];
30595                         var v = uvLayer[ uvIndex * 2 + 1 ];
30596
30597                         uvs[ j ] = new THREE.UV( u, v );
30598
30599                     }
30600
30601                     geometry.faceVertexUvs[ i ][ fi ] = uvs;
30602
30603                 }
30604
30605             }
30606
30607             if ( hasFaceNormal ) {
30608
30609                 var normalIndex = faces[ offset ++ ] * 3;
30610
30611                 var normal = new THREE.Vector3();
30612
30613                 normal.x = normals[ normalIndex ++ ];
30614                 normal.y = normals[ normalIndex ++ ];
30615                 normal.z = normals[ normalIndex ];
30616
30617                 face.normal = normal;
30618
30619             }
30620
30621             if ( hasFaceVertexNormal ) {
30622
30623                 for ( i = 0; i < nVertices; i ++ ) {
30624
30625                     var normalIndex = faces[ offset ++ ] * 3;
30626
30627                     var normal = new THREE.Vector3();
30628
30629                     normal.x = normals[ normalIndex ++ ];
30630                     normal.y = normals[ normalIndex ++ ];
30631                     normal.z = normals[ normalIndex ];
30632
30633                     face.vertexNormals.push( normal );
30634
30635                 }
30636
30637             }
30638
30639
30640             if ( hasFaceColor ) {
30641
30642                 var colorIndex = faces[ offset ++ ];
30643
30644                 face.color = new THREE.Color( colors[ colorIndex ] );
30645
30646             }
30647
30648
30649             if ( hasFaceVertexColor ) {
30650
30651                 for ( var i = 0; i < nVertices; i ++ ) {
30652
30653                     var colorIndex = faces[ offset ++ ];
30654
30655                     face.vertexColors.push( new THREE.Color( colors[ colorIndex ] ) );
30656
30657                 }
30658
30659             }
30660
30661             geometry.faces.push( face );
30662
30663         }
30664
30665
30666         // skin
30667
30668         if ( data.skinWeights ) {
30669
30670             for ( var i = 0, l = data.skinWeights.length; i < l; i += 2 ) {
30671
30672                 var x = data.skinWeights[ i ];
30673                 var y = data.skinWeights[ i + 1 ];
30674                 var z = 0;
30675                 var w = 0;
30676
30677                 geometry.skinWeights.push( new THREE.Vector4( x, y, z, w ) );
30678
30679             }
30680
30681         }
30682
30683         if ( data.skinIndices ) {
30684
30685             for ( var i = 0, l = data.skinIndices.length; i < l; i += 2 ) {
30686
30687                 var a = data.skinIndices[ i ];
30688                 var b = data.skinIndices[ i + 1 ];
30689                 var c = 0;
30690                 var d = 0;
30691
30692                 geometry.skinIndices.push( new THREE.Vector4( a, b, c, d ) );
30693
30694             }
30695
30696         }
30697
30698         geometry.bones = data.bones;
30699         geometry.animation = data.animation;
30700
30701
30702         // morphing
30703
30704         if ( data.morphTargets ) {
30705
30706             for ( var i = 0, l = data.morphTargets.length; i < l; i ++ ) {
30707
30708                 geometry.morphTargets[ i ] = {};
30709                 geometry.morphTargets[ i ].name = data.morphTargets[ i ].name;
30710                 geometry.morphTargets[ i ].vertices = [];
30711
30712                 var dstVertices = geometry.morphTargets[ i ].vertices;
30713                 var srcVertices = data.morphTargets [ i ].vertices;
30714
30715                 for( var v = 0, vl = srcVertices.length; v < vl; v += 3 ) {
30716
30717                     var vertex = new THREE.Vector3();
30718                     vertex.x = srcVertices[ v ] * scale;
30719                     vertex.y = srcVertices[ v + 1 ] * scale;
30720                     vertex.z = srcVertices[ v + 2 ] * scale;
30721
30722                     dstVertices.push( vertex );
30723
30724                 }
30725
30726             }
30727
30728         }
30729
30730         if ( data.morphColors ) {
30731
30732             for ( var i = 0, l = data.morphColors.length; i < l; i++ ) {
30733
30734                 geometry.morphColors[ i ] = {};
30735                 geometry.morphColors[ i ].name = data.morphColors[ i ].name;
30736                 geometry.morphColors[ i ].colors = [];
30737
30738                 var dstColors = geometry.morphColors[ i ].colors;
30739                 var srcColors = data.morphColors [ i ].colors;
30740
30741                 for ( var c = 0, cl = srcColors.length; c < cl; c += 3 ) {
30742
30743                     var color = new THREE.Color( 0xffaa00 );
30744                     color.setRGB( srcColors[ c ], srcColors[ c + 1 ], srcColors[ c + 2 ] );
30745
30746                     dstColors.push( color );
30747
30748                 }
30749
30750             }
30751
30752         }
30753
30754         geometry.computeCentroids();
30755         geometry.computeFaceNormals();
30756
30757         return geometry;
30758
30759     }
30760
30761 };
30762 /**
30763  * @author alteredq / http://alteredqualia.com/
30764  */
30765
30766 THREE.SceneLoader = function () {
30767
30768     this.onLoadStart = function () {};
30769     this.onLoadProgress = function() {};
30770     this.onLoadComplete = function () {};
30771
30772     this.callbackSync = function () {};
30773     this.callbackProgress = function () {};
30774
30775     this.geometryHandlerMap = {};
30776
30777     this.addGeometryHandler( "ascii", THREE.JSONLoader );
30778     this.addGeometryHandler( "binary", THREE.BinaryLoader );
30779
30780 };
30781
30782 THREE.SceneLoader.prototype.constructor = THREE.SceneLoader;
30783
30784 THREE.SceneLoader.prototype.load = function ( url, callbackFinished ) {
30785
30786     var scope = this;
30787
30788     var xhr = new XMLHttpRequest();
30789
30790     xhr.onreadystatechange = function () {
30791
30792         if ( xhr.readyState === 4 ) {
30793
30794             if ( xhr.status === 200 || xhr.status === 0 ) {
30795
30796                 var json = JSON.parse( xhr.responseText );
30797                 scope.parse( json, callbackFinished, url );
30798
30799             } else {
30800
30801                 console.error( "THREE.SceneLoader: Couldn't load [" + url + "] [" + xhr.status + "]" );
30802
30803             }
30804
30805         }
30806
30807     };
30808
30809     xhr.open( "GET", url, true );
30810     xhr.send( null );
30811
30812 };
30813
30814 THREE.SceneLoader.prototype.addGeometryHandler = function ( typeID, loaderClass ) {
30815
30816     this.geometryHandlerMap[ typeID ] = { "loaderClass": loaderClass };
30817
30818 };
30819
30820 THREE.SceneLoader.prototype.parse = function ( json, callbackFinished, url ) {
30821
30822     var scope = this;
30823
30824     var urlBase = THREE.Loader.prototype.extractUrlBase( url );
30825
30826     var dg, dm, dl, dc, df, dt,
30827         g, m, l, d, p, r, q, s, c, t, f, tt, pp, u,
30828         geometry, material, camera, fog,
30829         texture, images,
30830         light,
30831         counter_models, counter_textures,
30832         total_models, total_textures,
30833         result;
30834
30835     var data = json;
30836
30837     // async geometry loaders
30838
30839     for ( var typeID in this.geometryHandlerMap ) {
30840
30841         var loaderClass = this.geometryHandlerMap[ typeID ][ "loaderClass" ];
30842         this.geometryHandlerMap[ typeID ][ "loaderObject" ] = new loaderClass();
30843
30844     }
30845
30846     counter_models = 0;
30847     counter_textures = 0;
30848
30849     result = {
30850
30851         scene: new THREE.Scene(),
30852         geometries: {},
30853         materials: {},
30854         textures: {},
30855         objects: {},
30856         cameras: {},
30857         lights: {},
30858         fogs: {},
30859         empties: {}
30860
30861     };
30862
30863     if ( data.transform ) {
30864
30865         var position = data.transform.position,
30866             rotation = data.transform.rotation,
30867             scale = data.transform.scale;
30868
30869         if ( position )
30870             result.scene.position.set( position[ 0 ], position[ 1 ], position [ 2 ] );
30871
30872         if ( rotation )
30873             result.scene.rotation.set( rotation[ 0 ], rotation[ 1 ], rotation [ 2 ] );
30874
30875         if ( scale )
30876             result.scene.scale.set( scale[ 0 ], scale[ 1 ], scale [ 2 ] );
30877
30878         if ( position || rotation || scale ) {
30879
30880             result.scene.updateMatrix();
30881             result.scene.updateMatrixWorld();
30882
30883         }
30884
30885     }
30886
30887     function get_url( source_url, url_type ) {
30888
30889         if ( url_type == "relativeToHTML" ) {
30890
30891             return source_url;
30892
30893         } else {
30894
30895             return urlBase + "/" + source_url;
30896
30897         }
30898
30899     };
30900
30901     // toplevel loader function, delegates to handle_children
30902
30903     function handle_objects() {
30904
30905         handle_children( result.scene, data.objects );
30906
30907     }
30908
30909     // handle all the children from the loaded json and attach them to given parent
30910
30911     function handle_children( parent, children ) {
30912
30913         for ( var dd in children ) {
30914
30915             // check by id if child has already been handled,
30916             // if not, create new object
30917
30918             if ( result.objects[ dd ] === undefined ) {
30919
30920                 var o = children[ dd ];
30921
30922                 var object = null;
30923
30924                 if ( o.geometry !== undefined ) {
30925
30926                     geometry = result.geometries[ o.geometry ];
30927
30928                     // geometry already loaded
30929
30930                     if ( geometry ) {
30931
30932                         var hasNormals = false;
30933
30934                         // not anymore support for multiple materials
30935                         // shouldn't really be array
30936
30937                         material = result.materials[ o.materials[ 0 ] ];
30938                         hasNormals = material instanceof THREE.ShaderMaterial;
30939
30940                         if ( hasNormals ) {
30941
30942                             geometry.computeTangents();
30943
30944                         }
30945
30946                         p = o.position;
30947                         r = o.rotation;
30948                         q = o.quaternion;
30949                         s = o.scale;
30950                         m = o.matrix;
30951
30952                         // turn off quaternions, for the moment
30953
30954                         q = 0;
30955
30956                         if ( o.materials.length === 0 ) {
30957
30958                             material = new THREE.MeshFaceMaterial();
30959
30960                         }
30961
30962                         // dirty hack to handle meshes with multiple materials
30963                         // just use face materials defined in model
30964
30965                         if ( o.materials.length > 1 ) {
30966
30967                             material = new THREE.MeshFaceMaterial();
30968
30969                         }
30970
30971                         if ( o.morph ) {
30972
30973                             object = new THREE.MorphAnimMesh( geometry, material );
30974
30975                             if ( o.duration !== undefined ) {
30976
30977                                 object.duration = o.duration;
30978
30979                             }
30980
30981                             if ( o.time !== undefined ) {
30982
30983                                 object.time = o.time;
30984
30985                             }
30986
30987                             if ( o.mirroredLoop !== undefined ) {
30988
30989                                 object.mirroredLoop = o.mirroredLoop;
30990
30991                             }
30992
30993                             if ( material.morphNormals ) {
30994
30995                                 geometry.computeMorphNormals();
30996
30997                             }
30998
30999                         } else {
31000
31001                             object = new THREE.Mesh( geometry, material );
31002
31003                         }
31004
31005                         object.name = dd;
31006
31007                         if ( m ) {
31008
31009                             object.matrixAutoUpdate = false;
31010                             object.matrix.set(
31011                                 m[0], m[1], m[2], m[3],
31012                                 m[4], m[5], m[6], m[7],
31013                                 m[8], m[9], m[10], m[11],
31014                                 m[12], m[13], m[14], m[15]
31015                             );
31016
31017                         } else {
31018
31019                             object.position.set( p[0], p[1], p[2] );
31020
31021                             if ( q ) {
31022
31023                                 object.quaternion.set( q[0], q[1], q[2], q[3] );
31024                                 object.useQuaternion = true;
31025
31026                             } else {
31027
31028                                 object.rotation.set( r[0], r[1], r[2] );
31029
31030                             }
31031
31032                             object.scale.set( s[0], s[1], s[2] );
31033
31034                         }
31035
31036                         object.visible = o.visible;
31037                         object.castShadow = o.castShadow;
31038                         object.receiveShadow = o.receiveShadow;
31039
31040                         parent.add( object );
31041
31042                         result.objects[ dd ] = object;
31043
31044                     }
31045
31046                 // pure Object3D
31047
31048                 } else {
31049
31050                     p = o.position;
31051                     r = o.rotation;
31052                     q = o.quaternion;
31053                     s = o.scale;
31054
31055                     // turn off quaternions, for the moment
31056
31057                     q = 0;
31058
31059                     object = new THREE.Object3D();
31060                     object.name = dd;
31061                     object.position.set( p[0], p[1], p[2] );
31062
31063                     if ( q ) {
31064
31065                         object.quaternion.set( q[0], q[1], q[2], q[3] );
31066                         object.useQuaternion = true;
31067
31068                     } else {
31069
31070                         object.rotation.set( r[0], r[1], r[2] );
31071
31072                     }
31073
31074                     object.scale.set( s[0], s[1], s[2] );
31075                     object.visible = ( o.visible !== undefined ) ? o.visible : false;
31076
31077                     parent.add( object );
31078
31079                     result.objects[ dd ] = object;
31080                     result.empties[ dd ] = object;
31081
31082                 }
31083
31084                 if ( object ) {
31085
31086                     if ( o.properties !== undefined )  {
31087
31088                         for ( var key in o.properties ) {
31089
31090                             var value = o.properties[ key ];
31091                             object.properties[ key ] = value;
31092
31093                         }
31094
31095                     }
31096
31097                     if ( o.children !== undefined ) {
31098
31099                         handle_children( object, o.children );
31100
31101                     }
31102
31103                 }
31104
31105             }
31106
31107         }
31108
31109     };
31110
31111     function handle_mesh( geo, id ) {
31112
31113         result.geometries[ id ] = geo;
31114         handle_objects();
31115
31116     };
31117
31118     function create_callback( id ) {
31119
31120         return function( geo ) {
31121
31122             handle_mesh( geo, id );
31123
31124             counter_models -= 1;
31125
31126             scope.onLoadComplete();
31127
31128             async_callback_gate();
31129
31130         }
31131
31132     };
31133
31134     function create_callback_embed( id ) {
31135
31136         return function( geo ) {
31137
31138             result.geometries[ id ] = geo;
31139
31140         }
31141
31142     };
31143
31144     function async_callback_gate() {
31145
31146         var progress = {
31147
31148             totalModels : total_models,
31149             totalTextures : total_textures,
31150             loadedModels : total_models - counter_models,
31151             loadedTextures : total_textures - counter_textures
31152
31153         };
31154
31155         scope.callbackProgress( progress, result );
31156
31157         scope.onLoadProgress();
31158
31159         if ( counter_models === 0 && counter_textures === 0 ) {
31160
31161             callbackFinished( result );
31162
31163         }
31164
31165     };
31166
31167     var callbackTexture = function ( count ) {
31168
31169         counter_textures -= count;
31170         async_callback_gate();
31171
31172         scope.onLoadComplete();
31173
31174     };
31175
31176     // must use this instead of just directly calling callbackTexture
31177     // because of closure in the calling context loop
31178
31179     var generateTextureCallback = function ( count ) {
31180
31181         return function() {
31182
31183             callbackTexture( count );
31184
31185         };
31186
31187     };
31188
31189     // first go synchronous elements
31190
31191     // cameras
31192
31193     for( dc in data.cameras ) {
31194
31195         c = data.cameras[ dc ];
31196
31197         if ( c.type === "perspective" ) {
31198
31199             camera = new THREE.PerspectiveCamera( c.fov, c.aspect, c.near, c.far );
31200
31201         } else if ( c.type === "ortho" ) {
31202
31203             camera = new THREE.OrthographicCamera( c.left, c.right, c.top, c.bottom, c.near, c.far );
31204
31205         }
31206
31207         p = c.position;
31208         t = c.target;
31209         u = c.up;
31210
31211         camera.position.set( p[0], p[1], p[2] );
31212         camera.target = new THREE.Vector3( t[0], t[1], t[2] );
31213         if ( u ) camera.up.set( u[0], u[1], u[2] );
31214
31215         result.cameras[ dc ] = camera;
31216
31217     }
31218
31219     // lights
31220
31221     var hex, intensity;
31222
31223     for ( dl in data.lights ) {
31224
31225         l = data.lights[ dl ];
31226
31227         hex = ( l.color !== undefined ) ? l.color : 0xffffff;
31228         intensity = ( l.intensity !== undefined ) ? l.intensity : 1;
31229
31230         if ( l.type === "directional" ) {
31231
31232             p = l.direction;
31233
31234             light = new THREE.DirectionalLight( hex, intensity );
31235             light.position.set( p[0], p[1], p[2] );
31236             light.position.normalize();
31237
31238         } else if ( l.type === "point" ) {
31239
31240             p = l.position;
31241             d = l.distance;
31242
31243             light = new THREE.PointLight( hex, intensity, d );
31244             light.position.set( p[0], p[1], p[2] );
31245
31246         } else if ( l.type === "ambient" ) {
31247
31248             light = new THREE.AmbientLight( hex );
31249
31250         }
31251
31252         result.scene.add( light );
31253
31254         result.lights[ dl ] = light;
31255
31256     }
31257
31258     // fogs
31259
31260     for( df in data.fogs ) {
31261
31262         f = data.fogs[ df ];
31263
31264         if ( f.type === "linear" ) {
31265
31266             fog = new THREE.Fog( 0x000000, f.near, f.far );
31267
31268         } else if ( f.type === "exp2" ) {
31269
31270             fog = new THREE.FogExp2( 0x000000, f.density );
31271
31272         }
31273
31274         c = f.color;
31275         fog.color.setRGB( c[0], c[1], c[2] );
31276
31277         result.fogs[ df ] = fog;
31278
31279     }
31280
31281     // defaults
31282
31283     if ( result.cameras && data.defaults && data.defaults.camera ) {
31284
31285         result.currentCamera = result.cameras[ data.defaults.camera ];
31286
31287     }
31288
31289     if ( result.fogs && data.defaults && data.defaults.fog ) {
31290
31291         result.scene.fog = result.fogs[ data.defaults.fog ];
31292
31293     }
31294
31295     c = data.defaults.bgcolor;
31296     result.bgColor = new THREE.Color();
31297     result.bgColor.setRGB( c[0], c[1], c[2] );
31298
31299     result.bgColorAlpha = data.defaults.bgalpha;
31300
31301     // now come potentially asynchronous elements
31302
31303     // geometries
31304
31305     // count how many models will be loaded asynchronously
31306
31307     for( dg in data.geometries ) {
31308
31309         g = data.geometries[ dg ];
31310
31311         if ( g.type in this.geometryHandlerMap ) {
31312
31313             counter_models += 1;
31314
31315             scope.onLoadStart();
31316
31317         }
31318
31319     }
31320
31321     total_models = counter_models;
31322
31323     for ( dg in data.geometries ) {
31324
31325         g = data.geometries[ dg ];
31326
31327         if ( g.type === "cube" ) {
31328
31329             geometry = new THREE.CubeGeometry( g.width, g.height, g.depth, g.segmentsWidth, g.segmentsHeight, g.segmentsDepth, null, g.flipped, g.sides );
31330             result.geometries[ dg ] = geometry;
31331
31332         } else if ( g.type === "plane" ) {
31333
31334             geometry = new THREE.PlaneGeometry( g.width, g.height, g.segmentsWidth, g.segmentsHeight );
31335             result.geometries[ dg ] = geometry;
31336
31337         } else if ( g.type === "sphere" ) {
31338
31339             geometry = new THREE.SphereGeometry( g.radius, g.segmentsWidth, g.segmentsHeight );
31340             result.geometries[ dg ] = geometry;
31341
31342         } else if ( g.type === "cylinder" ) {
31343
31344             geometry = new THREE.CylinderGeometry( g.topRad, g.botRad, g.height, g.radSegs, g.heightSegs );
31345             result.geometries[ dg ] = geometry;
31346
31347         } else if ( g.type === "torus" ) {
31348
31349             geometry = new THREE.TorusGeometry( g.radius, g.tube, g.segmentsR, g.segmentsT );
31350             result.geometries[ dg ] = geometry;
31351
31352         } else if ( g.type === "icosahedron" ) {
31353
31354             geometry = new THREE.IcosahedronGeometry( g.radius, g.subdivisions );
31355             result.geometries[ dg ] = geometry;
31356
31357         } else if ( g.type in this.geometryHandlerMap ) {
31358
31359             var loaderParameters = {};
31360             for ( var parType in g ) {
31361
31362                 if ( parType !== "type" && parType !== "url" ) {
31363
31364                     loaderParameters[ parType ] = g[ parType ];
31365
31366                 }
31367
31368             }
31369
31370             var loader = this.geometryHandlerMap[ g.type ][ "loaderObject" ];
31371             loader.load( get_url( g.url, data.urlBaseType ), create_callback( dg ), loaderParameters );
31372
31373         } else if ( g.type === "embedded" ) {
31374
31375             var modelJson = data.embeds[ g.id ],
31376                 texture_path = "";
31377
31378             // pass metadata along to jsonLoader so it knows the format version
31379
31380             modelJson.metadata = data.metadata;
31381
31382             if ( modelJson ) {
31383
31384                 var jsonLoader = this.geometryHandlerMap[ "ascii" ][ "loaderObject" ];
31385                 jsonLoader.createModel( modelJson, create_callback_embed( dg ), texture_path );
31386
31387             }
31388
31389         }
31390
31391     }
31392
31393     // textures
31394
31395     // count how many textures will be loaded asynchronously
31396
31397     for( dt in data.textures ) {
31398
31399         tt = data.textures[ dt ];
31400
31401         if( tt.url instanceof Array ) {
31402
31403             counter_textures += tt.url.length;
31404
31405             for( var n = 0; n < tt.url.length; n ++ ) {
31406
31407                 scope.onLoadStart();
31408
31409             }
31410
31411         } else {
31412
31413             counter_textures += 1;
31414
31415             scope.onLoadStart();
31416
31417         }
31418
31419     }
31420
31421     total_textures = counter_textures;
31422
31423     for ( dt in data.textures ) {
31424
31425         tt = data.textures[ dt ];
31426
31427         if ( tt.mapping !== undefined && THREE[ tt.mapping ] !== undefined  ) {
31428
31429             tt.mapping = new THREE[ tt.mapping ]();
31430
31431         }
31432
31433         if ( tt.url instanceof Array ) {
31434
31435             var count = tt.url.length;
31436             var url_array = [];
31437
31438             for( var i = 0; i < count; i ++ ) {
31439
31440                 url_array[ i ] = get_url( tt.url[ i ], data.urlBaseType );
31441
31442             }
31443
31444             var isCompressed = url_array[ 0 ].endsWith( ".dds" );
31445
31446             if ( isCompressed ) {
31447
31448                 texture = THREE.ImageUtils.loadCompressedTextureCube( url_array, tt.mapping, generateTextureCallback( count ) );
31449
31450             } else {
31451
31452                 texture = THREE.ImageUtils.loadTextureCube( url_array, tt.mapping, generateTextureCallback( count ) );
31453
31454             }
31455
31456         } else {
31457
31458             var isCompressed = tt.url.toLowerCase().endsWith( ".dds" );
31459             var fullUrl = get_url( tt.url, data.urlBaseType );
31460             var textureCallback = generateTextureCallback( 1 );
31461
31462             if ( isCompressed ) {
31463
31464                 texture = THREE.ImageUtils.loadCompressedTexture( fullUrl, tt.mapping, textureCallback );
31465
31466             } else {
31467
31468                 texture = THREE.ImageUtils.loadTexture( fullUrl, tt.mapping, textureCallback );
31469
31470             }
31471
31472             if ( THREE[ tt.minFilter ] !== undefined )
31473                 texture.minFilter = THREE[ tt.minFilter ];
31474
31475             if ( THREE[ tt.magFilter ] !== undefined )
31476                 texture.magFilter = THREE[ tt.magFilter ];
31477
31478             if ( tt.anisotropy ) texture.anisotropy = tt.anisotropy;
31479
31480             if ( tt.repeat ) {
31481
31482                 texture.repeat.set( tt.repeat[ 0 ], tt.repeat[ 1 ] );
31483
31484                 if ( tt.repeat[ 0 ] !== 1 ) texture.wrapS = THREE.RepeatWrapping;
31485                 if ( tt.repeat[ 1 ] !== 1 ) texture.wrapT = THREE.RepeatWrapping;
31486
31487             }
31488
31489             if ( tt.offset ) {
31490
31491                 texture.offset.set( tt.offset[ 0 ], tt.offset[ 1 ] );
31492
31493             }
31494
31495             // handle wrap after repeat so that default repeat can be overriden
31496
31497             if ( tt.wrap ) {
31498
31499                 var wrapMap = {
31500                 "repeat"     : THREE.RepeatWrapping,
31501                 "mirror"    : THREE.MirroredRepeatWrapping
31502                 }
31503
31504                 if ( wrapMap[ tt.wrap[ 0 ] ] !== undefined ) texture.wrapS = wrapMap[ tt.wrap[ 0 ] ];
31505                 if ( wrapMap[ tt.wrap[ 1 ] ] !== undefined ) texture.wrapT = wrapMap[ tt.wrap[ 1 ] ];
31506
31507             }
31508
31509         }
31510
31511         result.textures[ dt ] = texture;
31512
31513     }
31514
31515     // materials
31516
31517     for ( dm in data.materials ) {
31518
31519         m = data.materials[ dm ];
31520
31521         for ( pp in m.parameters ) {
31522
31523             if ( pp === "envMap" || pp === "map" || pp === "lightMap" || pp === "bumpMap" ) {
31524
31525                 m.parameters[ pp ] = result.textures[ m.parameters[ pp ] ];
31526
31527             } else if ( pp === "shading" ) {
31528
31529                 m.parameters[ pp ] = ( m.parameters[ pp ] === "flat" ) ? THREE.FlatShading : THREE.SmoothShading;
31530
31531             } else if ( pp === "side" ) {
31532
31533                 if (  m.parameters[ pp ] == "double" ) {
31534
31535                     m.parameters[ pp ] = THREE.DoubleSide;
31536
31537                 } else if ( m.parameters[ pp ] == "back" ) {
31538
31539                     m.parameters[ pp ] = THREE.BackSide;
31540
31541                 } else {
31542
31543                     m.parameters[ pp ] = THREE.FrontSide;
31544
31545                 }
31546
31547             } else if ( pp === "blending" ) {
31548
31549                 m.parameters[ pp ] = m.parameters[ pp ] in THREE ? THREE[ m.parameters[ pp ] ] : THREE.NormalBlending;
31550
31551             } else if ( pp === "combine" ) {
31552
31553                 m.parameters[ pp ] = ( m.parameters[ pp ] == "MixOperation" ) ? THREE.MixOperation : THREE.MultiplyOperation;
31554
31555             } else if ( pp === "vertexColors" ) {
31556
31557                 if ( m.parameters[ pp ] == "face" ) {
31558
31559                     m.parameters[ pp ] = THREE.FaceColors;
31560
31561                 // default to vertex colors if "vertexColors" is anything else face colors or 0 / null / false
31562
31563                 } else if ( m.parameters[ pp ] )   {
31564
31565                     m.parameters[ pp ] = THREE.VertexColors;
31566
31567                 }
31568
31569             } else if ( pp === "wrapRGB" ) {
31570
31571                 var v3 = m.parameters[ pp ];
31572                 m.parameters[ pp ] = new THREE.Vector3( v3[ 0 ], v3[ 1 ], v3[ 2 ] );
31573
31574             }
31575
31576         }
31577
31578         if ( m.parameters.opacity !== undefined && m.parameters.opacity < 1.0 ) {
31579
31580             m.parameters.transparent = true;
31581
31582         }
31583
31584         if ( m.parameters.normalMap ) {
31585
31586             var shader = THREE.ShaderUtils.lib[ "normal" ];
31587             var uniforms = THREE.UniformsUtils.clone( shader.uniforms );
31588
31589             var diffuse = m.parameters.color;
31590             var specular = m.parameters.specular;
31591             var ambient = m.parameters.ambient;
31592             var shininess = m.parameters.shininess;
31593
31594             uniforms[ "tNormal" ].value = result.textures[ m.parameters.normalMap ];
31595
31596             if ( m.parameters.normalScale ) {
31597
31598                 uniforms[ "uNormalScale" ].value.set( m.parameters.normalScale[ 0 ], m.parameters.normalScale[ 1 ] );
31599
31600             }
31601
31602             if ( m.parameters.map ) {
31603
31604                 uniforms[ "tDiffuse" ].value = m.parameters.map;
31605                 uniforms[ "enableDiffuse" ].value = true;
31606
31607             }
31608
31609             if ( m.parameters.envMap ) {
31610
31611                 uniforms[ "tCube" ].value = m.parameters.envMap;
31612                 uniforms[ "enableReflection" ].value = true;
31613                 uniforms[ "uReflectivity" ].value = m.parameters.reflectivity;
31614
31615             }
31616
31617             if ( m.parameters.lightMap ) {
31618
31619                 uniforms[ "tAO" ].value = m.parameters.lightMap;
31620                 uniforms[ "enableAO" ].value = true;
31621
31622             }
31623
31624             if ( m.parameters.specularMap ) {
31625
31626                 uniforms[ "tSpecular" ].value = result.textures[ m.parameters.specularMap ];
31627                 uniforms[ "enableSpecular" ].value = true;
31628
31629             }
31630
31631             if ( m.parameters.displacementMap ) {
31632
31633                 uniforms[ "tDisplacement" ].value = result.textures[ m.parameters.displacementMap ];
31634                 uniforms[ "enableDisplacement" ].value = true;
31635
31636                 uniforms[ "uDisplacementBias" ].value = m.parameters.displacementBias;
31637                 uniforms[ "uDisplacementScale" ].value = m.parameters.displacementScale;
31638
31639             }
31640
31641             uniforms[ "uDiffuseColor" ].value.setHex( diffuse );
31642             uniforms[ "uSpecularColor" ].value.setHex( specular );
31643             uniforms[ "uAmbientColor" ].value.setHex( ambient );
31644
31645             uniforms[ "uShininess" ].value = shininess;
31646
31647             if ( m.parameters.opacity ) {
31648
31649                 uniforms[ "uOpacity" ].value = m.parameters.opacity;
31650
31651             }
31652
31653             var parameters = { fragmentShader: shader.fragmentShader, vertexShader: shader.vertexShader, uniforms: uniforms, lights: true, fog: true };
31654
31655             material = new THREE.ShaderMaterial( parameters );
31656
31657         } else {
31658
31659             material = new THREE[ m.type ]( m.parameters );
31660
31661         }
31662
31663         result.materials[ dm ] = material;
31664
31665     }
31666
31667     // objects ( synchronous init of procedural primitives )
31668
31669     handle_objects();
31670
31671     // synchronous callback
31672
31673     scope.callbackSync( result );
31674
31675     // just in case there are no async elements
31676
31677     async_callback_gate();
31678
31679 };
31680 /**
31681  * @author mrdoob / http://mrdoob.com/
31682  */
31683
31684 THREE.TextureLoader = function () {
31685
31686     THREE.EventTarget.call( this );
31687
31688     this.crossOrigin = null;
31689
31690 };
31691
31692 THREE.TextureLoader.prototype = {
31693
31694     constructor: THREE.TextureLoader,
31695
31696     load: function ( url ) {
31697
31698         var scope = this;
31699
31700         var image = new Image();
31701
31702         image.addEventListener( 'load', function () {
31703
31704             var texture = new THREE.Texture( image );
31705             texture.needsUpdate = true;
31706
31707             scope.dispatchEvent( { type: 'load', content: texture } );
31708
31709         }, false );
31710
31711         image.addEventListener( 'error', function () {
31712
31713             scope.dispatchEvent( { type: 'error', message: 'Couldn\'t load URL [' + url + ']' } );
31714
31715         }, false );
31716
31717         if ( scope.crossOrigin ) image.crossOrigin = scope.crossOrigin;
31718
31719         image.src = url;
31720
31721     }
31722
31723 }
31724 /**
31725  * @author mrdoob / http://mrdoob.com/
31726  * @author alteredq / http://alteredqualia.com/
31727  */
31728
31729 THREE.Material = function () {
31730
31731     this.id = THREE.MaterialCount ++;
31732
31733     this.name = '';
31734
31735     this.side = THREE.FrontSide;
31736
31737     this.opacity = 1;
31738     this.transparent = false;
31739
31740     this.blending = THREE.NormalBlending;
31741
31742     this.blendSrc = THREE.SrcAlphaFactor;
31743     this.blendDst = THREE.OneMinusSrcAlphaFactor;
31744     this.blendEquation = THREE.AddEquation;
31745
31746     this.depthTest = true;
31747     this.depthWrite = true;
31748
31749     this.polygonOffset = false;
31750     this.polygonOffsetFactor = 0;
31751     this.polygonOffsetUnits = 0;
31752
31753     this.alphaTest = 0;
31754
31755     this.overdraw = false; // Boolean for fixing antialiasing gaps in CanvasRenderer
31756
31757     this.visible = true;
31758
31759     this.needsUpdate = true;
31760
31761 };
31762
31763 THREE.Material.prototype.setValues = function ( values ) {
31764
31765     if ( values === undefined ) return;
31766
31767     for ( var key in values ) {
31768
31769         var newValue = values[ key ];
31770
31771         if ( newValue === undefined ) {
31772
31773             console.warn( 'THREE.Material: \'' + key + '\' parameter is undefined.' );
31774             continue;
31775
31776         }
31777
31778         if ( key in this ) {
31779
31780             var currentValue = this[ key ];
31781
31782             if ( currentValue instanceof THREE.Color && newValue instanceof THREE.Color ) {
31783
31784                 currentValue.copy( newValue );
31785
31786             } else if ( currentValue instanceof THREE.Color && typeof( newValue ) === "number" ) {
31787
31788                 currentValue.setHex( newValue );
31789
31790             } else if ( currentValue instanceof THREE.Vector3 && newValue instanceof THREE.Vector3 ) {
31791
31792                 currentValue.copy( newValue );
31793
31794             } else {
31795
31796                 this[ key ] = newValue;
31797
31798             }
31799
31800         }
31801
31802     }
31803
31804 };
31805
31806 THREE.Material.prototype.clone = function ( material ) {
31807
31808     if ( material === undefined ) material = new THREE.Material();
31809
31810     material.name = this.name;
31811
31812     material.side = this.side;
31813
31814     material.opacity = this.opacity;
31815     material.transparent = this.transparent;
31816
31817     material.blending = this.blending;
31818
31819     material.blendSrc = this.blendSrc;
31820     material.blendDst = this.blendDst;
31821     material.blendEquation = this.blendEquation;
31822
31823     material.depthTest = this.depthTest;
31824     material.depthWrite = this.depthWrite;
31825
31826     material.polygonOffset = this.polygonOffset;
31827     material.polygonOffsetFactor = this.polygonOffsetFactor;
31828     material.polygonOffsetUnits = this.polygonOffsetUnits;
31829
31830     material.alphaTest = this.alphaTest;
31831
31832     material.overdraw = this.overdraw;
31833
31834     material.visible = this.visible;
31835
31836     return material;
31837
31838 };
31839
31840 THREE.MaterialCount = 0;
31841 /**
31842  * @author mrdoob / http://mrdoob.com/
31843  * @author alteredq / http://alteredqualia.com/
31844  *
31845  * parameters = {
31846  *  color: <hex>,
31847  *  opacity: <float>,
31848  *
31849  *  blending: THREE.NormalBlending,
31850  *  depthTest: <bool>,
31851  *
31852  *  linewidth: <float>,
31853  *  linecap: "round",
31854  *  linejoin: "round",
31855  *
31856  *  vertexColors: <bool>
31857  *
31858  *  fog: <bool>
31859  * }
31860  */
31861
31862 THREE.LineBasicMaterial = function ( parameters ) {
31863
31864     THREE.Material.call( this );
31865
31866     this.color = new THREE.Color( 0xffffff );
31867
31868     this.linewidth = 1;
31869     this.linecap = 'round';
31870     this.linejoin = 'round';
31871
31872     this.vertexColors = false;
31873
31874     this.fog = true;
31875
31876     this.setValues( parameters );
31877
31878 };
31879
31880 THREE.LineBasicMaterial.prototype = Object.create( THREE.Material.prototype );
31881
31882 THREE.LineBasicMaterial.prototype.clone = function () {
31883
31884     var material = new THREE.LineBasicMaterial();
31885
31886     THREE.Material.prototype.clone.call( this, material );
31887
31888     material.color.copy( this.color );
31889
31890     material.linewidth = this.linewidth;
31891     material.linecap = this.linecap;
31892     material.linejoin = this.linejoin;
31893
31894     material.vertexColors = this.vertexColors;
31895
31896     material.fog = this.fog;
31897
31898     return material;
31899
31900 };
31901 /**
31902  * @author mrdoob / http://mrdoob.com/
31903  * @author alteredq / http://alteredqualia.com/
31904  *
31905  * parameters = {
31906  *  color: <hex>,
31907  *  opacity: <float>,
31908  *  map: new THREE.Texture( <Image> ),
31909  *
31910  *  lightMap: new THREE.Texture( <Image> ),
31911  *
31912  *  specularMap: new THREE.Texture( <Image> ),
31913  *
31914  *  envMap: new THREE.TextureCube( [posx, negx, posy, negy, posz, negz] ),
31915  *  combine: THREE.Multiply,
31916  *  reflectivity: <float>,
31917  *  refractionRatio: <float>,
31918  *
31919  *  shading: THREE.SmoothShading,
31920  *  blending: THREE.NormalBlending,
31921  *  depthTest: <bool>,
31922  *
31923  *  wireframe: <boolean>,
31924  *  wireframeLinewidth: <float>,
31925  *
31926  *  vertexColors: THREE.NoColors / THREE.VertexColors / THREE.FaceColors,
31927  *
31928  *  skinning: <bool>,
31929  *  morphTargets: <bool>,
31930  *
31931  *  fog: <bool>
31932  * }
31933  */
31934
31935 THREE.MeshBasicMaterial = function ( parameters ) {
31936
31937     THREE.Material.call( this );
31938
31939     this.color = new THREE.Color( 0xffffff ); // emissive
31940
31941     this.map = null;
31942
31943     this.lightMap = null;
31944
31945     this.specularMap = null;
31946
31947     this.envMap = null;
31948     this.combine = THREE.MultiplyOperation;
31949     this.reflectivity = 1;
31950     this.refractionRatio = 0.98;
31951
31952     this.fog = true;
31953
31954     this.shading = THREE.SmoothShading;
31955
31956     this.wireframe = false;
31957     this.wireframeLinewidth = 1;
31958     this.wireframeLinecap = 'round';
31959     this.wireframeLinejoin = 'round';
31960
31961     this.vertexColors = THREE.NoColors;
31962
31963     this.skinning = false;
31964     this.morphTargets = false;
31965
31966     this.setValues( parameters );
31967
31968 };
31969
31970 THREE.MeshBasicMaterial.prototype = Object.create( THREE.Material.prototype );
31971
31972 THREE.MeshBasicMaterial.prototype.clone = function () {
31973
31974     var material = new THREE.MeshBasicMaterial();
31975
31976     THREE.Material.prototype.clone.call( this, material );
31977
31978     material.color.copy( this.color );
31979
31980     material.map = this.map;
31981
31982     material.lightMap = this.lightMap;
31983
31984     material.specularMap = this.specularMap;
31985
31986     material.envMap = this.envMap;
31987     material.combine = this.combine;
31988     material.reflectivity = this.reflectivity;
31989     material.refractionRatio = this.refractionRatio;
31990
31991     material.fog = this.fog;
31992
31993     material.shading = this.shading;
31994
31995     material.wireframe = this.wireframe;
31996     material.wireframeLinewidth = this.wireframeLinewidth;
31997     material.wireframeLinecap = this.wireframeLinecap;
31998     material.wireframeLinejoin = this.wireframeLinejoin;
31999
32000     material.vertexColors = this.vertexColors;
32001
32002     material.skinning = this.skinning;
32003     material.morphTargets = this.morphTargets;
32004
32005     return material;
32006
32007 };
32008 /**
32009  * @author mrdoob / http://mrdoob.com/
32010  * @author alteredq / http://alteredqualia.com/
32011  *
32012  * parameters = {
32013  *  color: <hex>,
32014  *  ambient: <hex>,
32015  *  emissive: <hex>,
32016  *  opacity: <float>,
32017  *
32018  *  map: new THREE.Texture( <Image> ),
32019  *
32020  *  lightMap: new THREE.Texture( <Image> ),
32021  *
32022  *  specularMap: new THREE.Texture( <Image> ),
32023  *
32024  *  envMap: new THREE.TextureCube( [posx, negx, posy, negy, posz, negz] ),
32025  *  combine: THREE.Multiply,
32026  *  reflectivity: <float>,
32027  *  refractionRatio: <float>,
32028  *
32029  *  shading: THREE.SmoothShading,
32030  *  blending: THREE.NormalBlending,
32031  *  depthTest: <bool>,
32032  *
32033  *  wireframe: <boolean>,
32034  *  wireframeLinewidth: <float>,
32035  *
32036  *  vertexColors: THREE.NoColors / THREE.VertexColors / THREE.FaceColors,
32037  *
32038  *  skinning: <bool>,
32039  *  morphTargets: <bool>,
32040  *  morphNormals: <bool>,
32041  *
32042  *    fog: <bool>
32043  * }
32044  */
32045
32046 THREE.MeshLambertMaterial = function ( parameters ) {
32047
32048     THREE.Material.call( this );
32049
32050     this.color = new THREE.Color( 0xffffff ); // diffuse
32051     this.ambient = new THREE.Color( 0xffffff );
32052     this.emissive = new THREE.Color( 0x000000 );
32053
32054     this.wrapAround = false;
32055     this.wrapRGB = new THREE.Vector3( 1, 1, 1 );
32056
32057     this.map = null;
32058
32059     this.lightMap = null;
32060
32061     this.specularMap = null;
32062
32063     this.envMap = null;
32064     this.combine = THREE.MultiplyOperation;
32065     this.reflectivity = 1;
32066     this.refractionRatio = 0.98;
32067
32068     this.fog = true;
32069
32070     this.shading = THREE.SmoothShading;
32071
32072     this.wireframe = false;
32073     this.wireframeLinewidth = 1;
32074     this.wireframeLinecap = 'round';
32075     this.wireframeLinejoin = 'round';
32076
32077     this.vertexColors = THREE.NoColors;
32078
32079     this.skinning = false;
32080     this.morphTargets = false;
32081     this.morphNormals = false;
32082
32083     this.setValues( parameters );
32084
32085 };
32086
32087 THREE.MeshLambertMaterial.prototype = Object.create( THREE.Material.prototype );
32088
32089 THREE.MeshLambertMaterial.prototype.clone = function () {
32090
32091     var material = new THREE.MeshLambertMaterial();
32092
32093     THREE.Material.prototype.clone.call( this, material );
32094
32095     material.color.copy( this.color );
32096     material.ambient.copy( this.ambient );
32097     material.emissive.copy( this.emissive );
32098
32099     material.wrapAround = this.wrapAround;
32100     material.wrapRGB.copy( this.wrapRGB );
32101
32102     material.map = this.map;
32103
32104     material.lightMap = this.lightMap;
32105
32106     material.specularMap = this.specularMap;
32107
32108     material.envMap = this.envMap;
32109     material.combine = this.combine;
32110     material.reflectivity = this.reflectivity;
32111     material.refractionRatio = this.refractionRatio;
32112
32113     material.fog = this.fog;
32114
32115     material.shading = this.shading;
32116
32117     material.wireframe = this.wireframe;
32118     material.wireframeLinewidth = this.wireframeLinewidth;
32119     material.wireframeLinecap = this.wireframeLinecap;
32120     material.wireframeLinejoin = this.wireframeLinejoin;
32121
32122     material.vertexColors = this.vertexColors;
32123
32124     material.skinning = this.skinning;
32125     material.morphTargets = this.morphTargets;
32126     material.morphNormals = this.morphNormals;
32127
32128     return material;
32129
32130 };
32131 /**
32132  * @author mrdoob / http://mrdoob.com/
32133  * @author alteredq / http://alteredqualia.com/
32134  *
32135  * parameters = {
32136  *  color: <hex>,
32137  *  ambient: <hex>,
32138  *  emissive: <hex>,
32139  *  specular: <hex>,
32140  *  shininess: <float>,
32141  *  opacity: <float>,
32142  *
32143  *  map: new THREE.Texture( <Image> ),
32144  *
32145  *  lightMap: new THREE.Texture( <Image> ),
32146  *
32147  *  bumpMap: new THREE.Texture( <Image> ),
32148  *  bumpScale: <float>,
32149  *
32150  *  normalMap: new THREE.Texture( <Image> ),
32151  *  normalScale: <Vector2>,
32152  *
32153  *  specularMap: new THREE.Texture( <Image> ),
32154  *
32155  *  envMap: new THREE.TextureCube( [posx, negx, posy, negy, posz, negz] ),
32156  *  combine: THREE.Multiply,
32157  *  reflectivity: <float>,
32158  *  refractionRatio: <float>,
32159  *
32160  *  shading: THREE.SmoothShading,
32161  *  blending: THREE.NormalBlending,
32162  *  depthTest: <bool>,
32163  *
32164  *  wireframe: <boolean>,
32165  *  wireframeLinewidth: <float>,
32166  *
32167  *  vertexColors: THREE.NoColors / THREE.VertexColors / THREE.FaceColors,
32168  *
32169  *  skinning: <bool>,
32170  *  morphTargets: <bool>,
32171  *  morphNormals: <bool>,
32172  *
32173  *    fog: <bool>
32174  * }
32175  */
32176
32177 THREE.MeshPhongMaterial = function ( parameters ) {
32178
32179     THREE.Material.call( this );
32180
32181     this.color = new THREE.Color( 0xffffff ); // diffuse
32182     this.ambient = new THREE.Color( 0xffffff );
32183     this.emissive = new THREE.Color( 0x000000 );
32184     this.specular = new THREE.Color( 0x111111 );
32185     this.shininess = 30;
32186
32187     this.metal = false;
32188     this.perPixel = false;
32189
32190     this.wrapAround = false;
32191     this.wrapRGB = new THREE.Vector3( 1, 1, 1 );
32192
32193     this.map = null;
32194
32195     this.lightMap = null;
32196
32197     this.bumpMap = null;
32198     this.bumpScale = 1;
32199
32200     this.normalMap = null;
32201     this.normalScale = new THREE.Vector2( 1, 1 );
32202
32203     this.specularMap = null;
32204
32205     this.envMap = null;
32206     this.combine = THREE.MultiplyOperation;
32207     this.reflectivity = 1;
32208     this.refractionRatio = 0.98;
32209
32210     this.fog = true;
32211
32212     this.shading = THREE.SmoothShading;
32213
32214     this.wireframe = false;
32215     this.wireframeLinewidth = 1;
32216     this.wireframeLinecap = 'round';
32217     this.wireframeLinejoin = 'round';
32218
32219     this.vertexColors = THREE.NoColors;
32220
32221     this.skinning = false;
32222     this.morphTargets = false;
32223     this.morphNormals = false;
32224
32225     this.setValues( parameters );
32226
32227 };
32228
32229 THREE.MeshPhongMaterial.prototype = Object.create( THREE.Material.prototype );
32230
32231 THREE.MeshPhongMaterial.prototype.clone = function () {
32232
32233     var material = new THREE.MeshPhongMaterial();
32234
32235     THREE.Material.prototype.clone.call( this, material );
32236
32237     material.color.copy( this.color );
32238     material.ambient.copy( this.ambient );
32239     material.emissive.copy( this.emissive );
32240     material.specular.copy( this.specular );
32241     material.shininess = this.shininess;
32242
32243     material.metal = this.metal;
32244     material.perPixel = this.perPixel;
32245
32246     material.wrapAround = this.wrapAround;
32247     material.wrapRGB.copy( this.wrapRGB );
32248
32249     material.map = this.map;
32250
32251     material.lightMap = this.lightMap;
32252
32253     material.bumpMap = this.bumpMap;
32254     material.bumpScale = this.bumpScale;
32255
32256     material.normalMap = this.normalMap;
32257     material.normalScale.copy( this.normalScale );
32258
32259     material.specularMap = this.specularMap;
32260
32261     material.envMap = this.envMap;
32262     material.combine = this.combine;
32263     material.reflectivity = this.reflectivity;
32264     material.refractionRatio = this.refractionRatio;
32265
32266     material.fog = this.fog;
32267
32268     material.shading = this.shading;
32269
32270     material.wireframe = this.wireframe;
32271     material.wireframeLinewidth = this.wireframeLinewidth;
32272     material.wireframeLinecap = this.wireframeLinecap;
32273     material.wireframeLinejoin = this.wireframeLinejoin;
32274
32275     material.vertexColors = this.vertexColors;
32276
32277     material.skinning = this.skinning;
32278     material.morphTargets = this.morphTargets;
32279     material.morphNormals = this.morphNormals;
32280
32281     return material;
32282
32283 };
32284 /**
32285  * @author mrdoob / http://mrdoob.com/
32286  * @author alteredq / http://alteredqualia.com/
32287  *
32288  * parameters = {
32289  *  opacity: <float>,
32290
32291  *  blending: THREE.NormalBlending,
32292  *  depthTest: <bool>,
32293
32294  *  wireframe: <boolean>,
32295  *  wireframeLinewidth: <float>
32296  * }
32297  */
32298
32299 THREE.MeshDepthMaterial = function ( parameters ) {
32300
32301     THREE.Material.call( this );
32302
32303     this.wireframe = false;
32304     this.wireframeLinewidth = 1;
32305
32306     this.setValues( parameters );
32307
32308 };
32309
32310 THREE.MeshDepthMaterial.prototype = Object.create( THREE.Material.prototype );
32311
32312 THREE.MeshDepthMaterial.prototype.clone = function () {
32313
32314     var material = new THREE.LineBasicMaterial();
32315
32316     THREE.Material.prototype.clone.call( this, material );
32317
32318     material.wireframe = this.wireframe;
32319     material.wireframeLinewidth = this.wireframeLinewidth;
32320
32321     return material;
32322
32323 };
32324 /**
32325  * @author mrdoob / http://mrdoob.com/
32326  *
32327  * parameters = {
32328  *  opacity: <float>,
32329
32330  *  shading: THREE.FlatShading,
32331  *  blending: THREE.NormalBlending,
32332  *  depthTest: <bool>,
32333
32334  *  wireframe: <boolean>,
32335  *  wireframeLinewidth: <float>
32336  * }
32337  */
32338
32339 THREE.MeshNormalMaterial = function ( parameters ) {
32340
32341     THREE.Material.call( this, parameters );
32342
32343     this.shading = THREE.FlatShading;
32344
32345     this.wireframe = false;
32346     this.wireframeLinewidth = 1;
32347
32348     this.setValues( parameters );
32349
32350 };
32351
32352 THREE.MeshNormalMaterial.prototype = Object.create( THREE.Material.prototype );
32353
32354 THREE.MeshNormalMaterial.prototype.clone = function () {
32355
32356     var material = new THREE.MeshNormalMaterial();
32357
32358     THREE.Material.prototype.clone.call( this, material );
32359
32360     material.shading = this.shading;
32361
32362     material.wireframe = this.wireframe;
32363     material.wireframeLinewidth = this.wireframeLinewidth;
32364
32365     return material;
32366
32367 };
32368 /**
32369  * @author mrdoob / http://mrdoob.com/
32370  */
32371
32372 THREE.MeshFaceMaterial = function () {};
32373
32374 THREE.MeshFaceMaterial.prototype.clone = function () {
32375
32376     return new THREE.MeshFaceMaterial();
32377
32378 };
32379 /**
32380  * @author mrdoob / http://mrdoob.com/
32381  * @author alteredq / http://alteredqualia.com/
32382  *
32383  * parameters = {
32384  *  color: <hex>,
32385  *  opacity: <float>,
32386  *  map: new THREE.Texture( <Image> ),
32387  *
32388  *  size: <float>,
32389  *
32390  *  blending: THREE.NormalBlending,
32391  *  depthTest: <bool>,
32392  *
32393  *  vertexColors: <bool>,
32394  *
32395  *  fog: <bool>
32396  * }
32397  */
32398
32399 THREE.ParticleBasicMaterial = function ( parameters ) {
32400
32401     THREE.Material.call( this );
32402
32403     this.color = new THREE.Color( 0xffffff );
32404
32405     this.map = null;
32406
32407     this.size = 1;
32408     this.sizeAttenuation = true;
32409
32410     this.vertexColors = false;
32411
32412     this.fog = true;
32413
32414     this.setValues( parameters );
32415
32416 };
32417
32418 THREE.ParticleBasicMaterial.prototype = Object.create( THREE.Material.prototype );
32419
32420 THREE.ParticleBasicMaterial.prototype.clone = function () {
32421
32422     var material = new THREE.ParticleBasicMaterial();
32423
32424     THREE.Material.prototype.clone.call( this, material );
32425
32426     material.color.copy( this.color );
32427
32428     material.map = this.map;
32429
32430     material.size = this.size;
32431     material.sizeAttenuation = this.sizeAttenuation;
32432
32433     material.vertexColors = this.vertexColors;
32434
32435     material.fog = this.fog;
32436
32437     return material;
32438
32439 };
32440 /**
32441  * @author mrdoob / http://mrdoob.com/
32442  *
32443  * parameters = {
32444  *  color: <hex>,
32445  *  program: <function>,
32446  *  opacity: <float>,
32447  *  blending: THREE.NormalBlending
32448  * }
32449  */
32450
32451 THREE.ParticleCanvasMaterial = function ( parameters ) {
32452
32453     THREE.Material.call( this );
32454
32455     this.color = new THREE.Color( 0xffffff );
32456     this.program = function ( context, color ) {};
32457
32458     this.setValues( parameters );
32459
32460 };
32461
32462 THREE.ParticleCanvasMaterial.prototype = Object.create( THREE.Material.prototype );
32463
32464 THREE.ParticleCanvasMaterial.prototype.clone = function () {
32465
32466     var material = new THREE.ParticleCanvasMaterial();
32467
32468     THREE.Material.prototype.clone.call( this, material );
32469
32470     material.color.copy( this.color );
32471     material.program = this.program;
32472
32473     return material;
32474
32475 };
32476 /**
32477  * @author mrdoob / http://mrdoob.com/
32478  */
32479
32480 THREE.ParticleDOMMaterial = function ( element ) {
32481
32482     this.element = element;
32483
32484 };
32485
32486 THREE.ParticleDOMMaterial.prototype.clone = function(){
32487
32488     return new THREE.ParticleDOMMaterial( this.element );
32489
32490 };
32491 /**
32492  * @author alteredq / http://alteredqualia.com/
32493  *
32494  * parameters = {
32495  *  fragmentShader: <string>,
32496  *  vertexShader: <string>,
32497  *
32498  *  uniforms: { "parameter1": { type: "f", value: 1.0 }, "parameter2": { type: "i" value2: 2 } },
32499  *
32500  *  shading: THREE.SmoothShading,
32501  *  blending: THREE.NormalBlending,
32502  *  depthTest: <bool>,
32503  *
32504  *  wireframe: <boolean>,
32505  *  wireframeLinewidth: <float>,
32506  *
32507  *  lights: <bool>,
32508  *
32509  *  vertexColors: THREE.NoColors / THREE.VertexColors / THREE.FaceColors,
32510  *
32511  *  skinning: <bool>,
32512  *  morphTargets: <bool>,
32513  *  morphNormals: <bool>,
32514  *
32515  *    fog: <bool>
32516  * }
32517  */
32518
32519 THREE.ShaderMaterial = function ( parameters ) {
32520
32521     THREE.Material.call( this );
32522
32523     this.fragmentShader = "void main() {}";
32524     this.vertexShader = "void main() {}";
32525     this.uniforms = {};
32526     this.attributes = null;
32527
32528     this.shading = THREE.SmoothShading;
32529
32530     this.wireframe = false;
32531     this.wireframeLinewidth = 1;
32532
32533     this.fog = false; // set to use scene fog
32534
32535     this.lights = false; // set to use scene lights
32536
32537     this.vertexColors = THREE.NoColors; // set to use "color" attribute stream
32538
32539     this.skinning = false; // set to use skinning attribute streams
32540
32541     this.morphTargets = false; // set to use morph targets
32542     this.morphNormals = false; // set to use morph normals
32543
32544     this.setValues( parameters );
32545
32546 };
32547
32548 THREE.ShaderMaterial.prototype = Object.create( THREE.Material.prototype );
32549
32550 THREE.ShaderMaterial.prototype.clone = function () {
32551
32552     var material = new THREE.ShaderMaterial();
32553
32554     THREE.Material.prototype.clone.call( this, material );
32555
32556     material.fragmentShader = this.fragmentShader;
32557     material.vertexShader = this.vertexShader;
32558     material.uniforms = this.uniforms;
32559     material.attributes = this.attributes;
32560
32561     material.shading = this.shading;
32562
32563     material.wireframe = this.wireframe;
32564     material.wireframeLinewidth = this.wireframeLinewidth;
32565
32566     material.fog = this.fog;
32567
32568     material.lights = this.lights;
32569
32570     material.vertexColors = this.vertexColors;
32571
32572     material.skinning = this.skinning;
32573
32574     material.morphTargets = this.morphTargets;
32575     material.morphNormals = this.morphNormals;
32576
32577     return material;
32578
32579 };
32580 /**
32581  * @author mrdoob / http://mrdoob.com/
32582  * @author alteredq / http://alteredqualia.com/
32583  * @author szimek / https://github.com/szimek/
32584  */
32585
32586 THREE.Texture = function ( image, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy ) {
32587
32588     this.id = THREE.TextureCount ++;
32589
32590     this.image = image;
32591
32592     this.mapping = mapping !== undefined ? mapping : new THREE.UVMapping();
32593
32594     this.wrapS = wrapS !== undefined ? wrapS : THREE.ClampToEdgeWrapping;
32595     this.wrapT = wrapT !== undefined ? wrapT : THREE.ClampToEdgeWrapping;
32596
32597     this.magFilter = magFilter !== undefined ? magFilter : THREE.LinearFilter;
32598     this.minFilter = minFilter !== undefined ? minFilter : THREE.LinearMipMapLinearFilter;
32599
32600     this.anisotropy = anisotropy !== undefined ? anisotropy : 1;
32601
32602     this.format = format !== undefined ? format : THREE.RGBAFormat;
32603     this.type = type !== undefined ? type : THREE.UnsignedByteType;
32604
32605     this.offset = new THREE.Vector2( 0, 0 );
32606     this.repeat = new THREE.Vector2( 1, 1 );
32607
32608     this.generateMipmaps = true;
32609     this.premultiplyAlpha = false;
32610     this.flipY = true;
32611
32612     this.needsUpdate = false;
32613     this.onUpdate = null;
32614
32615 };
32616
32617 THREE.Texture.prototype = {
32618
32619     constructor: THREE.Texture,
32620
32621     clone: function () {
32622
32623         var texture = new THREE.Texture();
32624
32625         texture.image = this.image;
32626
32627         texture.mapping = this.mapping;
32628
32629         texture.wrapS = this.wrapS;
32630         texture.wrapT = this.wrapT;
32631
32632         texture.magFilter = this.magFilter;
32633         texture.minFilter = this.minFilter;
32634
32635         texture.anisotropy = this.anisotropy;
32636
32637         texture.format = this.format;
32638         texture.type = this.type;
32639
32640         texture.offset.copy( this.offset );
32641         texture.repeat.copy( this.repeat );
32642
32643         texture.generateMipmaps = this.generateMipmaps;
32644         texture.premultiplyAlpha = this.premultiplyAlpha;
32645         texture.flipY = this.flipY;
32646
32647         return texture;
32648
32649     }
32650
32651 };
32652
32653 THREE.TextureCount = 0;
32654 /**
32655  * @author alteredq / http://alteredqualia.com/
32656  */
32657
32658 THREE.CompressedTexture = function ( mipmaps, width, height, format, type, mapping, wrapS, wrapT, magFilter, minFilter ) {
32659
32660     THREE.Texture.call( this, null, mapping, wrapS, wrapT, magFilter, minFilter, format, type );
32661
32662     this.image = { width: width, height: height };
32663     this.mipmaps = mipmaps;
32664
32665 };
32666
32667 THREE.CompressedTexture.prototype = Object.create( THREE.Texture.prototype );
32668
32669 THREE.CompressedTexture.prototype.clone = function () {
32670
32671     var texture = new THREE.CompressedTexture();
32672
32673     texture.image = this.image;
32674     texture.mipmaps = this.mipmaps;
32675
32676     texture.format = this.format;
32677     texture.type = this.type;
32678
32679     texture.mapping = this.mapping;
32680
32681     texture.wrapS = this.wrapS;
32682     texture.wrapT = this.wrapT;
32683
32684     texture.magFilter = this.magFilter;
32685     texture.minFilter = this.minFilter;
32686
32687     texture.anisotropy = this.anisotropy;
32688
32689     texture.offset.copy( this.offset );
32690     texture.repeat.copy( this.repeat );
32691
32692     return texture;
32693
32694 };
32695 /**
32696  * @author alteredq / http://alteredqualia.com/
32697  */
32698
32699 THREE.DataTexture = function ( data, width, height, format, type, mapping, wrapS, wrapT, magFilter, minFilter ) {
32700
32701     THREE.Texture.call( this, null, mapping, wrapS, wrapT, magFilter, minFilter, format, type );
32702
32703     this.image = { data: data, width: width, height: height };
32704
32705 };
32706
32707 THREE.DataTexture.prototype = Object.create( THREE.Texture.prototype );
32708
32709 THREE.DataTexture.prototype.clone = function () {
32710
32711     var clonedTexture = new THREE.DataTexture( this.image.data,  this.image.width, this.image.height, this.format, this.type, this.mapping, this.wrapS, this.wrapT, this.magFilter, this.minFilter );
32712
32713     clonedTexture.offset.copy( this.offset );
32714     clonedTexture.repeat.copy( this.repeat );
32715
32716     return clonedTexture;
32717
32718 };
32719 /**
32720  * @author mrdoob / http://mrdoob.com/
32721  */
32722
32723 THREE.Particle = function ( material ) {
32724
32725     THREE.Object3D.call( this );
32726
32727     this.material = material;
32728
32729 };
32730
32731 THREE.Particle.prototype = Object.create( THREE.Object3D.prototype );
32732 /**
32733  * @author alteredq / http://alteredqualia.com/
32734  */
32735
32736 THREE.ParticleSystem = function ( geometry, material ) {
32737
32738     THREE.Object3D.call( this );
32739
32740     this.geometry = geometry;
32741     this.material = ( material !== undefined ) ? material : new THREE.ParticleBasicMaterial( { color: Math.random() * 0xffffff } );
32742
32743     this.sortParticles = false;
32744
32745     if ( this.geometry ) {
32746
32747         // calc bound radius
32748
32749         if( !this.geometry.boundingSphere ) {
32750
32751             this.geometry.computeBoundingSphere();
32752
32753         }
32754
32755         this.boundRadius = geometry.boundingSphere.radius;
32756
32757     }
32758
32759     this.frustumCulled = false;
32760
32761 };
32762
32763 THREE.ParticleSystem.prototype = Object.create( THREE.Object3D.prototype );
32764 /**
32765  * @author mrdoob / http://mrdoob.com/
32766  */
32767
32768 THREE.Line = function ( geometry, material, type ) {
32769
32770     THREE.Object3D.call( this );
32771
32772     this.geometry = geometry;
32773     this.material = ( material !== undefined ) ? material : new THREE.LineBasicMaterial( { color: Math.random() * 0xffffff } );
32774     this.type = ( type !== undefined ) ? type : THREE.LineStrip;
32775
32776     if ( this.geometry ) {
32777
32778         if ( ! this.geometry.boundingSphere ) {
32779
32780             this.geometry.computeBoundingSphere();
32781
32782         }
32783
32784     }
32785
32786 };
32787
32788 THREE.LineStrip = 0;
32789 THREE.LinePieces = 1;
32790
32791 THREE.Line.prototype = Object.create( THREE.Object3D.prototype );
32792 /**
32793  * @author mrdoob / http://mrdoob.com/
32794  * @author alteredq / http://alteredqualia.com/
32795  * @author mikael emtinger / http://gomo.se/
32796  */
32797
32798 THREE.Mesh = function ( geometry, material ) {
32799
32800     THREE.Object3D.call( this );
32801
32802     this.geometry = geometry;
32803     this.material = ( material !== undefined ) ? material : new THREE.MeshBasicMaterial( { color: Math.random() * 0xffffff, wireframe: true } );
32804
32805     if ( this.geometry ) {
32806
32807         // calc bound radius
32808
32809         if ( ! this.geometry.boundingSphere ) {
32810
32811             this.geometry.computeBoundingSphere();
32812
32813         }
32814
32815         this.boundRadius = geometry.boundingSphere.radius;
32816
32817
32818         // setup morph targets
32819
32820         if( this.geometry.morphTargets.length ) {
32821
32822             this.morphTargetBase = -1;
32823             this.morphTargetForcedOrder = [];
32824             this.morphTargetInfluences = [];
32825             this.morphTargetDictionary = {};
32826
32827             for( var m = 0; m < this.geometry.morphTargets.length; m ++ ) {
32828
32829                 this.morphTargetInfluences.push( 0 );
32830                 this.morphTargetDictionary[ this.geometry.morphTargets[ m ].name ] = m;
32831
32832             }
32833
32834         }
32835
32836     }
32837
32838 }
32839
32840 THREE.Mesh.prototype = Object.create( THREE.Object3D.prototype );
32841
32842
32843 /*
32844  * Get Morph Target Index by Name
32845  */
32846
32847 THREE.Mesh.prototype.getMorphTargetIndexByName = function( name ) {
32848
32849     if ( this.morphTargetDictionary[ name ] !== undefined ) {
32850
32851         return this.morphTargetDictionary[ name ];
32852     }
32853
32854     console.log( "THREE.Mesh.getMorphTargetIndexByName: morph target " + name + " does not exist. Returning 0." );
32855     return 0;
32856
32857 }
32858 /**
32859  * @author mikael emtinger / http://gomo.se/
32860  * @author alteredq / http://alteredqualia.com/
32861  */
32862
32863 THREE.Bone = function( belongsToSkin ) {
32864
32865     THREE.Object3D.call( this );
32866
32867     this.skin = belongsToSkin;
32868     this.skinMatrix = new THREE.Matrix4();
32869
32870 };
32871
32872 THREE.Bone.prototype = Object.create( THREE.Object3D.prototype );
32873
32874 THREE.Bone.prototype.update = function( parentSkinMatrix, forceUpdate ) {
32875
32876     // update local
32877
32878     if ( this.matrixAutoUpdate ) {
32879
32880         forceUpdate |= this.updateMatrix();
32881
32882     }
32883
32884     // update skin matrix
32885
32886     if ( forceUpdate || this.matrixWorldNeedsUpdate ) {
32887
32888         if( parentSkinMatrix ) {
32889
32890             this.skinMatrix.multiply( parentSkinMatrix, this.matrix );
32891
32892         } else {
32893
32894             this.skinMatrix.copy( this.matrix );
32895
32896         }
32897
32898         this.matrixWorldNeedsUpdate = false;
32899         forceUpdate = true;
32900
32901     }
32902
32903     // update children
32904
32905     var child, i, l = this.children.length;
32906
32907     for ( i = 0; i < l; i ++ ) {
32908
32909         this.children[ i ].update( this.skinMatrix, forceUpdate );
32910
32911     }
32912
32913 };
32914
32915 /**
32916  * @author mikael emtinger / http://gomo.se/
32917  * @author alteredq / http://alteredqualia.com/
32918  */
32919
32920 THREE.SkinnedMesh = function ( geometry, material, useVertexTexture ) {
32921
32922     THREE.Mesh.call( this, geometry, material );
32923
32924     //
32925
32926     this.useVertexTexture = useVertexTexture !== undefined ? useVertexTexture : true;
32927
32928     // init bones
32929
32930     this.identityMatrix = new THREE.Matrix4();
32931
32932     this.bones = [];
32933     this.boneMatrices = [];
32934
32935     var b, bone, gbone, p, q, s;
32936
32937     if ( this.geometry.bones !== undefined ) {
32938
32939         for ( b = 0; b < this.geometry.bones.length; b ++ ) {
32940
32941             gbone = this.geometry.bones[ b ];
32942
32943             p = gbone.pos;
32944             q = gbone.rotq;
32945             s = gbone.scl;
32946
32947             bone = this.addBone();
32948
32949             bone.name = gbone.name;
32950             bone.position.set( p[0], p[1], p[2] );
32951             bone.quaternion.set( q[0], q[1], q[2], q[3] );
32952             bone.useQuaternion = true;
32953
32954             if ( s !== undefined ) {
32955
32956                 bone.scale.set( s[0], s[1], s[2] );
32957
32958             } else {
32959
32960                 bone.scale.set( 1, 1, 1 );
32961
32962             }
32963
32964         }
32965
32966         for ( b = 0; b < this.bones.length; b ++ ) {
32967
32968             gbone = this.geometry.bones[ b ];
32969             bone = this.bones[ b ];
32970
32971             if ( gbone.parent === -1 ) {
32972
32973                 this.add( bone );
32974
32975             } else {
32976
32977                 this.bones[ gbone.parent ].add( bone );
32978
32979             }
32980
32981         }
32982
32983         //
32984
32985         var nBones = this.bones.length;
32986
32987         if ( this.useVertexTexture ) {
32988
32989             // layout (1 matrix = 4 pixels)
32990             //    RGBA RGBA RGBA RGBA (=> column1, column2, column3, column4)
32991             //  with  8x8  pixel texture max   16 bones  (8 * 8  / 4)
32992             //       16x16 pixel texture max   64 bones (16 * 16 / 4)
32993             //       32x32 pixel texture max  256 bones (32 * 32 / 4)
32994             //       64x64 pixel texture max 1024 bones (64 * 64 / 4)
32995
32996             var size;
32997
32998             if ( nBones > 256 )
32999                 size = 64;
33000             else if ( nBones > 64 )
33001                 size = 32;
33002             else if ( nBones > 16 )
33003                 size = 16;
33004             else
33005                 size = 8;
33006
33007             this.boneTextureWidth = size;
33008             this.boneTextureHeight = size;
33009
33010             this.boneMatrices = new Float32Array( this.boneTextureWidth * this.boneTextureHeight * 4 ); // 4 floats per RGBA pixel
33011             this.boneTexture = new THREE.DataTexture( this.boneMatrices, this.boneTextureWidth, this.boneTextureHeight, THREE.RGBAFormat, THREE.FloatType );
33012             this.boneTexture.minFilter = THREE.NearestFilter;
33013             this.boneTexture.magFilter = THREE.NearestFilter;
33014             this.boneTexture.generateMipmaps = false;
33015             this.boneTexture.flipY = false;
33016
33017         } else {
33018
33019             this.boneMatrices = new Float32Array( 16 * nBones );
33020
33021         }
33022
33023         this.pose();
33024
33025     }
33026
33027 };
33028
33029 THREE.SkinnedMesh.prototype = Object.create( THREE.Mesh.prototype );
33030
33031 THREE.SkinnedMesh.prototype.addBone = function( bone ) {
33032
33033     if ( bone === undefined ) {
33034
33035         bone = new THREE.Bone( this );
33036
33037     }
33038
33039     this.bones.push( bone );
33040
33041     return bone;
33042
33043 };
33044
33045 THREE.SkinnedMesh.prototype.updateMatrixWorld = function ( force ) {
33046
33047     this.matrixAutoUpdate && this.updateMatrix();
33048
33049     // update matrixWorld
33050
33051     if ( this.matrixWorldNeedsUpdate || force ) {
33052
33053         if ( this.parent ) {
33054
33055             this.matrixWorld.multiply( this.parent.matrixWorld, this.matrix );
33056
33057         } else {
33058
33059             this.matrixWorld.copy( this.matrix );
33060
33061         }
33062
33063         this.matrixWorldNeedsUpdate = false;
33064
33065         force = true;
33066
33067     }
33068
33069     // update children
33070
33071     for ( var i = 0, l = this.children.length; i < l; i ++ ) {
33072
33073         var child = this.children[ i ];
33074
33075         if ( child instanceof THREE.Bone ) {
33076
33077             child.update( this.identityMatrix, false );
33078
33079         } else {
33080
33081             child.updateMatrixWorld( true );
33082
33083         }
33084
33085     }
33086
33087     // make a snapshot of the bones' rest position
33088
33089     if ( this.boneInverses == undefined ) {
33090
33091         this.boneInverses = [];
33092
33093         for ( var b = 0, bl = this.bones.length; b < bl; b ++ ) {
33094
33095             var inverse = new THREE.Matrix4();
33096
33097             inverse.getInverse( this.bones[ b ].skinMatrix );
33098
33099             this.boneInverses.push( inverse );
33100
33101         }
33102
33103     }
33104
33105     // flatten bone matrices to array
33106
33107     for ( var b = 0, bl = this.bones.length; b < bl; b ++ ) {
33108
33109         // compute the offset between the current and the original transform;
33110
33111         //TODO: we could get rid of this multiplication step if the skinMatrix
33112         // was already representing the offset; however, this requires some
33113         // major changes to the animation system
33114
33115         THREE.SkinnedMesh.offsetMatrix.multiply( this.bones[ b ].skinMatrix, this.boneInverses[ b ] );
33116
33117         THREE.SkinnedMesh.offsetMatrix.flattenToArrayOffset( this.boneMatrices, b * 16 );
33118
33119     }
33120
33121     if ( this.useVertexTexture ) {
33122
33123         this.boneTexture.needsUpdate = true;
33124
33125     }
33126
33127 };
33128
33129 /*
33130  * Pose
33131  */
33132
33133 THREE.SkinnedMesh.prototype.pose = function() {
33134
33135     this.updateMatrixWorld( true );
33136
33137     for ( var i = 0; i < this.geometry.skinIndices.length; i ++ ) {
33138
33139         // normalize weights
33140
33141         var sw = this.geometry.skinWeights[ i ];
33142
33143         var scale = 1.0 / sw.lengthManhattan();
33144
33145         if ( scale !== Infinity ) {
33146
33147             sw.multiplyScalar( scale );
33148
33149         } else {
33150
33151             sw.set( 1 ); // this will be normalized by the shader anyway
33152
33153         }
33154
33155     }
33156
33157 };
33158
33159 THREE.SkinnedMesh.offsetMatrix = new THREE.Matrix4();
33160
33161 /**
33162  * @author alteredq / http://alteredqualia.com/
33163  */
33164
33165 THREE.MorphAnimMesh = function ( geometry, material ) {
33166
33167     THREE.Mesh.call( this, geometry, material );
33168
33169     // API
33170
33171     this.duration = 1000; // milliseconds
33172     this.mirroredLoop = false;
33173     this.time = 0;
33174
33175     // internals
33176
33177     this.lastKeyframe = 0;
33178     this.currentKeyframe = 0;
33179
33180     this.direction = 1;
33181     this.directionBackwards = false;
33182
33183     this.setFrameRange( 0, this.geometry.morphTargets.length - 1 );
33184
33185 };
33186
33187 THREE.MorphAnimMesh.prototype = Object.create( THREE.Mesh.prototype );
33188
33189 THREE.MorphAnimMesh.prototype.setFrameRange = function ( start, end ) {
33190
33191     this.startKeyframe = start;
33192     this.endKeyframe = end;
33193
33194     this.length = this.endKeyframe - this.startKeyframe + 1;
33195
33196 };
33197
33198 THREE.MorphAnimMesh.prototype.setDirectionForward = function () {
33199
33200     this.direction = 1;
33201     this.directionBackwards = false;
33202
33203 };
33204
33205 THREE.MorphAnimMesh.prototype.setDirectionBackward = function () {
33206
33207     this.direction = -1;
33208     this.directionBackwards = true;
33209
33210 };
33211
33212 THREE.MorphAnimMesh.prototype.parseAnimations = function () {
33213
33214     var geometry = this.geometry;
33215
33216     if ( ! geometry.animations ) geometry.animations = {};
33217
33218     var firstAnimation, animations = geometry.animations;
33219
33220     var pattern = /([a-z]+)(\d+)/;
33221
33222     for ( var i = 0, il = geometry.morphTargets.length; i < il; i ++ ) {
33223
33224         var morph = geometry.morphTargets[ i ];
33225         var parts = morph.name.match( pattern );
33226
33227         if ( parts && parts.length > 1 ) {
33228
33229             var label = parts[ 1 ];
33230             var num = parts[ 2 ];
33231
33232             if ( ! animations[ label ] ) animations[ label ] = { start: Infinity, end: -Infinity };
33233
33234             var animation = animations[ label ];
33235
33236             if ( i < animation.start ) animation.start = i;
33237             if ( i > animation.end ) animation.end = i;
33238
33239             if ( ! firstAnimation ) firstAnimation = label;
33240
33241         }
33242
33243     }
33244
33245     geometry.firstAnimation = firstAnimation;
33246
33247 };
33248
33249 THREE.MorphAnimMesh.prototype.setAnimationLabel = function ( label, start, end ) {
33250
33251     if ( ! this.geometry.animations ) this.geometry.animations = {};
33252
33253     this.geometry.animations[ label ] = { start: start, end: end };
33254
33255 };
33256
33257 THREE.MorphAnimMesh.prototype.playAnimation = function ( label, fps ) {
33258
33259     var animation = this.geometry.animations[ label ];
33260
33261     if ( animation ) {
33262
33263         this.setFrameRange( animation.start, animation.end );
33264         this.duration = 1000 * ( ( animation.end - animation.start ) / fps );
33265         this.time = 0;
33266
33267     } else {
33268
33269         console.warn( "animation[" + label + "] undefined" );
33270
33271     }
33272
33273 };
33274
33275 THREE.MorphAnimMesh.prototype.updateAnimation = function ( delta ) {
33276
33277     var frameTime = this.duration / this.length;
33278
33279     this.time += this.direction * delta;
33280
33281     if ( this.mirroredLoop ) {
33282
33283         if ( this.time > this.duration || this.time < 0 ) {
33284
33285             this.direction *= -1;
33286
33287             if ( this.time > this.duration ) {
33288
33289                 this.time = this.duration;
33290                 this.directionBackwards = true;
33291
33292             }
33293
33294             if ( this.time < 0 ) {
33295
33296                 this.time = 0;
33297                 this.directionBackwards = false;
33298
33299             }
33300
33301         }
33302
33303     } else {
33304
33305         this.time = this.time % this.duration;
33306
33307         if ( this.time < 0 ) this.time += this.duration;
33308
33309     }
33310
33311     var keyframe = this.startKeyframe + THREE.Math.clamp( Math.floor( this.time / frameTime ), 0, this.length - 1 );
33312
33313     if ( keyframe !== this.currentKeyframe ) {
33314
33315         this.morphTargetInfluences[ this.lastKeyframe ] = 0;
33316         this.morphTargetInfluences[ this.currentKeyframe ] = 1;
33317
33318         this.morphTargetInfluences[ keyframe ] = 0;
33319
33320         this.lastKeyframe = this.currentKeyframe;
33321         this.currentKeyframe = keyframe;
33322
33323     }
33324
33325     var mix = ( this.time % frameTime ) / frameTime;
33326
33327     if ( this.directionBackwards ) {
33328
33329         mix = 1 - mix;
33330
33331     }
33332
33333     this.morphTargetInfluences[ this.currentKeyframe ] = mix;
33334     this.morphTargetInfluences[ this.lastKeyframe ] = 1 - mix;
33335
33336 };
33337 /**
33338  * @author alteredq / http://alteredqualia.com/
33339  */
33340
33341 THREE.Ribbon = function ( geometry, material ) {
33342
33343     THREE.Object3D.call( this );
33344
33345     this.geometry = geometry;
33346     this.material = material;
33347
33348 };
33349
33350 THREE.Ribbon.prototype = Object.create( THREE.Object3D.prototype );
33351 /**
33352  * @author mikael emtinger / http://gomo.se/
33353  * @author alteredq / http://alteredqualia.com/
33354  * @author mrdoob / http://mrdoob.com/
33355  */
33356
33357 THREE.LOD = function () {
33358
33359     THREE.Object3D.call( this );
33360
33361     this.LODs = [];
33362
33363 };
33364
33365
33366 THREE.LOD.prototype = Object.create( THREE.Object3D.prototype );
33367
33368 THREE.LOD.prototype.addLevel = function ( object3D, visibleAtDistance ) {
33369
33370     if ( visibleAtDistance === undefined ) {
33371
33372         visibleAtDistance = 0;
33373
33374     }
33375
33376     visibleAtDistance = Math.abs( visibleAtDistance );
33377
33378     for ( var l = 0; l < this.LODs.length; l ++ ) {
33379
33380         if ( visibleAtDistance < this.LODs[ l ].visibleAtDistance ) {
33381
33382             break;
33383
33384         }
33385
33386     }
33387
33388     this.LODs.splice( l, 0, { visibleAtDistance: visibleAtDistance, object3D: object3D } );
33389     this.add( object3D );
33390
33391 };
33392
33393 THREE.LOD.prototype.update = function ( camera ) {
33394
33395     if ( this.LODs.length > 1 ) {
33396
33397         camera.matrixWorldInverse.getInverse( camera.matrixWorld );
33398
33399         var inverse  = camera.matrixWorldInverse;
33400         var distance = -( inverse.elements[2] * this.matrixWorld.elements[12] + inverse.elements[6] * this.matrixWorld.elements[13] + inverse.elements[10] * this.matrixWorld.elements[14] + inverse.elements[14] );
33401
33402         this.LODs[ 0 ].object3D.visible = true;
33403
33404         for ( var l = 1; l < this.LODs.length; l ++ ) {
33405
33406             if( distance >= this.LODs[ l ].visibleAtDistance ) {
33407
33408                 this.LODs[ l - 1 ].object3D.visible = false;
33409                 this.LODs[ l     ].object3D.visible = true;
33410
33411             } else {
33412
33413                 break;
33414
33415             }
33416
33417         }
33418
33419         for( ; l < this.LODs.length; l ++ ) {
33420
33421             this.LODs[ l ].object3D.visible = false;
33422
33423         }
33424
33425     }
33426
33427 };
33428 /**
33429  * @author mikael emtinger / http://gomo.se/
33430  */
33431
33432 THREE.Sprite = function ( parameters ) {
33433
33434     THREE.Object3D.call( this );
33435
33436     this.color = ( parameters.color !== undefined ) ? new THREE.Color( parameters.color ) : new THREE.Color( 0xffffff );
33437     this.map = ( parameters.map !== undefined ) ? parameters.map : new THREE.Texture();
33438
33439     this.blending = ( parameters.blending !== undefined ) ? parameters.blending : THREE.NormalBlending;
33440
33441     this.blendSrc = parameters.blendSrc !== undefined ? parameters.blendSrc : THREE.SrcAlphaFactor;
33442     this.blendDst = parameters.blendDst !== undefined ? parameters.blendDst : THREE.OneMinusSrcAlphaFactor;
33443     this.blendEquation = parameters.blendEquation !== undefined ? parameters.blendEquation : THREE.AddEquation;
33444
33445     this.useScreenCoordinates = ( parameters.useScreenCoordinates !== undefined ) ? parameters.useScreenCoordinates : true;
33446     this.mergeWith3D = ( parameters.mergeWith3D !== undefined ) ? parameters.mergeWith3D : !this.useScreenCoordinates;
33447     this.affectedByDistance = ( parameters.affectedByDistance !== undefined ) ? parameters.affectedByDistance : !this.useScreenCoordinates;
33448     this.scaleByViewport = ( parameters.scaleByViewport !== undefined ) ? parameters.scaleByViewport : !this.affectedByDistance;
33449     this.alignment = ( parameters.alignment instanceof THREE.Vector2 ) ? parameters.alignment : THREE.SpriteAlignment.center;
33450
33451     this.rotation3d = this.rotation;
33452     this.rotation = 0;
33453     this.opacity = 1;
33454
33455     this.uvOffset = new THREE.Vector2( 0, 0 );
33456     this.uvScale  = new THREE.Vector2( 1, 1 );
33457
33458 };
33459
33460 THREE.Sprite.prototype = Object.create( THREE.Object3D.prototype );
33461
33462 /*
33463  * Custom update matrix
33464  */
33465
33466 THREE.Sprite.prototype.updateMatrix = function () {
33467
33468     this.matrix.setPosition( this.position );
33469
33470     this.rotation3d.set( 0, 0, this.rotation );
33471     this.matrix.setRotationFromEuler( this.rotation3d );
33472
33473     if ( this.scale.x !== 1 || this.scale.y !== 1 ) {
33474
33475         this.matrix.scale( this.scale );
33476         this.boundRadiusScale = Math.max( this.scale.x, this.scale.y );
33477
33478     }
33479
33480     this.matrixWorldNeedsUpdate = true;
33481
33482 };
33483
33484 /*
33485  * Alignment
33486  */
33487
33488 THREE.SpriteAlignment = {};
33489 THREE.SpriteAlignment.topLeft = new THREE.Vector2( 1, -1 );
33490 THREE.SpriteAlignment.topCenter = new THREE.Vector2( 0, -1 );
33491 THREE.SpriteAlignment.topRight = new THREE.Vector2( -1, -1 );
33492 THREE.SpriteAlignment.centerLeft = new THREE.Vector2( 1, 0 );
33493 THREE.SpriteAlignment.center = new THREE.Vector2( 0, 0 );
33494 THREE.SpriteAlignment.centerRight = new THREE.Vector2( -1, 0 );
33495 THREE.SpriteAlignment.bottomLeft = new THREE.Vector2( 1, 1 );
33496 THREE.SpriteAlignment.bottomCenter = new THREE.Vector2( 0, 1 );
33497 THREE.SpriteAlignment.bottomRight = new THREE.Vector2( -1, 1 );
33498 /**
33499  * @author mrdoob / http://mrdoob.com/
33500  */
33501
33502 THREE.Scene = function () {
33503
33504     THREE.Object3D.call( this );
33505
33506     this.fog = null;
33507     this.overrideMaterial = null;
33508
33509     this.matrixAutoUpdate = false;
33510
33511     this.__objects = [];
33512     this.__lights = [];
33513
33514     this.__objectsAdded = [];
33515     this.__objectsRemoved = [];
33516
33517 };
33518
33519 THREE.Scene.prototype = Object.create( THREE.Object3D.prototype );
33520
33521 THREE.Scene.prototype.__addObject = function ( object ) {
33522
33523     if ( object instanceof THREE.Light ) {
33524
33525         if ( this.__lights.indexOf( object ) === - 1 ) {
33526
33527             this.__lights.push( object );
33528
33529         }
33530
33531         if ( object.target && object.target.parent === undefined ) {
33532
33533             this.add( object.target );
33534
33535         }
33536
33537     } else if ( !( object instanceof THREE.Camera || object instanceof THREE.Bone ) ) {
33538
33539         if ( this.__objects.indexOf( object ) === - 1 ) {
33540
33541             this.__objects.push( object );
33542             this.__objectsAdded.push( object );
33543
33544             // check if previously removed
33545
33546             var i = this.__objectsRemoved.indexOf( object );
33547
33548             if ( i !== -1 ) {
33549
33550                 this.__objectsRemoved.splice( i, 1 );
33551
33552             }
33553
33554         }
33555
33556     }
33557
33558     for ( var c = 0; c < object.children.length; c ++ ) {
33559
33560         this.__addObject( object.children[ c ] );
33561
33562     }
33563
33564 };
33565
33566 THREE.Scene.prototype.__removeObject = function ( object ) {
33567
33568     if ( object instanceof THREE.Light ) {
33569
33570         var i = this.__lights.indexOf( object );
33571
33572         if ( i !== -1 ) {
33573
33574             this.__lights.splice( i, 1 );
33575
33576         }
33577
33578     } else if ( !( object instanceof THREE.Camera ) ) {
33579
33580         var i = this.__objects.indexOf( object );
33581
33582         if( i !== -1 ) {
33583
33584             this.__objects.splice( i, 1 );
33585             this.__objectsRemoved.push( object );
33586
33587             // check if previously added
33588
33589             var ai = this.__objectsAdded.indexOf( object );
33590
33591             if ( ai !== -1 ) {
33592
33593                 this.__objectsAdded.splice( ai, 1 );
33594
33595             }
33596
33597         }
33598
33599     }
33600
33601     for ( var c = 0; c < object.children.length; c ++ ) {
33602
33603         this.__removeObject( object.children[ c ] );
33604
33605     }
33606
33607 };
33608 /**
33609  * @author mrdoob / http://mrdoob.com/
33610  * @author alteredq / http://alteredqualia.com/
33611  */
33612
33613 THREE.Fog = function ( hex, near, far ) {
33614
33615     this.color = new THREE.Color( hex );
33616
33617     this.near = ( near !== undefined ) ? near : 1;
33618     this.far = ( far !== undefined ) ? far : 1000;
33619
33620 };
33621 /**
33622  * @author mrdoob / http://mrdoob.com/
33623  * @author alteredq / http://alteredqualia.com/
33624  */
33625
33626 THREE.FogExp2 = function ( hex, density ) {
33627
33628     this.color = new THREE.Color( hex );
33629     this.density = ( density !== undefined ) ? density : 0.00025;
33630
33631 };
33632 /**
33633  * @author mrdoob / http://mrdoob.com/
33634  */
33635
33636 THREE.CanvasRenderer = function ( parameters ) {
33637
33638     console.log( 'THREE.CanvasRenderer', THREE.REVISION );
33639
33640     parameters = parameters || {};
33641
33642     var _this = this,
33643     _renderData, _elements, _lights,
33644     _projector = new THREE.Projector(),
33645
33646     _canvas = parameters.canvas !== undefined ? parameters.canvas : document.createElement( 'canvas' ),
33647
33648     _canvasWidth, _canvasHeight, _canvasWidthHalf, _canvasHeightHalf,
33649     _context = _canvas.getContext( '2d' ),
33650
33651     _clearColor = new THREE.Color( 0x000000 ),
33652     _clearOpacity = 0,
33653
33654     _contextGlobalAlpha = 1,
33655     _contextGlobalCompositeOperation = 0,
33656     _contextStrokeStyle = null,
33657     _contextFillStyle = null,
33658     _contextLineWidth = null,
33659     _contextLineCap = null,
33660     _contextLineJoin = null,
33661
33662     _v1, _v2, _v3, _v4,
33663     _v5 = new THREE.RenderableVertex(),
33664     _v6 = new THREE.RenderableVertex(),
33665
33666     _v1x, _v1y, _v2x, _v2y, _v3x, _v3y,
33667     _v4x, _v4y, _v5x, _v5y, _v6x, _v6y,
33668
33669     _color = new THREE.Color(),
33670     _color1 = new THREE.Color(),
33671     _color2 = new THREE.Color(),
33672     _color3 = new THREE.Color(),
33673     _color4 = new THREE.Color(),
33674
33675     _patterns = {}, _imagedatas = {},
33676
33677     _near, _far,
33678
33679     _image, _uvs,
33680     _uv1x, _uv1y, _uv2x, _uv2y, _uv3x, _uv3y,
33681
33682     _clipRect = new THREE.Rectangle(),
33683     _clearRect = new THREE.Rectangle(),
33684     _bboxRect = new THREE.Rectangle(),
33685
33686     _enableLighting = false,
33687     _ambientLight = new THREE.Color(),
33688     _directionalLights = new THREE.Color(),
33689     _pointLights = new THREE.Color(),
33690
33691     _pi2 = Math.PI * 2,
33692     _vector3 = new THREE.Vector3(), // Needed for PointLight
33693
33694     _pixelMap, _pixelMapContext, _pixelMapImage, _pixelMapData,
33695     _gradientMap, _gradientMapContext, _gradientMapQuality = 16;
33696
33697     _pixelMap = document.createElement( 'canvas' );
33698     _pixelMap.width = _pixelMap.height = 2;
33699
33700     _pixelMapContext = _pixelMap.getContext( '2d' );
33701     _pixelMapContext.fillStyle = 'rgba(0,0,0,1)';
33702     _pixelMapContext.fillRect( 0, 0, 2, 2 );
33703
33704     _pixelMapImage = _pixelMapContext.getImageData( 0, 0, 2, 2 );
33705     _pixelMapData = _pixelMapImage.data;
33706
33707     _gradientMap = document.createElement( 'canvas' );
33708     _gradientMap.width = _gradientMap.height = _gradientMapQuality;
33709
33710     _gradientMapContext = _gradientMap.getContext( '2d' );
33711     _gradientMapContext.translate( - _gradientMapQuality / 2, - _gradientMapQuality / 2 );
33712     _gradientMapContext.scale( _gradientMapQuality, _gradientMapQuality );
33713
33714     _gradientMapQuality --; // Fix UVs
33715
33716     this.domElement = _canvas;
33717
33718     this.autoClear = true;
33719     this.sortObjects = true;
33720     this.sortElements = true;
33721
33722     this.info = {
33723
33724         render: {
33725
33726             vertices: 0,
33727             faces: 0
33728
33729         }
33730
33731     }
33732
33733     this.setSize = function ( width, height ) {
33734
33735         _canvasWidth = width;
33736         _canvasHeight = height;
33737         _canvasWidthHalf = Math.floor( _canvasWidth / 2 );
33738         _canvasHeightHalf = Math.floor( _canvasHeight / 2 );
33739
33740         _canvas.width = _canvasWidth;
33741         _canvas.height = _canvasHeight;
33742
33743         _clipRect.set( - _canvasWidthHalf, - _canvasHeightHalf, _canvasWidthHalf, _canvasHeightHalf );
33744         _clearRect.set( - _canvasWidthHalf, - _canvasHeightHalf, _canvasWidthHalf, _canvasHeightHalf );
33745
33746         _contextGlobalAlpha = 1;
33747         _contextGlobalCompositeOperation = 0;
33748         _contextStrokeStyle = null;
33749         _contextFillStyle = null;
33750         _contextLineWidth = null;
33751         _contextLineCap = null;
33752         _contextLineJoin = null;
33753
33754     };
33755
33756     this.setClearColor = function ( color, opacity ) {
33757
33758         _clearColor.copy( color );
33759         _clearOpacity = opacity !== undefined ? opacity : 1;
33760
33761         _clearRect.set( - _canvasWidthHalf, - _canvasHeightHalf, _canvasWidthHalf, _canvasHeightHalf );
33762
33763     };
33764
33765     this.setClearColorHex = function ( hex, opacity ) {
33766
33767         _clearColor.setHex( hex );
33768         _clearOpacity = opacity !== undefined ? opacity : 1;
33769
33770         _clearRect.set( - _canvasWidthHalf, - _canvasHeightHalf, _canvasWidthHalf, _canvasHeightHalf );
33771
33772     };
33773
33774     this.getMaxAnisotropy  = function () {
33775
33776         return 0;
33777
33778     };
33779
33780     this.clear = function () {
33781
33782         _context.setTransform( 1, 0, 0, - 1, _canvasWidthHalf, _canvasHeightHalf );
33783
33784         if ( _clearRect.isEmpty() === false ) {
33785
33786             _clearRect.minSelf( _clipRect );
33787             _clearRect.inflate( 2 );
33788
33789             if ( _clearOpacity < 1 ) {
33790
33791                 _context.clearRect( Math.floor( _clearRect.getX() ), Math.floor( _clearRect.getY() ), Math.floor( _clearRect.getWidth() ), Math.floor( _clearRect.getHeight() ) );
33792
33793             }
33794
33795             if ( _clearOpacity > 0 ) {
33796
33797                 setBlending( THREE.NormalBlending );
33798                 setOpacity( 1 );
33799
33800                 setFillStyle( 'rgba(' + Math.floor( _clearColor.r * 255 ) + ',' + Math.floor( _clearColor.g * 255 ) + ',' + Math.floor( _clearColor.b * 255 ) + ',' + _clearOpacity + ')' );
33801
33802                 _context.fillRect( Math.floor( _clearRect.getX() ), Math.floor( _clearRect.getY() ), Math.floor( _clearRect.getWidth() ), Math.floor( _clearRect.getHeight() ) );
33803
33804             }
33805
33806             _clearRect.empty();
33807
33808         }
33809
33810
33811     };
33812
33813     this.render = function ( scene, camera ) {
33814
33815         if ( camera instanceof THREE.Camera === false ) {
33816
33817             console.error( 'THREE.CanvasRenderer.render: camera is not an instance of THREE.Camera.' );
33818             return;
33819
33820         }
33821
33822         var e, el, element, material;
33823
33824         this.autoClear === true ? this.clear() : _context.setTransform( 1, 0, 0, - 1, _canvasWidthHalf, _canvasHeightHalf );
33825
33826         _this.info.render.vertices = 0;
33827         _this.info.render.faces = 0;
33828
33829         _renderData = _projector.projectScene( scene, camera, this.sortObjects, this.sortElements );
33830         _elements = _renderData.elements;
33831         _lights = _renderData.lights;
33832
33833         /* DEBUG
33834         _context.fillStyle = 'rgba( 0, 255, 255, 0.5 )';
33835         _context.fillRect( _clipRect.getX(), _clipRect.getY(), _clipRect.getWidth(), _clipRect.getHeight() );
33836         */
33837
33838         _enableLighting = _lights.length > 0;
33839
33840         if ( _enableLighting === true ) {
33841
33842              calculateLights();
33843
33844         }
33845
33846         for ( e = 0, el = _elements.length; e < el; e++ ) {
33847
33848             element = _elements[ e ];
33849
33850             material = element.material;
33851
33852             if ( material === undefined || material.visible === false ) continue;
33853
33854             _bboxRect.empty();
33855
33856             if ( element instanceof THREE.RenderableParticle ) {
33857
33858                 _v1 = element;
33859                 _v1.x *= _canvasWidthHalf; _v1.y *= _canvasHeightHalf;
33860
33861                 renderParticle( _v1, element, material, scene );
33862
33863             } else if ( element instanceof THREE.RenderableLine ) {
33864
33865                 _v1 = element.v1; _v2 = element.v2;
33866
33867                 _v1.positionScreen.x *= _canvasWidthHalf; _v1.positionScreen.y *= _canvasHeightHalf;
33868                 _v2.positionScreen.x *= _canvasWidthHalf; _v2.positionScreen.y *= _canvasHeightHalf;
33869
33870                 _bboxRect.addPoint( _v1.positionScreen.x, _v1.positionScreen.y );
33871                 _bboxRect.addPoint( _v2.positionScreen.x, _v2.positionScreen.y );
33872
33873                 if ( _clipRect.intersects( _bboxRect ) === true ) {
33874
33875                     renderLine( _v1, _v2, element, material, scene );
33876
33877                 }
33878
33879
33880             } else if ( element instanceof THREE.RenderableFace3 ) {
33881
33882                 _v1 = element.v1; _v2 = element.v2; _v3 = element.v3;
33883
33884                 _v1.positionScreen.x *= _canvasWidthHalf; _v1.positionScreen.y *= _canvasHeightHalf;
33885                 _v2.positionScreen.x *= _canvasWidthHalf; _v2.positionScreen.y *= _canvasHeightHalf;
33886                 _v3.positionScreen.x *= _canvasWidthHalf; _v3.positionScreen.y *= _canvasHeightHalf;
33887
33888                 if ( material.overdraw === true ) {
33889
33890                     expand( _v1.positionScreen, _v2.positionScreen );
33891                     expand( _v2.positionScreen, _v3.positionScreen );
33892                     expand( _v3.positionScreen, _v1.positionScreen );
33893
33894                 }
33895
33896                 _bboxRect.add3Points( _v1.positionScreen.x, _v1.positionScreen.y,
33897                               _v2.positionScreen.x, _v2.positionScreen.y,
33898                               _v3.positionScreen.x, _v3.positionScreen.y );
33899
33900                 if ( _clipRect.intersects( _bboxRect ) === true ) {
33901
33902                     renderFace3( _v1, _v2, _v3, 0, 1, 2, element, material, scene );
33903
33904                 }
33905
33906             } else if ( element instanceof THREE.RenderableFace4 ) {
33907
33908                 _v1 = element.v1; _v2 = element.v2; _v3 = element.v3; _v4 = element.v4;
33909
33910                 _v1.positionScreen.x *= _canvasWidthHalf; _v1.positionScreen.y *= _canvasHeightHalf;
33911                 _v2.positionScreen.x *= _canvasWidthHalf; _v2.positionScreen.y *= _canvasHeightHalf;
33912                 _v3.positionScreen.x *= _canvasWidthHalf; _v3.positionScreen.y *= _canvasHeightHalf;
33913                 _v4.positionScreen.x *= _canvasWidthHalf; _v4.positionScreen.y *= _canvasHeightHalf;
33914
33915                 _v5.positionScreen.copy( _v2.positionScreen );
33916                 _v6.positionScreen.copy( _v4.positionScreen );
33917
33918                 if ( material.overdraw === true ) {
33919
33920                     expand( _v1.positionScreen, _v2.positionScreen );
33921                     expand( _v2.positionScreen, _v4.positionScreen );
33922                     expand( _v4.positionScreen, _v1.positionScreen );
33923
33924                     expand( _v3.positionScreen, _v5.positionScreen );
33925                     expand( _v3.positionScreen, _v6.positionScreen );
33926
33927                 }
33928
33929                 _bboxRect.addPoint( _v1.positionScreen.x, _v1.positionScreen.y );
33930                 _bboxRect.addPoint( _v2.positionScreen.x, _v2.positionScreen.y );
33931                 _bboxRect.addPoint( _v3.positionScreen.x, _v3.positionScreen.y );
33932                 _bboxRect.addPoint( _v4.positionScreen.x, _v4.positionScreen.y );
33933
33934                 if ( _clipRect.intersects( _bboxRect ) === true ) {
33935
33936                     renderFace4( _v1, _v2, _v3, _v4, _v5, _v6, element, material, scene );
33937
33938                 }
33939
33940             }
33941
33942             /* DEBUG
33943             _context.lineWidth = 1;
33944             _context.strokeStyle = 'rgba( 0, 255, 0, 0.5 )';
33945             _context.strokeRect( _bboxRect.getX(), _bboxRect.getY(), _bboxRect.getWidth(), _bboxRect.getHeight() );
33946             */
33947
33948             _clearRect.addRectangle( _bboxRect );
33949
33950
33951         }
33952
33953         /* DEBUG
33954         _context.lineWidth = 1;
33955         _context.strokeStyle = 'rgba( 255, 0, 0, 0.5 )';
33956         _context.strokeRect( _clearRect.getX(), _clearRect.getY(), _clearRect.getWidth(), _clearRect.getHeight() );
33957         */
33958
33959         _context.setTransform( 1, 0, 0, 1, 0, 0 );
33960
33961         //
33962
33963         function calculateLights() {
33964
33965             _ambientLight.setRGB( 0, 0, 0 );
33966             _directionalLights.setRGB( 0, 0, 0 );
33967             _pointLights.setRGB( 0, 0, 0 );
33968
33969             for ( var l = 0, ll = _lights.length; l < ll; l ++ ) {
33970
33971                 var light = _lights[ l ];
33972                 var lightColor = light.color;
33973
33974                 if ( light instanceof THREE.AmbientLight ) {
33975
33976                     _ambientLight.r += lightColor.r;
33977                     _ambientLight.g += lightColor.g;
33978                     _ambientLight.b += lightColor.b;
33979
33980                 } else if ( light instanceof THREE.DirectionalLight ) {
33981
33982                     // for particles
33983
33984                     _directionalLights.r += lightColor.r;
33985                     _directionalLights.g += lightColor.g;
33986                     _directionalLights.b += lightColor.b;
33987
33988                 } else if ( light instanceof THREE.PointLight ) {
33989
33990                     // for particles
33991
33992                     _pointLights.r += lightColor.r;
33993                     _pointLights.g += lightColor.g;
33994                     _pointLights.b += lightColor.b;
33995
33996                 }
33997
33998             }
33999
34000         }
34001
34002         function calculateLight( position, normal, color ) {
34003
34004             for ( var l = 0, ll = _lights.length; l < ll; l ++ ) {
34005
34006                 var light = _lights[ l ];
34007                 var lightColor = light.color;
34008
34009                 if ( light instanceof THREE.DirectionalLight ) {
34010
34011                     var lightPosition = light.matrixWorld.getPosition().normalize();
34012
34013                     var amount = normal.dot( lightPosition );
34014
34015                     if ( amount <= 0 ) continue;
34016
34017                     amount *= light.intensity;
34018
34019                     color.r += lightColor.r * amount;
34020                     color.g += lightColor.g * amount;
34021                     color.b += lightColor.b * amount;
34022
34023                 } else if ( light instanceof THREE.PointLight ) {
34024
34025                     var lightPosition = light.matrixWorld.getPosition();
34026
34027                     var amount = normal.dot( _vector3.sub( lightPosition, position ).normalize() );
34028
34029                     if ( amount <= 0 ) continue;
34030
34031                     amount *= light.distance == 0 ? 1 : 1 - Math.min( position.distanceTo( lightPosition ) / light.distance, 1 );
34032
34033                     if ( amount == 0 ) continue;
34034
34035                     amount *= light.intensity;
34036
34037                     color.r += lightColor.r * amount;
34038                     color.g += lightColor.g * amount;
34039                     color.b += lightColor.b * amount;
34040
34041                 }
34042
34043             }
34044
34045         }
34046
34047         function renderParticle( v1, element, material, scene ) {
34048
34049             setOpacity( material.opacity );
34050             setBlending( material.blending );
34051
34052             var width, height, scaleX, scaleY,
34053             bitmap, bitmapWidth, bitmapHeight;
34054
34055             if ( material instanceof THREE.ParticleBasicMaterial ) {
34056
34057                 if ( material.map === null ) {
34058
34059                     scaleX = element.object.scale.x;
34060                     scaleY = element.object.scale.y;
34061
34062                     // TODO: Be able to disable this
34063
34064                     scaleX *= element.scale.x * _canvasWidthHalf;
34065                     scaleY *= element.scale.y * _canvasHeightHalf;
34066
34067                     _bboxRect.set( v1.x - scaleX, v1.y - scaleY, v1.x  + scaleX, v1.y + scaleY );
34068
34069                     if ( _clipRect.intersects( _bboxRect ) === false ) {
34070
34071                         return;
34072
34073                     }
34074
34075                     setFillStyle( material.color.getContextStyle() );
34076
34077                     _context.save();
34078                     _context.translate( v1.x, v1.y );
34079                     _context.rotate( - element.rotation );
34080                     _context.scale( scaleX, scaleY );
34081                     _context.fillRect( -1, -1, 2, 2 );
34082                     _context.restore();
34083
34084                 } else {
34085
34086                     bitmap = material.map.image;
34087                     bitmapWidth = bitmap.width >> 1;
34088                     bitmapHeight = bitmap.height >> 1;
34089
34090                     scaleX = element.scale.x * _canvasWidthHalf;
34091                     scaleY = element.scale.y * _canvasHeightHalf;
34092
34093                     width = scaleX * bitmapWidth;
34094                     height = scaleY * bitmapHeight;
34095
34096                     // TODO: Rotations break this...
34097
34098                     _bboxRect.set( v1.x - width, v1.y - height, v1.x  + width, v1.y + height );
34099
34100                     if ( _clipRect.intersects( _bboxRect ) === false ) {
34101
34102                         return;
34103
34104                     }
34105
34106                     _context.save();
34107                     _context.translate( v1.x, v1.y );
34108                     _context.rotate( - element.rotation );
34109                     _context.scale( scaleX, - scaleY );
34110
34111                     _context.translate( - bitmapWidth, - bitmapHeight );
34112                     _context.drawImage( bitmap, 0, 0 );
34113                     _context.restore();
34114
34115                 }
34116
34117                 /* DEBUG
34118                 setStrokeStyle( 'rgb(255,255,0)' );
34119                 _context.beginPath();
34120                 _context.moveTo( v1.x - 10, v1.y );
34121                 _context.lineTo( v1.x + 10, v1.y );
34122                 _context.moveTo( v1.x, v1.y - 10 );
34123                 _context.lineTo( v1.x, v1.y + 10 );
34124                 _context.stroke();
34125                 */
34126
34127             } else if ( material instanceof THREE.ParticleCanvasMaterial ) {
34128
34129                 width = element.scale.x * _canvasWidthHalf;
34130                 height = element.scale.y * _canvasHeightHalf;
34131
34132                 _bboxRect.set( v1.x - width, v1.y - height, v1.x + width, v1.y + height );
34133
34134                 if ( _clipRect.intersects( _bboxRect ) === false ) {
34135
34136                     return;
34137
34138                 }
34139
34140                 setStrokeStyle( material.color.getContextStyle() );
34141                 setFillStyle( material.color.getContextStyle() );
34142
34143                 _context.save();
34144                 _context.translate( v1.x, v1.y );
34145                 _context.rotate( - element.rotation );
34146                 _context.scale( width, height );
34147
34148                 material.program( _context );
34149
34150                 _context.restore();
34151
34152             }
34153
34154         }
34155
34156         function renderLine( v1, v2, element, material, scene ) {
34157
34158             setOpacity( material.opacity );
34159             setBlending( material.blending );
34160
34161             _context.beginPath();
34162             _context.moveTo( v1.positionScreen.x, v1.positionScreen.y );
34163             _context.lineTo( v2.positionScreen.x, v2.positionScreen.y );
34164
34165             if ( material instanceof THREE.LineBasicMaterial ) {
34166
34167                 setLineWidth( material.linewidth );
34168                 setLineCap( material.linecap );
34169                 setLineJoin( material.linejoin );
34170                 setStrokeStyle( material.color.getContextStyle() );
34171
34172                 _context.stroke();
34173                 _bboxRect.inflate( material.linewidth * 2 );
34174
34175             }
34176
34177         }
34178
34179         function renderFace3( v1, v2, v3, uv1, uv2, uv3, element, material, scene ) {
34180
34181             _this.info.render.vertices += 3;
34182             _this.info.render.faces ++;
34183
34184             setOpacity( material.opacity );
34185             setBlending( material.blending );
34186
34187             _v1x = v1.positionScreen.x; _v1y = v1.positionScreen.y;
34188             _v2x = v2.positionScreen.x; _v2y = v2.positionScreen.y;
34189             _v3x = v3.positionScreen.x; _v3y = v3.positionScreen.y;
34190
34191             drawTriangle( _v1x, _v1y, _v2x, _v2y, _v3x, _v3y );
34192
34193             if ( ( material instanceof THREE.MeshLambertMaterial || material instanceof THREE.MeshPhongMaterial ) && material.map === null && material.map === null ) {
34194
34195                 if ( _enableLighting === true ) {
34196
34197                     var diffuse = material.color;
34198                     var emissive = material.emissive;
34199
34200                     if ( material.wireframe === false && material.shading == THREE.SmoothShading && element.vertexNormalsLength == 3 ) {
34201
34202                         _color1.r = _color2.r = _color3.r = _ambientLight.r;
34203                         _color1.g = _color2.g = _color3.g = _ambientLight.g;
34204                         _color1.b = _color2.b = _color3.b = _ambientLight.b;
34205
34206                         calculateLight( element.v1.positionWorld, element.vertexNormalsWorld[ 0 ], _color1 );
34207                         calculateLight( element.v2.positionWorld, element.vertexNormalsWorld[ 1 ], _color2 );
34208                         calculateLight( element.v3.positionWorld, element.vertexNormalsWorld[ 2 ], _color3 );
34209
34210                         _color1.r = diffuse.r * _color1.r + emissive.r;
34211                         _color1.g = diffuse.g * _color1.g + emissive.g;
34212                         _color1.b = diffuse.b * _color1.b + emissive.b;
34213
34214                         _color2.r = diffuse.r * _color2.r + emissive.r;
34215                         _color2.g = diffuse.g * _color2.g + emissive.g;
34216                         _color2.b = diffuse.b * _color2.b + emissive.b;
34217
34218                         _color3.r = diffuse.r * _color3.r + emissive.r;
34219                         _color3.g = diffuse.g * _color3.g + emissive.g;
34220                         _color3.b = diffuse.b * _color3.b + emissive.b;
34221
34222                         _color4.r = ( _color2.r + _color3.r ) * 0.5;
34223                         _color4.g = ( _color2.g + _color3.g ) * 0.5;
34224                         _color4.b = ( _color2.b + _color3.b ) * 0.5;
34225
34226                         _image = getGradientTexture( _color1, _color2, _color3, _color4 );
34227
34228                         clipImage( _v1x, _v1y, _v2x, _v2y, _v3x, _v3y, 0, 0, 1, 0, 0, 1, _image );
34229
34230                     } else {
34231
34232                         _color.r = _ambientLight.r;
34233                         _color.g = _ambientLight.g;
34234                         _color.b = _ambientLight.b;
34235
34236                         calculateLight( element.centroidWorld, element.normalWorld, _color );
34237
34238                         _color.r = diffuse.r * _color.r + emissive.r;
34239                         _color.g = diffuse.g * _color.g + emissive.g;
34240                         _color.b = diffuse.b * _color.b + emissive.b;
34241
34242                         material.wireframe === true ? strokePath( _color, material.wireframeLinewidth, material.wireframeLinecap, material.wireframeLinejoin ) : fillPath( _color );
34243
34244                     }
34245
34246                 } else {
34247
34248                     material.wireframe === true ? strokePath( material.color, material.wireframeLinewidth, material.wireframeLinecap, material.wireframeLinejoin ) : fillPath( material.color );
34249
34250                 }
34251
34252             } else if ( material instanceof THREE.MeshBasicMaterial || material instanceof THREE.MeshLambertMaterial || material instanceof THREE.MeshPhongMaterial ) {
34253
34254                 if ( material.map !== null ) {
34255
34256                     if ( material.map.mapping instanceof THREE.UVMapping ) {
34257
34258                         _uvs = element.uvs[ 0 ];
34259                         patternPath( _v1x, _v1y, _v2x, _v2y, _v3x, _v3y, _uvs[ uv1 ].u, _uvs[ uv1 ].v, _uvs[ uv2 ].u, _uvs[ uv2 ].v, _uvs[ uv3 ].u, _uvs[ uv3 ].v, material.map );
34260
34261                     }
34262
34263
34264                 } else if ( material.envMap !== null ) {
34265
34266                     if ( material.envMap.mapping instanceof THREE.SphericalReflectionMapping ) {
34267
34268                         var cameraMatrix = camera.matrixWorldInverse;
34269
34270                         _vector3.copy( element.vertexNormalsWorld[ uv1 ] );
34271                         _uv1x = ( _vector3.x * cameraMatrix.elements[0] + _vector3.y * cameraMatrix.elements[4] + _vector3.z * cameraMatrix.elements[8] ) * 0.5 + 0.5;
34272                         _uv1y = ( _vector3.x * cameraMatrix.elements[1] + _vector3.y * cameraMatrix.elements[5] + _vector3.z * cameraMatrix.elements[9] ) * 0.5 + 0.5;
34273
34274                         _vector3.copy( element.vertexNormalsWorld[ uv2 ] );
34275                         _uv2x = ( _vector3.x * cameraMatrix.elements[0] + _vector3.y * cameraMatrix.elements[4] + _vector3.z * cameraMatrix.elements[8] ) * 0.5 + 0.5;
34276                         _uv2y = ( _vector3.x * cameraMatrix.elements[1] + _vector3.y * cameraMatrix.elements[5] + _vector3.z * cameraMatrix.elements[9] ) * 0.5 + 0.5;
34277
34278                         _vector3.copy( element.vertexNormalsWorld[ uv3 ] );
34279                         _uv3x = ( _vector3.x * cameraMatrix.elements[0] + _vector3.y * cameraMatrix.elements[4] + _vector3.z * cameraMatrix.elements[8] ) * 0.5 + 0.5;
34280                         _uv3y = ( _vector3.x * cameraMatrix.elements[1] + _vector3.y * cameraMatrix.elements[5] + _vector3.z * cameraMatrix.elements[9] ) * 0.5 + 0.5;
34281
34282                         patternPath( _v1x, _v1y, _v2x, _v2y, _v3x, _v3y, _uv1x, _uv1y, _uv2x, _uv2y, _uv3x, _uv3y, material.envMap );
34283
34284                     }/* else if ( material.envMap.mapping == THREE.SphericalRefractionMapping ) {
34285
34286
34287
34288                     }*/
34289
34290
34291                 } else {
34292
34293                     material.wireframe === true ? strokePath( material.color, material.wireframeLinewidth, material.wireframeLinecap, material.wireframeLinejoin ) : fillPath( material.color );
34294
34295                 }
34296
34297             } else if ( material instanceof THREE.MeshDepthMaterial ) {
34298
34299                 _near = camera.near;
34300                 _far = camera.far;
34301
34302                 _color1.r = _color1.g = _color1.b = 1 - smoothstep( v1.positionScreen.z, _near, _far );
34303                 _color2.r = _color2.g = _color2.b = 1 - smoothstep( v2.positionScreen.z, _near, _far );
34304                 _color3.r = _color3.g = _color3.b = 1 - smoothstep( v3.positionScreen.z, _near, _far );
34305
34306                 _color4.r = ( _color2.r + _color3.r ) * 0.5;
34307                 _color4.g = ( _color2.g + _color3.g ) * 0.5;
34308                 _color4.b = ( _color2.b + _color3.b ) * 0.5;
34309
34310                 _image = getGradientTexture( _color1, _color2, _color3, _color4 );
34311
34312                 clipImage( _v1x, _v1y, _v2x, _v2y, _v3x, _v3y, 0, 0, 1, 0, 0, 1, _image );
34313
34314             } else if ( material instanceof THREE.MeshNormalMaterial ) {
34315
34316                 _color.r = normalToComponent( element.normalWorld.x );
34317                 _color.g = normalToComponent( element.normalWorld.y );
34318                 _color.b = normalToComponent( element.normalWorld.z );
34319
34320                 material.wireframe === true ? strokePath( _color, material.wireframeLinewidth, material.wireframeLinecap, material.wireframeLinejoin ) : fillPath( _color );
34321
34322             }
34323
34324         }
34325
34326         function renderFace4( v1, v2, v3, v4, v5, v6, element, material, scene ) {
34327
34328             _this.info.render.vertices += 4;
34329             _this.info.render.faces ++;
34330
34331             setOpacity( material.opacity );
34332             setBlending( material.blending );
34333
34334             if ( ( material.map !== undefined && material.map !== null ) || ( material.envMap !== undefined && material.envMap !== null ) ) {
34335
34336                 // Let renderFace3() handle this
34337
34338                 renderFace3( v1, v2, v4, 0, 1, 3, element, material, scene );
34339                 renderFace3( v5, v3, v6, 1, 2, 3, element, material, scene );
34340
34341                 return;
34342
34343             }
34344
34345             _v1x = v1.positionScreen.x; _v1y = v1.positionScreen.y;
34346             _v2x = v2.positionScreen.x; _v2y = v2.positionScreen.y;
34347             _v3x = v3.positionScreen.x; _v3y = v3.positionScreen.y;
34348             _v4x = v4.positionScreen.x; _v4y = v4.positionScreen.y;
34349             _v5x = v5.positionScreen.x; _v5y = v5.positionScreen.y;
34350             _v6x = v6.positionScreen.x; _v6y = v6.positionScreen.y;
34351
34352             if ( material instanceof THREE.MeshLambertMaterial || material instanceof THREE.MeshPhongMaterial ) {
34353
34354                 if ( _enableLighting === true ) {
34355
34356                     var diffuse = material.color;
34357                     var emissive = material.emissive;
34358
34359                     if ( material.wireframe === false && material.shading == THREE.SmoothShading && element.vertexNormalsLength == 4 ) {
34360
34361                         _color1.r = _color2.r = _color3.r = _color4.r = _ambientLight.r;
34362                         _color1.g = _color2.g = _color3.g = _color4.g = _ambientLight.g;
34363                         _color1.b = _color2.b = _color3.b = _color4.b = _ambientLight.b;
34364
34365                         calculateLight( element.v1.positionWorld, element.vertexNormalsWorld[ 0 ], _color1 );
34366                         calculateLight( element.v2.positionWorld, element.vertexNormalsWorld[ 1 ], _color2 );
34367                         calculateLight( element.v4.positionWorld, element.vertexNormalsWorld[ 3 ], _color3 );
34368                         calculateLight( element.v3.positionWorld, element.vertexNormalsWorld[ 2 ], _color4 );
34369
34370                         _color1.r = diffuse.r * _color1.r + emissive.r;
34371                         _color1.g = diffuse.g * _color1.g + emissive.g;
34372                         _color1.b = diffuse.b * _color1.b + emissive.b;
34373
34374                         _color2.r = diffuse.r * _color2.r + emissive.r;
34375                         _color2.g = diffuse.g * _color2.g + emissive.g;
34376                         _color2.b = diffuse.b * _color2.b + emissive.b;
34377
34378                         _color3.r = diffuse.r * _color3.r + emissive.r;
34379                         _color3.g = diffuse.g * _color3.g + emissive.g;
34380                         _color3.b = diffuse.b * _color3.b + emissive.b;
34381
34382                         _color4.r = diffuse.r * _color4.r + emissive.r;
34383                         _color4.g = diffuse.g * _color4.g + emissive.g;
34384                         _color4.b = diffuse.b * _color4.b + emissive.b;
34385
34386                         _image = getGradientTexture( _color1, _color2, _color3, _color4 );
34387
34388                         // TODO: UVs are incorrect, v4->v3?
34389
34390                         drawTriangle( _v1x, _v1y, _v2x, _v2y, _v4x, _v4y );
34391                         clipImage( _v1x, _v1y, _v2x, _v2y, _v4x, _v4y, 0, 0, 1, 0, 0, 1, _image );
34392
34393                         drawTriangle( _v5x, _v5y, _v3x, _v3y, _v6x, _v6y );
34394                         clipImage( _v5x, _v5y, _v3x, _v3y, _v6x, _v6y, 1, 0, 1, 1, 0, 1, _image );
34395
34396                     } else {
34397
34398                         _color.r = _ambientLight.r;
34399                         _color.g = _ambientLight.g;
34400                         _color.b = _ambientLight.b;
34401
34402                         calculateLight( element.centroidWorld, element.normalWorld, _color );
34403
34404                         _color.r = diffuse.r * _color.r + emissive.r;
34405                         _color.g = diffuse.g * _color.g + emissive.g;
34406                         _color.b = diffuse.b * _color.b + emissive.b;
34407
34408                         drawQuad( _v1x, _v1y, _v2x, _v2y, _v3x, _v3y, _v4x, _v4y );
34409
34410                         material.wireframe === true ? strokePath( _color, material.wireframeLinewidth, material.wireframeLinecap, material.wireframeLinejoin ) : fillPath( _color );
34411
34412                     }
34413
34414                 } else {
34415
34416                     drawQuad( _v1x, _v1y, _v2x, _v2y, _v3x, _v3y, _v4x, _v4y );
34417
34418                     material.wireframe === true ? strokePath( material.color, material.wireframeLinewidth, material.wireframeLinecap, material.wireframeLinejoin ) : fillPath( material.color );
34419
34420                 }
34421
34422             } else if ( material instanceof THREE.MeshBasicMaterial ) {
34423
34424                 drawQuad( _v1x, _v1y, _v2x, _v2y, _v3x, _v3y, _v4x, _v4y );
34425
34426                 material.wireframe === true ? strokePath( material.color, material.wireframeLinewidth, material.wireframeLinecap, material.wireframeLinejoin ) : fillPath( material.color );
34427
34428             } else if ( material instanceof THREE.MeshNormalMaterial ) {
34429
34430                 _color.r = normalToComponent( element.normalWorld.x );
34431                 _color.g = normalToComponent( element.normalWorld.y );
34432                 _color.b = normalToComponent( element.normalWorld.z );
34433
34434                 drawQuad( _v1x, _v1y, _v2x, _v2y, _v3x, _v3y, _v4x, _v4y );
34435
34436                 material.wireframe === true ? strokePath( _color, material.wireframeLinewidth, material.wireframeLinecap, material.wireframeLinejoin ) : fillPath( _color );
34437
34438             } else if ( material instanceof THREE.MeshDepthMaterial ) {
34439
34440                 _near = camera.near;
34441                 _far = camera.far;
34442
34443                 _color1.r = _color1.g = _color1.b = 1 - smoothstep( v1.positionScreen.z, _near, _far );
34444                 _color2.r = _color2.g = _color2.b = 1 - smoothstep( v2.positionScreen.z, _near, _far );
34445                 _color3.r = _color3.g = _color3.b = 1 - smoothstep( v4.positionScreen.z, _near, _far );
34446                 _color4.r = _color4.g = _color4.b = 1 - smoothstep( v3.positionScreen.z, _near, _far );
34447
34448                 _image = getGradientTexture( _color1, _color2, _color3, _color4 );
34449
34450                 // TODO: UVs are incorrect, v4->v3?
34451
34452                 drawTriangle( _v1x, _v1y, _v2x, _v2y, _v4x, _v4y );
34453                 clipImage( _v1x, _v1y, _v2x, _v2y, _v4x, _v4y, 0, 0, 1, 0, 0, 1, _image );
34454
34455                 drawTriangle( _v5x, _v5y, _v3x, _v3y, _v6x, _v6y );
34456                 clipImage( _v5x, _v5y, _v3x, _v3y, _v6x, _v6y, 1, 0, 1, 1, 0, 1, _image );
34457
34458             }
34459
34460         }
34461
34462         //
34463
34464         function drawTriangle( x0, y0, x1, y1, x2, y2 ) {
34465
34466             _context.beginPath();
34467             _context.moveTo( x0, y0 );
34468             _context.lineTo( x1, y1 );
34469             _context.lineTo( x2, y2 );
34470             _context.closePath();
34471
34472         }
34473
34474         function drawQuad( x0, y0, x1, y1, x2, y2, x3, y3 ) {
34475
34476             _context.beginPath();
34477             _context.moveTo( x0, y0 );
34478             _context.lineTo( x1, y1 );
34479             _context.lineTo( x2, y2 );
34480             _context.lineTo( x3, y3 );
34481             _context.closePath();
34482
34483         }
34484
34485         function strokePath( color, linewidth, linecap, linejoin ) {
34486
34487             setLineWidth( linewidth );
34488             setLineCap( linecap );
34489             setLineJoin( linejoin );
34490             setStrokeStyle( color.getContextStyle() );
34491
34492             _context.stroke();
34493
34494             _bboxRect.inflate( linewidth * 2 );
34495
34496         }
34497
34498         function fillPath( color ) {
34499
34500             setFillStyle( color.getContextStyle() );
34501             _context.fill();
34502
34503         }
34504
34505         function patternPath( x0, y0, x1, y1, x2, y2, u0, v0, u1, v1, u2, v2, texture ) {
34506
34507             if ( texture instanceof THREE.DataTexture || texture.image === undefined || texture.image.width == 0 ) return;
34508
34509             if ( texture.needsUpdate === true ) {
34510
34511                 var repeatX = texture.wrapS == THREE.RepeatWrapping;
34512                 var repeatY = texture.wrapT == THREE.RepeatWrapping;
34513
34514                 _patterns[ texture.id ] = _context.createPattern(
34515                     texture.image, repeatX === true && repeatY === true
34516                         ? 'repeat'
34517                         : repeatX === true && repeatY === false
34518                             ? 'repeat-x'
34519                             : repeatX === false && repeatY === true
34520                                 ? 'repeat-y'
34521                                 : 'no-repeat'
34522                 );
34523
34524                 texture.needsUpdate = false;
34525
34526             }
34527
34528             _patterns[ texture.id ] === undefined
34529                 ? setFillStyle( 'rgba(0,0,0,1)' )
34530                 : setFillStyle( _patterns[ texture.id ] );
34531
34532             // http://extremelysatisfactorytotalitarianism.com/blog/?p=2120
34533
34534             var a, b, c, d, e, f, det, idet,
34535             offsetX = texture.offset.x / texture.repeat.x,
34536             offsetY = texture.offset.y / texture.repeat.y,
34537             width = texture.image.width * texture.repeat.x,
34538             height = texture.image.height * texture.repeat.y;
34539
34540             u0 = ( u0 + offsetX ) * width;
34541             v0 = ( 1.0 - v0 + offsetY ) * height;
34542
34543             u1 = ( u1 + offsetX ) * width;
34544             v1 = ( 1.0 - v1 + offsetY ) * height;
34545
34546             u2 = ( u2 + offsetX ) * width;
34547             v2 = ( 1.0 - v2 + offsetY ) * height;
34548
34549             x1 -= x0; y1 -= y0;
34550             x2 -= x0; y2 -= y0;
34551
34552             u1 -= u0; v1 -= v0;
34553             u2 -= u0; v2 -= v0;
34554
34555             det = u1 * v2 - u2 * v1;
34556
34557             if ( det === 0 ) {
34558
34559                 if ( _imagedatas[ texture.id ] === undefined ) {
34560
34561                     var canvas = document.createElement( 'canvas' )
34562                     canvas.width = texture.image.width;
34563                     canvas.height = texture.image.height;
34564
34565                     var context = canvas.getContext( '2d' );
34566                     context.drawImage( texture.image, 0, 0 );
34567
34568                     _imagedatas[ texture.id ] = context.getImageData( 0, 0, texture.image.width, texture.image.height ).data;
34569
34570                 }
34571
34572                 var data = _imagedatas[ texture.id ];
34573                 var index = ( Math.floor( u0 ) + Math.floor( v0 ) * texture.image.width ) * 4;
34574
34575                 _color.setRGB( data[ index ] / 255, data[ index + 1 ] / 255, data[ index + 2 ] / 255 );
34576                 fillPath( _color );
34577
34578                 return;
34579
34580             }
34581
34582             idet = 1 / det;
34583
34584             a = ( v2 * x1 - v1 * x2 ) * idet;
34585             b = ( v2 * y1 - v1 * y2 ) * idet;
34586             c = ( u1 * x2 - u2 * x1 ) * idet;
34587             d = ( u1 * y2 - u2 * y1 ) * idet;
34588
34589             e = x0 - a * u0 - c * v0;
34590             f = y0 - b * u0 - d * v0;
34591
34592             _context.save();
34593             _context.transform( a, b, c, d, e, f );
34594             _context.fill();
34595             _context.restore();
34596
34597         }
34598
34599         function clipImage( x0, y0, x1, y1, x2, y2, u0, v0, u1, v1, u2, v2, image ) {
34600
34601             // http://extremelysatisfactorytotalitarianism.com/blog/?p=2120
34602
34603             var a, b, c, d, e, f, det, idet,
34604             width = image.width - 1,
34605             height = image.height - 1;
34606
34607             u0 *= width; v0 *= height;
34608             u1 *= width; v1 *= height;
34609             u2 *= width; v2 *= height;
34610
34611             x1 -= x0; y1 -= y0;
34612             x2 -= x0; y2 -= y0;
34613
34614             u1 -= u0; v1 -= v0;
34615             u2 -= u0; v2 -= v0;
34616
34617             det = u1 * v2 - u2 * v1;
34618
34619             idet = 1 / det;
34620
34621             a = ( v2 * x1 - v1 * x2 ) * idet;
34622             b = ( v2 * y1 - v1 * y2 ) * idet;
34623             c = ( u1 * x2 - u2 * x1 ) * idet;
34624             d = ( u1 * y2 - u2 * y1 ) * idet;
34625
34626             e = x0 - a * u0 - c * v0;
34627             f = y0 - b * u0 - d * v0;
34628
34629             _context.save();
34630             _context.transform( a, b, c, d, e, f );
34631             _context.clip();
34632             _context.drawImage( image, 0, 0 );
34633             _context.restore();
34634
34635         }
34636
34637         function getGradientTexture( color1, color2, color3, color4 ) {
34638
34639             // http://mrdoob.com/blog/post/710
34640
34641             _pixelMapData[ 0 ] = ( color1.r * 255 ) | 0;
34642             _pixelMapData[ 1 ] = ( color1.g * 255 ) | 0;
34643             _pixelMapData[ 2 ] = ( color1.b * 255 ) | 0;
34644
34645             _pixelMapData[ 4 ] = ( color2.r * 255 ) | 0;
34646             _pixelMapData[ 5 ] = ( color2.g * 255 ) | 0;
34647             _pixelMapData[ 6 ] = ( color2.b * 255 ) | 0;
34648
34649             _pixelMapData[ 8 ] = ( color3.r * 255 ) | 0;
34650             _pixelMapData[ 9 ] = ( color3.g * 255 ) | 0;
34651             _pixelMapData[ 10 ] = ( color3.b * 255 ) | 0;
34652
34653             _pixelMapData[ 12 ] = ( color4.r * 255 ) | 0;
34654             _pixelMapData[ 13 ] = ( color4.g * 255 ) | 0;
34655             _pixelMapData[ 14 ] = ( color4.b * 255 ) | 0;
34656
34657             _pixelMapContext.putImageData( _pixelMapImage, 0, 0 );
34658             _gradientMapContext.drawImage( _pixelMap, 0, 0 );
34659
34660             return _gradientMap;
34661
34662         }
34663
34664         function smoothstep( value, min, max ) {
34665
34666             var x = ( value - min ) / ( max - min );
34667             return x * x * ( 3 - 2 * x );
34668
34669         }
34670
34671         function normalToComponent( normal ) {
34672
34673             var component = ( normal + 1 ) * 0.5;
34674             return component < 0 ? 0 : ( component > 1 ? 1 : component );
34675
34676         }
34677
34678         // Hide anti-alias gaps
34679
34680         function expand( v1, v2 ) {
34681
34682             var x = v2.x - v1.x, y =  v2.y - v1.y,
34683             det = x * x + y * y, idet;
34684
34685             if ( det === 0 ) return;
34686
34687             idet = 1 / Math.sqrt( det );
34688
34689             x *= idet; y *= idet;
34690
34691             v2.x += x; v2.y += y;
34692             v1.x -= x; v1.y -= y;
34693
34694         }
34695     };
34696
34697     // Context cached methods.
34698
34699     function setOpacity( value ) {
34700
34701         if ( _contextGlobalAlpha !== value ) {
34702
34703             _context.globalAlpha = value;
34704             _contextGlobalAlpha = value;
34705
34706         }
34707
34708     }
34709
34710     function setBlending( value ) {
34711
34712         if ( _contextGlobalCompositeOperation !== value ) {
34713
34714             if ( value === THREE.NormalBlending ) {
34715
34716                 _context.globalCompositeOperation = 'source-over';
34717
34718             } else if ( value === THREE.AdditiveBlending ) {
34719
34720                 _context.globalCompositeOperation = 'lighter';
34721
34722             } else if ( value === THREE.SubtractiveBlending ) {
34723
34724                 _context.globalCompositeOperation = 'darker';
34725
34726             }
34727
34728             _contextGlobalCompositeOperation = value;
34729
34730         }
34731
34732     }
34733
34734     function setLineWidth( value ) {
34735
34736         if ( _contextLineWidth !== value ) {
34737
34738             _context.lineWidth = value;
34739             _contextLineWidth = value;
34740
34741         }
34742
34743     }
34744
34745     function setLineCap( value ) {
34746
34747         // "butt", "round", "square"
34748
34749         if ( _contextLineCap !== value ) {
34750
34751             _context.lineCap = value;
34752             _contextLineCap = value;
34753
34754         }
34755
34756     }
34757
34758     function setLineJoin( value ) {
34759
34760         // "round", "bevel", "miter"
34761
34762         if ( _contextLineJoin !== value ) {
34763
34764             _context.lineJoin = value;
34765             _contextLineJoin = value;
34766
34767         }
34768
34769     }
34770
34771     function setStrokeStyle( value ) {
34772
34773         if ( _contextStrokeStyle !== value ) {
34774
34775             _context.strokeStyle = value;
34776             _contextStrokeStyle = value;
34777
34778         }
34779
34780     }
34781
34782     function setFillStyle( value ) {
34783
34784         if ( _contextFillStyle !== value ) {
34785
34786             _context.fillStyle = value;
34787             _contextFillStyle = value;
34788
34789         }
34790
34791     }
34792
34793 };
34794 /**
34795  * @author alteredq / http://alteredqualia.com/
34796  * @author mrdoob / http://mrdoob.com/
34797  * @author mikael emtinger / http://gomo.se/
34798  */
34799
34800 THREE.ShaderChunk = {
34801
34802     // FOG
34803
34804     fog_pars_fragment: [
34805
34806         "#ifdef USE_FOG",
34807
34808             "uniform vec3 fogColor;",
34809
34810             "#ifdef FOG_EXP2",
34811
34812                 "uniform float fogDensity;",
34813
34814             "#else",
34815
34816                 "uniform float fogNear;",
34817                 "uniform float fogFar;",
34818
34819             "#endif",
34820
34821         "#endif"
34822
34823     ].join("\n"),
34824
34825     fog_fragment: [
34826
34827         "#ifdef USE_FOG",
34828
34829             "float depth = gl_FragCoord.z / gl_FragCoord.w;",
34830
34831             "#ifdef FOG_EXP2",
34832
34833                 "const float LOG2 = 1.442695;",
34834                 "float fogFactor = exp2( - fogDensity * fogDensity * depth * depth * LOG2 );",
34835                 "fogFactor = 1.0 - clamp( fogFactor, 0.0, 1.0 );",
34836
34837             "#else",
34838
34839                 "float fogFactor = smoothstep( fogNear, fogFar, depth );",
34840
34841             "#endif",
34842
34843             "gl_FragColor = mix( gl_FragColor, vec4( fogColor, gl_FragColor.w ), fogFactor );",
34844
34845         "#endif"
34846
34847     ].join("\n"),
34848
34849     // ENVIRONMENT MAP
34850
34851     envmap_pars_fragment: [
34852
34853         "#ifdef USE_ENVMAP",
34854
34855             "uniform float reflectivity;",
34856             "uniform samplerCube envMap;",
34857             "uniform float flipEnvMap;",
34858             "uniform int combine;",
34859
34860             "#if defined( USE_BUMPMAP ) || defined( USE_NORMALMAP )",
34861
34862                 "uniform bool useRefract;",
34863                 "uniform float refractionRatio;",
34864
34865             "#else",
34866
34867                 "varying vec3 vReflect;",
34868
34869             "#endif",
34870
34871         "#endif"
34872
34873     ].join("\n"),
34874
34875     envmap_fragment: [
34876
34877         "#ifdef USE_ENVMAP",
34878
34879             "vec3 reflectVec;",
34880
34881             "#if defined( USE_BUMPMAP ) || defined( USE_NORMALMAP )",
34882
34883                 "vec3 cameraToVertex = normalize( vWorldPosition - cameraPosition );",
34884
34885                 "if ( useRefract ) {",
34886
34887                     "reflectVec = refract( cameraToVertex, normal, refractionRatio );",
34888
34889                 "} else { ",
34890
34891                     "reflectVec = reflect( cameraToVertex, normal );",
34892
34893                 "}",
34894
34895             "#else",
34896
34897                 "reflectVec = vReflect;",
34898
34899             "#endif",
34900
34901             "#ifdef DOUBLE_SIDED",
34902
34903                 "float flipNormal = ( -1.0 + 2.0 * float( gl_FrontFacing ) );",
34904                 "vec4 cubeColor = textureCube( envMap, flipNormal * vec3( flipEnvMap * reflectVec.x, reflectVec.yz ) );",
34905
34906             "#else",
34907
34908                 "vec4 cubeColor = textureCube( envMap, vec3( flipEnvMap * reflectVec.x, reflectVec.yz ) );",
34909
34910             "#endif",
34911
34912             "#ifdef GAMMA_INPUT",
34913
34914                 "cubeColor.xyz *= cubeColor.xyz;",
34915
34916             "#endif",
34917
34918             "if ( combine == 1 ) {",
34919
34920                 "gl_FragColor.xyz = mix( gl_FragColor.xyz, cubeColor.xyz, specularStrength * reflectivity );",
34921
34922             "} else {",
34923
34924                 "gl_FragColor.xyz = mix( gl_FragColor.xyz, gl_FragColor.xyz * cubeColor.xyz, specularStrength * reflectivity );",
34925
34926             "}",
34927
34928         "#endif"
34929
34930     ].join("\n"),
34931
34932     envmap_pars_vertex: [
34933
34934         "#if defined( USE_ENVMAP ) && ! defined( USE_BUMPMAP ) && ! defined( USE_NORMALMAP )",
34935
34936             "varying vec3 vReflect;",
34937
34938             "uniform float refractionRatio;",
34939             "uniform bool useRefract;",
34940
34941         "#endif"
34942
34943     ].join("\n"),
34944
34945     worldpos_vertex : [
34946
34947         "#if defined( USE_ENVMAP ) || defined( PHONG ) || defined( LAMBERT ) || defined ( USE_SHADOWMAP )",
34948
34949             "#ifdef USE_SKINNING",
34950
34951                 "vec4 mPosition = modelMatrix * skinned;",
34952
34953             "#endif",
34954
34955             "#if defined( USE_MORPHTARGETS ) && ! defined( USE_SKINNING )",
34956
34957                 "vec4 mPosition = modelMatrix * vec4( morphed, 1.0 );",
34958
34959             "#endif",
34960
34961             "#if ! defined( USE_MORPHTARGETS ) && ! defined( USE_SKINNING )",
34962
34963                 "vec4 mPosition = modelMatrix * vec4( position, 1.0 );",
34964
34965             "#endif",
34966
34967         "#endif"
34968
34969     ].join("\n"),
34970
34971     envmap_vertex : [
34972
34973         "#if defined( USE_ENVMAP ) && ! defined( USE_BUMPMAP ) && ! defined( USE_NORMALMAP )",
34974
34975             "vec3 nWorld = mat3( modelMatrix[ 0 ].xyz, modelMatrix[ 1 ].xyz, modelMatrix[ 2 ].xyz ) * objectNormal;",
34976
34977             "if ( useRefract ) {",
34978
34979                 "vReflect = refract( normalize( mPosition.xyz - cameraPosition ), normalize( nWorld.xyz ), refractionRatio );",
34980
34981             "} else {",
34982
34983                 "vReflect = reflect( normalize( mPosition.xyz - cameraPosition ), normalize( nWorld.xyz ) );",
34984
34985             "}",
34986
34987         "#endif"
34988
34989     ].join("\n"),
34990
34991     // COLOR MAP (particles)
34992
34993     map_particle_pars_fragment: [
34994
34995         "#ifdef USE_MAP",
34996
34997             "uniform sampler2D map;",
34998
34999         "#endif"
35000
35001     ].join("\n"),
35002
35003
35004     map_particle_fragment: [
35005
35006         "#ifdef USE_MAP",
35007
35008             "gl_FragColor = gl_FragColor * texture2D( map, vec2( gl_PointCoord.x, 1.0 - gl_PointCoord.y ) );",
35009
35010         "#endif"
35011
35012     ].join("\n"),
35013
35014     // COLOR MAP (triangles)
35015
35016     map_pars_vertex: [
35017
35018         "#if defined( USE_MAP ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( USE_SPECULARMAP )",
35019
35020             "varying vec2 vUv;",
35021             "uniform vec4 offsetRepeat;",
35022
35023         "#endif"
35024
35025     ].join("\n"),
35026
35027     map_pars_fragment: [
35028
35029         "#if defined( USE_MAP ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( USE_SPECULARMAP )",
35030
35031             "varying vec2 vUv;",
35032
35033         "#endif",
35034
35035         "#ifdef USE_MAP",
35036
35037             "uniform sampler2D map;",
35038
35039         "#endif",
35040
35041     ].join("\n"),
35042
35043     map_vertex: [
35044
35045         "#if defined( USE_MAP ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP ) || defined( USE_SPECULARMAP )",
35046
35047             "vUv = uv * offsetRepeat.zw + offsetRepeat.xy;",
35048
35049         "#endif"
35050
35051     ].join("\n"),
35052
35053     map_fragment: [
35054
35055         "#ifdef USE_MAP",
35056
35057             "#ifdef GAMMA_INPUT",
35058
35059                 "vec4 texelColor = texture2D( map, vUv );",
35060                 "texelColor.xyz *= texelColor.xyz;",
35061
35062                 "gl_FragColor = gl_FragColor * texelColor;",
35063
35064             "#else",
35065
35066                 "gl_FragColor = gl_FragColor * texture2D( map, vUv );",
35067
35068             "#endif",
35069
35070         "#endif"
35071
35072     ].join("\n"),
35073
35074     // LIGHT MAP
35075
35076     lightmap_pars_fragment: [
35077
35078         "#ifdef USE_LIGHTMAP",
35079
35080             "varying vec2 vUv2;",
35081             "uniform sampler2D lightMap;",
35082
35083         "#endif"
35084
35085     ].join("\n"),
35086
35087     lightmap_pars_vertex: [
35088
35089         "#ifdef USE_LIGHTMAP",
35090
35091             "varying vec2 vUv2;",
35092
35093         "#endif"
35094
35095     ].join("\n"),
35096
35097     lightmap_fragment: [
35098
35099         "#ifdef USE_LIGHTMAP",
35100
35101             "gl_FragColor = gl_FragColor * texture2D( lightMap, vUv2 );",
35102
35103         "#endif"
35104
35105     ].join("\n"),
35106
35107     lightmap_vertex: [
35108
35109         "#ifdef USE_LIGHTMAP",
35110
35111             "vUv2 = uv2;",
35112
35113         "#endif"
35114
35115     ].join("\n"),
35116
35117     // BUMP MAP
35118
35119     bumpmap_pars_fragment: [
35120
35121         "#ifdef USE_BUMPMAP",
35122
35123             "uniform sampler2D bumpMap;",
35124             "uniform float bumpScale;",
35125
35126             // Derivative maps - bump mapping unparametrized surfaces by Morten Mikkelsen
35127             //    http://mmikkelsen3d.blogspot.sk/2011/07/derivative-maps.html
35128
35129             // Evaluate the derivative of the height w.r.t. screen-space using forward differencing (listing 2)
35130
35131             "vec2 dHdxy_fwd() {",
35132
35133                 "vec2 dSTdx = dFdx( vUv );",
35134                 "vec2 dSTdy = dFdy( vUv );",
35135
35136                 "float Hll = bumpScale * texture2D( bumpMap, vUv ).x;",
35137                 "float dBx = bumpScale * texture2D( bumpMap, vUv + dSTdx ).x - Hll;",
35138                 "float dBy = bumpScale * texture2D( bumpMap, vUv + dSTdy ).x - Hll;",
35139
35140                 "return vec2( dBx, dBy );",
35141
35142             "}",
35143
35144             "vec3 perturbNormalArb( vec3 surf_pos, vec3 surf_norm, vec2 dHdxy ) {",
35145
35146                 "vec3 vSigmaX = dFdx( surf_pos );",
35147                 "vec3 vSigmaY = dFdy( surf_pos );",
35148                 "vec3 vN = surf_norm;",        // normalized
35149
35150                 "vec3 R1 = cross( vSigmaY, vN );",
35151                 "vec3 R2 = cross( vN, vSigmaX );",
35152
35153                 "float fDet = dot( vSigmaX, R1 );",
35154
35155                 "vec3 vGrad = sign( fDet ) * ( dHdxy.x * R1 + dHdxy.y * R2 );",
35156                 "return normalize( abs( fDet ) * surf_norm - vGrad );",
35157
35158             "}",
35159
35160         "#endif"
35161
35162     ].join("\n"),
35163
35164     // NORMAL MAP
35165
35166     normalmap_pars_fragment: [
35167
35168         "#ifdef USE_NORMALMAP",
35169
35170             "uniform sampler2D normalMap;",
35171             "uniform vec2 normalScale;",
35172
35173             // Per-Pixel Tangent Space Normal Mapping
35174             // http://hacksoflife.blogspot.ch/2009/11/per-pixel-tangent-space-normal-mapping.html
35175
35176             "vec3 perturbNormal2Arb( vec3 eye_pos, vec3 surf_norm ) {",
35177
35178                 "vec3 q0 = dFdx( eye_pos.xyz );",
35179                 "vec3 q1 = dFdy( eye_pos.xyz );",
35180                 "vec2 st0 = dFdx( vUv.st );",
35181                 "vec2 st1 = dFdy( vUv.st );",
35182
35183                 "vec3 S = normalize(  q0 * st1.t - q1 * st0.t );",
35184                 "vec3 T = normalize( -q0 * st1.s + q1 * st0.s );",
35185                 "vec3 N = normalize( surf_norm );",
35186
35187                 "vec3 mapN = texture2D( normalMap, vUv ).xyz * 2.0 - 1.0;",
35188                 "mapN.xy = normalScale * mapN.xy;",
35189                 "mat3 tsn = mat3( S, T, N );",
35190                 "return normalize( tsn * mapN );",
35191
35192             "}",
35193
35194         "#endif"
35195
35196     ].join("\n"),
35197
35198     // SPECULAR MAP
35199
35200     specularmap_pars_fragment: [
35201
35202         "#ifdef USE_SPECULARMAP",
35203
35204             "uniform sampler2D specularMap;",
35205
35206         "#endif"
35207
35208     ].join("\n"),
35209
35210     specularmap_fragment: [
35211
35212         "float specularStrength;",
35213
35214         "#ifdef USE_SPECULARMAP",
35215
35216             "vec4 texelSpecular = texture2D( specularMap, vUv );",
35217             "specularStrength = texelSpecular.r;",
35218
35219         "#else",
35220
35221             "specularStrength = 1.0;",
35222
35223         "#endif"
35224
35225     ].join("\n"),
35226
35227     // LIGHTS LAMBERT
35228
35229     lights_lambert_pars_vertex: [
35230
35231         "uniform vec3 ambient;",
35232         "uniform vec3 diffuse;",
35233         "uniform vec3 emissive;",
35234
35235         "uniform vec3 ambientLightColor;",
35236
35237         "#if MAX_DIR_LIGHTS > 0",
35238
35239             "uniform vec3 directionalLightColor[ MAX_DIR_LIGHTS ];",
35240             "uniform vec3 directionalLightDirection[ MAX_DIR_LIGHTS ];",
35241
35242         "#endif",
35243
35244         "#if MAX_HEMI_LIGHTS > 0",
35245
35246             "uniform vec3 hemisphereLightSkyColor[ MAX_HEMI_LIGHTS ];",
35247             "uniform vec3 hemisphereLightGroundColor[ MAX_HEMI_LIGHTS ];",
35248             "uniform vec3 hemisphereLightPosition[ MAX_HEMI_LIGHTS ];",
35249
35250         "#endif",
35251
35252         "#if MAX_POINT_LIGHTS > 0",
35253
35254             "uniform vec3 pointLightColor[ MAX_POINT_LIGHTS ];",
35255             "uniform vec3 pointLightPosition[ MAX_POINT_LIGHTS ];",
35256             "uniform float pointLightDistance[ MAX_POINT_LIGHTS ];",
35257
35258         "#endif",
35259
35260         "#if MAX_SPOT_LIGHTS > 0",
35261
35262             "uniform vec3 spotLightColor[ MAX_SPOT_LIGHTS ];",
35263             "uniform vec3 spotLightPosition[ MAX_SPOT_LIGHTS ];",
35264             "uniform vec3 spotLightDirection[ MAX_SPOT_LIGHTS ];",
35265             "uniform float spotLightDistance[ MAX_SPOT_LIGHTS ];",
35266             "uniform float spotLightAngle[ MAX_SPOT_LIGHTS ];",
35267             "uniform float spotLightExponent[ MAX_SPOT_LIGHTS ];",
35268
35269         "#endif",
35270
35271         "#ifdef WRAP_AROUND",
35272
35273             "uniform vec3 wrapRGB;",
35274
35275         "#endif"
35276
35277     ].join("\n"),
35278
35279     lights_lambert_vertex: [
35280
35281         "vLightFront = vec3( 0.0 );",
35282
35283         "#ifdef DOUBLE_SIDED",
35284
35285             "vLightBack = vec3( 0.0 );",
35286
35287         "#endif",
35288
35289         "transformedNormal = normalize( transformedNormal );",
35290
35291         "#if MAX_DIR_LIGHTS > 0",
35292
35293         "for( int i = 0; i < MAX_DIR_LIGHTS; i ++ ) {",
35294
35295             "vec4 lDirection = viewMatrix * vec4( directionalLightDirection[ i ], 0.0 );",
35296             "vec3 dirVector = normalize( lDirection.xyz );",
35297
35298             "float dotProduct = dot( transformedNormal, dirVector );",
35299             "vec3 directionalLightWeighting = vec3( max( dotProduct, 0.0 ) );",
35300
35301             "#ifdef DOUBLE_SIDED",
35302
35303                 "vec3 directionalLightWeightingBack = vec3( max( -dotProduct, 0.0 ) );",
35304
35305                 "#ifdef WRAP_AROUND",
35306
35307                     "vec3 directionalLightWeightingHalfBack = vec3( max( -0.5 * dotProduct + 0.5, 0.0 ) );",
35308
35309                 "#endif",
35310
35311             "#endif",
35312
35313             "#ifdef WRAP_AROUND",
35314
35315                 "vec3 directionalLightWeightingHalf = vec3( max( 0.5 * dotProduct + 0.5, 0.0 ) );",
35316                 "directionalLightWeighting = mix( directionalLightWeighting, directionalLightWeightingHalf, wrapRGB );",
35317
35318                 "#ifdef DOUBLE_SIDED",
35319
35320                     "directionalLightWeightingBack = mix( directionalLightWeightingBack, directionalLightWeightingHalfBack, wrapRGB );",
35321
35322                 "#endif",
35323
35324             "#endif",
35325
35326             "vLightFront += directionalLightColor[ i ] * directionalLightWeighting;",
35327
35328             "#ifdef DOUBLE_SIDED",
35329
35330                 "vLightBack += directionalLightColor[ i ] * directionalLightWeightingBack;",
35331
35332             "#endif",
35333
35334         "}",
35335
35336         "#endif",
35337
35338         "#if MAX_POINT_LIGHTS > 0",
35339
35340             "for( int i = 0; i < MAX_POINT_LIGHTS; i ++ ) {",
35341
35342                 "vec4 lPosition = viewMatrix * vec4( pointLightPosition[ i ], 1.0 );",
35343                 "vec3 lVector = lPosition.xyz - mvPosition.xyz;",
35344
35345                 "float lDistance = 1.0;",
35346                 "if ( pointLightDistance[ i ] > 0.0 )",
35347                     "lDistance = 1.0 - min( ( length( lVector ) / pointLightDistance[ i ] ), 1.0 );",
35348
35349                 "lVector = normalize( lVector );",
35350                 "float dotProduct = dot( transformedNormal, lVector );",
35351
35352                 "vec3 pointLightWeighting = vec3( max( dotProduct, 0.0 ) );",
35353
35354                 "#ifdef DOUBLE_SIDED",
35355
35356                     "vec3 pointLightWeightingBack = vec3( max( -dotProduct, 0.0 ) );",
35357
35358                     "#ifdef WRAP_AROUND",
35359
35360                         "vec3 pointLightWeightingHalfBack = vec3( max( -0.5 * dotProduct + 0.5, 0.0 ) );",
35361
35362                     "#endif",
35363
35364                 "#endif",
35365
35366                 "#ifdef WRAP_AROUND",
35367
35368                     "vec3 pointLightWeightingHalf = vec3( max( 0.5 * dotProduct + 0.5, 0.0 ) );",
35369                     "pointLightWeighting = mix( pointLightWeighting, pointLightWeightingHalf, wrapRGB );",
35370
35371                     "#ifdef DOUBLE_SIDED",
35372
35373                         "pointLightWeightingBack = mix( pointLightWeightingBack, pointLightWeightingHalfBack, wrapRGB );",
35374
35375                     "#endif",
35376
35377                 "#endif",
35378
35379                 "vLightFront += pointLightColor[ i ] * pointLightWeighting * lDistance;",
35380
35381                 "#ifdef DOUBLE_SIDED",
35382
35383                     "vLightBack += pointLightColor[ i ] * pointLightWeightingBack * lDistance;",
35384
35385                 "#endif",
35386
35387             "}",
35388
35389         "#endif",
35390
35391         "#if MAX_SPOT_LIGHTS > 0",
35392
35393             "for( int i = 0; i < MAX_SPOT_LIGHTS; i ++ ) {",
35394
35395                 "vec4 lPosition = viewMatrix * vec4( spotLightPosition[ i ], 1.0 );",
35396                 "vec3 lVector = lPosition.xyz - mvPosition.xyz;",
35397
35398                 "lVector = normalize( lVector );",
35399
35400                 "float spotEffect = dot( spotLightDirection[ i ], normalize( spotLightPosition[ i ] - mPosition.xyz ) );",
35401
35402                 "if ( spotEffect > spotLightAngle[ i ] ) {",
35403
35404                     "spotEffect = pow( spotEffect, spotLightExponent[ i ] );",
35405
35406                     "float lDistance = 1.0;",
35407                     "if ( spotLightDistance[ i ] > 0.0 )",
35408                         "lDistance = 1.0 - min( ( length( lVector ) / spotLightDistance[ i ] ), 1.0 );",
35409
35410                     "float dotProduct = dot( transformedNormal, lVector );",
35411                     "vec3 spotLightWeighting = vec3( max( dotProduct, 0.0 ) );",
35412
35413                     "#ifdef DOUBLE_SIDED",
35414
35415                         "vec3 spotLightWeightingBack = vec3( max( -dotProduct, 0.0 ) );",
35416
35417                         "#ifdef WRAP_AROUND",
35418
35419                             "vec3 spotLightWeightingHalfBack = vec3( max( -0.5 * dotProduct + 0.5, 0.0 ) );",
35420
35421                         "#endif",
35422
35423                     "#endif",
35424
35425                     "#ifdef WRAP_AROUND",
35426
35427                         "vec3 spotLightWeightingHalf = vec3( max( 0.5 * dotProduct + 0.5, 0.0 ) );",
35428                         "spotLightWeighting = mix( spotLightWeighting, spotLightWeightingHalf, wrapRGB );",
35429
35430                         "#ifdef DOUBLE_SIDED",
35431
35432                             "spotLightWeightingBack = mix( spotLightWeightingBack, spotLightWeightingHalfBack, wrapRGB );",
35433
35434                         "#endif",
35435
35436                     "#endif",
35437
35438                     "vLightFront += spotLightColor[ i ] * spotLightWeighting * lDistance * spotEffect;",
35439
35440                     "#ifdef DOUBLE_SIDED",
35441
35442                         "vLightBack += spotLightColor[ i ] * spotLightWeightingBack * lDistance * spotEffect;",
35443
35444                     "#endif",
35445
35446                 "}",
35447
35448             "}",
35449
35450         "#endif",
35451
35452         "#if MAX_HEMI_LIGHTS > 0",
35453
35454             "for( int i = 0; i < MAX_HEMI_LIGHTS; i ++ ) {",
35455
35456                 "vec4 lPosition = viewMatrix * vec4( hemisphereLightPosition[ i ], 1.0 );",
35457                 "vec3 lVector = lPosition.xyz - mvPosition.xyz;",
35458
35459                 "lVector = normalize( lVector );",
35460
35461                 "float dotProduct = dot( transformedNormal, lVector );",
35462
35463                 "float hemiDiffuseWeight = 0.5 * dotProduct + 0.5;",
35464                 "float hemiDiffuseWeightBack = -0.5 * dotProduct + 0.5;",
35465
35466                 "vLightFront += mix( hemisphereLightGroundColor[ i ], hemisphereLightSkyColor[ i ], hemiDiffuseWeight );",
35467
35468                 "#ifdef DOUBLE_SIDED",
35469
35470                     "vLightBack += mix( hemisphereLightGroundColor[ i ], hemisphereLightSkyColor[ i ], hemiDiffuseWeightBack );",
35471
35472                 "#endif",
35473
35474             "}",
35475
35476         "#endif",
35477
35478         "vLightFront = vLightFront * diffuse + ambient * ambientLightColor + emissive;",
35479
35480         "#ifdef DOUBLE_SIDED",
35481
35482             "vLightBack = vLightBack * diffuse + ambient * ambientLightColor + emissive;",
35483
35484         "#endif"
35485
35486     ].join("\n"),
35487
35488     // LIGHTS PHONG
35489
35490     lights_phong_pars_vertex: [
35491
35492         "#ifndef PHONG_PER_PIXEL",
35493
35494         "#if MAX_POINT_LIGHTS > 0",
35495
35496             "uniform vec3 pointLightPosition[ MAX_POINT_LIGHTS ];",
35497             "uniform float pointLightDistance[ MAX_POINT_LIGHTS ];",
35498
35499             "varying vec4 vPointLight[ MAX_POINT_LIGHTS ];",
35500
35501         "#endif",
35502
35503         "#if MAX_SPOT_LIGHTS > 0",
35504
35505             "uniform vec3 spotLightPosition[ MAX_SPOT_LIGHTS ];",
35506             "uniform float spotLightDistance[ MAX_SPOT_LIGHTS ];",
35507
35508             "varying vec4 vSpotLight[ MAX_SPOT_LIGHTS ];",
35509
35510         "#endif",
35511
35512         "#endif",
35513
35514         "#if MAX_SPOT_LIGHTS > 0 || defined( USE_BUMPMAP )",
35515
35516             "varying vec3 vWorldPosition;",
35517
35518         "#endif"
35519
35520     ].join("\n"),
35521
35522
35523     lights_phong_vertex: [
35524
35525         "#ifndef PHONG_PER_PIXEL",
35526
35527         "#if MAX_POINT_LIGHTS > 0",
35528
35529             "for( int i = 0; i < MAX_POINT_LIGHTS; i ++ ) {",
35530
35531                 "vec4 lPosition = viewMatrix * vec4( pointLightPosition[ i ], 1.0 );",
35532                 "vec3 lVector = lPosition.xyz - mvPosition.xyz;",
35533
35534                 "float lDistance = 1.0;",
35535                 "if ( pointLightDistance[ i ] > 0.0 )",
35536                     "lDistance = 1.0 - min( ( length( lVector ) / pointLightDistance[ i ] ), 1.0 );",
35537
35538                 "vPointLight[ i ] = vec4( lVector, lDistance );",
35539
35540             "}",
35541
35542         "#endif",
35543
35544         "#if MAX_SPOT_LIGHTS > 0",
35545
35546             "for( int i = 0; i < MAX_SPOT_LIGHTS; i ++ ) {",
35547
35548                 "vec4 lPosition = viewMatrix * vec4( spotLightPosition[ i ], 1.0 );",
35549                 "vec3 lVector = lPosition.xyz - mvPosition.xyz;",
35550
35551                 "float lDistance = 1.0;",
35552                 "if ( spotLightDistance[ i ] > 0.0 )",
35553                     "lDistance = 1.0 - min( ( length( lVector ) / spotLightDistance[ i ] ), 1.0 );",
35554
35555                 "vSpotLight[ i ] = vec4( lVector, lDistance );",
35556
35557             "}",
35558
35559         "#endif",
35560
35561         "#endif",
35562
35563         "#if MAX_SPOT_LIGHTS > 0 || defined( USE_BUMPMAP )",
35564
35565             "vWorldPosition = mPosition.xyz;",
35566
35567         "#endif"
35568
35569     ].join("\n"),
35570
35571     lights_phong_pars_fragment: [
35572
35573         "uniform vec3 ambientLightColor;",
35574
35575         "#if MAX_DIR_LIGHTS > 0",
35576
35577             "uniform vec3 directionalLightColor[ MAX_DIR_LIGHTS ];",
35578             "uniform vec3 directionalLightDirection[ MAX_DIR_LIGHTS ];",
35579
35580         "#endif",
35581
35582         "#if MAX_HEMI_LIGHTS > 0",
35583
35584             "uniform vec3 hemisphereLightSkyColor[ MAX_HEMI_LIGHTS ];",
35585             "uniform vec3 hemisphereLightGroundColor[ MAX_HEMI_LIGHTS ];",
35586             "uniform vec3 hemisphereLightPosition[ MAX_HEMI_LIGHTS ];",
35587
35588         "#endif",
35589
35590         "#if MAX_POINT_LIGHTS > 0",
35591
35592             "uniform vec3 pointLightColor[ MAX_POINT_LIGHTS ];",
35593
35594             "#ifdef PHONG_PER_PIXEL",
35595
35596                 "uniform vec3 pointLightPosition[ MAX_POINT_LIGHTS ];",
35597                 "uniform float pointLightDistance[ MAX_POINT_LIGHTS ];",
35598
35599             "#else",
35600
35601                 "varying vec4 vPointLight[ MAX_POINT_LIGHTS ];",
35602
35603             "#endif",
35604
35605         "#endif",
35606
35607         "#if MAX_SPOT_LIGHTS > 0",
35608
35609             "uniform vec3 spotLightColor[ MAX_SPOT_LIGHTS ];",
35610             "uniform vec3 spotLightPosition[ MAX_SPOT_LIGHTS ];",
35611             "uniform vec3 spotLightDirection[ MAX_SPOT_LIGHTS ];",
35612             "uniform float spotLightAngle[ MAX_SPOT_LIGHTS ];",
35613             "uniform float spotLightExponent[ MAX_SPOT_LIGHTS ];",
35614
35615             "#ifdef PHONG_PER_PIXEL",
35616
35617                 "uniform float spotLightDistance[ MAX_SPOT_LIGHTS ];",
35618
35619             "#else",
35620
35621                 "varying vec4 vSpotLight[ MAX_SPOT_LIGHTS ];",
35622
35623             "#endif",
35624
35625         "#endif",
35626
35627         "#if MAX_SPOT_LIGHTS > 0 || defined( USE_BUMPMAP )",
35628
35629             "varying vec3 vWorldPosition;",
35630
35631         "#endif",
35632
35633         "#ifdef WRAP_AROUND",
35634
35635             "uniform vec3 wrapRGB;",
35636
35637         "#endif",
35638
35639         "varying vec3 vViewPosition;",
35640         "varying vec3 vNormal;"
35641
35642     ].join("\n"),
35643
35644     lights_phong_fragment: [
35645
35646         "vec3 normal = normalize( vNormal );",
35647         "vec3 viewPosition = normalize( vViewPosition );",
35648
35649         "#ifdef DOUBLE_SIDED",
35650
35651             "normal = normal * ( -1.0 + 2.0 * float( gl_FrontFacing ) );",
35652
35653         "#endif",
35654
35655         "#ifdef USE_NORMALMAP",
35656
35657             "normal = perturbNormal2Arb( -viewPosition, normal );",
35658
35659         "#elif defined( USE_BUMPMAP )",
35660
35661             "normal = perturbNormalArb( -vViewPosition, normal, dHdxy_fwd() );",
35662
35663         "#endif",
35664
35665         "#if MAX_POINT_LIGHTS > 0",
35666
35667             "vec3 pointDiffuse  = vec3( 0.0 );",
35668             "vec3 pointSpecular = vec3( 0.0 );",
35669
35670             "for ( int i = 0; i < MAX_POINT_LIGHTS; i ++ ) {",
35671
35672                 "#ifdef PHONG_PER_PIXEL",
35673
35674                     "vec4 lPosition = viewMatrix * vec4( pointLightPosition[ i ], 1.0 );",
35675                     "vec3 lVector = lPosition.xyz + vViewPosition.xyz;",
35676
35677                     "float lDistance = 1.0;",
35678                     "if ( pointLightDistance[ i ] > 0.0 )",
35679                         "lDistance = 1.0 - min( ( length( lVector ) / pointLightDistance[ i ] ), 1.0 );",
35680
35681                     "lVector = normalize( lVector );",
35682
35683                 "#else",
35684
35685                     "vec3 lVector = normalize( vPointLight[ i ].xyz );",
35686                     "float lDistance = vPointLight[ i ].w;",
35687
35688                 "#endif",
35689
35690                 // diffuse
35691
35692                 "float dotProduct = dot( normal, lVector );",
35693
35694                 "#ifdef WRAP_AROUND",
35695
35696                     "float pointDiffuseWeightFull = max( dotProduct, 0.0 );",
35697                     "float pointDiffuseWeightHalf = max( 0.5 * dotProduct + 0.5, 0.0 );",
35698
35699                     "vec3 pointDiffuseWeight = mix( vec3 ( pointDiffuseWeightFull ), vec3( pointDiffuseWeightHalf ), wrapRGB );",
35700
35701                 "#else",
35702
35703                     "float pointDiffuseWeight = max( dotProduct, 0.0 );",
35704
35705                 "#endif",
35706
35707                 "pointDiffuse  += diffuse * pointLightColor[ i ] * pointDiffuseWeight * lDistance;",
35708
35709                 // specular
35710
35711                 "vec3 pointHalfVector = normalize( lVector + viewPosition );",
35712                 "float pointDotNormalHalf = max( dot( normal, pointHalfVector ), 0.0 );",
35713                 "float pointSpecularWeight = specularStrength * max( pow( pointDotNormalHalf, shininess ), 0.0 );",
35714
35715                 "#ifdef PHYSICALLY_BASED_SHADING",
35716
35717                     // 2.0 => 2.0001 is hack to work around ANGLE bug
35718
35719                     "float specularNormalization = ( shininess + 2.0001 ) / 8.0;",
35720
35721                     "vec3 schlick = specular + vec3( 1.0 - specular ) * pow( 1.0 - dot( lVector, pointHalfVector ), 5.0 );",
35722                     "pointSpecular += schlick * pointLightColor[ i ] * pointSpecularWeight * pointDiffuseWeight * lDistance * specularNormalization;",
35723
35724                 "#else",
35725
35726                     "pointSpecular += specular * pointLightColor[ i ] * pointSpecularWeight * pointDiffuseWeight * lDistance;",
35727
35728                 "#endif",
35729
35730             "}",
35731
35732         "#endif",
35733
35734         "#if MAX_SPOT_LIGHTS > 0",
35735
35736             "vec3 spotDiffuse  = vec3( 0.0 );",
35737             "vec3 spotSpecular = vec3( 0.0 );",
35738
35739             "for ( int i = 0; i < MAX_SPOT_LIGHTS; i ++ ) {",
35740
35741                 "#ifdef PHONG_PER_PIXEL",
35742
35743                     "vec4 lPosition = viewMatrix * vec4( spotLightPosition[ i ], 1.0 );",
35744                     "vec3 lVector = lPosition.xyz + vViewPosition.xyz;",
35745
35746                     "float lDistance = 1.0;",
35747                     "if ( spotLightDistance[ i ] > 0.0 )",
35748                         "lDistance = 1.0 - min( ( length( lVector ) / spotLightDistance[ i ] ), 1.0 );",
35749
35750                     "lVector = normalize( lVector );",
35751
35752                 "#else",
35753
35754                     "vec3 lVector = normalize( vSpotLight[ i ].xyz );",
35755                     "float lDistance = vSpotLight[ i ].w;",
35756
35757                 "#endif",
35758
35759                 "float spotEffect = dot( spotLightDirection[ i ], normalize( spotLightPosition[ i ] - vWorldPosition ) );",
35760
35761                 "if ( spotEffect > spotLightAngle[ i ] ) {",
35762
35763                     "spotEffect = pow( spotEffect, spotLightExponent[ i ] );",
35764
35765                     // diffuse
35766
35767                     "float dotProduct = dot( normal, lVector );",
35768
35769                     "#ifdef WRAP_AROUND",
35770
35771                         "float spotDiffuseWeightFull = max( dotProduct, 0.0 );",
35772                         "float spotDiffuseWeightHalf = max( 0.5 * dotProduct + 0.5, 0.0 );",
35773
35774                         "vec3 spotDiffuseWeight = mix( vec3 ( spotDiffuseWeightFull ), vec3( spotDiffuseWeightHalf ), wrapRGB );",
35775
35776                     "#else",
35777
35778                         "float spotDiffuseWeight = max( dotProduct, 0.0 );",
35779
35780                     "#endif",
35781
35782                     "spotDiffuse += diffuse * spotLightColor[ i ] * spotDiffuseWeight * lDistance * spotEffect;",
35783
35784                     // specular
35785
35786                     "vec3 spotHalfVector = normalize( lVector + viewPosition );",
35787                     "float spotDotNormalHalf = max( dot( normal, spotHalfVector ), 0.0 );",
35788                     "float spotSpecularWeight = specularStrength * max( pow( spotDotNormalHalf, shininess ), 0.0 );",
35789
35790                     "#ifdef PHYSICALLY_BASED_SHADING",
35791
35792                         // 2.0 => 2.0001 is hack to work around ANGLE bug
35793
35794                         "float specularNormalization = ( shininess + 2.0001 ) / 8.0;",
35795
35796                         "vec3 schlick = specular + vec3( 1.0 - specular ) * pow( 1.0 - dot( lVector, spotHalfVector ), 5.0 );",
35797                         "spotSpecular += schlick * spotLightColor[ i ] * spotSpecularWeight * spotDiffuseWeight * lDistance * specularNormalization * spotEffect;",
35798
35799                     "#else",
35800
35801                         "spotSpecular += specular * spotLightColor[ i ] * spotSpecularWeight * spotDiffuseWeight * lDistance * spotEffect;",
35802
35803                     "#endif",
35804
35805                 "}",
35806
35807             "}",
35808
35809         "#endif",
35810
35811         "#if MAX_DIR_LIGHTS > 0",
35812
35813             "vec3 dirDiffuse  = vec3( 0.0 );",
35814             "vec3 dirSpecular = vec3( 0.0 );" ,
35815
35816             "for( int i = 0; i < MAX_DIR_LIGHTS; i ++ ) {",
35817
35818                 "vec4 lDirection = viewMatrix * vec4( directionalLightDirection[ i ], 0.0 );",
35819                 "vec3 dirVector = normalize( lDirection.xyz );",
35820
35821                 // diffuse
35822
35823                 "float dotProduct = dot( normal, dirVector );",
35824
35825                 "#ifdef WRAP_AROUND",
35826
35827                     "float dirDiffuseWeightFull = max( dotProduct, 0.0 );",
35828                     "float dirDiffuseWeightHalf = max( 0.5 * dotProduct + 0.5, 0.0 );",
35829
35830                     "vec3 dirDiffuseWeight = mix( vec3( dirDiffuseWeightFull ), vec3( dirDiffuseWeightHalf ), wrapRGB );",
35831
35832                 "#else",
35833
35834                     "float dirDiffuseWeight = max( dotProduct, 0.0 );",
35835
35836                 "#endif",
35837
35838                 "dirDiffuse  += diffuse * directionalLightColor[ i ] * dirDiffuseWeight;",
35839
35840                 // specular
35841
35842                 "vec3 dirHalfVector = normalize( dirVector + viewPosition );",
35843                 "float dirDotNormalHalf = max( dot( normal, dirHalfVector ), 0.0 );",
35844                 "float dirSpecularWeight = specularStrength * max( pow( dirDotNormalHalf, shininess ), 0.0 );",
35845
35846                 "#ifdef PHYSICALLY_BASED_SHADING",
35847
35848                     /*
35849                     // fresnel term from skin shader
35850                     "const float F0 = 0.128;",
35851
35852                     "float base = 1.0 - dot( viewPosition, dirHalfVector );",
35853                     "float exponential = pow( base, 5.0 );",
35854
35855                     "float fresnel = exponential + F0 * ( 1.0 - exponential );",
35856                     */
35857
35858                     /*
35859                     // fresnel term from fresnel shader
35860                     "const float mFresnelBias = 0.08;",
35861                     "const float mFresnelScale = 0.3;",
35862                     "const float mFresnelPower = 5.0;",
35863
35864                     "float fresnel = mFresnelBias + mFresnelScale * pow( 1.0 + dot( normalize( -viewPosition ), normal ), mFresnelPower );",
35865                     */
35866
35867                     // 2.0 => 2.0001 is hack to work around ANGLE bug
35868
35869                     "float specularNormalization = ( shininess + 2.0001 ) / 8.0;",
35870
35871                     //"dirSpecular += specular * directionalLightColor[ i ] * dirSpecularWeight * dirDiffuseWeight * specularNormalization * fresnel;",
35872
35873                     "vec3 schlick = specular + vec3( 1.0 - specular ) * pow( 1.0 - dot( dirVector, dirHalfVector ), 5.0 );",
35874                     "dirSpecular += schlick * directionalLightColor[ i ] * dirSpecularWeight * dirDiffuseWeight * specularNormalization;",
35875
35876                 "#else",
35877
35878                     "dirSpecular += specular * directionalLightColor[ i ] * dirSpecularWeight * dirDiffuseWeight;",
35879
35880                 "#endif",
35881
35882             "}",
35883
35884         "#endif",
35885
35886         "#if MAX_HEMI_LIGHTS > 0",
35887
35888             "vec3 hemiDiffuse  = vec3( 0.0 );",
35889             "vec3 hemiSpecular = vec3( 0.0 );" ,
35890
35891             "for( int i = 0; i < MAX_HEMI_LIGHTS; i ++ ) {",
35892
35893                 "vec4 lPosition = viewMatrix * vec4( hemisphereLightPosition[ i ], 1.0 );",
35894                 "vec3 lVector = normalize( lPosition.xyz + vViewPosition.xyz );",
35895
35896                 // diffuse
35897
35898                 "float dotProduct = dot( normal, lVector );",
35899                 "float hemiDiffuseWeight = 0.5 * dotProduct + 0.5;",
35900
35901                 "vec3 hemiColor = mix( hemisphereLightGroundColor[ i ], hemisphereLightSkyColor[ i ], hemiDiffuseWeight );",
35902
35903                 "hemiDiffuse += diffuse * hemiColor;",
35904
35905                 // specular (sky light)
35906
35907                 "vec3 hemiHalfVectorSky = normalize( lVector + viewPosition );",
35908                 "float hemiDotNormalHalfSky = 0.5 * dot( normal, hemiHalfVectorSky ) + 0.5;",
35909                 "float hemiSpecularWeightSky = specularStrength * max( pow( hemiDotNormalHalfSky, shininess ), 0.0 );",
35910
35911                 // specular (ground light)
35912
35913                 "vec3 lVectorGround = normalize( -lPosition.xyz + vViewPosition.xyz );",
35914
35915                 "vec3 hemiHalfVectorGround = normalize( lVectorGround + viewPosition );",
35916                 "float hemiDotNormalHalfGround = 0.5 * dot( normal, hemiHalfVectorGround ) + 0.5;",
35917                 "float hemiSpecularWeightGround = specularStrength * max( pow( hemiDotNormalHalfGround, shininess ), 0.0 );",
35918
35919                 "#ifdef PHYSICALLY_BASED_SHADING",
35920
35921                     "float dotProductGround = dot( normal, lVectorGround );",
35922
35923                     // 2.0 => 2.0001 is hack to work around ANGLE bug
35924
35925                     "float specularNormalization = ( shininess + 2.0001 ) / 8.0;",
35926
35927                     "vec3 schlickSky = specular + vec3( 1.0 - specular ) * pow( 1.0 - dot( lVector, hemiHalfVectorSky ), 5.0 );",
35928                     "vec3 schlickGround = specular + vec3( 1.0 - specular ) * pow( 1.0 - dot( lVectorGround, hemiHalfVectorGround ), 5.0 );",
35929                     "hemiSpecular += hemiColor * specularNormalization * ( schlickSky * hemiSpecularWeightSky * max( dotProduct, 0.0 ) + schlickGround * hemiSpecularWeightGround * max( dotProductGround, 0.0 ) );",
35930
35931                 "#else",
35932
35933                     "hemiSpecular += specular * hemiColor * ( hemiSpecularWeightSky + hemiSpecularWeightGround ) * hemiDiffuseWeight;",
35934
35935                 "#endif",
35936
35937             "}",
35938
35939         "#endif",
35940
35941         "vec3 totalDiffuse = vec3( 0.0 );",
35942         "vec3 totalSpecular = vec3( 0.0 );",
35943
35944         "#if MAX_DIR_LIGHTS > 0",
35945
35946             "totalDiffuse += dirDiffuse;",
35947             "totalSpecular += dirSpecular;",
35948
35949         "#endif",
35950
35951         "#if MAX_HEMI_LIGHTS > 0",
35952
35953             "totalDiffuse += hemiDiffuse;",
35954             "totalSpecular += hemiSpecular;",
35955
35956         "#endif",
35957
35958         "#if MAX_POINT_LIGHTS > 0",
35959
35960             "totalDiffuse += pointDiffuse;",
35961             "totalSpecular += pointSpecular;",
35962
35963         "#endif",
35964
35965         "#if MAX_SPOT_LIGHTS > 0",
35966
35967             "totalDiffuse += spotDiffuse;",
35968             "totalSpecular += spotSpecular;",
35969
35970         "#endif",
35971
35972         "#ifdef METAL",
35973
35974             "gl_FragColor.xyz = gl_FragColor.xyz * ( emissive + totalDiffuse + ambientLightColor * ambient + totalSpecular );",
35975
35976         "#else",
35977
35978             "gl_FragColor.xyz = gl_FragColor.xyz * ( emissive + totalDiffuse + ambientLightColor * ambient ) + totalSpecular;",
35979
35980         "#endif"
35981
35982     ].join("\n"),
35983
35984     // VERTEX COLORS
35985
35986     color_pars_fragment: [
35987
35988         "#ifdef USE_COLOR",
35989
35990             "varying vec3 vColor;",
35991
35992         "#endif"
35993
35994     ].join("\n"),
35995
35996
35997     color_fragment: [
35998
35999         "#ifdef USE_COLOR",
36000
36001             "gl_FragColor = gl_FragColor * vec4( vColor, opacity );",
36002
36003         "#endif"
36004
36005     ].join("\n"),
36006
36007     color_pars_vertex: [
36008
36009         "#ifdef USE_COLOR",
36010
36011             "varying vec3 vColor;",
36012
36013         "#endif"
36014
36015     ].join("\n"),
36016
36017
36018     color_vertex: [
36019
36020         "#ifdef USE_COLOR",
36021
36022             "#ifdef GAMMA_INPUT",
36023
36024                 "vColor = color * color;",
36025
36026             "#else",
36027
36028                 "vColor = color;",
36029
36030             "#endif",
36031
36032         "#endif"
36033
36034     ].join("\n"),
36035
36036     // SKINNING
36037
36038     skinning_pars_vertex: [
36039
36040         "#ifdef USE_SKINNING",
36041
36042             "#ifdef BONE_TEXTURE",
36043
36044                 "uniform sampler2D boneTexture;",
36045
36046                 "mat4 getBoneMatrix( const in float i ) {",
36047
36048                     "float j = i * 4.0;",
36049                     "float x = mod( j, N_BONE_PIXEL_X );",
36050                     "float y = floor( j / N_BONE_PIXEL_X );",
36051
36052                     "const float dx = 1.0 / N_BONE_PIXEL_X;",
36053                     "const float dy = 1.0 / N_BONE_PIXEL_Y;",
36054
36055                     "y = dy * ( y + 0.5 );",
36056
36057                     "vec4 v1 = texture2D( boneTexture, vec2( dx * ( x + 0.5 ), y ) );",
36058                     "vec4 v2 = texture2D( boneTexture, vec2( dx * ( x + 1.5 ), y ) );",
36059                     "vec4 v3 = texture2D( boneTexture, vec2( dx * ( x + 2.5 ), y ) );",
36060                     "vec4 v4 = texture2D( boneTexture, vec2( dx * ( x + 3.5 ), y ) );",
36061
36062                     "mat4 bone = mat4( v1, v2, v3, v4 );",
36063
36064                     "return bone;",
36065
36066                 "}",
36067
36068             "#else",
36069
36070                 "uniform mat4 boneGlobalMatrices[ MAX_BONES ];",
36071
36072                 "mat4 getBoneMatrix( const in float i ) {",
36073
36074                     "mat4 bone = boneGlobalMatrices[ int(i) ];",
36075                     "return bone;",
36076
36077                 "}",
36078
36079             "#endif",
36080
36081         "#endif"
36082
36083     ].join("\n"),
36084
36085     skinbase_vertex: [
36086
36087         "#ifdef USE_SKINNING",
36088
36089             "mat4 boneMatX = getBoneMatrix( skinIndex.x );",
36090             "mat4 boneMatY = getBoneMatrix( skinIndex.y );",
36091
36092         "#endif"
36093
36094     ].join("\n"),
36095
36096     skinning_vertex: [
36097
36098         "#ifdef USE_SKINNING",
36099
36100             "#ifdef USE_MORPHTARGETS",
36101
36102             "vec4 skinVertex = vec4( morphed, 1.0 );",
36103
36104             "#else",
36105
36106             "vec4 skinVertex = vec4( position, 1.0 );",
36107
36108             "#endif",
36109
36110             "vec4 skinned  = boneMatX * skinVertex * skinWeight.x;",
36111             "skinned       += boneMatY * skinVertex * skinWeight.y;",
36112
36113         "#endif"
36114
36115     ].join("\n"),
36116
36117     // MORPHING
36118
36119     morphtarget_pars_vertex: [
36120
36121         "#ifdef USE_MORPHTARGETS",
36122
36123             "#ifndef USE_MORPHNORMALS",
36124
36125             "uniform float morphTargetInfluences[ 8 ];",
36126
36127             "#else",
36128
36129             "uniform float morphTargetInfluences[ 4 ];",
36130
36131             "#endif",
36132
36133         "#endif"
36134
36135     ].join("\n"),
36136
36137     morphtarget_vertex: [
36138
36139         "#ifdef USE_MORPHTARGETS",
36140
36141             "vec3 morphed = vec3( 0.0 );",
36142             "morphed += ( morphTarget0 - position ) * morphTargetInfluences[ 0 ];",
36143             "morphed += ( morphTarget1 - position ) * morphTargetInfluences[ 1 ];",
36144             "morphed += ( morphTarget2 - position ) * morphTargetInfluences[ 2 ];",
36145             "morphed += ( morphTarget3 - position ) * morphTargetInfluences[ 3 ];",
36146
36147             "#ifndef USE_MORPHNORMALS",
36148
36149             "morphed += ( morphTarget4 - position ) * morphTargetInfluences[ 4 ];",
36150             "morphed += ( morphTarget5 - position ) * morphTargetInfluences[ 5 ];",
36151             "morphed += ( morphTarget6 - position ) * morphTargetInfluences[ 6 ];",
36152             "morphed += ( morphTarget7 - position ) * morphTargetInfluences[ 7 ];",
36153
36154             "#endif",
36155
36156             "morphed += position;",
36157
36158         "#endif"
36159
36160     ].join("\n"),
36161
36162     default_vertex : [
36163
36164         "vec4 mvPosition;",
36165
36166         "#ifdef USE_SKINNING",
36167
36168             "mvPosition = modelViewMatrix * skinned;",
36169
36170         "#endif",
36171
36172         "#if !defined( USE_SKINNING ) && defined( USE_MORPHTARGETS )",
36173
36174             "mvPosition = modelViewMatrix * vec4( morphed, 1.0 );",
36175
36176         "#endif",
36177
36178         "#if !defined( USE_SKINNING ) && ! defined( USE_MORPHTARGETS )",
36179
36180             "mvPosition = modelViewMatrix * vec4( position, 1.0 );",
36181
36182         "#endif",
36183
36184         "gl_Position = projectionMatrix * mvPosition;",
36185
36186     ].join("\n"),
36187
36188     morphnormal_vertex: [
36189
36190         "#ifdef USE_MORPHNORMALS",
36191
36192             "vec3 morphedNormal = vec3( 0.0 );",
36193
36194             "morphedNormal +=  ( morphNormal0 - normal ) * morphTargetInfluences[ 0 ];",
36195             "morphedNormal +=  ( morphNormal1 - normal ) * morphTargetInfluences[ 1 ];",
36196             "morphedNormal +=  ( morphNormal2 - normal ) * morphTargetInfluences[ 2 ];",
36197             "morphedNormal +=  ( morphNormal3 - normal ) * morphTargetInfluences[ 3 ];",
36198
36199             "morphedNormal += normal;",
36200
36201         "#endif"
36202
36203     ].join("\n"),
36204
36205     skinnormal_vertex: [
36206
36207         "#ifdef USE_SKINNING",
36208
36209             "mat4 skinMatrix = skinWeight.x * boneMatX;",
36210             "skinMatrix     += skinWeight.y * boneMatY;",
36211
36212             "#ifdef USE_MORPHNORMALS",
36213
36214             "vec4 skinnedNormal = skinMatrix * vec4( morphedNormal, 0.0 );",
36215
36216             "#else",
36217
36218             "vec4 skinnedNormal = skinMatrix * vec4( normal, 0.0 );",
36219
36220             "#endif",
36221
36222         "#endif"
36223
36224     ].join("\n"),
36225
36226     defaultnormal_vertex: [
36227
36228         "vec3 objectNormal;",
36229
36230         "#ifdef USE_SKINNING",
36231
36232             "objectNormal = skinnedNormal.xyz;",
36233
36234         "#endif",
36235
36236         "#if !defined( USE_SKINNING ) && defined( USE_MORPHNORMALS )",
36237
36238             "objectNormal = morphedNormal;",
36239
36240         "#endif",
36241
36242         "#if !defined( USE_SKINNING ) && ! defined( USE_MORPHNORMALS )",
36243
36244             "objectNormal = normal;",
36245
36246         "#endif",
36247
36248         "#ifdef FLIP_SIDED",
36249
36250             "objectNormal = -objectNormal;",
36251
36252         "#endif",
36253
36254         "vec3 transformedNormal = normalMatrix * objectNormal;",
36255
36256     ].join("\n"),
36257
36258     // SHADOW MAP
36259
36260     // based on SpiderGL shadow map and Fabien Sanglard's GLSL shadow mapping examples
36261     //  http://spidergl.org/example.php?id=6
36262     //     http://fabiensanglard.net/shadowmapping
36263
36264     shadowmap_pars_fragment: [
36265
36266         "#ifdef USE_SHADOWMAP",
36267
36268             "uniform sampler2D shadowMap[ MAX_SHADOWS ];",
36269             "uniform vec2 shadowMapSize[ MAX_SHADOWS ];",
36270
36271             "uniform float shadowDarkness[ MAX_SHADOWS ];",
36272             "uniform float shadowBias[ MAX_SHADOWS ];",
36273
36274             "varying vec4 vShadowCoord[ MAX_SHADOWS ];",
36275
36276             "float unpackDepth( const in vec4 rgba_depth ) {",
36277
36278                 "const vec4 bit_shift = vec4( 1.0 / ( 256.0 * 256.0 * 256.0 ), 1.0 / ( 256.0 * 256.0 ), 1.0 / 256.0, 1.0 );",
36279                 "float depth = dot( rgba_depth, bit_shift );",
36280                 "return depth;",
36281
36282             "}",
36283
36284         "#endif"
36285
36286     ].join("\n"),
36287
36288     shadowmap_fragment: [
36289
36290         "#ifdef USE_SHADOWMAP",
36291
36292             "#ifdef SHADOWMAP_DEBUG",
36293
36294                 "vec3 frustumColors[3];",
36295                 "frustumColors[0] = vec3( 1.0, 0.5, 0.0 );",
36296                 "frustumColors[1] = vec3( 0.0, 1.0, 0.8 );",
36297                 "frustumColors[2] = vec3( 0.0, 0.5, 1.0 );",
36298
36299             "#endif",
36300
36301             "#ifdef SHADOWMAP_CASCADE",
36302
36303                 "int inFrustumCount = 0;",
36304
36305             "#endif",
36306
36307             "float fDepth;",
36308             "vec3 shadowColor = vec3( 1.0 );",
36309
36310             "for( int i = 0; i < MAX_SHADOWS; i ++ ) {",
36311
36312                 "vec3 shadowCoord = vShadowCoord[ i ].xyz / vShadowCoord[ i ].w;",
36313
36314                 // "if ( something && something )"          breaks ATI OpenGL shader compiler
36315                 // "if ( all( something, something ) )"  using this instead
36316
36317                 "bvec4 inFrustumVec = bvec4 ( shadowCoord.x >= 0.0, shadowCoord.x <= 1.0, shadowCoord.y >= 0.0, shadowCoord.y <= 1.0 );",
36318                 "bool inFrustum = all( inFrustumVec );",
36319
36320                 // don't shadow pixels outside of light frustum
36321                 // use just first frustum (for cascades)
36322                 // don't shadow pixels behind far plane of light frustum
36323
36324                 "#ifdef SHADOWMAP_CASCADE",
36325
36326                     "inFrustumCount += int( inFrustum );",
36327                     "bvec3 frustumTestVec = bvec3( inFrustum, inFrustumCount == 1, shadowCoord.z <= 1.0 );",
36328
36329                 "#else",
36330
36331                     "bvec2 frustumTestVec = bvec2( inFrustum, shadowCoord.z <= 1.0 );",
36332
36333                 "#endif",
36334
36335                 "bool frustumTest = all( frustumTestVec );",
36336
36337                 "if ( frustumTest ) {",
36338
36339                     "shadowCoord.z += shadowBias[ i ];",
36340
36341                     "#ifdef SHADOWMAP_SOFT",
36342
36343                         // Percentage-close filtering
36344                         // (9 pixel kernel)
36345                         // http://fabiensanglard.net/shadowmappingPCF/
36346
36347                         "float shadow = 0.0;",
36348
36349                         /*
36350                         // nested loops breaks shader compiler / validator on some ATI cards when using OpenGL
36351                         // must enroll loop manually
36352
36353                         "for ( float y = -1.25; y <= 1.25; y += 1.25 )",
36354                             "for ( float x = -1.25; x <= 1.25; x += 1.25 ) {",
36355
36356                                 "vec4 rgbaDepth = texture2D( shadowMap[ i ], vec2( x * xPixelOffset, y * yPixelOffset ) + shadowCoord.xy );",
36357
36358                                 // doesn't seem to produce any noticeable visual difference compared to simple "texture2D" lookup
36359                                 //"vec4 rgbaDepth = texture2DProj( shadowMap[ i ], vec4( vShadowCoord[ i ].w * ( vec2( x * xPixelOffset, y * yPixelOffset ) + shadowCoord.xy ), 0.05, vShadowCoord[ i ].w ) );",
36360
36361                                 "float fDepth = unpackDepth( rgbaDepth );",
36362
36363                                 "if ( fDepth < shadowCoord.z )",
36364                                     "shadow += 1.0;",
36365
36366                         "}",
36367
36368                         "shadow /= 9.0;",
36369
36370                         */
36371
36372                         "const float shadowDelta = 1.0 / 9.0;",
36373
36374                         "float xPixelOffset = 1.0 / shadowMapSize[ i ].x;",
36375                         "float yPixelOffset = 1.0 / shadowMapSize[ i ].y;",
36376
36377                         "float dx0 = -1.25 * xPixelOffset;",
36378                         "float dy0 = -1.25 * yPixelOffset;",
36379                         "float dx1 = 1.25 * xPixelOffset;",
36380                         "float dy1 = 1.25 * yPixelOffset;",
36381
36382                         "fDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx0, dy0 ) ) );",
36383                         "if ( fDepth < shadowCoord.z ) shadow += shadowDelta;",
36384
36385                         "fDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( 0.0, dy0 ) ) );",
36386                         "if ( fDepth < shadowCoord.z ) shadow += shadowDelta;",
36387
36388                         "fDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx1, dy0 ) ) );",
36389                         "if ( fDepth < shadowCoord.z ) shadow += shadowDelta;",
36390
36391                         "fDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx0, 0.0 ) ) );",
36392                         "if ( fDepth < shadowCoord.z ) shadow += shadowDelta;",
36393
36394                         "fDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy ) );",
36395                         "if ( fDepth < shadowCoord.z ) shadow += shadowDelta;",
36396
36397                         "fDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx1, 0.0 ) ) );",
36398                         "if ( fDepth < shadowCoord.z ) shadow += shadowDelta;",
36399
36400                         "fDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx0, dy1 ) ) );",
36401                         "if ( fDepth < shadowCoord.z ) shadow += shadowDelta;",
36402
36403                         "fDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( 0.0, dy1 ) ) );",
36404                         "if ( fDepth < shadowCoord.z ) shadow += shadowDelta;",
36405
36406                         "fDepth = unpackDepth( texture2D( shadowMap[ i ], shadowCoord.xy + vec2( dx1, dy1 ) ) );",
36407                         "if ( fDepth < shadowCoord.z ) shadow += shadowDelta;",
36408
36409                         "shadowColor = shadowColor * vec3( ( 1.0 - shadowDarkness[ i ] * shadow ) );",
36410
36411                     "#else",
36412
36413                         "vec4 rgbaDepth = texture2D( shadowMap[ i ], shadowCoord.xy );",
36414                         "float fDepth = unpackDepth( rgbaDepth );",
36415
36416                         "if ( fDepth < shadowCoord.z )",
36417
36418                             // spot with multiple shadows is darker
36419
36420                             "shadowColor = shadowColor * vec3( 1.0 - shadowDarkness[ i ] );",
36421
36422                             // spot with multiple shadows has the same color as single shadow spot
36423
36424                             //"shadowColor = min( shadowColor, vec3( shadowDarkness[ i ] ) );",
36425
36426                     "#endif",
36427
36428                 "}",
36429
36430
36431                 "#ifdef SHADOWMAP_DEBUG",
36432
36433                     "#ifdef SHADOWMAP_CASCADE",
36434
36435                         "if ( inFrustum && inFrustumCount == 1 ) gl_FragColor.xyz *= frustumColors[ i ];",
36436
36437                     "#else",
36438
36439                         "if ( inFrustum ) gl_FragColor.xyz *= frustumColors[ i ];",
36440
36441                     "#endif",
36442
36443                 "#endif",
36444
36445             "}",
36446
36447             "#ifdef GAMMA_OUTPUT",
36448
36449                 "shadowColor *= shadowColor;",
36450
36451             "#endif",
36452
36453             "gl_FragColor.xyz = gl_FragColor.xyz * shadowColor;",
36454
36455         "#endif"
36456
36457     ].join("\n"),
36458
36459     shadowmap_pars_vertex: [
36460
36461         "#ifdef USE_SHADOWMAP",
36462
36463             "varying vec4 vShadowCoord[ MAX_SHADOWS ];",
36464             "uniform mat4 shadowMatrix[ MAX_SHADOWS ];",
36465
36466         "#endif"
36467
36468     ].join("\n"),
36469
36470     shadowmap_vertex: [
36471
36472         "#ifdef USE_SHADOWMAP",
36473
36474             "for( int i = 0; i < MAX_SHADOWS; i ++ ) {",
36475
36476                 "vShadowCoord[ i ] = shadowMatrix[ i ] * mPosition;",
36477
36478             "}",
36479
36480         "#endif"
36481
36482     ].join("\n"),
36483
36484     // ALPHATEST
36485
36486     alphatest_fragment: [
36487
36488         "#ifdef ALPHATEST",
36489
36490             "if ( gl_FragColor.a < ALPHATEST ) discard;",
36491
36492         "#endif"
36493
36494     ].join("\n"),
36495
36496     // LINEAR SPACE
36497
36498     linear_to_gamma_fragment: [
36499
36500         "#ifdef GAMMA_OUTPUT",
36501
36502             "gl_FragColor.xyz = sqrt( gl_FragColor.xyz );",
36503
36504         "#endif"
36505
36506     ].join("\n"),
36507
36508
36509 };
36510
36511 THREE.UniformsUtils = {
36512
36513     merge: function ( uniforms ) {
36514
36515         var u, p, tmp, merged = {};
36516
36517         for ( u = 0; u < uniforms.length; u ++ ) {
36518
36519             tmp = this.clone( uniforms[ u ] );
36520
36521             for ( p in tmp ) {
36522
36523                 merged[ p ] = tmp[ p ];
36524
36525             }
36526
36527         }
36528
36529         return merged;
36530
36531     },
36532
36533     clone: function ( uniforms_src ) {
36534
36535         var u, p, parameter, parameter_src, uniforms_dst = {};
36536
36537         for ( u in uniforms_src ) {
36538
36539             uniforms_dst[ u ] = {};
36540
36541             for ( p in uniforms_src[ u ] ) {
36542
36543                 parameter_src = uniforms_src[ u ][ p ];
36544
36545                 if ( parameter_src instanceof THREE.Color ||
36546                      parameter_src instanceof THREE.Vector2 ||
36547                      parameter_src instanceof THREE.Vector3 ||
36548                      parameter_src instanceof THREE.Vector4 ||
36549                      parameter_src instanceof THREE.Matrix4 ||
36550                      parameter_src instanceof THREE.Texture ) {
36551
36552                     uniforms_dst[ u ][ p ] = parameter_src.clone();
36553
36554                 } else if ( parameter_src instanceof Array ) {
36555
36556                     uniforms_dst[ u ][ p ] = parameter_src.slice();
36557
36558                 } else {
36559
36560                     uniforms_dst[ u ][ p ] = parameter_src;
36561
36562                 }
36563
36564             }
36565
36566         }
36567
36568         return uniforms_dst;
36569
36570     }
36571
36572 };
36573
36574 THREE.UniformsLib = {
36575
36576     common: {
36577
36578         "diffuse" : { type: "c", value: new THREE.Color( 0xeeeeee ) },
36579         "opacity" : { type: "f", value: 1.0 },
36580
36581         "map" : { type: "t", value: null },
36582         "offsetRepeat" : { type: "v4", value: new THREE.Vector4( 0, 0, 1, 1 ) },
36583
36584         "lightMap" : { type: "t", value: null },
36585         "specularMap" : { type: "t", value: null },
36586
36587         "envMap" : { type: "t", value: null },
36588         "flipEnvMap" : { type: "f", value: -1 },
36589         "useRefract" : { type: "i", value: 0 },
36590         "reflectivity" : { type: "f", value: 1.0 },
36591         "refractionRatio" : { type: "f", value: 0.98 },
36592         "combine" : { type: "i", value: 0 },
36593
36594         "morphTargetInfluences" : { type: "f", value: 0 }
36595
36596     },
36597
36598     bump: {
36599
36600         "bumpMap" : { type: "t", value: null },
36601         "bumpScale" : { type: "f", value: 1 }
36602
36603     },
36604
36605     normalmap: {
36606
36607         "normalMap" : { type: "t", value: null },
36608         "normalScale" : { type: "v2", value: new THREE.Vector2( 1, 1 ) }
36609     },
36610
36611     fog : {
36612
36613         "fogDensity" : { type: "f", value: 0.00025 },
36614         "fogNear" : { type: "f", value: 1 },
36615         "fogFar" : { type: "f", value: 2000 },
36616         "fogColor" : { type: "c", value: new THREE.Color( 0xffffff ) }
36617
36618     },
36619
36620     lights: {
36621
36622         "ambientLightColor" : { type: "fv", value: [] },
36623
36624         "directionalLightDirection" : { type: "fv", value: [] },
36625         "directionalLightColor" : { type: "fv", value: [] },
36626
36627         "hemisphereLightPosition" : { type: "fv", value: [] },
36628         "hemisphereLightSkyColor" : { type: "fv", value: [] },
36629         "hemisphereLightGroundColor" : { type: "fv", value: [] },
36630
36631         "pointLightColor" : { type: "fv", value: [] },
36632         "pointLightPosition" : { type: "fv", value: [] },
36633         "pointLightDistance" : { type: "fv1", value: [] },
36634
36635         "spotLightColor" : { type: "fv", value: [] },
36636         "spotLightPosition" : { type: "fv", value: [] },
36637         "spotLightDirection" : { type: "fv", value: [] },
36638         "spotLightDistance" : { type: "fv1", value: [] },
36639         "spotLightAngle" : { type: "fv1", value: [] },
36640         "spotLightExponent" : { type: "fv1", value: [] }
36641
36642     },
36643
36644     particle: {
36645
36646         "psColor" : { type: "c", value: new THREE.Color( 0xeeeeee ) },
36647         "opacity" : { type: "f", value: 1.0 },
36648         "size" : { type: "f", value: 1.0 },
36649         "scale" : { type: "f", value: 1.0 },
36650         "map" : { type: "t", value: null },
36651
36652         "fogDensity" : { type: "f", value: 0.00025 },
36653         "fogNear" : { type: "f", value: 1 },
36654         "fogFar" : { type: "f", value: 2000 },
36655         "fogColor" : { type: "c", value: new THREE.Color( 0xffffff ) }
36656
36657     },
36658
36659     shadowmap: {
36660
36661         "shadowMap": { type: "tv", value: [] },
36662         "shadowMapSize": { type: "v2v", value: [] },
36663
36664         "shadowBias" : { type: "fv1", value: [] },
36665         "shadowDarkness": { type: "fv1", value: [] },
36666
36667         "shadowMatrix" : { type: "m4v", value: [] },
36668
36669     }
36670
36671 };
36672
36673 THREE.ShaderLib = {
36674
36675     'depth': {
36676
36677         uniforms: {
36678
36679             "mNear": { type: "f", value: 1.0 },
36680             "mFar" : { type: "f", value: 2000.0 },
36681             "opacity" : { type: "f", value: 1.0 }
36682
36683         },
36684
36685         vertexShader: [
36686
36687             "void main() {",
36688
36689                 "gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );",
36690
36691             "}"
36692
36693         ].join("\n"),
36694
36695         fragmentShader: [
36696
36697             "uniform float mNear;",
36698             "uniform float mFar;",
36699             "uniform float opacity;",
36700
36701             "void main() {",
36702
36703                 "float depth = gl_FragCoord.z / gl_FragCoord.w;",
36704                 "float color = 1.0 - smoothstep( mNear, mFar, depth );",
36705                 "gl_FragColor = vec4( vec3( color ), opacity );",
36706
36707             "}"
36708
36709         ].join("\n")
36710
36711     },
36712
36713     'normal': {
36714
36715         uniforms: {
36716
36717             "opacity" : { type: "f", value: 1.0 }
36718
36719         },
36720
36721         vertexShader: [
36722
36723             "varying vec3 vNormal;",
36724
36725             "void main() {",
36726
36727                 "vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );",
36728                 "vNormal = normalMatrix * normal;",
36729
36730                 "gl_Position = projectionMatrix * mvPosition;",
36731
36732             "}"
36733
36734         ].join("\n"),
36735
36736         fragmentShader: [
36737
36738             "uniform float opacity;",
36739             "varying vec3 vNormal;",
36740
36741             "void main() {",
36742
36743                 "gl_FragColor = vec4( 0.5 * normalize( vNormal ) + 0.5, opacity );",
36744
36745             "}"
36746
36747         ].join("\n")
36748
36749     },
36750
36751     'basic': {
36752
36753         uniforms: THREE.UniformsUtils.merge( [
36754
36755             THREE.UniformsLib[ "common" ],
36756             THREE.UniformsLib[ "fog" ],
36757             THREE.UniformsLib[ "shadowmap" ]
36758
36759         ] ),
36760
36761         vertexShader: [
36762
36763             THREE.ShaderChunk[ "map_pars_vertex" ],
36764             THREE.ShaderChunk[ "lightmap_pars_vertex" ],
36765             THREE.ShaderChunk[ "envmap_pars_vertex" ],
36766             THREE.ShaderChunk[ "color_pars_vertex" ],
36767             THREE.ShaderChunk[ "morphtarget_pars_vertex" ],
36768             THREE.ShaderChunk[ "skinning_pars_vertex" ],
36769             THREE.ShaderChunk[ "shadowmap_pars_vertex" ],
36770
36771             "void main() {",
36772
36773                 THREE.ShaderChunk[ "map_vertex" ],
36774                 THREE.ShaderChunk[ "lightmap_vertex" ],
36775                 THREE.ShaderChunk[ "color_vertex" ],
36776
36777                 "#ifdef USE_ENVMAP",
36778
36779                 THREE.ShaderChunk[ "morphnormal_vertex" ],
36780                 THREE.ShaderChunk[ "skinbase_vertex" ],
36781                 THREE.ShaderChunk[ "skinnormal_vertex" ],
36782                 THREE.ShaderChunk[ "defaultnormal_vertex" ],
36783
36784                 "#endif",
36785
36786                 THREE.ShaderChunk[ "morphtarget_vertex" ],
36787                 THREE.ShaderChunk[ "skinning_vertex" ],
36788                 THREE.ShaderChunk[ "default_vertex" ],
36789
36790                 THREE.ShaderChunk[ "worldpos_vertex" ],
36791                 THREE.ShaderChunk[ "envmap_vertex" ],
36792                 THREE.ShaderChunk[ "shadowmap_vertex" ],
36793
36794             "}"
36795
36796         ].join("\n"),
36797
36798         fragmentShader: [
36799
36800             "uniform vec3 diffuse;",
36801             "uniform float opacity;",
36802
36803             THREE.ShaderChunk[ "color_pars_fragment" ],
36804             THREE.ShaderChunk[ "map_pars_fragment" ],
36805             THREE.ShaderChunk[ "lightmap_pars_fragment" ],
36806             THREE.ShaderChunk[ "envmap_pars_fragment" ],
36807             THREE.ShaderChunk[ "fog_pars_fragment" ],
36808             THREE.ShaderChunk[ "shadowmap_pars_fragment" ],
36809             THREE.ShaderChunk[ "specularmap_pars_fragment" ],
36810
36811             "void main() {",
36812
36813                 "gl_FragColor = vec4( diffuse, opacity );",
36814
36815                 THREE.ShaderChunk[ "map_fragment" ],
36816                 THREE.ShaderChunk[ "alphatest_fragment" ],
36817                 THREE.ShaderChunk[ "specularmap_fragment" ],
36818                 THREE.ShaderChunk[ "lightmap_fragment" ],
36819                 THREE.ShaderChunk[ "color_fragment" ],
36820                 THREE.ShaderChunk[ "envmap_fragment" ],
36821                 THREE.ShaderChunk[ "shadowmap_fragment" ],
36822
36823                 THREE.ShaderChunk[ "linear_to_gamma_fragment" ],
36824
36825                 THREE.ShaderChunk[ "fog_fragment" ],
36826
36827             "}"
36828
36829         ].join("\n")
36830
36831     },
36832
36833     'lambert': {
36834
36835         uniforms: THREE.UniformsUtils.merge( [
36836
36837             THREE.UniformsLib[ "common" ],
36838             THREE.UniformsLib[ "fog" ],
36839             THREE.UniformsLib[ "lights" ],
36840             THREE.UniformsLib[ "shadowmap" ],
36841
36842             {
36843                 "ambient"  : { type: "c", value: new THREE.Color( 0xffffff ) },
36844                 "emissive" : { type: "c", value: new THREE.Color( 0x000000 ) },
36845                 "wrapRGB"  : { type: "v3", value: new THREE.Vector3( 1, 1, 1 ) }
36846             }
36847
36848         ] ),
36849
36850         vertexShader: [
36851
36852             "#define LAMBERT",
36853
36854             "varying vec3 vLightFront;",
36855
36856             "#ifdef DOUBLE_SIDED",
36857
36858                 "varying vec3 vLightBack;",
36859
36860             "#endif",
36861
36862             THREE.ShaderChunk[ "map_pars_vertex" ],
36863             THREE.ShaderChunk[ "lightmap_pars_vertex" ],
36864             THREE.ShaderChunk[ "envmap_pars_vertex" ],
36865             THREE.ShaderChunk[ "lights_lambert_pars_vertex" ],
36866             THREE.ShaderChunk[ "color_pars_vertex" ],
36867             THREE.ShaderChunk[ "morphtarget_pars_vertex" ],
36868             THREE.ShaderChunk[ "skinning_pars_vertex" ],
36869             THREE.ShaderChunk[ "shadowmap_pars_vertex" ],
36870
36871             "void main() {",
36872
36873                 THREE.ShaderChunk[ "map_vertex" ],
36874                 THREE.ShaderChunk[ "lightmap_vertex" ],
36875                 THREE.ShaderChunk[ "color_vertex" ],
36876
36877                 THREE.ShaderChunk[ "morphnormal_vertex" ],
36878                 THREE.ShaderChunk[ "skinbase_vertex" ],
36879                 THREE.ShaderChunk[ "skinnormal_vertex" ],
36880                 THREE.ShaderChunk[ "defaultnormal_vertex" ],
36881
36882                 THREE.ShaderChunk[ "morphtarget_vertex" ],
36883                 THREE.ShaderChunk[ "skinning_vertex" ],
36884                 THREE.ShaderChunk[ "default_vertex" ],
36885
36886                 THREE.ShaderChunk[ "worldpos_vertex" ],
36887                 THREE.ShaderChunk[ "envmap_vertex" ],
36888                 THREE.ShaderChunk[ "lights_lambert_vertex" ],
36889                 THREE.ShaderChunk[ "shadowmap_vertex" ],
36890
36891             "}"
36892
36893         ].join("\n"),
36894
36895         fragmentShader: [
36896
36897             "uniform float opacity;",
36898
36899             "varying vec3 vLightFront;",
36900
36901             "#ifdef DOUBLE_SIDED",
36902
36903                 "varying vec3 vLightBack;",
36904
36905             "#endif",
36906
36907             THREE.ShaderChunk[ "color_pars_fragment" ],
36908             THREE.ShaderChunk[ "map_pars_fragment" ],
36909             THREE.ShaderChunk[ "lightmap_pars_fragment" ],
36910             THREE.ShaderChunk[ "envmap_pars_fragment" ],
36911             THREE.ShaderChunk[ "fog_pars_fragment" ],
36912             THREE.ShaderChunk[ "shadowmap_pars_fragment" ],
36913             THREE.ShaderChunk[ "specularmap_pars_fragment" ],
36914
36915             "void main() {",
36916
36917                 "gl_FragColor = vec4( vec3 ( 1.0 ), opacity );",
36918
36919                 THREE.ShaderChunk[ "map_fragment" ],
36920                 THREE.ShaderChunk[ "alphatest_fragment" ],
36921                 THREE.ShaderChunk[ "specularmap_fragment" ],
36922
36923                 "#ifdef DOUBLE_SIDED",
36924
36925                     //"float isFront = float( gl_FrontFacing );",
36926                     //"gl_FragColor.xyz *= isFront * vLightFront + ( 1.0 - isFront ) * vLightBack;",
36927
36928                     "if ( gl_FrontFacing )",
36929                         "gl_FragColor.xyz *= vLightFront;",
36930                     "else",
36931                         "gl_FragColor.xyz *= vLightBack;",
36932
36933                 "#else",
36934
36935                     "gl_FragColor.xyz *= vLightFront;",
36936
36937                 "#endif",
36938
36939                 THREE.ShaderChunk[ "lightmap_fragment" ],
36940                 THREE.ShaderChunk[ "color_fragment" ],
36941                 THREE.ShaderChunk[ "envmap_fragment" ],
36942                 THREE.ShaderChunk[ "shadowmap_fragment" ],
36943
36944                 THREE.ShaderChunk[ "linear_to_gamma_fragment" ],
36945
36946                 THREE.ShaderChunk[ "fog_fragment" ],
36947
36948             "}"
36949
36950         ].join("\n")
36951
36952     },
36953
36954     'phong': {
36955
36956         uniforms: THREE.UniformsUtils.merge( [
36957
36958             THREE.UniformsLib[ "common" ],
36959             THREE.UniformsLib[ "bump" ],
36960             THREE.UniformsLib[ "normalmap" ],
36961             THREE.UniformsLib[ "fog" ],
36962             THREE.UniformsLib[ "lights" ],
36963             THREE.UniformsLib[ "shadowmap" ],
36964
36965             {
36966                 "ambient"  : { type: "c", value: new THREE.Color( 0xffffff ) },
36967                 "emissive" : { type: "c", value: new THREE.Color( 0x000000 ) },
36968                 "specular" : { type: "c", value: new THREE.Color( 0x111111 ) },
36969                 "shininess": { type: "f", value: 30 },
36970                 "wrapRGB"  : { type: "v3", value: new THREE.Vector3( 1, 1, 1 ) }
36971             }
36972
36973         ] ),
36974
36975         vertexShader: [
36976
36977             "#define PHONG",
36978
36979             "varying vec3 vViewPosition;",
36980             "varying vec3 vNormal;",
36981
36982             THREE.ShaderChunk[ "map_pars_vertex" ],
36983             THREE.ShaderChunk[ "lightmap_pars_vertex" ],
36984             THREE.ShaderChunk[ "envmap_pars_vertex" ],
36985             THREE.ShaderChunk[ "lights_phong_pars_vertex" ],
36986             THREE.ShaderChunk[ "color_pars_vertex" ],
36987             THREE.ShaderChunk[ "morphtarget_pars_vertex" ],
36988             THREE.ShaderChunk[ "skinning_pars_vertex" ],
36989             THREE.ShaderChunk[ "shadowmap_pars_vertex" ],
36990
36991             "void main() {",
36992
36993                 THREE.ShaderChunk[ "map_vertex" ],
36994                 THREE.ShaderChunk[ "lightmap_vertex" ],
36995                 THREE.ShaderChunk[ "color_vertex" ],
36996
36997                 THREE.ShaderChunk[ "morphnormal_vertex" ],
36998                 THREE.ShaderChunk[ "skinbase_vertex" ],
36999                 THREE.ShaderChunk[ "skinnormal_vertex" ],
37000                 THREE.ShaderChunk[ "defaultnormal_vertex" ],
37001
37002                 "vNormal = transformedNormal;",
37003
37004                 THREE.ShaderChunk[ "morphtarget_vertex" ],
37005                 THREE.ShaderChunk[ "skinning_vertex" ],
37006                 THREE.ShaderChunk[ "default_vertex" ],
37007
37008                 "vViewPosition = -mvPosition.xyz;",
37009
37010                 THREE.ShaderChunk[ "worldpos_vertex" ],
37011                 THREE.ShaderChunk[ "envmap_vertex" ],
37012                 THREE.ShaderChunk[ "lights_phong_vertex" ],
37013                 THREE.ShaderChunk[ "shadowmap_vertex" ],
37014
37015             "}"
37016
37017         ].join("\n"),
37018
37019         fragmentShader: [
37020
37021             "uniform vec3 diffuse;",
37022             "uniform float opacity;",
37023
37024             "uniform vec3 ambient;",
37025             "uniform vec3 emissive;",
37026             "uniform vec3 specular;",
37027             "uniform float shininess;",
37028
37029             THREE.ShaderChunk[ "color_pars_fragment" ],
37030             THREE.ShaderChunk[ "map_pars_fragment" ],
37031             THREE.ShaderChunk[ "lightmap_pars_fragment" ],
37032             THREE.ShaderChunk[ "envmap_pars_fragment" ],
37033             THREE.ShaderChunk[ "fog_pars_fragment" ],
37034             THREE.ShaderChunk[ "lights_phong_pars_fragment" ],
37035             THREE.ShaderChunk[ "shadowmap_pars_fragment" ],
37036             THREE.ShaderChunk[ "bumpmap_pars_fragment" ],
37037             THREE.ShaderChunk[ "normalmap_pars_fragment" ],
37038             THREE.ShaderChunk[ "specularmap_pars_fragment" ],
37039
37040             "void main() {",
37041
37042                 "gl_FragColor = vec4( vec3 ( 1.0 ), opacity );",
37043
37044                 THREE.ShaderChunk[ "map_fragment" ],
37045                 THREE.ShaderChunk[ "alphatest_fragment" ],
37046                 THREE.ShaderChunk[ "specularmap_fragment" ],
37047
37048                 THREE.ShaderChunk[ "lights_phong_fragment" ],
37049
37050                 THREE.ShaderChunk[ "lightmap_fragment" ],
37051                 THREE.ShaderChunk[ "color_fragment" ],
37052                 THREE.ShaderChunk[ "envmap_fragment" ],
37053                 THREE.ShaderChunk[ "shadowmap_fragment" ],
37054
37055                 THREE.ShaderChunk[ "linear_to_gamma_fragment" ],
37056
37057                 THREE.ShaderChunk[ "fog_fragment" ],
37058
37059             "}"
37060
37061         ].join("\n")
37062
37063     },
37064
37065     'particle_basic': {
37066
37067         uniforms:  THREE.UniformsUtils.merge( [
37068
37069             THREE.UniformsLib[ "particle" ],
37070             THREE.UniformsLib[ "shadowmap" ]
37071
37072         ] ),
37073
37074         vertexShader: [
37075
37076             "uniform float size;",
37077             "uniform float scale;",
37078
37079             THREE.ShaderChunk[ "color_pars_vertex" ],
37080             THREE.ShaderChunk[ "shadowmap_pars_vertex" ],
37081
37082             "void main() {",
37083
37084                 THREE.ShaderChunk[ "color_vertex" ],
37085
37086                 "vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );",
37087
37088                 "#ifdef USE_SIZEATTENUATION",
37089                     "gl_PointSize = size * ( scale / length( mvPosition.xyz ) );",
37090                 "#else",
37091                     "gl_PointSize = size;",
37092                 "#endif",
37093
37094                 "gl_Position = projectionMatrix * mvPosition;",
37095
37096                 THREE.ShaderChunk[ "worldpos_vertex" ],
37097                 THREE.ShaderChunk[ "shadowmap_vertex" ],
37098
37099             "}"
37100
37101         ].join("\n"),
37102
37103         fragmentShader: [
37104
37105             "uniform vec3 psColor;",
37106             "uniform float opacity;",
37107
37108             THREE.ShaderChunk[ "color_pars_fragment" ],
37109             THREE.ShaderChunk[ "map_particle_pars_fragment" ],
37110             THREE.ShaderChunk[ "fog_pars_fragment" ],
37111             THREE.ShaderChunk[ "shadowmap_pars_fragment" ],
37112
37113             "void main() {",
37114
37115                 "gl_FragColor = vec4( psColor, opacity );",
37116
37117                 THREE.ShaderChunk[ "map_particle_fragment" ],
37118                 THREE.ShaderChunk[ "alphatest_fragment" ],
37119                 THREE.ShaderChunk[ "color_fragment" ],
37120                 THREE.ShaderChunk[ "shadowmap_fragment" ],
37121                 THREE.ShaderChunk[ "fog_fragment" ],
37122
37123             "}"
37124
37125         ].join("\n")
37126
37127     },
37128
37129     // Depth encoding into RGBA texture
37130     //     based on SpiderGL shadow map example
37131     //         http://spidergl.org/example.php?id=6
37132     //     originally from
37133     //        http://www.gamedev.net/topic/442138-packing-a-float-into-a-a8r8g8b8-texture-shader/page__whichpage__1%25EF%25BF%25BD
37134     //     see also here:
37135     //        http://aras-p.info/blog/2009/07/30/encoding-floats-to-rgba-the-final/
37136
37137     'depthRGBA': {
37138
37139         uniforms: {},
37140
37141         vertexShader: [
37142
37143             THREE.ShaderChunk[ "morphtarget_pars_vertex" ],
37144             THREE.ShaderChunk[ "skinning_pars_vertex" ],
37145
37146             "void main() {",
37147
37148                 THREE.ShaderChunk[ "skinbase_vertex" ],
37149                 THREE.ShaderChunk[ "morphtarget_vertex" ],
37150                 THREE.ShaderChunk[ "skinning_vertex" ],
37151                 THREE.ShaderChunk[ "default_vertex" ],
37152
37153             "}"
37154
37155         ].join("\n"),
37156
37157         fragmentShader: [
37158
37159             "vec4 pack_depth( const in float depth ) {",
37160
37161                 "const vec4 bit_shift = vec4( 256.0 * 256.0 * 256.0, 256.0 * 256.0, 256.0, 1.0 );",
37162                 "const vec4 bit_mask  = vec4( 0.0, 1.0 / 256.0, 1.0 / 256.0, 1.0 / 256.0 );",
37163                 "vec4 res = fract( depth * bit_shift );",
37164                 "res -= res.xxyz * bit_mask;",
37165                 "return res;",
37166
37167             "}",
37168
37169             "void main() {",
37170
37171                 "gl_FragData[ 0 ] = pack_depth( gl_FragCoord.z );",
37172
37173                 //"gl_FragData[ 0 ] = pack_depth( gl_FragCoord.z / gl_FragCoord.w );",
37174                 //"float z = ( ( gl_FragCoord.z / gl_FragCoord.w ) - 3.0 ) / ( 4000.0 - 3.0 );",
37175                 //"gl_FragData[ 0 ] = pack_depth( z );",
37176                 //"gl_FragData[ 0 ] = vec4( z, z, z, 1.0 );",
37177
37178             "}"
37179
37180         ].join("\n")
37181
37182     }
37183
37184 };
37185 /**
37186  * @author supereggbert / http://www.paulbrunt.co.uk/
37187  * @author mrdoob / http://mrdoob.com/
37188  * @author alteredq / http://alteredqualia.com/
37189  * @author szimek / https://github.com/szimek/
37190  */
37191
37192 THREE.WebGLRenderer = function ( parameters ) {
37193
37194     console.log( 'THREE.WebGLRenderer', THREE.REVISION );
37195
37196     parameters = parameters || {};
37197
37198     var _canvas = parameters.canvas !== undefined ? parameters.canvas : document.createElement( 'canvas' ),
37199
37200     _precision = parameters.precision !== undefined ? parameters.precision : 'highp',
37201
37202     _alpha = parameters.alpha !== undefined ? parameters.alpha : true,
37203     _premultipliedAlpha = parameters.premultipliedAlpha !== undefined ? parameters.premultipliedAlpha : true,
37204     _antialias = parameters.antialias !== undefined ? parameters.antialias : false,
37205     _stencil = parameters.stencil !== undefined ? parameters.stencil : true,
37206     _preserveDrawingBuffer = parameters.preserveDrawingBuffer !== undefined ? parameters.preserveDrawingBuffer : false,
37207
37208     _clearColor = parameters.clearColor !== undefined ? new THREE.Color( parameters.clearColor ) : new THREE.Color( 0x000000 ),
37209     _clearAlpha = parameters.clearAlpha !== undefined ? parameters.clearAlpha : 0,
37210
37211     _maxLights = parameters.maxLights !== undefined ? parameters.maxLights : 4;
37212
37213     // public properties
37214
37215     this.domElement = _canvas;
37216     this.context = null;
37217
37218     // clearing
37219
37220     this.autoClear = true;
37221     this.autoClearColor = true;
37222     this.autoClearDepth = true;
37223     this.autoClearStencil = true;
37224
37225     // scene graph
37226
37227     this.sortObjects = true;
37228
37229     this.autoUpdateObjects = true;
37230     this.autoUpdateScene = true;
37231
37232     // physically based shading
37233
37234     this.gammaInput = false;
37235     this.gammaOutput = false;
37236     this.physicallyBasedShading = false;
37237
37238     // shadow map
37239
37240     this.shadowMapEnabled = false;
37241     this.shadowMapAutoUpdate = true;
37242     this.shadowMapSoft = true;
37243     this.shadowMapCullFrontFaces = true;
37244     this.shadowMapDebug = false;
37245     this.shadowMapCascade = false;
37246
37247     // morphs
37248
37249     this.maxMorphTargets = 8;
37250     this.maxMorphNormals = 4;
37251
37252     // flags
37253
37254     this.autoScaleCubemaps = true;
37255
37256     // custom render plugins
37257
37258     this.renderPluginsPre = [];
37259     this.renderPluginsPost = [];
37260
37261     // info
37262
37263     this.info = {
37264
37265         memory: {
37266
37267             programs: 0,
37268             geometries: 0,
37269             textures: 0
37270
37271         },
37272
37273         render: {
37274
37275             calls: 0,
37276             vertices: 0,
37277             faces: 0,
37278             points: 0
37279
37280         }
37281
37282     };
37283
37284     // internal properties
37285
37286     var _this = this,
37287
37288     _programs = [],
37289     _programs_counter = 0,
37290
37291     // internal state cache
37292
37293     _currentProgram = null,
37294     _currentFramebuffer = null,
37295     _currentMaterialId = -1,
37296     _currentGeometryGroupHash = null,
37297     _currentCamera = null,
37298     _geometryGroupCounter = 0,
37299
37300     _usedTextureUnits = 0,
37301
37302     // GL state cache
37303
37304     _oldDoubleSided = -1,
37305     _oldFlipSided = -1,
37306
37307     _oldBlending = -1,
37308
37309     _oldBlendEquation = -1,
37310     _oldBlendSrc = -1,
37311     _oldBlendDst = -1,
37312
37313     _oldDepthTest = -1,
37314     _oldDepthWrite = -1,
37315
37316     _oldPolygonOffset = null,
37317     _oldPolygonOffsetFactor = null,
37318     _oldPolygonOffsetUnits = null,
37319
37320     _oldLineWidth = null,
37321
37322     _viewportX = 0,
37323     _viewportY = 0,
37324     _viewportWidth = 0,
37325     _viewportHeight = 0,
37326     _currentWidth = 0,
37327     _currentHeight = 0,
37328
37329     // frustum
37330
37331     _frustum = new THREE.Frustum(),
37332
37333      // camera matrices cache
37334
37335     _projScreenMatrix = new THREE.Matrix4(),
37336     _projScreenMatrixPS = new THREE.Matrix4(),
37337
37338     _vector3 = new THREE.Vector4(),
37339
37340     // light arrays cache
37341
37342     _direction = new THREE.Vector3(),
37343
37344     _lightsNeedUpdate = true,
37345
37346     _lights = {
37347
37348         ambient: [ 0, 0, 0 ],
37349         directional: { length: 0, colors: new Array(), positions: new Array() },
37350         point: { length: 0, colors: new Array(), positions: new Array(), distances: new Array() },
37351         spot: { length: 0, colors: new Array(), positions: new Array(), distances: new Array(), directions: new Array(), angles: new Array(), exponents: new Array() },
37352         hemi: { length: 0, skyColors: new Array(), groundColors: new Array(), positions: new Array() }
37353
37354     };
37355
37356     // initialize
37357
37358     var _gl;
37359
37360     var _glExtensionTextureFloat;
37361     var _glExtensionStandardDerivatives;
37362     var _glExtensionTextureFilterAnisotropic;
37363     var _glExtensionCompressedTextureS3TC;
37364
37365     initGL();
37366
37367     setDefaultGLState();
37368
37369     this.context = _gl;
37370
37371     // GPU capabilities
37372
37373     var _maxTextures = _gl.getParameter( _gl.MAX_TEXTURE_IMAGE_UNITS );
37374     var _maxVertexTextures = _gl.getParameter( _gl.MAX_VERTEX_TEXTURE_IMAGE_UNITS );
37375     var _maxTextureSize = _gl.getParameter( _gl.MAX_TEXTURE_SIZE );
37376     var _maxCubemapSize = _gl.getParameter( _gl.MAX_CUBE_MAP_TEXTURE_SIZE );
37377
37378     var _maxAnisotropy = _glExtensionTextureFilterAnisotropic ? _gl.getParameter( _glExtensionTextureFilterAnisotropic.MAX_TEXTURE_MAX_ANISOTROPY_EXT ) : 0;
37379
37380     var _supportsVertexTextures = ( _maxVertexTextures > 0 );
37381     var _supportsBoneTextures = _supportsVertexTextures && _glExtensionTextureFloat;
37382
37383     var _compressedTextureFormats = _glExtensionCompressedTextureS3TC ? _gl.getParameter( _gl.COMPRESSED_TEXTURE_FORMATS ) : [];
37384
37385     // API
37386
37387     this.getContext = function () {
37388
37389         return _gl;
37390
37391     };
37392
37393     this.supportsVertexTextures = function () {
37394
37395         return _supportsVertexTextures;
37396
37397     };
37398
37399     this.getMaxAnisotropy  = function () {
37400
37401         return _maxAnisotropy;
37402
37403     };
37404
37405     this.setSize = function ( width, height ) {
37406
37407         _canvas.width = width;
37408         _canvas.height = height;
37409
37410         this.setViewport( 0, 0, _canvas.width, _canvas.height );
37411
37412     };
37413
37414     this.setViewport = function ( x, y, width, height ) {
37415
37416         _viewportX = x !== undefined ? x : 0;
37417         _viewportY = y !== undefined ? y : 0;
37418
37419         _viewportWidth = width !== undefined ? width : _canvas.width;
37420         _viewportHeight = height !== undefined ? height : _canvas.height;
37421
37422         _gl.viewport( _viewportX, _viewportY, _viewportWidth, _viewportHeight );
37423
37424     };
37425
37426     this.setScissor = function ( x, y, width, height ) {
37427
37428         _gl.scissor( x, y, width, height );
37429
37430     };
37431
37432     this.enableScissorTest = function ( enable ) {
37433
37434         enable ? _gl.enable( _gl.SCISSOR_TEST ) : _gl.disable( _gl.SCISSOR_TEST );
37435
37436     };
37437
37438     // Clearing
37439
37440     this.setClearColorHex = function ( hex, alpha ) {
37441
37442         _clearColor.setHex( hex );
37443         _clearAlpha = alpha;
37444
37445         _gl.clearColor( _clearColor.r, _clearColor.g, _clearColor.b, _clearAlpha );
37446
37447     };
37448
37449     this.setClearColor = function ( color, alpha ) {
37450
37451         _clearColor.copy( color );
37452         _clearAlpha = alpha;
37453
37454         _gl.clearColor( _clearColor.r, _clearColor.g, _clearColor.b, _clearAlpha );
37455
37456     };
37457
37458     this.getClearColor = function () {
37459
37460         return _clearColor;
37461
37462     };
37463
37464     this.getClearAlpha = function () {
37465
37466         return _clearAlpha;
37467
37468     };
37469
37470     this.clear = function ( color, depth, stencil ) {
37471
37472         var bits = 0;
37473
37474         if ( color === undefined || color ) bits |= _gl.COLOR_BUFFER_BIT;
37475         if ( depth === undefined || depth ) bits |= _gl.DEPTH_BUFFER_BIT;
37476         if ( stencil === undefined || stencil ) bits |= _gl.STENCIL_BUFFER_BIT;
37477
37478         _gl.clear( bits );
37479
37480     };
37481
37482     this.clearTarget = function ( renderTarget, color, depth, stencil ) {
37483
37484         this.setRenderTarget( renderTarget );
37485         this.clear( color, depth, stencil );
37486
37487     };
37488
37489     // Plugins
37490
37491     this.addPostPlugin = function ( plugin ) {
37492
37493         plugin.init( this );
37494         this.renderPluginsPost.push( plugin );
37495
37496     };
37497
37498     this.addPrePlugin = function ( plugin ) {
37499
37500         plugin.init( this );
37501         this.renderPluginsPre.push( plugin );
37502
37503     };
37504
37505     // Deallocation
37506
37507     this.deallocateObject = function ( object ) {
37508
37509         if ( ! object.__webglInit ) return;
37510
37511         object.__webglInit = false;
37512
37513         delete object._modelViewMatrix;
37514         delete object._normalMatrix;
37515
37516         delete object._normalMatrixArray;
37517         delete object._modelViewMatrixArray;
37518         delete object._modelMatrixArray;
37519
37520         if ( object instanceof THREE.Mesh ) {
37521
37522             for ( var g in object.geometry.geometryGroups ) {
37523
37524                 deleteMeshBuffers( object.geometry.geometryGroups[ g ] );
37525
37526             }
37527
37528         } else if ( object instanceof THREE.Ribbon ) {
37529
37530             deleteRibbonBuffers( object.geometry );
37531
37532         } else if ( object instanceof THREE.Line ) {
37533
37534             deleteLineBuffers( object.geometry );
37535
37536         } else if ( object instanceof THREE.ParticleSystem ) {
37537
37538             deleteParticleBuffers( object.geometry );
37539
37540         }
37541
37542     };
37543
37544     this.deallocateTexture = function ( texture ) {
37545
37546         if ( ! texture.__webglInit ) return;
37547
37548         texture.__webglInit = false;
37549         _gl.deleteTexture( texture.__webglTexture );
37550
37551         _this.info.memory.textures --;
37552
37553     };
37554
37555     this.deallocateRenderTarget = function ( renderTarget ) {
37556
37557         if ( !renderTarget || ! renderTarget.__webglTexture ) return;
37558
37559         _gl.deleteTexture( renderTarget.__webglTexture );
37560
37561         if ( renderTarget instanceof THREE.WebGLRenderTargetCube ) {
37562
37563             for ( var i = 0; i < 6; i ++ ) {
37564
37565                 _gl.deleteFramebuffer( renderTarget.__webglFramebuffer[ i ] );
37566                 _gl.deleteRenderbuffer( renderTarget.__webglRenderbuffer[ i ] );
37567
37568             }
37569
37570         } else {
37571
37572             _gl.deleteFramebuffer( renderTarget.__webglFramebuffer );
37573             _gl.deleteRenderbuffer( renderTarget.__webglRenderbuffer );
37574
37575         }
37576
37577     };
37578
37579     this.deallocateMaterial = function ( material ) {
37580
37581         var program = material.program;
37582
37583         if ( ! program ) return;
37584
37585         material.program = undefined;
37586
37587         // only deallocate GL program if this was the last use of shared program
37588         // assumed there is only single copy of any program in the _programs list
37589         // (that's how it's constructed)
37590
37591         var i, il, programInfo;
37592         var deleteProgram = false;
37593
37594         for ( i = 0, il = _programs.length; i < il; i ++ ) {
37595
37596             programInfo = _programs[ i ];
37597
37598             if ( programInfo.program === program ) {
37599
37600                 programInfo.usedTimes --;
37601
37602                 if ( programInfo.usedTimes === 0 ) {
37603
37604                     deleteProgram = true;
37605
37606                 }
37607
37608                 break;
37609
37610             }
37611
37612         }
37613
37614         if ( deleteProgram ) {
37615
37616             // avoid using array.splice, this is costlier than creating new array from scratch
37617
37618             var newPrograms = [];
37619
37620             for ( i = 0, il = _programs.length; i < il; i ++ ) {
37621
37622                 programInfo = _programs[ i ];
37623
37624                 if ( programInfo.program !== program ) {
37625
37626                     newPrograms.push( programInfo );
37627
37628                 }
37629
37630             }
37631
37632             _programs = newPrograms;
37633
37634             _gl.deleteProgram( program );
37635
37636             _this.info.memory.programs --;
37637
37638         }
37639
37640     };
37641
37642     // Rendering
37643
37644     this.updateShadowMap = function ( scene, camera ) {
37645
37646         _currentProgram = null;
37647         _oldBlending = -1;
37648         _oldDepthTest = -1;
37649         _oldDepthWrite = -1;
37650         _currentGeometryGroupHash = -1;
37651         _currentMaterialId = -1;
37652         _lightsNeedUpdate = true;
37653         _oldDoubleSided = -1;
37654         _oldFlipSided = -1;
37655
37656         this.shadowMapPlugin.update( scene, camera );
37657
37658     };
37659
37660     // Internal functions
37661
37662     // Buffer allocation
37663
37664     function createParticleBuffers ( geometry ) {
37665
37666         geometry.__webglVertexBuffer = _gl.createBuffer();
37667         geometry.__webglColorBuffer = _gl.createBuffer();
37668
37669         _this.info.memory.geometries ++;
37670
37671     };
37672
37673     function createLineBuffers ( geometry ) {
37674
37675         geometry.__webglVertexBuffer = _gl.createBuffer();
37676         geometry.__webglColorBuffer = _gl.createBuffer();
37677
37678         _this.info.memory.geometries ++;
37679
37680     };
37681
37682     function createRibbonBuffers ( geometry ) {
37683
37684         geometry.__webglVertexBuffer = _gl.createBuffer();
37685         geometry.__webglColorBuffer = _gl.createBuffer();
37686
37687         _this.info.memory.geometries ++;
37688
37689     };
37690
37691     function createMeshBuffers ( geometryGroup ) {
37692
37693         geometryGroup.__webglVertexBuffer = _gl.createBuffer();
37694         geometryGroup.__webglNormalBuffer = _gl.createBuffer();
37695         geometryGroup.__webglTangentBuffer = _gl.createBuffer();
37696         geometryGroup.__webglColorBuffer = _gl.createBuffer();
37697         geometryGroup.__webglUVBuffer = _gl.createBuffer();
37698         geometryGroup.__webglUV2Buffer = _gl.createBuffer();
37699
37700         geometryGroup.__webglSkinIndicesBuffer = _gl.createBuffer();
37701         geometryGroup.__webglSkinWeightsBuffer = _gl.createBuffer();
37702
37703         geometryGroup.__webglFaceBuffer = _gl.createBuffer();
37704         geometryGroup.__webglLineBuffer = _gl.createBuffer();
37705
37706         var m, ml;
37707
37708         if ( geometryGroup.numMorphTargets ) {
37709
37710             geometryGroup.__webglMorphTargetsBuffers = [];
37711
37712             for ( m = 0, ml = geometryGroup.numMorphTargets; m < ml; m ++ ) {
37713
37714                 geometryGroup.__webglMorphTargetsBuffers.push( _gl.createBuffer() );
37715
37716             }
37717
37718         }
37719
37720         if ( geometryGroup.numMorphNormals ) {
37721
37722             geometryGroup.__webglMorphNormalsBuffers = [];
37723
37724             for ( m = 0, ml = geometryGroup.numMorphNormals; m < ml; m ++ ) {
37725
37726                 geometryGroup.__webglMorphNormalsBuffers.push( _gl.createBuffer() );
37727
37728             }
37729
37730         }
37731
37732         _this.info.memory.geometries ++;
37733
37734     };
37735
37736     // Buffer deallocation
37737
37738     function deleteParticleBuffers ( geometry ) {
37739
37740         _gl.deleteBuffer( geometry.__webglVertexBuffer );
37741         _gl.deleteBuffer( geometry.__webglColorBuffer );
37742
37743         _this.info.memory.geometries --;
37744
37745     };
37746
37747     function deleteLineBuffers ( geometry ) {
37748
37749         _gl.deleteBuffer( geometry.__webglVertexBuffer );
37750         _gl.deleteBuffer( geometry.__webglColorBuffer );
37751
37752         _this.info.memory.geometries --;
37753
37754     };
37755
37756     function deleteRibbonBuffers ( geometry ) {
37757
37758         _gl.deleteBuffer( geometry.__webglVertexBuffer );
37759         _gl.deleteBuffer( geometry.__webglColorBuffer );
37760
37761         _this.info.memory.geometries --;
37762
37763     };
37764
37765     function deleteMeshBuffers ( geometryGroup ) {
37766
37767         _gl.deleteBuffer( geometryGroup.__webglVertexBuffer );
37768         _gl.deleteBuffer( geometryGroup.__webglNormalBuffer );
37769         _gl.deleteBuffer( geometryGroup.__webglTangentBuffer );
37770         _gl.deleteBuffer( geometryGroup.__webglColorBuffer );
37771         _gl.deleteBuffer( geometryGroup.__webglUVBuffer );
37772         _gl.deleteBuffer( geometryGroup.__webglUV2Buffer );
37773
37774         _gl.deleteBuffer( geometryGroup.__webglSkinIndicesBuffer );
37775         _gl.deleteBuffer( geometryGroup.__webglSkinWeightsBuffer );
37776
37777         _gl.deleteBuffer( geometryGroup.__webglFaceBuffer );
37778         _gl.deleteBuffer( geometryGroup.__webglLineBuffer );
37779
37780         var m, ml;
37781
37782         if ( geometryGroup.numMorphTargets ) {
37783
37784             for ( m = 0, ml = geometryGroup.numMorphTargets; m < ml; m ++ ) {
37785
37786                 _gl.deleteBuffer( geometryGroup.__webglMorphTargetsBuffers[ m ] );
37787
37788             }
37789
37790         }
37791
37792         if ( geometryGroup.numMorphNormals ) {
37793
37794             for ( m = 0, ml = geometryGroup.numMorphNormals; m < ml; m ++ ) {
37795
37796                 _gl.deleteBuffer( geometryGroup.__webglMorphNormalsBuffers[ m ] );
37797
37798             }
37799
37800         }
37801
37802
37803         if ( geometryGroup.__webglCustomAttributesList ) {
37804
37805             for ( var id in geometryGroup.__webglCustomAttributesList ) {
37806
37807                 _gl.deleteBuffer( geometryGroup.__webglCustomAttributesList[ id ].buffer );
37808
37809             }
37810
37811         }
37812
37813         _this.info.memory.geometries --;
37814
37815     };
37816
37817     // Buffer initialization
37818
37819     function initCustomAttributes ( geometry, object ) {
37820
37821         var nvertices = geometry.vertices.length;
37822
37823         var material = object.material;
37824
37825         if ( material.attributes ) {
37826
37827             if ( geometry.__webglCustomAttributesList === undefined ) {
37828
37829                 geometry.__webglCustomAttributesList = [];
37830
37831             }
37832
37833             for ( var a in material.attributes ) {
37834
37835                 var attribute = material.attributes[ a ];
37836
37837                 if( !attribute.__webglInitialized || attribute.createUniqueBuffers ) {
37838
37839                     attribute.__webglInitialized = true;
37840
37841                     var size = 1;        // "f" and "i"
37842
37843                     if ( attribute.type === "v2" ) size = 2;
37844                     else if ( attribute.type === "v3" ) size = 3;
37845                     else if ( attribute.type === "v4" ) size = 4;
37846                     else if ( attribute.type === "c"  ) size = 3;
37847
37848                     attribute.size = size;
37849
37850                     attribute.array = new Float32Array( nvertices * size );
37851
37852                     attribute.buffer = _gl.createBuffer();
37853                     attribute.buffer.belongsToAttribute = a;
37854
37855                     attribute.needsUpdate = true;
37856
37857                 }
37858
37859                 geometry.__webglCustomAttributesList.push( attribute );
37860
37861             }
37862
37863         }
37864
37865     };
37866
37867     function initParticleBuffers ( geometry, object ) {
37868
37869         var nvertices = geometry.vertices.length;
37870
37871         geometry.__vertexArray = new Float32Array( nvertices * 3 );
37872         geometry.__colorArray = new Float32Array( nvertices * 3 );
37873
37874         geometry.__sortArray = [];
37875
37876         geometry.__webglParticleCount = nvertices;
37877
37878         initCustomAttributes ( geometry, object );
37879
37880     };
37881
37882     function initLineBuffers ( geometry, object ) {
37883
37884         var nvertices = geometry.vertices.length;
37885
37886         geometry.__vertexArray = new Float32Array( nvertices * 3 );
37887         geometry.__colorArray = new Float32Array( nvertices * 3 );
37888
37889         geometry.__webglLineCount = nvertices;
37890
37891         initCustomAttributes ( geometry, object );
37892
37893     };
37894
37895     function initRibbonBuffers ( geometry ) {
37896
37897         var nvertices = geometry.vertices.length;
37898
37899         geometry.__vertexArray = new Float32Array( nvertices * 3 );
37900         geometry.__colorArray = new Float32Array( nvertices * 3 );
37901
37902         geometry.__webglVertexCount = nvertices;
37903
37904     };
37905
37906     function initMeshBuffers ( geometryGroup, object ) {
37907
37908         var geometry = object.geometry,
37909             faces3 = geometryGroup.faces3,
37910             faces4 = geometryGroup.faces4,
37911
37912             nvertices = faces3.length * 3 + faces4.length * 4,
37913             ntris     = faces3.length * 1 + faces4.length * 2,
37914             nlines    = faces3.length * 3 + faces4.length * 4,
37915
37916             material = getBufferMaterial( object, geometryGroup ),
37917
37918             uvType = bufferGuessUVType( material ),
37919             normalType = bufferGuessNormalType( material ),
37920             vertexColorType = bufferGuessVertexColorType( material );
37921
37922         //console.log( "uvType", uvType, "normalType", normalType, "vertexColorType", vertexColorType, object, geometryGroup, material );
37923
37924         geometryGroup.__vertexArray = new Float32Array( nvertices * 3 );
37925
37926         if ( normalType ) {
37927
37928             geometryGroup.__normalArray = new Float32Array( nvertices * 3 );
37929
37930         }
37931
37932         if ( geometry.hasTangents ) {
37933
37934             geometryGroup.__tangentArray = new Float32Array( nvertices * 4 );
37935
37936         }
37937
37938         if ( vertexColorType ) {
37939
37940             geometryGroup.__colorArray = new Float32Array( nvertices * 3 );
37941
37942         }
37943
37944         if ( uvType ) {
37945
37946             if ( geometry.faceUvs.length > 0 || geometry.faceVertexUvs.length > 0 ) {
37947
37948                 geometryGroup.__uvArray = new Float32Array( nvertices * 2 );
37949
37950             }
37951
37952             if ( geometry.faceUvs.length > 1 || geometry.faceVertexUvs.length > 1 ) {
37953
37954                 geometryGroup.__uv2Array = new Float32Array( nvertices * 2 );
37955
37956             }
37957
37958         }
37959
37960         if ( object.geometry.skinWeights.length && object.geometry.skinIndices.length ) {
37961
37962             geometryGroup.__skinIndexArray = new Float32Array( nvertices * 4 );
37963             geometryGroup.__skinWeightArray = new Float32Array( nvertices * 4 );
37964
37965         }
37966
37967         geometryGroup.__faceArray = new Uint16Array( ntris * 3 );
37968         geometryGroup.__lineArray = new Uint16Array( nlines * 2 );
37969
37970         var m, ml;
37971
37972         if ( geometryGroup.numMorphTargets ) {
37973
37974             geometryGroup.__morphTargetsArrays = [];
37975
37976             for ( m = 0, ml = geometryGroup.numMorphTargets; m < ml; m ++ ) {
37977
37978                 geometryGroup.__morphTargetsArrays.push( new Float32Array( nvertices * 3 ) );
37979
37980             }
37981
37982         }
37983
37984         if ( geometryGroup.numMorphNormals ) {
37985
37986             geometryGroup.__morphNormalsArrays = [];
37987
37988             for ( m = 0, ml = geometryGroup.numMorphNormals; m < ml; m ++ ) {
37989
37990                 geometryGroup.__morphNormalsArrays.push( new Float32Array( nvertices * 3 ) );
37991
37992             }
37993
37994         }
37995
37996         geometryGroup.__webglFaceCount = ntris * 3;
37997         geometryGroup.__webglLineCount = nlines * 2;
37998
37999
38000         // custom attributes
38001
38002         if ( material.attributes ) {
38003
38004             if ( geometryGroup.__webglCustomAttributesList === undefined ) {
38005
38006                 geometryGroup.__webglCustomAttributesList = [];
38007
38008             }
38009
38010             for ( var a in material.attributes ) {
38011
38012                 // Do a shallow copy of the attribute object so different geometryGroup chunks use different
38013                 // attribute buffers which are correctly indexed in the setMeshBuffers function
38014
38015                 var originalAttribute = material.attributes[ a ];
38016
38017                 var attribute = {};
38018
38019                 for ( var property in originalAttribute ) {
38020
38021                     attribute[ property ] = originalAttribute[ property ];
38022
38023                 }
38024
38025                 if( !attribute.__webglInitialized || attribute.createUniqueBuffers ) {
38026
38027                     attribute.__webglInitialized = true;
38028
38029                     var size = 1;        // "f" and "i"
38030
38031                     if( attribute.type === "v2" ) size = 2;
38032                     else if( attribute.type === "v3" ) size = 3;
38033                     else if( attribute.type === "v4" ) size = 4;
38034                     else if( attribute.type === "c"  ) size = 3;
38035
38036                     attribute.size = size;
38037
38038                     attribute.array = new Float32Array( nvertices * size );
38039
38040                     attribute.buffer = _gl.createBuffer();
38041                     attribute.buffer.belongsToAttribute = a;
38042
38043                     originalAttribute.needsUpdate = true;
38044                     attribute.__original = originalAttribute;
38045
38046                 }
38047
38048                 geometryGroup.__webglCustomAttributesList.push( attribute );
38049
38050             }
38051
38052         }
38053
38054         geometryGroup.__inittedArrays = true;
38055
38056     };
38057
38058     function getBufferMaterial( object, geometryGroup ) {
38059
38060         if ( object.material && ! ( object.material instanceof THREE.MeshFaceMaterial ) ) {
38061
38062             return object.material;
38063
38064         } else if ( geometryGroup.materialIndex >= 0 ) {
38065
38066             return object.geometry.materials[ geometryGroup.materialIndex ];
38067
38068         }
38069
38070     };
38071
38072     function materialNeedsSmoothNormals ( material ) {
38073
38074         return material && material.shading !== undefined && material.shading === THREE.SmoothShading;
38075
38076     };
38077
38078     function bufferGuessNormalType ( material ) {
38079
38080         // only MeshBasicMaterial and MeshDepthMaterial don't need normals
38081
38082         if ( ( material instanceof THREE.MeshBasicMaterial && !material.envMap ) || material instanceof THREE.MeshDepthMaterial ) {
38083
38084             return false;
38085
38086         }
38087
38088         if ( materialNeedsSmoothNormals( material ) ) {
38089
38090             return THREE.SmoothShading;
38091
38092         } else {
38093
38094             return THREE.FlatShading;
38095
38096         }
38097
38098     };
38099
38100     function bufferGuessVertexColorType ( material ) {
38101
38102         if ( material.vertexColors ) {
38103
38104             return material.vertexColors;
38105
38106         }
38107
38108         return false;
38109
38110     };
38111
38112     function bufferGuessUVType ( material ) {
38113
38114         // material must use some texture to require uvs
38115
38116         if ( material.map || material.lightMap || material.bumpMap || material.normalMap || material.specularMap || material instanceof THREE.ShaderMaterial ) {
38117
38118             return true;
38119
38120         }
38121
38122         return false;
38123
38124     };
38125
38126     //
38127
38128     function initDirectBuffers( geometry ) {
38129
38130         var a, attribute, type;
38131
38132         for ( a in geometry.attributes ) {
38133
38134             if ( a === "index" ) {
38135
38136                 type = _gl.ELEMENT_ARRAY_BUFFER;
38137
38138             } else {
38139
38140                 type = _gl.ARRAY_BUFFER;
38141
38142             }
38143
38144             attribute = geometry.attributes[ a ];
38145
38146             attribute.buffer = _gl.createBuffer();
38147
38148             _gl.bindBuffer( type, attribute.buffer );
38149             _gl.bufferData( type, attribute.array, _gl.STATIC_DRAW );
38150
38151         }
38152
38153     };
38154
38155     // Buffer setting
38156
38157     function setParticleBuffers ( geometry, hint, object ) {
38158
38159         var v, c, vertex, offset, index, color,
38160
38161         vertices = geometry.vertices,
38162         vl = vertices.length,
38163
38164         colors = geometry.colors,
38165         cl = colors.length,
38166
38167         vertexArray = geometry.__vertexArray,
38168         colorArray = geometry.__colorArray,
38169
38170         sortArray = geometry.__sortArray,
38171
38172         dirtyVertices = geometry.verticesNeedUpdate,
38173         dirtyElements = geometry.elementsNeedUpdate,
38174         dirtyColors = geometry.colorsNeedUpdate,
38175
38176         customAttributes = geometry.__webglCustomAttributesList,
38177         i, il,
38178         a, ca, cal, value,
38179         customAttribute;
38180
38181         if ( object.sortParticles ) {
38182
38183             _projScreenMatrixPS.copy( _projScreenMatrix );
38184             _projScreenMatrixPS.multiplySelf( object.matrixWorld );
38185
38186             for ( v = 0; v < vl; v ++ ) {
38187
38188                 vertex = vertices[ v ];
38189
38190                 _vector3.copy( vertex );
38191                 _projScreenMatrixPS.multiplyVector3( _vector3 );
38192
38193                 sortArray[ v ] = [ _vector3.z, v ];
38194
38195             }
38196
38197             sortArray.sort( function( a, b ) { return b[ 0 ] - a[ 0 ]; } );
38198
38199             for ( v = 0; v < vl; v ++ ) {
38200
38201                 vertex = vertices[ sortArray[v][1] ];
38202
38203                 offset = v * 3;
38204
38205                 vertexArray[ offset ]     = vertex.x;
38206                 vertexArray[ offset + 1 ] = vertex.y;
38207                 vertexArray[ offset + 2 ] = vertex.z;
38208
38209             }
38210
38211             for ( c = 0; c < cl; c ++ ) {
38212
38213                 offset = c * 3;
38214
38215                 color = colors[ sortArray[c][1] ];
38216
38217                 colorArray[ offset ]     = color.r;
38218                 colorArray[ offset + 1 ] = color.g;
38219                 colorArray[ offset + 2 ] = color.b;
38220
38221             }
38222
38223             if ( customAttributes ) {
38224
38225                 for ( i = 0, il = customAttributes.length; i < il; i ++ ) {
38226
38227                     customAttribute = customAttributes[ i ];
38228
38229                     if ( ! ( customAttribute.boundTo === undefined || customAttribute.boundTo === "vertices" ) ) continue;
38230
38231                     offset = 0;
38232
38233                     cal = customAttribute.value.length;
38234
38235                     if ( customAttribute.size === 1 ) {
38236
38237                         for ( ca = 0; ca < cal; ca ++ ) {
38238
38239                             index = sortArray[ ca ][ 1 ];
38240
38241                             customAttribute.array[ ca ] = customAttribute.value[ index ];
38242
38243                         }
38244
38245                     } else if ( customAttribute.size === 2 ) {
38246
38247                         for ( ca = 0; ca < cal; ca ++ ) {
38248
38249                             index = sortArray[ ca ][ 1 ];
38250
38251                             value = customAttribute.value[ index ];
38252
38253                             customAttribute.array[ offset ]     = value.x;
38254                             customAttribute.array[ offset + 1 ] = value.y;
38255
38256                             offset += 2;
38257
38258                         }
38259
38260                     } else if ( customAttribute.size === 3 ) {
38261
38262                         if ( customAttribute.type === "c" ) {
38263
38264                             for ( ca = 0; ca < cal; ca ++ ) {
38265
38266                                 index = sortArray[ ca ][ 1 ];
38267
38268                                 value = customAttribute.value[ index ];
38269
38270                                 customAttribute.array[ offset ]     = value.r;
38271                                 customAttribute.array[ offset + 1 ] = value.g;
38272                                 customAttribute.array[ offset + 2 ] = value.b;
38273
38274                                 offset += 3;
38275
38276                             }
38277
38278                         } else {
38279
38280                             for ( ca = 0; ca < cal; ca ++ ) {
38281
38282                                 index = sortArray[ ca ][ 1 ];
38283
38284                                 value = customAttribute.value[ index ];
38285
38286                                 customAttribute.array[ offset ]     = value.x;
38287                                 customAttribute.array[ offset + 1 ] = value.y;
38288                                 customAttribute.array[ offset + 2 ] = value.z;
38289
38290                                 offset += 3;
38291
38292                             }
38293
38294                         }
38295
38296                     } else if ( customAttribute.size === 4 ) {
38297
38298                         for ( ca = 0; ca < cal; ca ++ ) {
38299
38300                             index = sortArray[ ca ][ 1 ];
38301
38302                             value = customAttribute.value[ index ];
38303
38304                             customAttribute.array[ offset ]      = value.x;
38305                             customAttribute.array[ offset + 1  ] = value.y;
38306                             customAttribute.array[ offset + 2  ] = value.z;
38307                             customAttribute.array[ offset + 3  ] = value.w;
38308
38309                             offset += 4;
38310
38311                         }
38312
38313                     }
38314
38315                 }
38316
38317             }
38318
38319         } else {
38320
38321             if ( dirtyVertices ) {
38322
38323                 for ( v = 0; v < vl; v ++ ) {
38324
38325                     vertex = vertices[ v ];
38326
38327                     offset = v * 3;
38328
38329                     vertexArray[ offset ]     = vertex.x;
38330                     vertexArray[ offset + 1 ] = vertex.y;
38331                     vertexArray[ offset + 2 ] = vertex.z;
38332
38333                 }
38334
38335             }
38336
38337             if ( dirtyColors ) {
38338
38339                 for ( c = 0; c < cl; c ++ ) {
38340
38341                     color = colors[ c ];
38342
38343                     offset = c * 3;
38344
38345                     colorArray[ offset ]     = color.r;
38346                     colorArray[ offset + 1 ] = color.g;
38347                     colorArray[ offset + 2 ] = color.b;
38348
38349                 }
38350
38351             }
38352
38353             if ( customAttributes ) {
38354
38355                 for ( i = 0, il = customAttributes.length; i < il; i ++ ) {
38356
38357                     customAttribute = customAttributes[ i ];
38358
38359                     if ( customAttribute.needsUpdate &&
38360                          ( customAttribute.boundTo === undefined ||
38361                            customAttribute.boundTo === "vertices") ) {
38362
38363                         cal = customAttribute.value.length;
38364
38365                         offset = 0;
38366
38367                         if ( customAttribute.size === 1 ) {
38368
38369                             for ( ca = 0; ca < cal; ca ++ ) {
38370
38371                                 customAttribute.array[ ca ] = customAttribute.value[ ca ];
38372
38373                             }
38374
38375                         } else if ( customAttribute.size === 2 ) {
38376
38377                             for ( ca = 0; ca < cal; ca ++ ) {
38378
38379                                 value = customAttribute.value[ ca ];
38380
38381                                 customAttribute.array[ offset ]     = value.x;
38382                                 customAttribute.array[ offset + 1 ] = value.y;
38383
38384                                 offset += 2;
38385
38386                             }
38387
38388                         } else if ( customAttribute.size === 3 ) {
38389
38390                             if ( customAttribute.type === "c" ) {
38391
38392                                 for ( ca = 0; ca < cal; ca ++ ) {
38393
38394                                     value = customAttribute.value[ ca ];
38395
38396                                     customAttribute.array[ offset ]     = value.r;
38397                                     customAttribute.array[ offset + 1 ] = value.g;
38398                                     customAttribute.array[ offset + 2 ] = value.b;
38399
38400                                     offset += 3;
38401
38402                                 }
38403
38404                             } else {
38405
38406                                 for ( ca = 0; ca < cal; ca ++ ) {
38407
38408                                     value = customAttribute.value[ ca ];
38409
38410                                     customAttribute.array[ offset ]     = value.x;
38411                                     customAttribute.array[ offset + 1 ] = value.y;
38412                                     customAttribute.array[ offset + 2 ] = value.z;
38413
38414                                     offset += 3;
38415
38416                                 }
38417
38418                             }
38419
38420                         } else if ( customAttribute.size === 4 ) {
38421
38422                             for ( ca = 0; ca < cal; ca ++ ) {
38423
38424                                 value = customAttribute.value[ ca ];
38425
38426                                 customAttribute.array[ offset ]      = value.x;
38427                                 customAttribute.array[ offset + 1  ] = value.y;
38428                                 customAttribute.array[ offset + 2  ] = value.z;
38429                                 customAttribute.array[ offset + 3  ] = value.w;
38430
38431                                 offset += 4;
38432
38433                             }
38434
38435                         }
38436
38437                     }
38438
38439                 }
38440
38441             }
38442
38443         }
38444
38445         if ( dirtyVertices || object.sortParticles ) {
38446
38447             _gl.bindBuffer( _gl.ARRAY_BUFFER, geometry.__webglVertexBuffer );
38448             _gl.bufferData( _gl.ARRAY_BUFFER, vertexArray, hint );
38449
38450         }
38451
38452         if ( dirtyColors || object.sortParticles ) {
38453
38454             _gl.bindBuffer( _gl.ARRAY_BUFFER, geometry.__webglColorBuffer );
38455             _gl.bufferData( _gl.ARRAY_BUFFER, colorArray, hint );
38456
38457         }
38458
38459         if ( customAttributes ) {
38460
38461             for ( i = 0, il = customAttributes.length; i < il; i ++ ) {
38462
38463                 customAttribute = customAttributes[ i ];
38464
38465                 if ( customAttribute.needsUpdate || object.sortParticles ) {
38466
38467                     _gl.bindBuffer( _gl.ARRAY_BUFFER, customAttribute.buffer );
38468                     _gl.bufferData( _gl.ARRAY_BUFFER, customAttribute.array, hint );
38469
38470                 }
38471
38472             }
38473
38474         }
38475
38476
38477     };
38478
38479     function setLineBuffers ( geometry, hint ) {
38480
38481         var v, c, vertex, offset, color,
38482
38483         vertices = geometry.vertices,
38484         colors = geometry.colors,
38485         vl = vertices.length,
38486         cl = colors.length,
38487
38488         vertexArray = geometry.__vertexArray,
38489         colorArray = geometry.__colorArray,
38490
38491         dirtyVertices = geometry.verticesNeedUpdate,
38492         dirtyColors = geometry.colorsNeedUpdate,
38493
38494         customAttributes = geometry.__webglCustomAttributesList,
38495
38496         i, il,
38497         a, ca, cal, value,
38498         customAttribute;
38499
38500         if ( dirtyVertices ) {
38501
38502             for ( v = 0; v < vl; v ++ ) {
38503
38504                 vertex = vertices[ v ];
38505
38506                 offset = v * 3;
38507
38508                 vertexArray[ offset ]     = vertex.x;
38509                 vertexArray[ offset + 1 ] = vertex.y;
38510                 vertexArray[ offset + 2 ] = vertex.z;
38511
38512             }
38513
38514             _gl.bindBuffer( _gl.ARRAY_BUFFER, geometry.__webglVertexBuffer );
38515             _gl.bufferData( _gl.ARRAY_BUFFER, vertexArray, hint );
38516
38517         }
38518
38519         if ( dirtyColors ) {
38520
38521             for ( c = 0; c < cl; c ++ ) {
38522
38523                 color = colors[ c ];
38524
38525                 offset = c * 3;
38526
38527                 colorArray[ offset ]     = color.r;
38528                 colorArray[ offset + 1 ] = color.g;
38529                 colorArray[ offset + 2 ] = color.b;
38530
38531             }
38532
38533             _gl.bindBuffer( _gl.ARRAY_BUFFER, geometry.__webglColorBuffer );
38534             _gl.bufferData( _gl.ARRAY_BUFFER, colorArray, hint );
38535
38536         }
38537
38538         if ( customAttributes ) {
38539
38540             for ( i = 0, il = customAttributes.length; i < il; i ++ ) {
38541
38542                 customAttribute = customAttributes[ i ];
38543
38544                 if ( customAttribute.needsUpdate &&
38545                      ( customAttribute.boundTo === undefined ||
38546                        customAttribute.boundTo === "vertices" ) ) {
38547
38548                     offset = 0;
38549
38550                     cal = customAttribute.value.length;
38551
38552                     if ( customAttribute.size === 1 ) {
38553
38554                         for ( ca = 0; ca < cal; ca ++ ) {
38555
38556                             customAttribute.array[ ca ] = customAttribute.value[ ca ];
38557
38558                         }
38559
38560                     } else if ( customAttribute.size === 2 ) {
38561
38562                         for ( ca = 0; ca < cal; ca ++ ) {
38563
38564                             value = customAttribute.value[ ca ];
38565
38566                             customAttribute.array[ offset ]     = value.x;
38567                             customAttribute.array[ offset + 1 ] = value.y;
38568
38569                             offset += 2;
38570
38571                         }
38572
38573                     } else if ( customAttribute.size === 3 ) {
38574
38575                         if ( customAttribute.type === "c" ) {
38576
38577                             for ( ca = 0; ca < cal; ca ++ ) {
38578
38579                                 value = customAttribute.value[ ca ];
38580
38581                                 customAttribute.array[ offset ]     = value.r;
38582                                 customAttribute.array[ offset + 1 ] = value.g;
38583                                 customAttribute.array[ offset + 2 ] = value.b;
38584
38585                                 offset += 3;
38586
38587                             }
38588
38589                         } else {
38590
38591                             for ( ca = 0; ca < cal; ca ++ ) {
38592
38593                                 value = customAttribute.value[ ca ];
38594
38595                                 customAttribute.array[ offset ]     = value.x;
38596                                 customAttribute.array[ offset + 1 ] = value.y;
38597                                 customAttribute.array[ offset + 2 ] = value.z;
38598
38599                                 offset += 3;
38600
38601                             }
38602
38603                         }
38604
38605                     } else if ( customAttribute.size === 4 ) {
38606
38607                         for ( ca = 0; ca < cal; ca ++ ) {
38608
38609                             value = customAttribute.value[ ca ];
38610
38611                             customAttribute.array[ offset ]      = value.x;
38612                             customAttribute.array[ offset + 1  ] = value.y;
38613                             customAttribute.array[ offset + 2  ] = value.z;
38614                             customAttribute.array[ offset + 3  ] = value.w;
38615
38616                             offset += 4;
38617
38618                         }
38619
38620                     }
38621
38622                     _gl.bindBuffer( _gl.ARRAY_BUFFER, customAttribute.buffer );
38623                     _gl.bufferData( _gl.ARRAY_BUFFER, customAttribute.array, hint );
38624
38625                 }
38626
38627             }
38628
38629         }
38630
38631     };
38632
38633     function setRibbonBuffers ( geometry, hint ) {
38634
38635         var v, c, vertex, offset, color,
38636
38637         vertices = geometry.vertices,
38638         colors = geometry.colors,
38639         vl = vertices.length,
38640         cl = colors.length,
38641
38642         vertexArray = geometry.__vertexArray,
38643         colorArray = geometry.__colorArray,
38644
38645         dirtyVertices = geometry.verticesNeedUpdate,
38646         dirtyColors = geometry.colorsNeedUpdate;
38647
38648         if ( dirtyVertices ) {
38649
38650             for ( v = 0; v < vl; v ++ ) {
38651
38652                 vertex = vertices[ v ];
38653
38654                 offset = v * 3;
38655
38656                 vertexArray[ offset ]     = vertex.x;
38657                 vertexArray[ offset + 1 ] = vertex.y;
38658                 vertexArray[ offset + 2 ] = vertex.z;
38659
38660             }
38661
38662             _gl.bindBuffer( _gl.ARRAY_BUFFER, geometry.__webglVertexBuffer );
38663             _gl.bufferData( _gl.ARRAY_BUFFER, vertexArray, hint );
38664
38665         }
38666
38667         if ( dirtyColors ) {
38668
38669             for ( c = 0; c < cl; c ++ ) {
38670
38671                 color = colors[ c ];
38672
38673                 offset = c * 3;
38674
38675                 colorArray[ offset ]     = color.r;
38676                 colorArray[ offset + 1 ] = color.g;
38677                 colorArray[ offset + 2 ] = color.b;
38678
38679             }
38680
38681             _gl.bindBuffer( _gl.ARRAY_BUFFER, geometry.__webglColorBuffer );
38682             _gl.bufferData( _gl.ARRAY_BUFFER, colorArray, hint );
38683
38684         }
38685
38686     };
38687
38688     function setMeshBuffers( geometryGroup, object, hint, dispose, material ) {
38689
38690         if ( ! geometryGroup.__inittedArrays ) {
38691
38692             // console.log( object );
38693             return;
38694
38695         }
38696
38697         var normalType = bufferGuessNormalType( material ),
38698         vertexColorType = bufferGuessVertexColorType( material ),
38699         uvType = bufferGuessUVType( material ),
38700
38701         needsSmoothNormals = ( normalType === THREE.SmoothShading );
38702
38703         var f, fl, fi, face,
38704         vertexNormals, faceNormal, normal,
38705         vertexColors, faceColor,
38706         vertexTangents,
38707         uv, uv2, v1, v2, v3, v4, t1, t2, t3, t4, n1, n2, n3, n4,
38708         c1, c2, c3, c4,
38709         sw1, sw2, sw3, sw4,
38710         si1, si2, si3, si4,
38711         sa1, sa2, sa3, sa4,
38712         sb1, sb2, sb3, sb4,
38713         m, ml, i, il,
38714         vn, uvi, uv2i,
38715         vk, vkl, vka,
38716         nka, chf, faceVertexNormals,
38717         a,
38718
38719         vertexIndex = 0,
38720
38721         offset = 0,
38722         offset_uv = 0,
38723         offset_uv2 = 0,
38724         offset_face = 0,
38725         offset_normal = 0,
38726         offset_tangent = 0,
38727         offset_line = 0,
38728         offset_color = 0,
38729         offset_skin = 0,
38730         offset_morphTarget = 0,
38731         offset_custom = 0,
38732         offset_customSrc = 0,
38733
38734         value,
38735
38736         vertexArray = geometryGroup.__vertexArray,
38737         uvArray = geometryGroup.__uvArray,
38738         uv2Array = geometryGroup.__uv2Array,
38739         normalArray = geometryGroup.__normalArray,
38740         tangentArray = geometryGroup.__tangentArray,
38741         colorArray = geometryGroup.__colorArray,
38742
38743         skinIndexArray = geometryGroup.__skinIndexArray,
38744         skinWeightArray = geometryGroup.__skinWeightArray,
38745
38746         morphTargetsArrays = geometryGroup.__morphTargetsArrays,
38747         morphNormalsArrays = geometryGroup.__morphNormalsArrays,
38748
38749         customAttributes = geometryGroup.__webglCustomAttributesList,
38750         customAttribute,
38751
38752         faceArray = geometryGroup.__faceArray,
38753         lineArray = geometryGroup.__lineArray,
38754
38755         geometry = object.geometry, // this is shared for all chunks
38756
38757         dirtyVertices = geometry.verticesNeedUpdate,
38758         dirtyElements = geometry.elementsNeedUpdate,
38759         dirtyUvs = geometry.uvsNeedUpdate,
38760         dirtyNormals = geometry.normalsNeedUpdate,
38761         dirtyTangents = geometry.tangentsNeedUpdate,
38762         dirtyColors = geometry.colorsNeedUpdate,
38763         dirtyMorphTargets = geometry.morphTargetsNeedUpdate,
38764
38765         vertices = geometry.vertices,
38766         chunk_faces3 = geometryGroup.faces3,
38767         chunk_faces4 = geometryGroup.faces4,
38768         obj_faces = geometry.faces,
38769
38770         obj_uvs  = geometry.faceVertexUvs[ 0 ],
38771         obj_uvs2 = geometry.faceVertexUvs[ 1 ],
38772
38773         obj_colors = geometry.colors,
38774
38775         obj_skinIndices = geometry.skinIndices,
38776         obj_skinWeights = geometry.skinWeights,
38777
38778         morphTargets = geometry.morphTargets,
38779         morphNormals = geometry.morphNormals;
38780
38781         if ( dirtyVertices ) {
38782
38783             for ( f = 0, fl = chunk_faces3.length; f < fl; f ++ ) {
38784
38785                 face = obj_faces[ chunk_faces3[ f ] ];
38786
38787                 v1 = vertices[ face.a ];
38788                 v2 = vertices[ face.b ];
38789                 v3 = vertices[ face.c ];
38790
38791                 vertexArray[ offset ]     = v1.x;
38792                 vertexArray[ offset + 1 ] = v1.y;
38793                 vertexArray[ offset + 2 ] = v1.z;
38794
38795                 vertexArray[ offset + 3 ] = v2.x;
38796                 vertexArray[ offset + 4 ] = v2.y;
38797                 vertexArray[ offset + 5 ] = v2.z;
38798
38799                 vertexArray[ offset + 6 ] = v3.x;
38800                 vertexArray[ offset + 7 ] = v3.y;
38801                 vertexArray[ offset + 8 ] = v3.z;
38802
38803                 offset += 9;
38804
38805             }
38806
38807             for ( f = 0, fl = chunk_faces4.length; f < fl; f ++ ) {
38808
38809                 face = obj_faces[ chunk_faces4[ f ] ];
38810
38811                 v1 = vertices[ face.a ];
38812                 v2 = vertices[ face.b ];
38813                 v3 = vertices[ face.c ];
38814                 v4 = vertices[ face.d ];
38815
38816                 vertexArray[ offset ]     = v1.x;
38817                 vertexArray[ offset + 1 ] = v1.y;
38818                 vertexArray[ offset + 2 ] = v1.z;
38819
38820                 vertexArray[ offset + 3 ] = v2.x;
38821                 vertexArray[ offset + 4 ] = v2.y;
38822                 vertexArray[ offset + 5 ] = v2.z;
38823
38824                 vertexArray[ offset + 6 ] = v3.x;
38825                 vertexArray[ offset + 7 ] = v3.y;
38826                 vertexArray[ offset + 8 ] = v3.z;
38827
38828                 vertexArray[ offset + 9 ]  = v4.x;
38829                 vertexArray[ offset + 10 ] = v4.y;
38830                 vertexArray[ offset + 11 ] = v4.z;
38831
38832                 offset += 12;
38833
38834             }
38835
38836             _gl.bindBuffer( _gl.ARRAY_BUFFER, geometryGroup.__webglVertexBuffer );
38837             _gl.bufferData( _gl.ARRAY_BUFFER, vertexArray, hint );
38838
38839         }
38840
38841         if ( dirtyMorphTargets ) {
38842
38843             for ( vk = 0, vkl = morphTargets.length; vk < vkl; vk ++ ) {
38844
38845                 offset_morphTarget = 0;
38846
38847                 for ( f = 0, fl = chunk_faces3.length; f < fl; f ++ ) {
38848
38849                     chf = chunk_faces3[ f ];
38850                     face = obj_faces[ chf ];
38851
38852                     // morph positions
38853
38854                     v1 = morphTargets[ vk ].vertices[ face.a ];
38855                     v2 = morphTargets[ vk ].vertices[ face.b ];
38856                     v3 = morphTargets[ vk ].vertices[ face.c ];
38857
38858                     vka = morphTargetsArrays[ vk ];
38859
38860                     vka[ offset_morphTarget ]       = v1.x;
38861                     vka[ offset_morphTarget + 1 ] = v1.y;
38862                     vka[ offset_morphTarget + 2 ] = v1.z;
38863
38864                     vka[ offset_morphTarget + 3 ] = v2.x;
38865                     vka[ offset_morphTarget + 4 ] = v2.y;
38866                     vka[ offset_morphTarget + 5 ] = v2.z;
38867
38868                     vka[ offset_morphTarget + 6 ] = v3.x;
38869                     vka[ offset_morphTarget + 7 ] = v3.y;
38870                     vka[ offset_morphTarget + 8 ] = v3.z;
38871
38872                     // morph normals
38873
38874                     if ( material.morphNormals ) {
38875
38876                         if ( needsSmoothNormals ) {
38877
38878                             faceVertexNormals = morphNormals[ vk ].vertexNormals[ chf ];
38879
38880                             n1 = faceVertexNormals.a;
38881                             n2 = faceVertexNormals.b;
38882                             n3 = faceVertexNormals.c;
38883
38884                         } else {
38885
38886                             n1 = morphNormals[ vk ].faceNormals[ chf ];
38887                             n2 = n1;
38888                             n3 = n1;
38889
38890                         }
38891
38892                         nka = morphNormalsArrays[ vk ];
38893
38894                         nka[ offset_morphTarget ]       = n1.x;
38895                         nka[ offset_morphTarget + 1 ] = n1.y;
38896                         nka[ offset_morphTarget + 2 ] = n1.z;
38897
38898                         nka[ offset_morphTarget + 3 ] = n2.x;
38899                         nka[ offset_morphTarget + 4 ] = n2.y;
38900                         nka[ offset_morphTarget + 5 ] = n2.z;
38901
38902                         nka[ offset_morphTarget + 6 ] = n3.x;
38903                         nka[ offset_morphTarget + 7 ] = n3.y;
38904                         nka[ offset_morphTarget + 8 ] = n3.z;
38905
38906                     }
38907
38908                     //
38909
38910                     offset_morphTarget += 9;
38911
38912                 }
38913
38914                 for ( f = 0, fl = chunk_faces4.length; f < fl; f ++ ) {
38915
38916                     chf = chunk_faces4[ f ];
38917                     face = obj_faces[ chf ];
38918
38919                     // morph positions
38920
38921                     v1 = morphTargets[ vk ].vertices[ face.a ];
38922                     v2 = morphTargets[ vk ].vertices[ face.b ];
38923                     v3 = morphTargets[ vk ].vertices[ face.c ];
38924                     v4 = morphTargets[ vk ].vertices[ face.d ];
38925
38926                     vka = morphTargetsArrays[ vk ];
38927
38928                     vka[ offset_morphTarget ]       = v1.x;
38929                     vka[ offset_morphTarget + 1 ] = v1.y;
38930                     vka[ offset_morphTarget + 2 ] = v1.z;
38931
38932                     vka[ offset_morphTarget + 3 ] = v2.x;
38933                     vka[ offset_morphTarget + 4 ] = v2.y;
38934                     vka[ offset_morphTarget + 5 ] = v2.z;
38935
38936                     vka[ offset_morphTarget + 6 ] = v3.x;
38937                     vka[ offset_morphTarget + 7 ] = v3.y;
38938                     vka[ offset_morphTarget + 8 ] = v3.z;
38939
38940                     vka[ offset_morphTarget + 9 ]  = v4.x;
38941                     vka[ offset_morphTarget + 10 ] = v4.y;
38942                     vka[ offset_morphTarget + 11 ] = v4.z;
38943
38944                     // morph normals
38945
38946                     if ( material.morphNormals ) {
38947
38948                         if ( needsSmoothNormals ) {
38949
38950                             faceVertexNormals = morphNormals[ vk ].vertexNormals[ chf ];
38951
38952                             n1 = faceVertexNormals.a;
38953                             n2 = faceVertexNormals.b;
38954                             n3 = faceVertexNormals.c;
38955                             n4 = faceVertexNormals.d;
38956
38957                         } else {
38958
38959                             n1 = morphNormals[ vk ].faceNormals[ chf ];
38960                             n2 = n1;
38961                             n3 = n1;
38962                             n4 = n1;
38963
38964                         }
38965
38966                         nka = morphNormalsArrays[ vk ];
38967
38968                         nka[ offset_morphTarget ]       = n1.x;
38969                         nka[ offset_morphTarget + 1 ] = n1.y;
38970                         nka[ offset_morphTarget + 2 ] = n1.z;
38971
38972                         nka[ offset_morphTarget + 3 ] = n2.x;
38973                         nka[ offset_morphTarget + 4 ] = n2.y;
38974                         nka[ offset_morphTarget + 5 ] = n2.z;
38975
38976                         nka[ offset_morphTarget + 6 ] = n3.x;
38977                         nka[ offset_morphTarget + 7 ] = n3.y;
38978                         nka[ offset_morphTarget + 8 ] = n3.z;
38979
38980                         nka[ offset_morphTarget + 9 ]  = n4.x;
38981                         nka[ offset_morphTarget + 10 ] = n4.y;
38982                         nka[ offset_morphTarget + 11 ] = n4.z;
38983
38984                     }
38985
38986                     //
38987
38988                     offset_morphTarget += 12;
38989
38990                 }
38991
38992                 _gl.bindBuffer( _gl.ARRAY_BUFFER, geometryGroup.__webglMorphTargetsBuffers[ vk ] );
38993                 _gl.bufferData( _gl.ARRAY_BUFFER, morphTargetsArrays[ vk ], hint );
38994
38995                 if ( material.morphNormals ) {
38996
38997                     _gl.bindBuffer( _gl.ARRAY_BUFFER, geometryGroup.__webglMorphNormalsBuffers[ vk ] );
38998                     _gl.bufferData( _gl.ARRAY_BUFFER, morphNormalsArrays[ vk ], hint );
38999
39000                 }
39001
39002             }
39003
39004         }
39005
39006         if ( obj_skinWeights.length ) {
39007
39008             for ( f = 0, fl = chunk_faces3.length; f < fl; f ++ ) {
39009
39010                 face = obj_faces[ chunk_faces3[ f ]    ];
39011
39012                 // weights
39013
39014                 sw1 = obj_skinWeights[ face.a ];
39015                 sw2 = obj_skinWeights[ face.b ];
39016                 sw3 = obj_skinWeights[ face.c ];
39017
39018                 skinWeightArray[ offset_skin ]     = sw1.x;
39019                 skinWeightArray[ offset_skin + 1 ] = sw1.y;
39020                 skinWeightArray[ offset_skin + 2 ] = sw1.z;
39021                 skinWeightArray[ offset_skin + 3 ] = sw1.w;
39022
39023                 skinWeightArray[ offset_skin + 4 ] = sw2.x;
39024                 skinWeightArray[ offset_skin + 5 ] = sw2.y;
39025                 skinWeightArray[ offset_skin + 6 ] = sw2.z;
39026                 skinWeightArray[ offset_skin + 7 ] = sw2.w;
39027
39028                 skinWeightArray[ offset_skin + 8 ]  = sw3.x;
39029                 skinWeightArray[ offset_skin + 9 ]  = sw3.y;
39030                 skinWeightArray[ offset_skin + 10 ] = sw3.z;
39031                 skinWeightArray[ offset_skin + 11 ] = sw3.w;
39032
39033                 // indices
39034
39035                 si1 = obj_skinIndices[ face.a ];
39036                 si2 = obj_skinIndices[ face.b ];
39037                 si3 = obj_skinIndices[ face.c ];
39038
39039                 skinIndexArray[ offset_skin ]     = si1.x;
39040                 skinIndexArray[ offset_skin + 1 ] = si1.y;
39041                 skinIndexArray[ offset_skin + 2 ] = si1.z;
39042                 skinIndexArray[ offset_skin + 3 ] = si1.w;
39043
39044                 skinIndexArray[ offset_skin + 4 ] = si2.x;
39045                 skinIndexArray[ offset_skin + 5 ] = si2.y;
39046                 skinIndexArray[ offset_skin + 6 ] = si2.z;
39047                 skinIndexArray[ offset_skin + 7 ] = si2.w;
39048
39049                 skinIndexArray[ offset_skin + 8 ]  = si3.x;
39050                 skinIndexArray[ offset_skin + 9 ]  = si3.y;
39051                 skinIndexArray[ offset_skin + 10 ] = si3.z;
39052                 skinIndexArray[ offset_skin + 11 ] = si3.w;
39053
39054                 offset_skin += 12;
39055
39056             }
39057
39058             for ( f = 0, fl = chunk_faces4.length; f < fl; f ++ ) {
39059
39060                 face = obj_faces[ chunk_faces4[ f ] ];
39061
39062                 // weights
39063
39064                 sw1 = obj_skinWeights[ face.a ];
39065                 sw2 = obj_skinWeights[ face.b ];
39066                 sw3 = obj_skinWeights[ face.c ];
39067                 sw4 = obj_skinWeights[ face.d ];
39068
39069                 skinWeightArray[ offset_skin ]     = sw1.x;
39070                 skinWeightArray[ offset_skin + 1 ] = sw1.y;
39071                 skinWeightArray[ offset_skin + 2 ] = sw1.z;
39072                 skinWeightArray[ offset_skin + 3 ] = sw1.w;
39073
39074                 skinWeightArray[ offset_skin + 4 ] = sw2.x;
39075                 skinWeightArray[ offset_skin + 5 ] = sw2.y;
39076                 skinWeightArray[ offset_skin + 6 ] = sw2.z;
39077                 skinWeightArray[ offset_skin + 7 ] = sw2.w;
39078
39079                 skinWeightArray[ offset_skin + 8 ]  = sw3.x;
39080                 skinWeightArray[ offset_skin + 9 ]  = sw3.y;
39081                 skinWeightArray[ offset_skin + 10 ] = sw3.z;
39082                 skinWeightArray[ offset_skin + 11 ] = sw3.w;
39083
39084                 skinWeightArray[ offset_skin + 12 ] = sw4.x;
39085                 skinWeightArray[ offset_skin + 13 ] = sw4.y;
39086                 skinWeightArray[ offset_skin + 14 ] = sw4.z;
39087                 skinWeightArray[ offset_skin + 15 ] = sw4.w;
39088
39089                 // indices
39090
39091                 si1 = obj_skinIndices[ face.a ];
39092                 si2 = obj_skinIndices[ face.b ];
39093                 si3 = obj_skinIndices[ face.c ];
39094                 si4 = obj_skinIndices[ face.d ];
39095
39096                 skinIndexArray[ offset_skin ]     = si1.x;
39097                 skinIndexArray[ offset_skin + 1 ] = si1.y;
39098                 skinIndexArray[ offset_skin + 2 ] = si1.z;
39099                 skinIndexArray[ offset_skin + 3 ] = si1.w;
39100
39101                 skinIndexArray[ offset_skin + 4 ] = si2.x;
39102                 skinIndexArray[ offset_skin + 5 ] = si2.y;
39103                 skinIndexArray[ offset_skin + 6 ] = si2.z;
39104                 skinIndexArray[ offset_skin + 7 ] = si2.w;
39105
39106                 skinIndexArray[ offset_skin + 8 ]  = si3.x;
39107                 skinIndexArray[ offset_skin + 9 ]  = si3.y;
39108                 skinIndexArray[ offset_skin + 10 ] = si3.z;
39109                 skinIndexArray[ offset_skin + 11 ] = si3.w;
39110
39111                 skinIndexArray[ offset_skin + 12 ] = si4.x;
39112                 skinIndexArray[ offset_skin + 13 ] = si4.y;
39113                 skinIndexArray[ offset_skin + 14 ] = si4.z;
39114                 skinIndexArray[ offset_skin + 15 ] = si4.w;
39115
39116                 offset_skin += 16;
39117
39118             }
39119
39120             if ( offset_skin > 0 ) {
39121
39122                 _gl.bindBuffer( _gl.ARRAY_BUFFER, geometryGroup.__webglSkinIndicesBuffer );
39123                 _gl.bufferData( _gl.ARRAY_BUFFER, skinIndexArray, hint );
39124
39125                 _gl.bindBuffer( _gl.ARRAY_BUFFER, geometryGroup.__webglSkinWeightsBuffer );
39126                 _gl.bufferData( _gl.ARRAY_BUFFER, skinWeightArray, hint );
39127
39128             }
39129
39130         }
39131
39132         if ( dirtyColors && vertexColorType ) {
39133
39134             for ( f = 0, fl = chunk_faces3.length; f < fl; f ++ ) {
39135
39136                 face = obj_faces[ chunk_faces3[ f ]    ];
39137
39138                 vertexColors = face.vertexColors;
39139                 faceColor = face.color;
39140
39141                 if ( vertexColors.length === 3 && vertexColorType === THREE.VertexColors ) {
39142
39143                     c1 = vertexColors[ 0 ];
39144                     c2 = vertexColors[ 1 ];
39145                     c3 = vertexColors[ 2 ];
39146
39147                 } else {
39148
39149                     c1 = faceColor;
39150                     c2 = faceColor;
39151                     c3 = faceColor;
39152
39153                 }
39154
39155                 colorArray[ offset_color ]     = c1.r;
39156                 colorArray[ offset_color + 1 ] = c1.g;
39157                 colorArray[ offset_color + 2 ] = c1.b;
39158
39159                 colorArray[ offset_color + 3 ] = c2.r;
39160                 colorArray[ offset_color + 4 ] = c2.g;
39161                 colorArray[ offset_color + 5 ] = c2.b;
39162
39163                 colorArray[ offset_color + 6 ] = c3.r;
39164                 colorArray[ offset_color + 7 ] = c3.g;
39165                 colorArray[ offset_color + 8 ] = c3.b;
39166
39167                 offset_color += 9;
39168
39169             }
39170
39171             for ( f = 0, fl = chunk_faces4.length; f < fl; f ++ ) {
39172
39173                 face = obj_faces[ chunk_faces4[ f ] ];
39174
39175                 vertexColors = face.vertexColors;
39176                 faceColor = face.color;
39177
39178                 if ( vertexColors.length === 4 && vertexColorType === THREE.VertexColors ) {
39179
39180                     c1 = vertexColors[ 0 ];
39181                     c2 = vertexColors[ 1 ];
39182                     c3 = vertexColors[ 2 ];
39183                     c4 = vertexColors[ 3 ];
39184
39185                 } else {
39186
39187                     c1 = faceColor;
39188                     c2 = faceColor;
39189                     c3 = faceColor;
39190                     c4 = faceColor;
39191
39192                 }
39193
39194                 colorArray[ offset_color ]     = c1.r;
39195                 colorArray[ offset_color + 1 ] = c1.g;
39196                 colorArray[ offset_color + 2 ] = c1.b;
39197
39198                 colorArray[ offset_color + 3 ] = c2.r;
39199                 colorArray[ offset_color + 4 ] = c2.g;
39200                 colorArray[ offset_color + 5 ] = c2.b;
39201
39202                 colorArray[ offset_color + 6 ] = c3.r;
39203                 colorArray[ offset_color + 7 ] = c3.g;
39204                 colorArray[ offset_color + 8 ] = c3.b;
39205
39206                 colorArray[ offset_color + 9 ]  = c4.r;
39207                 colorArray[ offset_color + 10 ] = c4.g;
39208                 colorArray[ offset_color + 11 ] = c4.b;
39209
39210                 offset_color += 12;
39211
39212             }
39213
39214             if ( offset_color > 0 ) {
39215
39216                 _gl.bindBuffer( _gl.ARRAY_BUFFER, geometryGroup.__webglColorBuffer );
39217                 _gl.bufferData( _gl.ARRAY_BUFFER, colorArray, hint );
39218
39219             }
39220
39221         }
39222
39223         if ( dirtyTangents && geometry.hasTangents ) {
39224
39225             for ( f = 0, fl = chunk_faces3.length; f < fl; f ++ ) {
39226
39227                 face = obj_faces[ chunk_faces3[ f ]    ];
39228
39229                 vertexTangents = face.vertexTangents;
39230
39231                 t1 = vertexTangents[ 0 ];
39232                 t2 = vertexTangents[ 1 ];
39233                 t3 = vertexTangents[ 2 ];
39234
39235                 tangentArray[ offset_tangent ]     = t1.x;
39236                 tangentArray[ offset_tangent + 1 ] = t1.y;
39237                 tangentArray[ offset_tangent + 2 ] = t1.z;
39238                 tangentArray[ offset_tangent + 3 ] = t1.w;
39239
39240                 tangentArray[ offset_tangent + 4 ] = t2.x;
39241                 tangentArray[ offset_tangent + 5 ] = t2.y;
39242                 tangentArray[ offset_tangent + 6 ] = t2.z;
39243                 tangentArray[ offset_tangent + 7 ] = t2.w;
39244
39245                 tangentArray[ offset_tangent + 8 ]  = t3.x;
39246                 tangentArray[ offset_tangent + 9 ]  = t3.y;
39247                 tangentArray[ offset_tangent + 10 ] = t3.z;
39248                 tangentArray[ offset_tangent + 11 ] = t3.w;
39249
39250                 offset_tangent += 12;
39251
39252             }
39253
39254             for ( f = 0, fl = chunk_faces4.length; f < fl; f ++ ) {
39255
39256                 face = obj_faces[ chunk_faces4[ f ] ];
39257
39258                 vertexTangents = face.vertexTangents;
39259
39260                 t1 = vertexTangents[ 0 ];
39261                 t2 = vertexTangents[ 1 ];
39262                 t3 = vertexTangents[ 2 ];
39263                 t4 = vertexTangents[ 3 ];
39264
39265                 tangentArray[ offset_tangent ]     = t1.x;
39266                 tangentArray[ offset_tangent + 1 ] = t1.y;
39267                 tangentArray[ offset_tangent + 2 ] = t1.z;
39268                 tangentArray[ offset_tangent + 3 ] = t1.w;
39269
39270                 tangentArray[ offset_tangent + 4 ] = t2.x;
39271                 tangentArray[ offset_tangent + 5 ] = t2.y;
39272                 tangentArray[ offset_tangent + 6 ] = t2.z;
39273                 tangentArray[ offset_tangent + 7 ] = t2.w;
39274
39275                 tangentArray[ offset_tangent + 8 ]  = t3.x;
39276                 tangentArray[ offset_tangent + 9 ]  = t3.y;
39277                 tangentArray[ offset_tangent + 10 ] = t3.z;
39278                 tangentArray[ offset_tangent + 11 ] = t3.w;
39279
39280                 tangentArray[ offset_tangent + 12 ] = t4.x;
39281                 tangentArray[ offset_tangent + 13 ] = t4.y;
39282                 tangentArray[ offset_tangent + 14 ] = t4.z;
39283                 tangentArray[ offset_tangent + 15 ] = t4.w;
39284
39285                 offset_tangent += 16;
39286
39287             }
39288
39289             _gl.bindBuffer( _gl.ARRAY_BUFFER, geometryGroup.__webglTangentBuffer );
39290             _gl.bufferData( _gl.ARRAY_BUFFER, tangentArray, hint );
39291
39292         }
39293
39294         if ( dirtyNormals && normalType ) {
39295
39296             for ( f = 0, fl = chunk_faces3.length; f < fl; f ++ ) {
39297
39298                 face = obj_faces[ chunk_faces3[ f ]    ];
39299
39300                 vertexNormals = face.vertexNormals;
39301                 faceNormal = face.normal;
39302
39303                 if ( vertexNormals.length === 3 && needsSmoothNormals ) {
39304
39305                     for ( i = 0; i < 3; i ++ ) {
39306
39307                         vn = vertexNormals[ i ];
39308
39309                         normalArray[ offset_normal ]     = vn.x;
39310                         normalArray[ offset_normal + 1 ] = vn.y;
39311                         normalArray[ offset_normal + 2 ] = vn.z;
39312
39313                         offset_normal += 3;
39314
39315                     }
39316
39317                 } else {
39318
39319                     for ( i = 0; i < 3; i ++ ) {
39320
39321                         normalArray[ offset_normal ]     = faceNormal.x;
39322                         normalArray[ offset_normal + 1 ] = faceNormal.y;
39323                         normalArray[ offset_normal + 2 ] = faceNormal.z;
39324
39325                         offset_normal += 3;
39326
39327                     }
39328
39329                 }
39330
39331             }
39332
39333             for ( f = 0, fl = chunk_faces4.length; f < fl; f ++ ) {
39334
39335                 face = obj_faces[ chunk_faces4[ f ] ];
39336
39337                 vertexNormals = face.vertexNormals;
39338                 faceNormal = face.normal;
39339
39340                 if ( vertexNormals.length === 4 && needsSmoothNormals ) {
39341
39342                     for ( i = 0; i < 4; i ++ ) {
39343
39344                         vn = vertexNormals[ i ];
39345
39346                         normalArray[ offset_normal ]     = vn.x;
39347                         normalArray[ offset_normal + 1 ] = vn.y;
39348                         normalArray[ offset_normal + 2 ] = vn.z;
39349
39350                         offset_normal += 3;
39351
39352                     }
39353
39354                 } else {
39355
39356                     for ( i = 0; i < 4; i ++ ) {
39357
39358                         normalArray[ offset_normal ]     = faceNormal.x;
39359                         normalArray[ offset_normal + 1 ] = faceNormal.y;
39360                         normalArray[ offset_normal + 2 ] = faceNormal.z;
39361
39362                         offset_normal += 3;
39363
39364                     }
39365
39366                 }
39367
39368             }
39369
39370             _gl.bindBuffer( _gl.ARRAY_BUFFER, geometryGroup.__webglNormalBuffer );
39371             _gl.bufferData( _gl.ARRAY_BUFFER, normalArray, hint );
39372
39373         }
39374
39375         if ( dirtyUvs && obj_uvs && uvType ) {
39376
39377             for ( f = 0, fl = chunk_faces3.length; f < fl; f ++ ) {
39378
39379                 fi = chunk_faces3[ f ];
39380
39381                 face = obj_faces[ fi ];
39382                 uv = obj_uvs[ fi ];
39383
39384                 if ( uv === undefined ) continue;
39385
39386                 for ( i = 0; i < 3; i ++ ) {
39387
39388                     uvi = uv[ i ];
39389
39390                     uvArray[ offset_uv ]     = uvi.u;
39391                     uvArray[ offset_uv + 1 ] = uvi.v;
39392
39393                     offset_uv += 2;
39394
39395                 }
39396
39397             }
39398
39399             for ( f = 0, fl = chunk_faces4.length; f < fl; f ++ ) {
39400
39401                 fi = chunk_faces4[ f ];
39402
39403                 face = obj_faces[ fi ];
39404                 uv = obj_uvs[ fi ];
39405
39406                 if ( uv === undefined ) continue;
39407
39408                 for ( i = 0; i < 4; i ++ ) {
39409
39410                     uvi = uv[ i ];
39411
39412                     uvArray[ offset_uv ]     = uvi.u;
39413                     uvArray[ offset_uv + 1 ] = uvi.v;
39414
39415                     offset_uv += 2;
39416
39417                 }
39418
39419             }
39420
39421             if ( offset_uv > 0 ) {
39422
39423                 _gl.bindBuffer( _gl.ARRAY_BUFFER, geometryGroup.__webglUVBuffer );
39424                 _gl.bufferData( _gl.ARRAY_BUFFER, uvArray, hint );
39425
39426             }
39427
39428         }
39429
39430         if ( dirtyUvs && obj_uvs2 && uvType ) {
39431
39432             for ( f = 0, fl = chunk_faces3.length; f < fl; f ++ ) {
39433
39434                 fi = chunk_faces3[ f ];
39435
39436                 face = obj_faces[ fi ];
39437                 uv2 = obj_uvs2[ fi ];
39438
39439                 if ( uv2 === undefined ) continue;
39440
39441                 for ( i = 0; i < 3; i ++ ) {
39442
39443                     uv2i = uv2[ i ];
39444
39445                     uv2Array[ offset_uv2 ]     = uv2i.u;
39446                     uv2Array[ offset_uv2 + 1 ] = uv2i.v;
39447
39448                     offset_uv2 += 2;
39449
39450                 }
39451
39452             }
39453
39454             for ( f = 0, fl = chunk_faces4.length; f < fl; f ++ ) {
39455
39456                 fi = chunk_faces4[ f ];
39457
39458                 face = obj_faces[ fi ];
39459                 uv2 = obj_uvs2[ fi ];
39460
39461                 if ( uv2 === undefined ) continue;
39462
39463                 for ( i = 0; i < 4; i ++ ) {
39464
39465                     uv2i = uv2[ i ];
39466
39467                     uv2Array[ offset_uv2 ]     = uv2i.u;
39468                     uv2Array[ offset_uv2 + 1 ] = uv2i.v;
39469
39470                     offset_uv2 += 2;
39471
39472                 }
39473
39474             }
39475
39476             if ( offset_uv2 > 0 ) {
39477
39478                 _gl.bindBuffer( _gl.ARRAY_BUFFER, geometryGroup.__webglUV2Buffer );
39479                 _gl.bufferData( _gl.ARRAY_BUFFER, uv2Array, hint );
39480
39481             }
39482
39483         }
39484
39485         if ( dirtyElements ) {
39486
39487             for ( f = 0, fl = chunk_faces3.length; f < fl; f ++ ) {
39488
39489                 face = obj_faces[ chunk_faces3[ f ]    ];
39490
39491                 faceArray[ offset_face ]      = vertexIndex;
39492                 faceArray[ offset_face + 1 ] = vertexIndex + 1;
39493                 faceArray[ offset_face + 2 ] = vertexIndex + 2;
39494
39495                 offset_face += 3;
39496
39497                 lineArray[ offset_line ]     = vertexIndex;
39498                 lineArray[ offset_line + 1 ] = vertexIndex + 1;
39499
39500                 lineArray[ offset_line + 2 ] = vertexIndex;
39501                 lineArray[ offset_line + 3 ] = vertexIndex + 2;
39502
39503                 lineArray[ offset_line + 4 ] = vertexIndex + 1;
39504                 lineArray[ offset_line + 5 ] = vertexIndex + 2;
39505
39506                 offset_line += 6;
39507
39508                 vertexIndex += 3;
39509
39510             }
39511
39512             for ( f = 0, fl = chunk_faces4.length; f < fl; f ++ ) {
39513
39514                 face = obj_faces[ chunk_faces4[ f ] ];
39515
39516                 faceArray[ offset_face ]     = vertexIndex;
39517                 faceArray[ offset_face + 1 ] = vertexIndex + 1;
39518                 faceArray[ offset_face + 2 ] = vertexIndex + 3;
39519
39520                 faceArray[ offset_face + 3 ] = vertexIndex + 1;
39521                 faceArray[ offset_face + 4 ] = vertexIndex + 2;
39522                 faceArray[ offset_face + 5 ] = vertexIndex + 3;
39523
39524                 offset_face += 6;
39525
39526                 lineArray[ offset_line ]     = vertexIndex;
39527                 lineArray[ offset_line + 1 ] = vertexIndex + 1;
39528
39529                 lineArray[ offset_line + 2 ] = vertexIndex;
39530                 lineArray[ offset_line + 3 ] = vertexIndex + 3;
39531
39532                 lineArray[ offset_line + 4 ] = vertexIndex + 1;
39533                 lineArray[ offset_line + 5 ] = vertexIndex + 2;
39534
39535                 lineArray[ offset_line + 6 ] = vertexIndex + 2;
39536                 lineArray[ offset_line + 7 ] = vertexIndex + 3;
39537
39538                 offset_line += 8;
39539
39540                 vertexIndex += 4;
39541
39542             }
39543
39544             _gl.bindBuffer( _gl.ELEMENT_ARRAY_BUFFER, geometryGroup.__webglFaceBuffer );
39545             _gl.bufferData( _gl.ELEMENT_ARRAY_BUFFER, faceArray, hint );
39546
39547             _gl.bindBuffer( _gl.ELEMENT_ARRAY_BUFFER, geometryGroup.__webglLineBuffer );
39548             _gl.bufferData( _gl.ELEMENT_ARRAY_BUFFER, lineArray, hint );
39549
39550         }
39551
39552         if ( customAttributes ) {
39553
39554             for ( i = 0, il = customAttributes.length; i < il; i ++ ) {
39555
39556                 customAttribute = customAttributes[ i ];
39557
39558                 if ( ! customAttribute.__original.needsUpdate ) continue;
39559
39560                 offset_custom = 0;
39561                 offset_customSrc = 0;
39562
39563                 if ( customAttribute.size === 1 ) {
39564
39565                     if ( customAttribute.boundTo === undefined || customAttribute.boundTo === "vertices" ) {
39566
39567                         for ( f = 0, fl = chunk_faces3.length; f < fl; f ++ ) {
39568
39569                             face = obj_faces[ chunk_faces3[ f ]    ];
39570
39571                             customAttribute.array[ offset_custom ]        = customAttribute.value[ face.a ];
39572                             customAttribute.array[ offset_custom + 1 ] = customAttribute.value[ face.b ];
39573                             customAttribute.array[ offset_custom + 2 ] = customAttribute.value[ face.c ];
39574
39575                             offset_custom += 3;
39576
39577                         }
39578
39579                         for ( f = 0, fl = chunk_faces4.length; f < fl; f ++ ) {
39580
39581                             face = obj_faces[ chunk_faces4[ f ] ];
39582
39583                             customAttribute.array[ offset_custom ]        = customAttribute.value[ face.a ];
39584                             customAttribute.array[ offset_custom + 1 ] = customAttribute.value[ face.b ];
39585                             customAttribute.array[ offset_custom + 2 ] = customAttribute.value[ face.c ];
39586                             customAttribute.array[ offset_custom + 3 ] = customAttribute.value[ face.d ];
39587
39588                             offset_custom += 4;
39589
39590                         }
39591
39592                     } else if ( customAttribute.boundTo === "faces" ) {
39593
39594                         for ( f = 0, fl = chunk_faces3.length; f < fl; f ++ ) {
39595
39596                             value = customAttribute.value[ chunk_faces3[ f ] ];
39597
39598                             customAttribute.array[ offset_custom ]        = value;
39599                             customAttribute.array[ offset_custom + 1 ] = value;
39600                             customAttribute.array[ offset_custom + 2 ] = value;
39601
39602                             offset_custom += 3;
39603
39604                         }
39605
39606                         for ( f = 0, fl = chunk_faces4.length; f < fl; f ++ ) {
39607
39608                             value = customAttribute.value[ chunk_faces4[ f ] ];
39609
39610                             customAttribute.array[ offset_custom ]        = value;
39611                             customAttribute.array[ offset_custom + 1 ] = value;
39612                             customAttribute.array[ offset_custom + 2 ] = value;
39613                             customAttribute.array[ offset_custom + 3 ] = value;
39614
39615                             offset_custom += 4;
39616
39617                         }
39618
39619                     }
39620
39621                 } else if ( customAttribute.size === 2 ) {
39622
39623                     if ( customAttribute.boundTo === undefined || customAttribute.boundTo === "vertices" ) {
39624
39625                         for ( f = 0, fl = chunk_faces3.length; f < fl; f ++ ) {
39626
39627                             face = obj_faces[ chunk_faces3[ f ]    ];
39628
39629                             v1 = customAttribute.value[ face.a ];
39630                             v2 = customAttribute.value[ face.b ];
39631                             v3 = customAttribute.value[ face.c ];
39632
39633                             customAttribute.array[ offset_custom ]        = v1.x;
39634                             customAttribute.array[ offset_custom + 1 ] = v1.y;
39635
39636                             customAttribute.array[ offset_custom + 2 ] = v2.x;
39637                             customAttribute.array[ offset_custom + 3 ] = v2.y;
39638
39639                             customAttribute.array[ offset_custom + 4 ] = v3.x;
39640                             customAttribute.array[ offset_custom + 5 ] = v3.y;
39641
39642                             offset_custom += 6;
39643
39644                         }
39645
39646                         for ( f = 0, fl = chunk_faces4.length; f < fl; f ++ ) {
39647
39648                             face = obj_faces[ chunk_faces4[ f ] ];
39649
39650                             v1 = customAttribute.value[ face.a ];
39651                             v2 = customAttribute.value[ face.b ];
39652                             v3 = customAttribute.value[ face.c ];
39653                             v4 = customAttribute.value[ face.d ];
39654
39655                             customAttribute.array[ offset_custom ]        = v1.x;
39656                             customAttribute.array[ offset_custom + 1 ] = v1.y;
39657
39658                             customAttribute.array[ offset_custom + 2 ] = v2.x;
39659                             customAttribute.array[ offset_custom + 3 ] = v2.y;
39660
39661                             customAttribute.array[ offset_custom + 4 ] = v3.x;
39662                             customAttribute.array[ offset_custom + 5 ] = v3.y;
39663
39664                             customAttribute.array[ offset_custom + 6 ] = v4.x;
39665                             customAttribute.array[ offset_custom + 7 ] = v4.y;
39666
39667                             offset_custom += 8;
39668
39669                         }
39670
39671                     } else if ( customAttribute.boundTo === "faces" ) {
39672
39673                         for ( f = 0, fl = chunk_faces3.length; f < fl; f ++ ) {
39674
39675                             value = customAttribute.value[ chunk_faces3[ f ] ];
39676
39677                             v1 = value;
39678                             v2 = value;
39679                             v3 = value;
39680
39681                             customAttribute.array[ offset_custom ]        = v1.x;
39682                             customAttribute.array[ offset_custom + 1 ] = v1.y;
39683
39684                             customAttribute.array[ offset_custom + 2 ] = v2.x;
39685                             customAttribute.array[ offset_custom + 3 ] = v2.y;
39686
39687                             customAttribute.array[ offset_custom + 4 ] = v3.x;
39688                             customAttribute.array[ offset_custom + 5 ] = v3.y;
39689
39690                             offset_custom += 6;
39691
39692                         }
39693
39694                         for ( f = 0, fl = chunk_faces4.length; f < fl; f ++ ) {
39695
39696                             value = customAttribute.value[ chunk_faces4[ f ] ];
39697
39698                             v1 = value;
39699                             v2 = value;
39700                             v3 = value;
39701                             v4 = value;
39702
39703                             customAttribute.array[ offset_custom ]        = v1.x;
39704                             customAttribute.array[ offset_custom + 1 ] = v1.y;
39705
39706                             customAttribute.array[ offset_custom + 2 ] = v2.x;
39707                             customAttribute.array[ offset_custom + 3 ] = v2.y;
39708
39709                             customAttribute.array[ offset_custom + 4 ] = v3.x;
39710                             customAttribute.array[ offset_custom + 5 ] = v3.y;
39711
39712                             customAttribute.array[ offset_custom + 6 ] = v4.x;
39713                             customAttribute.array[ offset_custom + 7 ] = v4.y;
39714
39715                             offset_custom += 8;
39716
39717                         }
39718
39719                     }
39720
39721                 } else if ( customAttribute.size === 3 ) {
39722
39723                     var pp;
39724
39725                     if ( customAttribute.type === "c" ) {
39726
39727                         pp = [ "r", "g", "b" ];
39728
39729                     } else {
39730
39731                         pp = [ "x", "y", "z" ];
39732
39733                     }
39734
39735                     if ( customAttribute.boundTo === undefined || customAttribute.boundTo === "vertices" ) {
39736
39737                         for ( f = 0, fl = chunk_faces3.length; f < fl; f ++ ) {
39738
39739                             face = obj_faces[ chunk_faces3[ f ]    ];
39740
39741                             v1 = customAttribute.value[ face.a ];
39742                             v2 = customAttribute.value[ face.b ];
39743                             v3 = customAttribute.value[ face.c ];
39744
39745                             customAttribute.array[ offset_custom ]        = v1[ pp[ 0 ] ];
39746                             customAttribute.array[ offset_custom + 1 ] = v1[ pp[ 1 ] ];
39747                             customAttribute.array[ offset_custom + 2 ] = v1[ pp[ 2 ] ];
39748
39749                             customAttribute.array[ offset_custom + 3 ] = v2[ pp[ 0 ] ];
39750                             customAttribute.array[ offset_custom + 4 ] = v2[ pp[ 1 ] ];
39751                             customAttribute.array[ offset_custom + 5 ] = v2[ pp[ 2 ] ];
39752
39753                             customAttribute.array[ offset_custom + 6 ] = v3[ pp[ 0 ] ];
39754                             customAttribute.array[ offset_custom + 7 ] = v3[ pp[ 1 ] ];
39755                             customAttribute.array[ offset_custom + 8 ] = v3[ pp[ 2 ] ];
39756
39757                             offset_custom += 9;
39758
39759                         }
39760
39761                         for ( f = 0, fl = chunk_faces4.length; f < fl; f ++ ) {
39762
39763                             face = obj_faces[ chunk_faces4[ f ] ];
39764
39765                             v1 = customAttribute.value[ face.a ];
39766                             v2 = customAttribute.value[ face.b ];
39767                             v3 = customAttribute.value[ face.c ];
39768                             v4 = customAttribute.value[ face.d ];
39769
39770                             customAttribute.array[ offset_custom  ]     = v1[ pp[ 0 ] ];
39771                             customAttribute.array[ offset_custom + 1  ] = v1[ pp[ 1 ] ];
39772                             customAttribute.array[ offset_custom + 2  ] = v1[ pp[ 2 ] ];
39773
39774                             customAttribute.array[ offset_custom + 3  ] = v2[ pp[ 0 ] ];
39775                             customAttribute.array[ offset_custom + 4  ] = v2[ pp[ 1 ] ];
39776                             customAttribute.array[ offset_custom + 5  ] = v2[ pp[ 2 ] ];
39777
39778                             customAttribute.array[ offset_custom + 6  ] = v3[ pp[ 0 ] ];
39779                             customAttribute.array[ offset_custom + 7  ] = v3[ pp[ 1 ] ];
39780                             customAttribute.array[ offset_custom + 8  ] = v3[ pp[ 2 ] ];
39781
39782                             customAttribute.array[ offset_custom + 9  ] = v4[ pp[ 0 ] ];
39783                             customAttribute.array[ offset_custom + 10 ] = v4[ pp[ 1 ] ];
39784                             customAttribute.array[ offset_custom + 11 ] = v4[ pp[ 2 ] ];
39785
39786                             offset_custom += 12;
39787
39788                         }
39789
39790                     } else if ( customAttribute.boundTo === "faces" ) {
39791
39792                         for ( f = 0, fl = chunk_faces3.length; f < fl; f ++ ) {
39793
39794                             value = customAttribute.value[ chunk_faces3[ f ] ];
39795
39796                             v1 = value;
39797                             v2 = value;
39798                             v3 = value;
39799
39800                             customAttribute.array[ offset_custom ]        = v1[ pp[ 0 ] ];
39801                             customAttribute.array[ offset_custom + 1 ] = v1[ pp[ 1 ] ];
39802                             customAttribute.array[ offset_custom + 2 ] = v1[ pp[ 2 ] ];
39803
39804                             customAttribute.array[ offset_custom + 3 ] = v2[ pp[ 0 ] ];
39805                             customAttribute.array[ offset_custom + 4 ] = v2[ pp[ 1 ] ];
39806                             customAttribute.array[ offset_custom + 5 ] = v2[ pp[ 2 ] ];
39807
39808                             customAttribute.array[ offset_custom + 6 ] = v3[ pp[ 0 ] ];
39809                             customAttribute.array[ offset_custom + 7 ] = v3[ pp[ 1 ] ];
39810                             customAttribute.array[ offset_custom + 8 ] = v3[ pp[ 2 ] ];
39811
39812                             offset_custom += 9;
39813
39814                         }
39815
39816                         for ( f = 0, fl = chunk_faces4.length; f < fl; f ++ ) {
39817
39818                             value = customAttribute.value[ chunk_faces4[ f ] ];
39819
39820                             v1 = value;
39821                             v2 = value;
39822                             v3 = value;
39823                             v4 = value;
39824
39825                             customAttribute.array[ offset_custom  ]     = v1[ pp[ 0 ] ];
39826                             customAttribute.array[ offset_custom + 1  ] = v1[ pp[ 1 ] ];
39827                             customAttribute.array[ offset_custom + 2  ] = v1[ pp[ 2 ] ];
39828
39829                             customAttribute.array[ offset_custom + 3  ] = v2[ pp[ 0 ] ];
39830                             customAttribute.array[ offset_custom + 4  ] = v2[ pp[ 1 ] ];
39831                             customAttribute.array[ offset_custom + 5  ] = v2[ pp[ 2 ] ];
39832
39833                             customAttribute.array[ offset_custom + 6  ] = v3[ pp[ 0 ] ];
39834                             customAttribute.array[ offset_custom + 7  ] = v3[ pp[ 1 ] ];
39835                             customAttribute.array[ offset_custom + 8  ] = v3[ pp[ 2 ] ];
39836
39837                             customAttribute.array[ offset_custom + 9  ] = v4[ pp[ 0 ] ];
39838                             customAttribute.array[ offset_custom + 10 ] = v4[ pp[ 1 ] ];
39839                             customAttribute.array[ offset_custom + 11 ] = v4[ pp[ 2 ] ];
39840
39841                             offset_custom += 12;
39842
39843                         }
39844
39845                     } else if ( customAttribute.boundTo === "faceVertices" ) {
39846
39847                         for ( f = 0, fl = chunk_faces3.length; f < fl; f ++ ) {
39848
39849                             value = customAttribute.value[ chunk_faces3[ f ] ];
39850
39851                             v1 = value[ 0 ];
39852                             v2 = value[ 1 ];
39853                             v3 = value[ 2 ];
39854
39855                             customAttribute.array[ offset_custom ]        = v1[ pp[ 0 ] ];
39856                             customAttribute.array[ offset_custom + 1 ] = v1[ pp[ 1 ] ];
39857                             customAttribute.array[ offset_custom + 2 ] = v1[ pp[ 2 ] ];
39858
39859                             customAttribute.array[ offset_custom + 3 ] = v2[ pp[ 0 ] ];
39860                             customAttribute.array[ offset_custom + 4 ] = v2[ pp[ 1 ] ];
39861                             customAttribute.array[ offset_custom + 5 ] = v2[ pp[ 2 ] ];
39862
39863                             customAttribute.array[ offset_custom + 6 ] = v3[ pp[ 0 ] ];
39864                             customAttribute.array[ offset_custom + 7 ] = v3[ pp[ 1 ] ];
39865                             customAttribute.array[ offset_custom + 8 ] = v3[ pp[ 2 ] ];
39866
39867                             offset_custom += 9;
39868
39869                         }
39870
39871                         for ( f = 0, fl = chunk_faces4.length; f < fl; f ++ ) {
39872
39873                             value = customAttribute.value[ chunk_faces4[ f ] ];
39874
39875                             v1 = value[ 0 ];
39876                             v2 = value[ 1 ];
39877                             v3 = value[ 2 ];
39878                             v4 = value[ 3 ];
39879
39880                             customAttribute.array[ offset_custom  ]     = v1[ pp[ 0 ] ];
39881                             customAttribute.array[ offset_custom + 1  ] = v1[ pp[ 1 ] ];
39882                             customAttribute.array[ offset_custom + 2  ] = v1[ pp[ 2 ] ];
39883
39884                             customAttribute.array[ offset_custom + 3  ] = v2[ pp[ 0 ] ];
39885                             customAttribute.array[ offset_custom + 4  ] = v2[ pp[ 1 ] ];
39886                             customAttribute.array[ offset_custom + 5  ] = v2[ pp[ 2 ] ];
39887
39888                             customAttribute.array[ offset_custom + 6  ] = v3[ pp[ 0 ] ];
39889                             customAttribute.array[ offset_custom + 7  ] = v3[ pp[ 1 ] ];
39890                             customAttribute.array[ offset_custom + 8  ] = v3[ pp[ 2 ] ];
39891
39892                             customAttribute.array[ offset_custom + 9  ] = v4[ pp[ 0 ] ];
39893                             customAttribute.array[ offset_custom + 10 ] = v4[ pp[ 1 ] ];
39894                             customAttribute.array[ offset_custom + 11 ] = v4[ pp[ 2 ] ];
39895
39896                             offset_custom += 12;
39897
39898                         }
39899
39900                     }
39901
39902                 } else if ( customAttribute.size === 4 ) {
39903
39904                     if ( customAttribute.boundTo === undefined || customAttribute.boundTo === "vertices" ) {
39905
39906                         for ( f = 0, fl = chunk_faces3.length; f < fl; f ++ ) {
39907
39908                             face = obj_faces[ chunk_faces3[ f ]    ];
39909
39910                             v1 = customAttribute.value[ face.a ];
39911                             v2 = customAttribute.value[ face.b ];
39912                             v3 = customAttribute.value[ face.c ];
39913
39914                             customAttribute.array[ offset_custom  ]     = v1.x;
39915                             customAttribute.array[ offset_custom + 1  ] = v1.y;
39916                             customAttribute.array[ offset_custom + 2  ] = v1.z;
39917                             customAttribute.array[ offset_custom + 3  ] = v1.w;
39918
39919                             customAttribute.array[ offset_custom + 4  ] = v2.x;
39920                             customAttribute.array[ offset_custom + 5  ] = v2.y;
39921                             customAttribute.array[ offset_custom + 6  ] = v2.z;
39922                             customAttribute.array[ offset_custom + 7  ] = v2.w;
39923
39924                             customAttribute.array[ offset_custom + 8  ] = v3.x;
39925                             customAttribute.array[ offset_custom + 9  ] = v3.y;
39926                             customAttribute.array[ offset_custom + 10 ] = v3.z;
39927                             customAttribute.array[ offset_custom + 11 ] = v3.w;
39928
39929                             offset_custom += 12;
39930
39931                         }
39932
39933                         for ( f = 0, fl = chunk_faces4.length; f < fl; f ++ ) {
39934
39935                             face = obj_faces[ chunk_faces4[ f ] ];
39936
39937                             v1 = customAttribute.value[ face.a ];
39938                             v2 = customAttribute.value[ face.b ];
39939                             v3 = customAttribute.value[ face.c ];
39940                             v4 = customAttribute.value[ face.d ];
39941
39942                             customAttribute.array[ offset_custom  ]     = v1.x;
39943                             customAttribute.array[ offset_custom + 1  ] = v1.y;
39944                             customAttribute.array[ offset_custom + 2  ] = v1.z;
39945                             customAttribute.array[ offset_custom + 3  ] = v1.w;
39946
39947                             customAttribute.array[ offset_custom + 4  ] = v2.x;
39948                             customAttribute.array[ offset_custom + 5  ] = v2.y;
39949                             customAttribute.array[ offset_custom + 6  ] = v2.z;
39950                             customAttribute.array[ offset_custom + 7  ] = v2.w;
39951
39952                             customAttribute.array[ offset_custom + 8  ] = v3.x;
39953                             customAttribute.array[ offset_custom + 9  ] = v3.y;
39954                             customAttribute.array[ offset_custom + 10 ] = v3.z;
39955                             customAttribute.array[ offset_custom + 11 ] = v3.w;
39956
39957                             customAttribute.array[ offset_custom + 12 ] = v4.x;
39958                             customAttribute.array[ offset_custom + 13 ] = v4.y;
39959                             customAttribute.array[ offset_custom + 14 ] = v4.z;
39960                             customAttribute.array[ offset_custom + 15 ] = v4.w;
39961
39962                             offset_custom += 16;
39963
39964                         }
39965
39966                     } else if ( customAttribute.boundTo === "faces" ) {
39967
39968                         for ( f = 0, fl = chunk_faces3.length; f < fl; f ++ ) {
39969
39970                             value = customAttribute.value[ chunk_faces3[ f ] ];
39971
39972                             v1 = value;
39973                             v2 = value;
39974                             v3 = value;
39975
39976                             customAttribute.array[ offset_custom  ]     = v1.x;
39977                             customAttribute.array[ offset_custom + 1  ] = v1.y;
39978                             customAttribute.array[ offset_custom + 2  ] = v1.z;
39979                             customAttribute.array[ offset_custom + 3  ] = v1.w;
39980
39981                             customAttribute.array[ offset_custom + 4  ] = v2.x;
39982                             customAttribute.array[ offset_custom + 5  ] = v2.y;
39983                             customAttribute.array[ offset_custom + 6  ] = v2.z;
39984                             customAttribute.array[ offset_custom + 7  ] = v2.w;
39985
39986                             customAttribute.array[ offset_custom + 8  ] = v3.x;
39987                             customAttribute.array[ offset_custom + 9  ] = v3.y;
39988                             customAttribute.array[ offset_custom + 10 ] = v3.z;
39989                             customAttribute.array[ offset_custom + 11 ] = v3.w;
39990
39991                             offset_custom += 12;
39992
39993                         }
39994
39995                         for ( f = 0, fl = chunk_faces4.length; f < fl; f ++ ) {
39996
39997                             value = customAttribute.value[ chunk_faces4[ f ] ];
39998
39999                             v1 = value;
40000                             v2 = value;
40001                             v3 = value;
40002                             v4 = value;
40003
40004                             customAttribute.array[ offset_custom  ]     = v1.x;
40005                             customAttribute.array[ offset_custom + 1  ] = v1.y;
40006                             customAttribute.array[ offset_custom + 2  ] = v1.z;
40007                             customAttribute.array[ offset_custom + 3  ] = v1.w;
40008
40009                             customAttribute.array[ offset_custom + 4  ] = v2.x;
40010                             customAttribute.array[ offset_custom + 5  ] = v2.y;
40011                             customAttribute.array[ offset_custom + 6  ] = v2.z;
40012                             customAttribute.array[ offset_custom + 7  ] = v2.w;
40013
40014                             customAttribute.array[ offset_custom + 8  ] = v3.x;
40015                             customAttribute.array[ offset_custom + 9  ] = v3.y;
40016                             customAttribute.array[ offset_custom + 10 ] = v3.z;
40017                             customAttribute.array[ offset_custom + 11 ] = v3.w;
40018
40019                             customAttribute.array[ offset_custom + 12 ] = v4.x;
40020                             customAttribute.array[ offset_custom + 13 ] = v4.y;
40021                             customAttribute.array[ offset_custom + 14 ] = v4.z;
40022                             customAttribute.array[ offset_custom + 15 ] = v4.w;
40023
40024                             offset_custom += 16;
40025
40026                         }
40027
40028                     } else if ( customAttribute.boundTo === "faceVertices" ) {
40029
40030                         for ( f = 0, fl = chunk_faces3.length; f < fl; f ++ ) {
40031
40032                             value = customAttribute.value[ chunk_faces3[ f ] ];
40033
40034                             v1 = value[ 0 ];
40035                             v2 = value[ 1 ];
40036                             v3 = value[ 2 ];
40037
40038                             customAttribute.array[ offset_custom  ]     = v1.x;
40039                             customAttribute.array[ offset_custom + 1  ] = v1.y;
40040                             customAttribute.array[ offset_custom + 2  ] = v1.z;
40041                             customAttribute.array[ offset_custom + 3  ] = v1.w;
40042
40043                             customAttribute.array[ offset_custom + 4  ] = v2.x;
40044                             customAttribute.array[ offset_custom + 5  ] = v2.y;
40045                             customAttribute.array[ offset_custom + 6  ] = v2.z;
40046                             customAttribute.array[ offset_custom + 7  ] = v2.w;
40047
40048                             customAttribute.array[ offset_custom + 8  ] = v3.x;
40049                             customAttribute.array[ offset_custom + 9  ] = v3.y;
40050                             customAttribute.array[ offset_custom + 10 ] = v3.z;
40051                             customAttribute.array[ offset_custom + 11 ] = v3.w;
40052
40053                             offset_custom += 12;
40054
40055                         }
40056
40057                         for ( f = 0, fl = chunk_faces4.length; f < fl; f ++ ) {
40058
40059                             value = customAttribute.value[ chunk_faces4[ f ] ];
40060
40061                             v1 = value[ 0 ];
40062                             v2 = value[ 1 ];
40063                             v3 = value[ 2 ];
40064                             v4 = value[ 3 ];
40065
40066                             customAttribute.array[ offset_custom  ]     = v1.x;
40067                             customAttribute.array[ offset_custom + 1  ] = v1.y;
40068                             customAttribute.array[ offset_custom + 2  ] = v1.z;
40069                             customAttribute.array[ offset_custom + 3  ] = v1.w;
40070
40071                             customAttribute.array[ offset_custom + 4  ] = v2.x;
40072                             customAttribute.array[ offset_custom + 5  ] = v2.y;
40073                             customAttribute.array[ offset_custom + 6  ] = v2.z;
40074                             customAttribute.array[ offset_custom + 7  ] = v2.w;
40075
40076                             customAttribute.array[ offset_custom + 8  ] = v3.x;
40077                             customAttribute.array[ offset_custom + 9  ] = v3.y;
40078                             customAttribute.array[ offset_custom + 10 ] = v3.z;
40079                             customAttribute.array[ offset_custom + 11 ] = v3.w;
40080
40081                             customAttribute.array[ offset_custom + 12 ] = v4.x;
40082                             customAttribute.array[ offset_custom + 13 ] = v4.y;
40083                             customAttribute.array[ offset_custom + 14 ] = v4.z;
40084                             customAttribute.array[ offset_custom + 15 ] = v4.w;
40085
40086                             offset_custom += 16;
40087
40088                         }
40089
40090                     }
40091
40092                 }
40093
40094                 _gl.bindBuffer( _gl.ARRAY_BUFFER, customAttribute.buffer );
40095                 _gl.bufferData( _gl.ARRAY_BUFFER, customAttribute.array, hint );
40096
40097             }
40098
40099         }
40100
40101         if ( dispose ) {
40102
40103             delete geometryGroup.__inittedArrays;
40104             delete geometryGroup.__colorArray;
40105             delete geometryGroup.__normalArray;
40106             delete geometryGroup.__tangentArray;
40107             delete geometryGroup.__uvArray;
40108             delete geometryGroup.__uv2Array;
40109             delete geometryGroup.__faceArray;
40110             delete geometryGroup.__vertexArray;
40111             delete geometryGroup.__lineArray;
40112             delete geometryGroup.__skinIndexArray;
40113             delete geometryGroup.__skinWeightArray;
40114
40115         }
40116
40117     };
40118
40119     function setDirectBuffers ( geometry, hint, dispose ) {
40120
40121         var attributes = geometry.attributes;
40122
40123         var index = attributes[ "index" ];
40124         var position = attributes[ "position" ];
40125         var normal = attributes[ "normal" ];
40126         var uv = attributes[ "uv" ];
40127         var color = attributes[ "color" ];
40128         var tangent = attributes[ "tangent" ];
40129
40130         if ( geometry.elementsNeedUpdate && index !== undefined ) {
40131
40132             _gl.bindBuffer( _gl.ELEMENT_ARRAY_BUFFER, index.buffer );
40133             _gl.bufferData( _gl.ELEMENT_ARRAY_BUFFER, index.array, hint );
40134
40135         }
40136
40137         if ( geometry.verticesNeedUpdate && position !== undefined ) {
40138
40139             _gl.bindBuffer( _gl.ARRAY_BUFFER, position.buffer );
40140             _gl.bufferData( _gl.ARRAY_BUFFER, position.array, hint );
40141
40142         }
40143
40144         if ( geometry.normalsNeedUpdate && normal !== undefined ) {
40145
40146             _gl.bindBuffer( _gl.ARRAY_BUFFER, normal.buffer );
40147             _gl.bufferData( _gl.ARRAY_BUFFER, normal.array, hint );
40148
40149         }
40150
40151         if ( geometry.uvsNeedUpdate && uv !== undefined ) {
40152
40153             _gl.bindBuffer( _gl.ARRAY_BUFFER, uv.buffer );
40154             _gl.bufferData( _gl.ARRAY_BUFFER, uv.array, hint );
40155
40156         }
40157
40158         if ( geometry.colorsNeedUpdate && color !== undefined ) {
40159
40160             _gl.bindBuffer( _gl.ARRAY_BUFFER, color.buffer );
40161             _gl.bufferData( _gl.ARRAY_BUFFER, color.array, hint );
40162
40163         }
40164
40165         if ( geometry.tangentsNeedUpdate && tangent !== undefined ) {
40166
40167             _gl.bindBuffer( _gl.ARRAY_BUFFER, tangent.buffer );
40168             _gl.bufferData( _gl.ARRAY_BUFFER, tangent.array, hint );
40169
40170         }
40171
40172         if ( dispose ) {
40173
40174             for ( var i in geometry.attributes ) {
40175
40176                 delete geometry.attributes[ i ].array;
40177
40178             }
40179
40180         }
40181
40182     };
40183
40184     // Buffer rendering
40185
40186     this.renderBufferImmediate = function ( object, program, material ) {
40187
40188         if ( object.hasPositions && ! object.__webglVertexBuffer ) object.__webglVertexBuffer = _gl.createBuffer();
40189         if ( object.hasNormals && ! object.__webglNormalBuffer ) object.__webglNormalBuffer = _gl.createBuffer();
40190         if ( object.hasUvs && ! object.__webglUvBuffer ) object.__webglUvBuffer = _gl.createBuffer();
40191         if ( object.hasColors && ! object.__webglColorBuffer ) object.__webglColorBuffer = _gl.createBuffer();
40192
40193         if ( object.hasPositions ) {
40194
40195             _gl.bindBuffer( _gl.ARRAY_BUFFER, object.__webglVertexBuffer );
40196             _gl.bufferData( _gl.ARRAY_BUFFER, object.positionArray, _gl.DYNAMIC_DRAW );
40197             _gl.enableVertexAttribArray( program.attributes.position );
40198             _gl.vertexAttribPointer( program.attributes.position, 3, _gl.FLOAT, false, 0, 0 );
40199
40200         }
40201
40202         if ( object.hasNormals ) {
40203
40204             _gl.bindBuffer( _gl.ARRAY_BUFFER, object.__webglNormalBuffer );
40205
40206             if ( material.shading === THREE.FlatShading ) {
40207
40208                 var nx, ny, nz,
40209                     nax, nbx, ncx, nay, nby, ncy, naz, nbz, ncz,
40210                     normalArray,
40211                     i, il = object.count * 3;
40212
40213                 for( i = 0; i < il; i += 9 ) {
40214
40215                     normalArray = object.normalArray;
40216
40217                     nax  = normalArray[ i ];
40218                     nay  = normalArray[ i + 1 ];
40219                     naz  = normalArray[ i + 2 ];
40220
40221                     nbx  = normalArray[ i + 3 ];
40222                     nby  = normalArray[ i + 4 ];
40223                     nbz  = normalArray[ i + 5 ];
40224
40225                     ncx  = normalArray[ i + 6 ];
40226                     ncy  = normalArray[ i + 7 ];
40227                     ncz  = normalArray[ i + 8 ];
40228
40229                     nx = ( nax + nbx + ncx ) / 3;
40230                     ny = ( nay + nby + ncy ) / 3;
40231                     nz = ( naz + nbz + ncz ) / 3;
40232
40233                     normalArray[ i ]      = nx;
40234                     normalArray[ i + 1 ] = ny;
40235                     normalArray[ i + 2 ] = nz;
40236
40237                     normalArray[ i + 3 ] = nx;
40238                     normalArray[ i + 4 ] = ny;
40239                     normalArray[ i + 5 ] = nz;
40240
40241                     normalArray[ i + 6 ] = nx;
40242                     normalArray[ i + 7 ] = ny;
40243                     normalArray[ i + 8 ] = nz;
40244
40245                 }
40246
40247             }
40248
40249             _gl.bufferData( _gl.ARRAY_BUFFER, object.normalArray, _gl.DYNAMIC_DRAW );
40250             _gl.enableVertexAttribArray( program.attributes.normal );
40251             _gl.vertexAttribPointer( program.attributes.normal, 3, _gl.FLOAT, false, 0, 0 );
40252
40253         }
40254
40255         if ( object.hasUvs && material.map ) {
40256
40257             _gl.bindBuffer( _gl.ARRAY_BUFFER, object.__webglUvBuffer );
40258             _gl.bufferData( _gl.ARRAY_BUFFER, object.uvArray, _gl.DYNAMIC_DRAW );
40259             _gl.enableVertexAttribArray( program.attributes.uv );
40260             _gl.vertexAttribPointer( program.attributes.uv, 2, _gl.FLOAT, false, 0, 0 );
40261
40262         }
40263
40264         if ( object.hasColors && material.vertexColors !== THREE.NoColors ) {
40265
40266             _gl.bindBuffer( _gl.ARRAY_BUFFER, object.__webglColorBuffer );
40267             _gl.bufferData( _gl.ARRAY_BUFFER, object.colorArray, _gl.DYNAMIC_DRAW );
40268             _gl.enableVertexAttribArray( program.attributes.color );
40269             _gl.vertexAttribPointer( program.attributes.color, 3, _gl.FLOAT, false, 0, 0 );
40270
40271         }
40272
40273         _gl.drawArrays( _gl.TRIANGLES, 0, object.count );
40274
40275         object.count = 0;
40276
40277     };
40278
40279     this.renderBufferDirect = function ( camera, lights, fog, material, geometry, object ) {
40280
40281         if ( material.visible === false ) return;
40282
40283         var program, attributes, linewidth, primitives, a, attribute;
40284
40285         program = setProgram( camera, lights, fog, material, object );
40286
40287         attributes = program.attributes;
40288
40289         var updateBuffers = false,
40290             wireframeBit = material.wireframe ? 1 : 0,
40291             geometryHash = ( geometry.id * 0xffffff ) + ( program.id * 2 ) + wireframeBit;
40292
40293         if ( geometryHash !== _currentGeometryGroupHash ) {
40294
40295             _currentGeometryGroupHash = geometryHash;
40296             updateBuffers = true;
40297
40298         }
40299
40300         // render mesh
40301
40302         if ( object instanceof THREE.Mesh ) {
40303
40304             var offsets = geometry.offsets;
40305
40306             // if there is more than 1 chunk
40307             // must set attribute pointers to use new offsets for each chunk
40308             // even if geometry and materials didn't change
40309
40310             if ( offsets.length > 1 ) updateBuffers = true;
40311
40312             for ( var i = 0, il = offsets.length; i < il; ++ i ) {
40313
40314                 var startIndex = offsets[ i ].index;
40315
40316                 if ( updateBuffers ) {
40317
40318                     // vertices
40319
40320                     var position = geometry.attributes[ "position" ];
40321                     var positionSize = position.itemSize;
40322
40323                     _gl.bindBuffer( _gl.ARRAY_BUFFER, position.buffer );
40324                     _gl.vertexAttribPointer( attributes.position, positionSize, _gl.FLOAT, false, 0, startIndex * positionSize * 4 ); // 4 bytes per Float32
40325
40326                     // normals
40327
40328                     var normal = geometry.attributes[ "normal" ];
40329
40330                     if ( attributes.normal >= 0 && normal ) {
40331
40332                         var normalSize = normal.itemSize;
40333
40334                         _gl.bindBuffer( _gl.ARRAY_BUFFER, normal.buffer );
40335                         _gl.vertexAttribPointer( attributes.normal, normalSize, _gl.FLOAT, false, 0, startIndex * normalSize * 4 );
40336
40337                     }
40338
40339                     // uvs
40340
40341                     var uv = geometry.attributes[ "uv" ];
40342
40343                     if ( attributes.uv >= 0 && uv ) {
40344
40345                         if ( uv.buffer ) {
40346
40347                             var uvSize = uv.itemSize;
40348
40349                             _gl.bindBuffer( _gl.ARRAY_BUFFER, uv.buffer );
40350                             _gl.vertexAttribPointer( attributes.uv, uvSize, _gl.FLOAT, false, 0, startIndex * uvSize * 4 );
40351
40352                             _gl.enableVertexAttribArray( attributes.uv );
40353
40354                         } else {
40355
40356                             _gl.disableVertexAttribArray( attributes.uv );
40357
40358                         }
40359
40360                     }
40361
40362                     // colors
40363
40364                     var color = geometry.attributes[ "color" ];
40365
40366                     if ( attributes.color >= 0 && color ) {
40367
40368                         var colorSize = color.itemSize;
40369
40370                         _gl.bindBuffer( _gl.ARRAY_BUFFER, color.buffer );
40371                         _gl.vertexAttribPointer( attributes.color, colorSize, _gl.FLOAT, false, 0, startIndex * colorSize * 4 );
40372
40373                     }
40374
40375                     // tangents
40376
40377                     var tangent = geometry.attributes[ "tangent" ];
40378
40379                     if ( attributes.tangent >= 0 && tangent ) {
40380
40381                         var tangentSize = tangent.itemSize;
40382
40383                         _gl.bindBuffer( _gl.ARRAY_BUFFER, tangent.buffer );
40384                         _gl.vertexAttribPointer( attributes.tangent, tangentSize, _gl.FLOAT, false, 0, startIndex * tangentSize * 4 );
40385
40386                     }
40387
40388                     // indices
40389
40390                     var index = geometry.attributes[ "index" ];
40391
40392                     _gl.bindBuffer( _gl.ELEMENT_ARRAY_BUFFER, index.buffer );
40393
40394                 }
40395
40396                 // render indexed triangles
40397
40398                 _gl.drawElements( _gl.TRIANGLES, offsets[ i ].count, _gl.UNSIGNED_SHORT, offsets[ i ].start * 2 ); // 2 bytes per Uint16
40399
40400                 _this.info.render.calls ++;
40401                 _this.info.render.vertices += offsets[ i ].count; // not really true, here vertices can be shared
40402                 _this.info.render.faces += offsets[ i ].count / 3;
40403
40404             }
40405
40406         // render particles
40407
40408         } else if ( object instanceof THREE.ParticleSystem ) {
40409
40410             if ( updateBuffers ) {
40411
40412                 // vertices
40413
40414                 var position = geometry.attributes[ "position" ];
40415                 var positionSize = position.itemSize;
40416
40417                 _gl.bindBuffer( _gl.ARRAY_BUFFER, position.buffer );
40418                 _gl.vertexAttribPointer( attributes.position, positionSize, _gl.FLOAT, false, 0, 0 );
40419
40420                 // colors
40421
40422                 var color = geometry.attributes[ "color" ];
40423
40424                 if ( attributes.color >= 0 && color ) {
40425
40426                     var colorSize = color.itemSize;
40427
40428                     _gl.bindBuffer( _gl.ARRAY_BUFFER, color.buffer );
40429                     _gl.vertexAttribPointer( attributes.color, colorSize, _gl.FLOAT, false, 0, 0 );
40430
40431                 }
40432
40433                 // render particles
40434
40435                 _gl.drawArrays( _gl.POINTS, 0, position.numItems / 3 );
40436
40437                 _this.info.render.calls ++;
40438                 _this.info.render.points += position.numItems / 3;
40439
40440             }
40441
40442         }
40443
40444     };
40445
40446     this.renderBuffer = function ( camera, lights, fog, material, geometryGroup, object ) {
40447
40448         if ( material.visible === false ) return;
40449
40450         var program, attributes, linewidth, primitives, a, attribute, i, il;
40451
40452         program = setProgram( camera, lights, fog, material, object );
40453
40454         attributes = program.attributes;
40455
40456         var updateBuffers = false,
40457             wireframeBit = material.wireframe ? 1 : 0,
40458             geometryGroupHash = ( geometryGroup.id * 0xffffff ) + ( program.id * 2 ) + wireframeBit;
40459
40460         if ( geometryGroupHash !== _currentGeometryGroupHash ) {
40461
40462             _currentGeometryGroupHash = geometryGroupHash;
40463             updateBuffers = true;
40464
40465         }
40466
40467         // vertices
40468
40469         if ( !material.morphTargets && attributes.position >= 0 ) {
40470
40471             if ( updateBuffers ) {
40472
40473                 _gl.bindBuffer( _gl.ARRAY_BUFFER, geometryGroup.__webglVertexBuffer );
40474                 _gl.vertexAttribPointer( attributes.position, 3, _gl.FLOAT, false, 0, 0 );
40475
40476             }
40477
40478         } else {
40479
40480             if ( object.morphTargetBase ) {
40481
40482                 setupMorphTargets( material, geometryGroup, object );
40483
40484             }
40485
40486         }
40487
40488
40489         if ( updateBuffers ) {
40490
40491             // custom attributes
40492
40493             // Use the per-geometryGroup custom attribute arrays which are setup in initMeshBuffers
40494
40495             if ( geometryGroup.__webglCustomAttributesList ) {
40496
40497                 for ( i = 0, il = geometryGroup.__webglCustomAttributesList.length; i < il; i ++ ) {
40498
40499                     attribute = geometryGroup.__webglCustomAttributesList[ i ];
40500
40501                     if( attributes[ attribute.buffer.belongsToAttribute ] >= 0 ) {
40502
40503                         _gl.bindBuffer( _gl.ARRAY_BUFFER, attribute.buffer );
40504                         _gl.vertexAttribPointer( attributes[ attribute.buffer.belongsToAttribute ], attribute.size, _gl.FLOAT, false, 0, 0 );
40505
40506                     }
40507
40508                 }
40509
40510             }
40511
40512
40513             // colors
40514
40515             if ( attributes.color >= 0 ) {
40516
40517                 _gl.bindBuffer( _gl.ARRAY_BUFFER, geometryGroup.__webglColorBuffer );
40518                 _gl.vertexAttribPointer( attributes.color, 3, _gl.FLOAT, false, 0, 0 );
40519
40520             }
40521
40522             // normals
40523
40524             if ( attributes.normal >= 0 ) {
40525
40526                 _gl.bindBuffer( _gl.ARRAY_BUFFER, geometryGroup.__webglNormalBuffer );
40527                 _gl.vertexAttribPointer( attributes.normal, 3, _gl.FLOAT, false, 0, 0 );
40528
40529             }
40530
40531             // tangents
40532
40533             if ( attributes.tangent >= 0 ) {
40534
40535                 _gl.bindBuffer( _gl.ARRAY_BUFFER, geometryGroup.__webglTangentBuffer );
40536                 _gl.vertexAttribPointer( attributes.tangent, 4, _gl.FLOAT, false, 0, 0 );
40537
40538             }
40539
40540             // uvs
40541
40542             if ( attributes.uv >= 0 ) {
40543
40544                 if ( geometryGroup.__webglUVBuffer ) {
40545
40546                     _gl.bindBuffer( _gl.ARRAY_BUFFER, geometryGroup.__webglUVBuffer );
40547                     _gl.vertexAttribPointer( attributes.uv, 2, _gl.FLOAT, false, 0, 0 );
40548
40549                     _gl.enableVertexAttribArray( attributes.uv );
40550
40551                 } else {
40552
40553                     _gl.disableVertexAttribArray( attributes.uv );
40554
40555                 }
40556
40557             }
40558
40559             if ( attributes.uv2 >= 0 ) {
40560
40561                 if ( geometryGroup.__webglUV2Buffer ) {
40562
40563                     _gl.bindBuffer( _gl.ARRAY_BUFFER, geometryGroup.__webglUV2Buffer );
40564                     _gl.vertexAttribPointer( attributes.uv2, 2, _gl.FLOAT, false, 0, 0 );
40565
40566                     _gl.enableVertexAttribArray( attributes.uv2 );
40567
40568                 } else {
40569
40570                     _gl.disableVertexAttribArray( attributes.uv2 );
40571
40572                 }
40573
40574             }
40575
40576             if ( material.skinning &&
40577                  attributes.skinIndex >= 0 && attributes.skinWeight >= 0 ) {
40578
40579                 _gl.bindBuffer( _gl.ARRAY_BUFFER, geometryGroup.__webglSkinIndicesBuffer );
40580                 _gl.vertexAttribPointer( attributes.skinIndex, 4, _gl.FLOAT, false, 0, 0 );
40581
40582                 _gl.bindBuffer( _gl.ARRAY_BUFFER, geometryGroup.__webglSkinWeightsBuffer );
40583                 _gl.vertexAttribPointer( attributes.skinWeight, 4, _gl.FLOAT, false, 0, 0 );
40584
40585             }
40586
40587         }
40588
40589         // render mesh
40590
40591         if ( object instanceof THREE.Mesh ) {
40592
40593             // wireframe
40594
40595             if ( material.wireframe ) {
40596
40597                 setLineWidth( material.wireframeLinewidth );
40598
40599                 if ( updateBuffers ) _gl.bindBuffer( _gl.ELEMENT_ARRAY_BUFFER, geometryGroup.__webglLineBuffer );
40600                 _gl.drawElements( _gl.LINES, geometryGroup.__webglLineCount, _gl.UNSIGNED_SHORT, 0 );
40601
40602             // triangles
40603
40604             } else {
40605
40606                 if ( updateBuffers ) _gl.bindBuffer( _gl.ELEMENT_ARRAY_BUFFER, geometryGroup.__webglFaceBuffer );
40607                 _gl.drawElements( _gl.TRIANGLES, geometryGroup.__webglFaceCount, _gl.UNSIGNED_SHORT, 0 );
40608
40609             }
40610
40611             _this.info.render.calls ++;
40612             _this.info.render.vertices += geometryGroup.__webglFaceCount;
40613             _this.info.render.faces += geometryGroup.__webglFaceCount / 3;
40614
40615         // render lines
40616
40617         } else if ( object instanceof THREE.Line ) {
40618
40619             primitives = ( object.type === THREE.LineStrip ) ? _gl.LINE_STRIP : _gl.LINES;
40620
40621             setLineWidth( material.linewidth );
40622
40623             _gl.drawArrays( primitives, 0, geometryGroup.__webglLineCount );
40624
40625             _this.info.render.calls ++;
40626
40627         // render particles
40628
40629         } else if ( object instanceof THREE.ParticleSystem ) {
40630
40631             _gl.drawArrays( _gl.POINTS, 0, geometryGroup.__webglParticleCount );
40632
40633             _this.info.render.calls ++;
40634             _this.info.render.points += geometryGroup.__webglParticleCount;
40635
40636         // render ribbon
40637
40638         } else if ( object instanceof THREE.Ribbon ) {
40639
40640             _gl.drawArrays( _gl.TRIANGLE_STRIP, 0, geometryGroup.__webglVertexCount );
40641
40642             _this.info.render.calls ++;
40643
40644         }
40645
40646     };
40647
40648     function setupMorphTargets ( material, geometryGroup, object ) {
40649
40650         // set base
40651
40652         var attributes = material.program.attributes;
40653
40654         if ( object.morphTargetBase !== -1 ) {
40655
40656             _gl.bindBuffer( _gl.ARRAY_BUFFER, geometryGroup.__webglMorphTargetsBuffers[ object.morphTargetBase ] );
40657             _gl.vertexAttribPointer( attributes.position, 3, _gl.FLOAT, false, 0, 0 );
40658
40659         } else if ( attributes.position >= 0 ) {
40660
40661             _gl.bindBuffer( _gl.ARRAY_BUFFER, geometryGroup.__webglVertexBuffer );
40662             _gl.vertexAttribPointer( attributes.position, 3, _gl.FLOAT, false, 0, 0 );
40663
40664         }
40665
40666         if ( object.morphTargetForcedOrder.length ) {
40667
40668             // set forced order
40669
40670             var m = 0;
40671             var order = object.morphTargetForcedOrder;
40672             var influences = object.morphTargetInfluences;
40673
40674             while ( m < material.numSupportedMorphTargets && m < order.length ) {
40675
40676                 _gl.bindBuffer( _gl.ARRAY_BUFFER, geometryGroup.__webglMorphTargetsBuffers[ order[ m ] ] );
40677                 _gl.vertexAttribPointer( attributes[ "morphTarget" + m ], 3, _gl.FLOAT, false, 0, 0 );
40678
40679                 if ( material.morphNormals ) {
40680
40681                     _gl.bindBuffer( _gl.ARRAY_BUFFER, geometryGroup.__webglMorphNormalsBuffers[ order[ m ] ] );
40682                     _gl.vertexAttribPointer( attributes[ "morphNormal" + m ], 3, _gl.FLOAT, false, 0, 0 );
40683
40684                 }
40685
40686                 object.__webglMorphTargetInfluences[ m ] = influences[ order[ m ] ];
40687
40688                 m ++;
40689             }
40690
40691         } else {
40692
40693             // find the most influencing
40694
40695             var influence, activeInfluenceIndices = [];
40696             var influences = object.morphTargetInfluences;
40697             var i, il = influences.length;
40698
40699             for ( i = 0; i < il; i ++ ) {
40700
40701                 influence = influences[ i ];
40702
40703                 if ( influence > 0 ) {
40704
40705                     activeInfluenceIndices.push( [ i, influence ] );
40706
40707                 }
40708
40709             }
40710
40711             if ( activeInfluenceIndices.length > material.numSupportedMorphTargets ) {
40712
40713                 activeInfluenceIndices.sort( numericalSort );
40714                 activeInfluenceIndices.length = material.numSupportedMorphTargets;
40715
40716             } else if ( activeInfluenceIndices.length > material.numSupportedMorphNormals ) {
40717
40718                 activeInfluenceIndices.sort( numericalSort );
40719
40720             } else if ( activeInfluenceIndices.length === 0 ) {
40721
40722                 activeInfluenceIndices.push( [ 0, 0 ] );
40723
40724             };
40725
40726             var influenceIndex, m = 0;
40727
40728             while ( m < material.numSupportedMorphTargets ) {
40729
40730                 if ( activeInfluenceIndices[ m ] ) {
40731
40732                     influenceIndex = activeInfluenceIndices[ m ][ 0 ];
40733
40734                     _gl.bindBuffer( _gl.ARRAY_BUFFER, geometryGroup.__webglMorphTargetsBuffers[ influenceIndex ] );
40735
40736                     _gl.vertexAttribPointer( attributes[ "morphTarget" + m ], 3, _gl.FLOAT, false, 0, 0 );
40737
40738                     if ( material.morphNormals ) {
40739
40740                         _gl.bindBuffer( _gl.ARRAY_BUFFER, geometryGroup.__webglMorphNormalsBuffers[ influenceIndex ] );
40741                         _gl.vertexAttribPointer( attributes[ "morphNormal" + m ], 3, _gl.FLOAT, false, 0, 0 );
40742
40743                     }
40744
40745                     object.__webglMorphTargetInfluences[ m ] = influences[ influenceIndex ];
40746
40747                 } else {
40748
40749                     _gl.vertexAttribPointer( attributes[ "morphTarget" + m ], 3, _gl.FLOAT, false, 0, 0 );
40750
40751                     if ( material.morphNormals ) {
40752
40753                         _gl.vertexAttribPointer( attributes[ "morphNormal" + m ], 3, _gl.FLOAT, false, 0, 0 );
40754
40755                     }
40756
40757                     object.__webglMorphTargetInfluences[ m ] = 0;
40758
40759                 }
40760
40761                 m ++;
40762
40763             }
40764
40765         }
40766
40767         // load updated influences uniform
40768
40769         if ( material.program.uniforms.morphTargetInfluences !== null ) {
40770
40771             _gl.uniform1fv( material.program.uniforms.morphTargetInfluences, object.__webglMorphTargetInfluences );
40772
40773         }
40774
40775     };
40776
40777     // Sorting
40778
40779     function painterSort ( a, b ) {
40780
40781         return b.z - a.z;
40782
40783     };
40784
40785     function numericalSort ( a, b ) {
40786
40787         return b[ 1 ] - a[ 1 ];
40788
40789     };
40790
40791
40792     // Rendering
40793
40794     this.render = function ( scene, camera, renderTarget, forceClear ) {
40795
40796         if ( camera instanceof THREE.Camera === false ) {
40797
40798             console.error( 'THREE.WebGLRenderer.render: camera is not an instance of THREE.Camera.' );
40799             return;
40800
40801         }
40802
40803         var i, il,
40804
40805         webglObject, object,
40806         renderList,
40807
40808         lights = scene.__lights,
40809         fog = scene.fog;
40810
40811         // reset caching for this frame
40812
40813         _currentMaterialId = -1;
40814         _lightsNeedUpdate = true;
40815
40816         // update scene graph
40817
40818         if ( this.autoUpdateScene ) scene.updateMatrixWorld();
40819
40820         // update camera matrices and frustum
40821
40822         if ( camera.parent === undefined ) camera.updateMatrixWorld();
40823
40824         if ( ! camera._viewMatrixArray ) camera._viewMatrixArray = new Float32Array( 16 );
40825         if ( ! camera._projectionMatrixArray ) camera._projectionMatrixArray = new Float32Array( 16 );
40826
40827         camera.matrixWorldInverse.getInverse( camera.matrixWorld );
40828
40829         camera.matrixWorldInverse.flattenToArray( camera._viewMatrixArray );
40830         camera.projectionMatrix.flattenToArray( camera._projectionMatrixArray );
40831
40832         _projScreenMatrix.multiply( camera.projectionMatrix, camera.matrixWorldInverse );
40833         _frustum.setFromMatrix( _projScreenMatrix );
40834
40835         // update WebGL objects
40836
40837         if ( this.autoUpdateObjects ) this.initWebGLObjects( scene );
40838
40839         // custom render plugins (pre pass)
40840
40841         renderPlugins( this.renderPluginsPre, scene, camera );
40842
40843         //
40844
40845         _this.info.render.calls = 0;
40846         _this.info.render.vertices = 0;
40847         _this.info.render.faces = 0;
40848         _this.info.render.points = 0;
40849
40850         this.setRenderTarget( renderTarget );
40851
40852         if ( this.autoClear || forceClear ) {
40853
40854             this.clear( this.autoClearColor, this.autoClearDepth, this.autoClearStencil );
40855
40856         }
40857
40858         // set matrices for regular objects (frustum culled)
40859
40860         renderList = scene.__webglObjects;
40861
40862         for ( i = 0, il = renderList.length; i < il; i ++ ) {
40863
40864             webglObject = renderList[ i ];
40865             object = webglObject.object;
40866
40867             webglObject.render = false;
40868
40869             if ( object.visible ) {
40870
40871                 if ( ! ( object instanceof THREE.Mesh || object instanceof THREE.ParticleSystem ) || ! ( object.frustumCulled ) || _frustum.contains( object ) ) {
40872
40873                     //object.matrixWorld.flattenToArray( object._modelMatrixArray );
40874
40875                     setupMatrices( object, camera );
40876
40877                     unrollBufferMaterial( webglObject );
40878
40879                     webglObject.render = true;
40880
40881                     if ( this.sortObjects === true ) {
40882
40883                         if ( object.renderDepth !== null ) {
40884
40885                             webglObject.z = object.renderDepth;
40886
40887                         } else {
40888
40889                             _vector3.copy( object.matrixWorld.getPosition() );
40890                             _projScreenMatrix.multiplyVector3( _vector3 );
40891
40892                             webglObject.z = _vector3.z;
40893
40894                         }
40895
40896                     }
40897
40898                 }
40899
40900             }
40901
40902         }
40903
40904         if ( this.sortObjects ) {
40905
40906             renderList.sort( painterSort );
40907
40908         }
40909
40910         // set matrices for immediate objects
40911
40912         renderList = scene.__webglObjectsImmediate;
40913
40914         for ( i = 0, il = renderList.length; i < il; i ++ ) {
40915
40916             webglObject = renderList[ i ];
40917             object = webglObject.object;
40918
40919             if ( object.visible ) {
40920
40921                 /*
40922                 if ( object.matrixAutoUpdate ) {
40923
40924                     object.matrixWorld.flattenToArray( object._modelMatrixArray );
40925
40926                 }
40927                 */
40928
40929                 setupMatrices( object, camera );
40930
40931                 unrollImmediateBufferMaterial( webglObject );
40932
40933             }
40934
40935         }
40936
40937         if ( scene.overrideMaterial ) {
40938
40939             var material = scene.overrideMaterial;
40940
40941             this.setBlending( material.blending, material.blendEquation, material.blendSrc, material.blendDst );
40942             this.setDepthTest( material.depthTest );
40943             this.setDepthWrite( material.depthWrite );
40944             setPolygonOffset( material.polygonOffset, material.polygonOffsetFactor, material.polygonOffsetUnits );
40945
40946             renderObjects( scene.__webglObjects, false, "", camera, lights, fog, true, material );
40947             renderObjectsImmediate( scene.__webglObjectsImmediate, "", camera, lights, fog, false, material );
40948
40949         } else {
40950
40951             // opaque pass (front-to-back order)
40952
40953             this.setBlending( THREE.NormalBlending );
40954
40955             renderObjects( scene.__webglObjects, true, "opaque", camera, lights, fog, false );
40956             renderObjectsImmediate( scene.__webglObjectsImmediate, "opaque", camera, lights, fog, false );
40957
40958             // transparent pass (back-to-front order)
40959
40960             renderObjects( scene.__webglObjects, false, "transparent", camera, lights, fog, true );
40961             renderObjectsImmediate( scene.__webglObjectsImmediate, "transparent", camera, lights, fog, true );
40962
40963         }
40964
40965         // custom render plugins (post pass)
40966
40967         renderPlugins( this.renderPluginsPost, scene, camera );
40968
40969
40970         // Generate mipmap if we're using any kind of mipmap filtering
40971
40972         if ( renderTarget && renderTarget.generateMipmaps && renderTarget.minFilter !== THREE.NearestFilter && renderTarget.minFilter !== THREE.LinearFilter ) {
40973
40974             updateRenderTargetMipmap( renderTarget );
40975
40976         }
40977
40978         // Ensure depth buffer writing is enabled so it can be cleared on next render
40979
40980         this.setDepthTest( true );
40981         this.setDepthWrite( true );
40982
40983         // _gl.finish();
40984
40985     };
40986
40987     function renderPlugins( plugins, scene, camera ) {
40988
40989         if ( ! plugins.length ) return;
40990
40991         for ( var i = 0, il = plugins.length; i < il; i ++ ) {
40992
40993             // reset state for plugin (to start from clean slate)
40994
40995             _currentProgram = null;
40996             _currentCamera = null;
40997
40998             _oldBlending = -1;
40999             _oldDepthTest = -1;
41000             _oldDepthWrite = -1;
41001             _oldDoubleSided = -1;
41002             _oldFlipSided = -1;
41003             _currentGeometryGroupHash = -1;
41004             _currentMaterialId = -1;
41005
41006             _lightsNeedUpdate = true;
41007
41008             plugins[ i ].render( scene, camera, _currentWidth, _currentHeight );
41009
41010             // reset state after plugin (anything could have changed)
41011
41012             _currentProgram = null;
41013             _currentCamera = null;
41014
41015             _oldBlending = -1;
41016             _oldDepthTest = -1;
41017             _oldDepthWrite = -1;
41018             _oldDoubleSided = -1;
41019             _oldFlipSided = -1;
41020             _currentGeometryGroupHash = -1;
41021             _currentMaterialId = -1;
41022
41023             _lightsNeedUpdate = true;
41024
41025         }
41026
41027     };
41028
41029     function renderObjects ( renderList, reverse, materialType, camera, lights, fog, useBlending, overrideMaterial ) {
41030
41031         var webglObject, object, buffer, material, start, end, delta;
41032
41033         if ( reverse ) {
41034
41035             start = renderList.length - 1;
41036             end = -1;
41037             delta = -1;
41038
41039         } else {
41040
41041             start = 0;
41042             end = renderList.length;
41043             delta = 1;
41044         }
41045
41046         for ( var i = start; i !== end; i += delta ) {
41047
41048             webglObject = renderList[ i ];
41049
41050             if ( webglObject.render ) {
41051
41052                 object = webglObject.object;
41053                 buffer = webglObject.buffer;
41054
41055                 if ( overrideMaterial ) {
41056
41057                     material = overrideMaterial;
41058
41059                 } else {
41060
41061                     material = webglObject[ materialType ];
41062
41063                     if ( ! material ) continue;
41064
41065                     if ( useBlending ) _this.setBlending( material.blending, material.blendEquation, material.blendSrc, material.blendDst );
41066
41067                     _this.setDepthTest( material.depthTest );
41068                     _this.setDepthWrite( material.depthWrite );
41069                     setPolygonOffset( material.polygonOffset, material.polygonOffsetFactor, material.polygonOffsetUnits );
41070
41071                 }
41072
41073                 _this.setMaterialFaces( material );
41074
41075                 if ( buffer instanceof THREE.BufferGeometry ) {
41076
41077                     _this.renderBufferDirect( camera, lights, fog, material, buffer, object );
41078
41079                 } else {
41080
41081                     _this.renderBuffer( camera, lights, fog, material, buffer, object );
41082
41083                 }
41084
41085             }
41086
41087         }
41088
41089     };
41090
41091     function renderObjectsImmediate ( renderList, materialType, camera, lights, fog, useBlending, overrideMaterial ) {
41092
41093         var webglObject, object, material, program;
41094
41095         for ( var i = 0, il = renderList.length; i < il; i ++ ) {
41096
41097             webglObject = renderList[ i ];
41098             object = webglObject.object;
41099
41100             if ( object.visible ) {
41101
41102                 if ( overrideMaterial ) {
41103
41104                     material = overrideMaterial;
41105
41106                 } else {
41107
41108                     material = webglObject[ materialType ];
41109
41110                     if ( ! material ) continue;
41111
41112                     if ( useBlending ) _this.setBlending( material.blending, material.blendEquation, material.blendSrc, material.blendDst );
41113
41114                     _this.setDepthTest( material.depthTest );
41115                     _this.setDepthWrite( material.depthWrite );
41116                     setPolygonOffset( material.polygonOffset, material.polygonOffsetFactor, material.polygonOffsetUnits );
41117
41118                 }
41119
41120                 _this.renderImmediateObject( camera, lights, fog, material, object );
41121
41122             }
41123
41124         }
41125
41126     };
41127
41128     this.renderImmediateObject = function ( camera, lights, fog, material, object ) {
41129
41130         var program = setProgram( camera, lights, fog, material, object );
41131
41132         _currentGeometryGroupHash = -1;
41133
41134         _this.setMaterialFaces( material );
41135
41136         if ( object.immediateRenderCallback ) {
41137
41138             object.immediateRenderCallback( program, _gl, _frustum );
41139
41140         } else {
41141
41142             object.render( function( object ) { _this.renderBufferImmediate( object, program, material ); } );
41143
41144         }
41145
41146     };
41147
41148     function unrollImmediateBufferMaterial ( globject ) {
41149
41150         var object = globject.object,
41151             material = object.material;
41152
41153         if ( material.transparent ) {
41154
41155             globject.transparent = material;
41156             globject.opaque = null;
41157
41158         } else {
41159
41160             globject.opaque = material;
41161             globject.transparent = null;
41162
41163         }
41164
41165     };
41166
41167     function unrollBufferMaterial ( globject ) {
41168
41169         var object = globject.object,
41170             buffer = globject.buffer,
41171             material, materialIndex, meshMaterial;
41172
41173         meshMaterial = object.material;
41174
41175         if ( meshMaterial instanceof THREE.MeshFaceMaterial ) {
41176
41177             materialIndex = buffer.materialIndex;
41178
41179             if ( materialIndex >= 0 ) {
41180
41181                 material = object.geometry.materials[ materialIndex ];
41182
41183                 if ( material.transparent ) {
41184
41185                     globject.transparent = material;
41186                     globject.opaque = null;
41187
41188                 } else {
41189
41190                     globject.opaque = material;
41191                     globject.transparent = null;
41192
41193                 }
41194
41195             }
41196
41197         } else {
41198
41199             material = meshMaterial;
41200
41201             if ( material ) {
41202
41203                 if ( material.transparent ) {
41204
41205                     globject.transparent = material;
41206                     globject.opaque = null;
41207
41208                 } else {
41209
41210                     globject.opaque = material;
41211                     globject.transparent = null;
41212
41213                 }
41214
41215             }
41216
41217         }
41218
41219     };
41220
41221     // Geometry splitting
41222
41223     function sortFacesByMaterial ( geometry ) {
41224
41225         var f, fl, face, materialIndex, vertices,
41226             materialHash, groupHash,
41227             hash_map = {};
41228
41229         var numMorphTargets = geometry.morphTargets.length;
41230         var numMorphNormals = geometry.morphNormals.length;
41231
41232         geometry.geometryGroups = {};
41233
41234         for ( f = 0, fl = geometry.faces.length; f < fl; f ++ ) {
41235
41236             face = geometry.faces[ f ];
41237             materialIndex = face.materialIndex;
41238
41239             materialHash = ( materialIndex !== undefined ) ? materialIndex : -1;
41240
41241             if ( hash_map[ materialHash ] === undefined ) {
41242
41243                 hash_map[ materialHash ] = { 'hash': materialHash, 'counter': 0 };
41244
41245             }
41246
41247             groupHash = hash_map[ materialHash ].hash + '_' + hash_map[ materialHash ].counter;
41248
41249             if ( geometry.geometryGroups[ groupHash ] === undefined ) {
41250
41251                 geometry.geometryGroups[ groupHash ] = { 'faces3': [], 'faces4': [], 'materialIndex': materialIndex, 'vertices': 0, 'numMorphTargets': numMorphTargets, 'numMorphNormals': numMorphNormals };
41252
41253             }
41254
41255             vertices = face instanceof THREE.Face3 ? 3 : 4;
41256
41257             if ( geometry.geometryGroups[ groupHash ].vertices + vertices > 65535 ) {
41258
41259                 hash_map[ materialHash ].counter += 1;
41260                 groupHash = hash_map[ materialHash ].hash + '_' + hash_map[ materialHash ].counter;
41261
41262                 if ( geometry.geometryGroups[ groupHash ] === undefined ) {
41263
41264                     geometry.geometryGroups[ groupHash ] = { 'faces3': [], 'faces4': [], 'materialIndex': materialIndex, 'vertices': 0, 'numMorphTargets': numMorphTargets, 'numMorphNormals': numMorphNormals };
41265
41266                 }
41267
41268             }
41269
41270             if ( face instanceof THREE.Face3 ) {
41271
41272                 geometry.geometryGroups[ groupHash ].faces3.push( f );
41273
41274             } else {
41275
41276                 geometry.geometryGroups[ groupHash ].faces4.push( f );
41277
41278             }
41279
41280             geometry.geometryGroups[ groupHash ].vertices += vertices;
41281
41282         }
41283
41284         geometry.geometryGroupsList = [];
41285
41286         for ( var g in geometry.geometryGroups ) {
41287
41288             geometry.geometryGroups[ g ].id = _geometryGroupCounter ++;
41289
41290             geometry.geometryGroupsList.push( geometry.geometryGroups[ g ] );
41291
41292         }
41293
41294     };
41295
41296     // Objects refresh
41297
41298     this.initWebGLObjects = function ( scene ) {
41299
41300         if ( !scene.__webglObjects ) {
41301
41302             scene.__webglObjects = [];
41303             scene.__webglObjectsImmediate = [];
41304             scene.__webglSprites = [];
41305             scene.__webglFlares = [];
41306
41307         }
41308
41309         while ( scene.__objectsAdded.length ) {
41310
41311             addObject( scene.__objectsAdded[ 0 ], scene );
41312             scene.__objectsAdded.splice( 0, 1 );
41313
41314         }
41315
41316         while ( scene.__objectsRemoved.length ) {
41317
41318             removeObject( scene.__objectsRemoved[ 0 ], scene );
41319             scene.__objectsRemoved.splice( 0, 1 );
41320
41321         }
41322
41323         // update must be called after objects adding / removal
41324
41325         for ( var o = 0, ol = scene.__webglObjects.length; o < ol; o ++ ) {
41326
41327             updateObject( scene.__webglObjects[ o ].object );
41328
41329         }
41330
41331     };
41332
41333     // Objects adding
41334
41335     function addObject ( object, scene ) {
41336
41337         var g, geometry, geometryGroup;
41338
41339         if ( ! object.__webglInit ) {
41340
41341             object.__webglInit = true;
41342
41343             object._modelViewMatrix = new THREE.Matrix4();
41344             object._normalMatrix = new THREE.Matrix3();
41345
41346             if ( object instanceof THREE.Mesh ) {
41347
41348                 geometry = object.geometry;
41349
41350                 if ( geometry instanceof THREE.Geometry ) {
41351
41352                     if ( geometry.geometryGroups === undefined ) {
41353
41354                         sortFacesByMaterial( geometry );
41355
41356                     }
41357
41358                     // create separate VBOs per geometry chunk
41359
41360                     for ( g in geometry.geometryGroups ) {
41361
41362                         geometryGroup = geometry.geometryGroups[ g ];
41363
41364                         // initialise VBO on the first access
41365
41366                         if ( ! geometryGroup.__webglVertexBuffer ) {
41367
41368                             createMeshBuffers( geometryGroup );
41369                             initMeshBuffers( geometryGroup, object );
41370
41371                             geometry.verticesNeedUpdate = true;
41372                             geometry.morphTargetsNeedUpdate = true;
41373                             geometry.elementsNeedUpdate = true;
41374                             geometry.uvsNeedUpdate = true;
41375                             geometry.normalsNeedUpdate = true;
41376                             geometry.tangentsNeedUpdate = true;
41377                             geometry.colorsNeedUpdate = true;
41378
41379                         }
41380
41381                     }
41382
41383                 } else if ( geometry instanceof THREE.BufferGeometry ) {
41384
41385                     initDirectBuffers( geometry );
41386
41387                 }
41388
41389             } else if ( object instanceof THREE.Ribbon ) {
41390
41391                 geometry = object.geometry;
41392
41393                 if( ! geometry.__webglVertexBuffer ) {
41394
41395                     createRibbonBuffers( geometry );
41396                     initRibbonBuffers( geometry );
41397
41398                     geometry.verticesNeedUpdate = true;
41399                     geometry.colorsNeedUpdate = true;
41400
41401                 }
41402
41403             } else if ( object instanceof THREE.Line ) {
41404
41405                 geometry = object.geometry;
41406
41407                 if( ! geometry.__webglVertexBuffer ) {
41408
41409                     createLineBuffers( geometry );
41410                     initLineBuffers( geometry, object );
41411
41412                     geometry.verticesNeedUpdate = true;
41413                     geometry.colorsNeedUpdate = true;
41414
41415                 }
41416
41417             } else if ( object instanceof THREE.ParticleSystem ) {
41418
41419                 geometry = object.geometry;
41420
41421                 if ( ! geometry.__webglVertexBuffer ) {
41422
41423                     if ( geometry instanceof THREE.Geometry ) {
41424
41425                         createParticleBuffers( geometry );
41426                         initParticleBuffers( geometry, object );
41427
41428                         geometry.verticesNeedUpdate = true;
41429                         geometry.colorsNeedUpdate = true;
41430
41431                     } else if ( geometry instanceof THREE.BufferGeometry ) {
41432
41433                         initDirectBuffers( geometry );
41434
41435                     }
41436
41437
41438                 }
41439
41440             }
41441
41442         }
41443
41444         if ( ! object.__webglActive ) {
41445
41446             if ( object instanceof THREE.Mesh ) {
41447
41448                 geometry = object.geometry;
41449
41450                 if ( geometry instanceof THREE.BufferGeometry ) {
41451
41452                     addBuffer( scene.__webglObjects, geometry, object );
41453
41454                 } else {
41455
41456                     for ( g in geometry.geometryGroups ) {
41457
41458                         geometryGroup = geometry.geometryGroups[ g ];
41459
41460                         addBuffer( scene.__webglObjects, geometryGroup, object );
41461
41462                     }
41463
41464                 }
41465
41466             } else if ( object instanceof THREE.Ribbon ||
41467                         object instanceof THREE.Line ||
41468                         object instanceof THREE.ParticleSystem ) {
41469
41470                 geometry = object.geometry;
41471                 addBuffer( scene.__webglObjects, geometry, object );
41472
41473             } else if ( object instanceof THREE.ImmediateRenderObject || object.immediateRenderCallback ) {
41474
41475                 addBufferImmediate( scene.__webglObjectsImmediate, object );
41476
41477             } else if ( object instanceof THREE.Sprite ) {
41478
41479                 scene.__webglSprites.push( object );
41480
41481             } else if ( object instanceof THREE.LensFlare ) {
41482
41483                 scene.__webglFlares.push( object );
41484
41485             }
41486
41487             object.__webglActive = true;
41488
41489         }
41490
41491     };
41492
41493     function addBuffer ( objlist, buffer, object ) {
41494
41495         objlist.push(
41496             {
41497                 buffer: buffer,
41498                 object: object,
41499                 opaque: null,
41500                 transparent: null
41501             }
41502         );
41503
41504     };
41505
41506     function addBufferImmediate ( objlist, object ) {
41507
41508         objlist.push(
41509             {
41510                 object: object,
41511                 opaque: null,
41512                 transparent: null
41513             }
41514         );
41515
41516     };
41517
41518     // Objects updates
41519
41520     function updateObject ( object ) {
41521
41522         var geometry = object.geometry,
41523             geometryGroup, customAttributesDirty, material;
41524
41525         if ( object instanceof THREE.Mesh ) {
41526
41527             if ( geometry instanceof THREE.BufferGeometry ) {
41528
41529                 if ( geometry.verticesNeedUpdate || geometry.elementsNeedUpdate ||
41530                      geometry.uvsNeedUpdate || geometry.normalsNeedUpdate ||
41531                      geometry.colorsNeedUpdate || geometry.tangentsNeedUpdate ) {
41532
41533                     setDirectBuffers( geometry, _gl.DYNAMIC_DRAW, !geometry.dynamic );
41534
41535                 }
41536
41537                 geometry.verticesNeedUpdate = false;
41538                 geometry.elementsNeedUpdate = false;
41539                 geometry.uvsNeedUpdate = false;
41540                 geometry.normalsNeedUpdate = false;
41541                 geometry.colorsNeedUpdate = false;
41542                 geometry.tangentsNeedUpdate = false;
41543
41544             } else {
41545
41546                 // check all geometry groups
41547
41548                 for( var i = 0, il = geometry.geometryGroupsList.length; i < il; i ++ ) {
41549
41550                     geometryGroup = geometry.geometryGroupsList[ i ];
41551
41552                     material = getBufferMaterial( object, geometryGroup );
41553
41554                     customAttributesDirty = material.attributes && areCustomAttributesDirty( material );
41555
41556                     if ( geometry.verticesNeedUpdate || geometry.morphTargetsNeedUpdate || geometry.elementsNeedUpdate ||
41557                          geometry.uvsNeedUpdate || geometry.normalsNeedUpdate ||
41558                          geometry.colorsNeedUpdate || geometry.tangentsNeedUpdate || customAttributesDirty ) {
41559
41560                         setMeshBuffers( geometryGroup, object, _gl.DYNAMIC_DRAW, !geometry.dynamic, material );
41561
41562                     }
41563
41564                 }
41565
41566                 geometry.verticesNeedUpdate = false;
41567                 geometry.morphTargetsNeedUpdate = false;
41568                 geometry.elementsNeedUpdate = false;
41569                 geometry.uvsNeedUpdate = false;
41570                 geometry.normalsNeedUpdate = false;
41571                 geometry.colorsNeedUpdate = false;
41572                 geometry.tangentsNeedUpdate = false;
41573
41574                 material.attributes && clearCustomAttributes( material );
41575
41576             }
41577
41578         } else if ( object instanceof THREE.Ribbon ) {
41579
41580             if ( geometry.verticesNeedUpdate || geometry.colorsNeedUpdate ) {
41581
41582                 setRibbonBuffers( geometry, _gl.DYNAMIC_DRAW );
41583
41584             }
41585
41586             geometry.verticesNeedUpdate = false;
41587             geometry.colorsNeedUpdate = false;
41588
41589         } else if ( object instanceof THREE.Line ) {
41590
41591             material = getBufferMaterial( object, geometryGroup );
41592
41593             customAttributesDirty = material.attributes && areCustomAttributesDirty( material );
41594
41595             if ( geometry.verticesNeedUpdate ||  geometry.colorsNeedUpdate || customAttributesDirty ) {
41596
41597                 setLineBuffers( geometry, _gl.DYNAMIC_DRAW );
41598
41599             }
41600
41601             geometry.verticesNeedUpdate = false;
41602             geometry.colorsNeedUpdate = false;
41603
41604             material.attributes && clearCustomAttributes( material );
41605
41606         } else if ( object instanceof THREE.ParticleSystem ) {
41607
41608             if ( geometry instanceof THREE.BufferGeometry ) {
41609
41610                 if ( geometry.verticesNeedUpdate || geometry.colorsNeedUpdate ) {
41611
41612                     setDirectBuffers( geometry, _gl.DYNAMIC_DRAW, !geometry.dynamic );
41613
41614                 }
41615
41616                 geometry.verticesNeedUpdate = false;
41617                 geometry.colorsNeedUpdate = false;
41618
41619             } else {
41620
41621                 material = getBufferMaterial( object, geometryGroup );
41622
41623                 customAttributesDirty = material.attributes && areCustomAttributesDirty( material );
41624
41625                 if ( geometry.verticesNeedUpdate || geometry.colorsNeedUpdate || object.sortParticles || customAttributesDirty ) {
41626
41627                     setParticleBuffers( geometry, _gl.DYNAMIC_DRAW, object );
41628
41629                 }
41630
41631                 geometry.verticesNeedUpdate = false;
41632                 geometry.colorsNeedUpdate = false;
41633
41634                 material.attributes && clearCustomAttributes( material );
41635
41636             }
41637
41638         }
41639
41640     };
41641
41642     // Objects updates - custom attributes check
41643
41644     function areCustomAttributesDirty ( material ) {
41645
41646         for ( var a in material.attributes ) {
41647
41648             if ( material.attributes[ a ].needsUpdate ) return true;
41649
41650         }
41651
41652         return false;
41653
41654     };
41655
41656     function clearCustomAttributes ( material ) {
41657
41658         for ( var a in material.attributes ) {
41659
41660             material.attributes[ a ].needsUpdate = false;
41661
41662         }
41663
41664     };
41665
41666     // Objects removal
41667
41668     function removeObject ( object, scene ) {
41669
41670         if ( object instanceof THREE.Mesh  ||
41671              object instanceof THREE.ParticleSystem ||
41672              object instanceof THREE.Ribbon ||
41673              object instanceof THREE.Line ) {
41674
41675             removeInstances( scene.__webglObjects, object );
41676
41677         } else if ( object instanceof THREE.Sprite ) {
41678
41679             removeInstancesDirect( scene.__webglSprites, object );
41680
41681         } else if ( object instanceof THREE.LensFlare ) {
41682
41683             removeInstancesDirect( scene.__webglFlares, object );
41684
41685         } else if ( object instanceof THREE.ImmediateRenderObject || object.immediateRenderCallback ) {
41686
41687             removeInstances( scene.__webglObjectsImmediate, object );
41688
41689         }
41690
41691         object.__webglActive = false;
41692
41693     };
41694
41695     function removeInstances ( objlist, object ) {
41696
41697         for ( var o = objlist.length - 1; o >= 0; o -- ) {
41698
41699             if ( objlist[ o ].object === object ) {
41700
41701                 objlist.splice( o, 1 );
41702
41703             }
41704
41705         }
41706
41707     };
41708
41709     function removeInstancesDirect ( objlist, object ) {
41710
41711         for ( var o = objlist.length - 1; o >= 0; o -- ) {
41712
41713             if ( objlist[ o ] === object ) {
41714
41715                 objlist.splice( o, 1 );
41716
41717             }
41718
41719         }
41720
41721     };
41722
41723     // Materials
41724
41725     this.initMaterial = function ( material, lights, fog, object ) {
41726
41727         var u, a, identifiers, i, parameters, maxLightCount, maxBones, maxShadows, shaderID;
41728
41729         if ( material instanceof THREE.MeshDepthMaterial ) {
41730
41731             shaderID = 'depth';
41732
41733         } else if ( material instanceof THREE.MeshNormalMaterial ) {
41734
41735             shaderID = 'normal';
41736
41737         } else if ( material instanceof THREE.MeshBasicMaterial ) {
41738
41739             shaderID = 'basic';
41740
41741         } else if ( material instanceof THREE.MeshLambertMaterial ) {
41742
41743             shaderID = 'lambert';
41744
41745         } else if ( material instanceof THREE.MeshPhongMaterial ) {
41746
41747             shaderID = 'phong';
41748
41749         } else if ( material instanceof THREE.LineBasicMaterial ) {
41750
41751             shaderID = 'basic';
41752
41753         } else if ( material instanceof THREE.ParticleBasicMaterial ) {
41754
41755             shaderID = 'particle_basic';
41756
41757         }
41758
41759         if ( shaderID ) {
41760
41761             setMaterialShaders( material, THREE.ShaderLib[ shaderID ] );
41762
41763         }
41764
41765         // heuristics to create shader parameters according to lights in the scene
41766         // (not to blow over maxLights budget)
41767
41768         maxLightCount = allocateLights( lights );
41769
41770         maxShadows = allocateShadows( lights );
41771
41772         maxBones = allocateBones( object );
41773
41774         parameters = {
41775
41776             map: !!material.map,
41777             envMap: !!material.envMap,
41778             lightMap: !!material.lightMap,
41779             bumpMap: !!material.bumpMap,
41780             normalMap: !!material.normalMap,
41781             specularMap: !!material.specularMap,
41782
41783             vertexColors: material.vertexColors,
41784
41785             fog: fog,
41786             useFog: material.fog,
41787
41788             sizeAttenuation: material.sizeAttenuation,
41789
41790             skinning: material.skinning,
41791             maxBones: maxBones,
41792             useVertexTexture: _supportsBoneTextures && object && object.useVertexTexture,
41793             boneTextureWidth: object && object.boneTextureWidth,
41794             boneTextureHeight: object && object.boneTextureHeight,
41795
41796             morphTargets: material.morphTargets,
41797             morphNormals: material.morphNormals,
41798             maxMorphTargets: this.maxMorphTargets,
41799             maxMorphNormals: this.maxMorphNormals,
41800
41801             maxDirLights: maxLightCount.directional,
41802             maxPointLights: maxLightCount.point,
41803             maxSpotLights: maxLightCount.spot,
41804             maxHemiLights: maxLightCount.hemi,
41805
41806             maxShadows: maxShadows,
41807             shadowMapEnabled: this.shadowMapEnabled && object.receiveShadow,
41808             shadowMapSoft: this.shadowMapSoft,
41809             shadowMapDebug: this.shadowMapDebug,
41810             shadowMapCascade: this.shadowMapCascade,
41811
41812             alphaTest: material.alphaTest,
41813             metal: material.metal,
41814             perPixel: material.perPixel,
41815             wrapAround: material.wrapAround,
41816             doubleSided: material.side === THREE.DoubleSide,
41817             flipSided: material.side === THREE.BackSide
41818
41819         };
41820
41821         material.program = buildProgram( shaderID, material.fragmentShader, material.vertexShader, material.uniforms, material.attributes, parameters );
41822
41823         var attributes = material.program.attributes;
41824
41825         if ( attributes.position >= 0 ) _gl.enableVertexAttribArray( attributes.position );
41826         if ( attributes.color >= 0 ) _gl.enableVertexAttribArray( attributes.color );
41827         if ( attributes.normal >= 0 ) _gl.enableVertexAttribArray( attributes.normal );
41828         if ( attributes.tangent >= 0 ) _gl.enableVertexAttribArray( attributes.tangent );
41829
41830         if ( material.skinning &&
41831              attributes.skinIndex >= 0 && attributes.skinWeight >= 0 ) {
41832
41833             _gl.enableVertexAttribArray( attributes.skinIndex );
41834             _gl.enableVertexAttribArray( attributes.skinWeight );
41835
41836         }
41837
41838         if ( material.attributes ) {
41839
41840             for ( a in material.attributes ) {
41841
41842                 if( attributes[ a ] !== undefined && attributes[ a ] >= 0 ) _gl.enableVertexAttribArray( attributes[ a ] );
41843
41844             }
41845
41846         }
41847
41848         if ( material.morphTargets ) {
41849
41850             material.numSupportedMorphTargets = 0;
41851
41852             var id, base = "morphTarget";
41853
41854             for ( i = 0; i < this.maxMorphTargets; i ++ ) {
41855
41856                 id = base + i;
41857
41858                 if ( attributes[ id ] >= 0 ) {
41859
41860                     _gl.enableVertexAttribArray( attributes[ id ] );
41861                     material.numSupportedMorphTargets ++;
41862
41863                 }
41864
41865             }
41866
41867         }
41868
41869         if ( material.morphNormals ) {
41870
41871             material.numSupportedMorphNormals = 0;
41872
41873             var id, base = "morphNormal";
41874
41875             for ( i = 0; i < this.maxMorphNormals; i ++ ) {
41876
41877                 id = base + i;
41878
41879                 if ( attributes[ id ] >= 0 ) {
41880
41881                     _gl.enableVertexAttribArray( attributes[ id ] );
41882                     material.numSupportedMorphNormals ++;
41883
41884                 }
41885
41886             }
41887
41888         }
41889
41890         material.uniformsList = [];
41891
41892         for ( u in material.uniforms ) {
41893
41894             material.uniformsList.push( [ material.uniforms[ u ], u ] );
41895
41896         }
41897
41898     };
41899
41900     function setMaterialShaders( material, shaders ) {
41901
41902         material.uniforms = THREE.UniformsUtils.clone( shaders.uniforms );
41903         material.vertexShader = shaders.vertexShader;
41904         material.fragmentShader = shaders.fragmentShader;
41905
41906     };
41907
41908     function setProgram( camera, lights, fog, material, object ) {
41909
41910         _usedTextureUnits = 0;
41911
41912         if ( material.needsUpdate ) {
41913
41914             if ( material.program ) _this.deallocateMaterial( material );
41915
41916             _this.initMaterial( material, lights, fog, object );
41917             material.needsUpdate = false;
41918
41919         }
41920
41921         if ( material.morphTargets ) {
41922
41923             if ( ! object.__webglMorphTargetInfluences ) {
41924
41925                 object.__webglMorphTargetInfluences = new Float32Array( _this.maxMorphTargets );
41926
41927             }
41928
41929         }
41930
41931         var refreshMaterial = false;
41932
41933         var program = material.program,
41934             p_uniforms = program.uniforms,
41935             m_uniforms = material.uniforms;
41936
41937         if ( program !== _currentProgram ) {
41938
41939             _gl.useProgram( program );
41940             _currentProgram = program;
41941
41942             refreshMaterial = true;
41943
41944         }
41945
41946         if ( material.id !== _currentMaterialId ) {
41947
41948             _currentMaterialId = material.id;
41949             refreshMaterial = true;
41950
41951         }
41952
41953         if ( refreshMaterial || camera !== _currentCamera ) {
41954
41955             _gl.uniformMatrix4fv( p_uniforms.projectionMatrix, false, camera._projectionMatrixArray );
41956
41957             if ( camera !== _currentCamera ) _currentCamera = camera;
41958
41959         }
41960
41961         // skinning uniforms must be set even if material didn't change
41962         // auto-setting of texture unit for bone texture must go before other textures
41963         // not sure why, but otherwise weird things happen
41964
41965         if ( material.skinning ) {
41966
41967             if ( _supportsBoneTextures && object.useVertexTexture ) {
41968
41969                 if ( p_uniforms.boneTexture !== null ) {
41970
41971                     var textureUnit = getTextureUnit();
41972
41973                     _gl.uniform1i( p_uniforms.boneTexture, textureUnit );
41974                     _this.setTexture( object.boneTexture, textureUnit );
41975
41976                 }
41977
41978             } else {
41979
41980                 if ( p_uniforms.boneGlobalMatrices !== null ) {
41981
41982                     _gl.uniformMatrix4fv( p_uniforms.boneGlobalMatrices, false, object.boneMatrices );
41983
41984                 }
41985
41986             }
41987
41988         }
41989
41990         if ( refreshMaterial ) {
41991
41992             // refresh uniforms common to several materials
41993
41994             if ( fog && material.fog ) {
41995
41996                 refreshUniformsFog( m_uniforms, fog );
41997
41998             }
41999
42000             if ( material instanceof THREE.MeshPhongMaterial ||
42001                  material instanceof THREE.MeshLambertMaterial ||
42002                  material.lights ) {
42003
42004                 if ( _lightsNeedUpdate ) {
42005
42006                     setupLights( program, lights );
42007                     _lightsNeedUpdate = false;
42008
42009                 }
42010
42011                 refreshUniformsLights( m_uniforms, _lights );
42012
42013             }
42014
42015             if ( material instanceof THREE.MeshBasicMaterial ||
42016                  material instanceof THREE.MeshLambertMaterial ||
42017                  material instanceof THREE.MeshPhongMaterial ) {
42018
42019                 refreshUniformsCommon( m_uniforms, material );
42020
42021             }
42022
42023             // refresh single material specific uniforms
42024
42025             if ( material instanceof THREE.LineBasicMaterial ) {
42026
42027                 refreshUniformsLine( m_uniforms, material );
42028
42029             } else if ( material instanceof THREE.ParticleBasicMaterial ) {
42030
42031                 refreshUniformsParticle( m_uniforms, material );
42032
42033             } else if ( material instanceof THREE.MeshPhongMaterial ) {
42034
42035                 refreshUniformsPhong( m_uniforms, material );
42036
42037             } else if ( material instanceof THREE.MeshLambertMaterial ) {
42038
42039                 refreshUniformsLambert( m_uniforms, material );
42040
42041             } else if ( material instanceof THREE.MeshDepthMaterial ) {
42042
42043                 m_uniforms.mNear.value = camera.near;
42044                 m_uniforms.mFar.value = camera.far;
42045                 m_uniforms.opacity.value = material.opacity;
42046
42047             } else if ( material instanceof THREE.MeshNormalMaterial ) {
42048
42049                 m_uniforms.opacity.value = material.opacity;
42050
42051             }
42052
42053             if ( object.receiveShadow && ! material._shadowPass ) {
42054
42055                 refreshUniformsShadow( m_uniforms, lights );
42056
42057             }
42058
42059             // load common uniforms
42060
42061             loadUniformsGeneric( program, material.uniformsList );
42062
42063             // load material specific uniforms
42064             // (shader material also gets them for the sake of genericity)
42065
42066             if ( material instanceof THREE.ShaderMaterial ||
42067                  material instanceof THREE.MeshPhongMaterial ||
42068                  material.envMap ) {
42069
42070                 if ( p_uniforms.cameraPosition !== null ) {
42071
42072                     var position = camera.matrixWorld.getPosition();
42073                     _gl.uniform3f( p_uniforms.cameraPosition, position.x, position.y, position.z );
42074
42075                 }
42076
42077             }
42078
42079             if ( material instanceof THREE.MeshPhongMaterial ||
42080                  material instanceof THREE.MeshLambertMaterial ||
42081                  material instanceof THREE.ShaderMaterial ||
42082                  material.skinning ) {
42083
42084                 if ( p_uniforms.viewMatrix !== null ) {
42085
42086                     _gl.uniformMatrix4fv( p_uniforms.viewMatrix, false, camera._viewMatrixArray );
42087
42088                 }
42089
42090             }
42091
42092         }
42093
42094         loadUniformsMatrices( p_uniforms, object );
42095
42096         if ( p_uniforms.modelMatrix !== null ) {
42097
42098             _gl.uniformMatrix4fv( p_uniforms.modelMatrix, false, object.matrixWorld.elements );
42099
42100         }
42101
42102         return program;
42103
42104     };
42105
42106     // Uniforms (refresh uniforms objects)
42107
42108     function refreshUniformsCommon ( uniforms, material ) {
42109
42110         uniforms.opacity.value = material.opacity;
42111
42112         if ( _this.gammaInput ) {
42113
42114             uniforms.diffuse.value.copyGammaToLinear( material.color );
42115
42116         } else {
42117
42118             uniforms.diffuse.value = material.color;
42119
42120         }
42121
42122         uniforms.map.value = material.map;
42123         uniforms.lightMap.value = material.lightMap;
42124         uniforms.specularMap.value = material.specularMap;
42125
42126         if ( material.bumpMap ) {
42127
42128             uniforms.bumpMap.value = material.bumpMap;
42129             uniforms.bumpScale.value = material.bumpScale;
42130
42131         }
42132
42133         if ( material.normalMap ) {
42134
42135             uniforms.normalMap.value = material.normalMap;
42136             uniforms.normalScale.value.copy( material.normalScale );
42137
42138         }
42139
42140         // uv repeat and offset setting priorities
42141         //    1. color map
42142         //    2. specular map
42143         //    3. normal map
42144         //    4. bump map
42145
42146         var uvScaleMap;
42147
42148         if ( material.map ) {
42149
42150             uvScaleMap = material.map;
42151
42152         } else if ( material.specularMap ) {
42153
42154             uvScaleMap = material.specularMap;
42155
42156         } else if ( material.normalMap ) {
42157
42158             uvScaleMap = material.normalMap;
42159
42160         } else if ( material.bumpMap ) {
42161
42162             uvScaleMap = material.bumpMap;
42163
42164         }
42165
42166         if ( uvScaleMap !== undefined ) {
42167
42168             var offset = uvScaleMap.offset;
42169             var repeat = uvScaleMap.repeat;
42170
42171             uniforms.offsetRepeat.value.set( offset.x, offset.y, repeat.x, repeat.y );
42172
42173         }
42174
42175         uniforms.envMap.value = material.envMap;
42176         uniforms.flipEnvMap.value = ( material.envMap instanceof THREE.WebGLRenderTargetCube ) ? 1 : -1;
42177
42178         if ( _this.gammaInput ) {
42179
42180             //uniforms.reflectivity.value = material.reflectivity * material.reflectivity;
42181             uniforms.reflectivity.value = material.reflectivity;
42182
42183         } else {
42184
42185             uniforms.reflectivity.value = material.reflectivity;
42186
42187         }
42188
42189         uniforms.refractionRatio.value = material.refractionRatio;
42190         uniforms.combine.value = material.combine;
42191         uniforms.useRefract.value = material.envMap && material.envMap.mapping instanceof THREE.CubeRefractionMapping;
42192
42193     };
42194
42195     function refreshUniformsLine ( uniforms, material ) {
42196
42197         uniforms.diffuse.value = material.color;
42198         uniforms.opacity.value = material.opacity;
42199
42200     };
42201
42202     function refreshUniformsParticle ( uniforms, material ) {
42203
42204         uniforms.psColor.value = material.color;
42205         uniforms.opacity.value = material.opacity;
42206         uniforms.size.value = material.size;
42207         uniforms.scale.value = _canvas.height / 2.0; // TODO: Cache this.
42208
42209         uniforms.map.value = material.map;
42210
42211     };
42212
42213     function refreshUniformsFog ( uniforms, fog ) {
42214
42215         uniforms.fogColor.value = fog.color;
42216
42217         if ( fog instanceof THREE.Fog ) {
42218
42219             uniforms.fogNear.value = fog.near;
42220             uniforms.fogFar.value = fog.far;
42221
42222         } else if ( fog instanceof THREE.FogExp2 ) {
42223
42224             uniforms.fogDensity.value = fog.density;
42225
42226         }
42227
42228     };
42229
42230     function refreshUniformsPhong ( uniforms, material ) {
42231
42232         uniforms.shininess.value = material.shininess;
42233
42234         if ( _this.gammaInput ) {
42235
42236             uniforms.ambient.value.copyGammaToLinear( material.ambient );
42237             uniforms.emissive.value.copyGammaToLinear( material.emissive );
42238             uniforms.specular.value.copyGammaToLinear( material.specular );
42239
42240         } else {
42241
42242             uniforms.ambient.value = material.ambient;
42243             uniforms.emissive.value = material.emissive;
42244             uniforms.specular.value = material.specular;
42245
42246         }
42247
42248         if ( material.wrapAround ) {
42249
42250             uniforms.wrapRGB.value.copy( material.wrapRGB );
42251
42252         }
42253
42254     };
42255
42256     function refreshUniformsLambert ( uniforms, material ) {
42257
42258         if ( _this.gammaInput ) {
42259
42260             uniforms.ambient.value.copyGammaToLinear( material.ambient );
42261             uniforms.emissive.value.copyGammaToLinear( material.emissive );
42262
42263         } else {
42264
42265             uniforms.ambient.value = material.ambient;
42266             uniforms.emissive.value = material.emissive;
42267
42268         }
42269
42270         if ( material.wrapAround ) {
42271
42272             uniforms.wrapRGB.value.copy( material.wrapRGB );
42273
42274         }
42275
42276     };
42277
42278     function refreshUniformsLights ( uniforms, lights ) {
42279
42280         uniforms.ambientLightColor.value = lights.ambient;
42281
42282         uniforms.directionalLightColor.value = lights.directional.colors;
42283         uniforms.directionalLightDirection.value = lights.directional.positions;
42284
42285         uniforms.pointLightColor.value = lights.point.colors;
42286         uniforms.pointLightPosition.value = lights.point.positions;
42287         uniforms.pointLightDistance.value = lights.point.distances;
42288
42289         uniforms.spotLightColor.value = lights.spot.colors;
42290         uniforms.spotLightPosition.value = lights.spot.positions;
42291         uniforms.spotLightDistance.value = lights.spot.distances;
42292         uniforms.spotLightDirection.value = lights.spot.directions;
42293         uniforms.spotLightAngle.value = lights.spot.angles;
42294         uniforms.spotLightExponent.value = lights.spot.exponents;
42295
42296         uniforms.hemisphereLightSkyColor.value = lights.hemi.skyColors;
42297         uniforms.hemisphereLightGroundColor.value = lights.hemi.groundColors;
42298         uniforms.hemisphereLightPosition.value = lights.hemi.positions;
42299
42300     };
42301
42302     function refreshUniformsShadow ( uniforms, lights ) {
42303
42304         if ( uniforms.shadowMatrix ) {
42305
42306             var j = 0;
42307
42308             for ( var i = 0, il = lights.length; i < il; i ++ ) {
42309
42310                 var light = lights[ i ];
42311
42312                 if ( ! light.castShadow ) continue;
42313
42314                 if ( light instanceof THREE.SpotLight || ( light instanceof THREE.DirectionalLight && ! light.shadowCascade ) ) {
42315
42316                     uniforms.shadowMap.value[ j ] = light.shadowMap;
42317                     uniforms.shadowMapSize.value[ j ] = light.shadowMapSize;
42318
42319                     uniforms.shadowMatrix.value[ j ] = light.shadowMatrix;
42320
42321                     uniforms.shadowDarkness.value[ j ] = light.shadowDarkness;
42322                     uniforms.shadowBias.value[ j ] = light.shadowBias;
42323
42324                     j ++;
42325
42326                 }
42327
42328             }
42329
42330         }
42331
42332     };
42333
42334     // Uniforms (load to GPU)
42335
42336     function loadUniformsMatrices ( uniforms, object ) {
42337
42338         _gl.uniformMatrix4fv( uniforms.modelViewMatrix, false, object._modelViewMatrix.elements );
42339
42340         if ( uniforms.normalMatrix ) {
42341
42342             _gl.uniformMatrix3fv( uniforms.normalMatrix, false, object._normalMatrix.elements );
42343
42344         }
42345
42346     };
42347
42348     function getTextureUnit() {
42349
42350         var textureUnit = _usedTextureUnits;
42351
42352         if ( textureUnit >= _maxTextures ) {
42353
42354             console.warn( "Trying to use " + textureUnit + " texture units while this GPU supports only " + _maxTextures );
42355
42356         }
42357
42358         _usedTextureUnits += 1;
42359
42360         return textureUnit;
42361
42362     };
42363
42364     function loadUniformsGeneric ( program, uniforms ) {
42365
42366         var uniform, value, type, location, texture, textureUnit, i, il, j, jl, offset;
42367
42368         for ( j = 0, jl = uniforms.length; j < jl; j ++ ) {
42369
42370             location = program.uniforms[ uniforms[ j ][ 1 ] ];
42371             if ( !location ) continue;
42372
42373             uniform = uniforms[ j ][ 0 ];
42374
42375             type = uniform.type;
42376             value = uniform.value;
42377
42378             if ( type === "i" ) { // single integer
42379
42380                 _gl.uniform1i( location, value );
42381
42382             } else if ( type === "f" ) { // single float
42383
42384                 _gl.uniform1f( location, value );
42385
42386             } else if ( type === "v2" ) { // single THREE.Vector2
42387
42388                 _gl.uniform2f( location, value.x, value.y );
42389
42390             } else if ( type === "v3" ) { // single THREE.Vector3
42391
42392                 _gl.uniform3f( location, value.x, value.y, value.z );
42393
42394             } else if ( type === "v4" ) { // single THREE.Vector4
42395
42396                 _gl.uniform4f( location, value.x, value.y, value.z, value.w );
42397
42398             } else if ( type === "c" ) { // single THREE.Color
42399
42400                 _gl.uniform3f( location, value.r, value.g, value.b );
42401
42402             } else if ( type === "iv1" ) { // flat array of integers (JS or typed array)
42403
42404                 _gl.uniform1iv( location, value );
42405
42406             } else if ( type === "iv" ) { // flat array of integers with 3 x N size (JS or typed array)
42407
42408                 _gl.uniform3iv( location, value );
42409
42410             } else if ( type === "fv1" ) { // flat array of floats (JS or typed array)
42411
42412                 _gl.uniform1fv( location, value );
42413
42414             } else if ( type === "fv" ) { // flat array of floats with 3 x N size (JS or typed array)
42415
42416                 _gl.uniform3fv( location, value );
42417
42418             } else if ( type === "v2v" ) { // array of THREE.Vector2
42419
42420                 if ( uniform._array === undefined ) {
42421
42422                     uniform._array = new Float32Array( 2 * value.length );
42423
42424                 }
42425
42426                 for ( i = 0, il = value.length; i < il; i ++ ) {
42427
42428                     offset = i * 2;
42429
42430                     uniform._array[ offset ]      = value[ i ].x;
42431                     uniform._array[ offset + 1 ] = value[ i ].y;
42432
42433                 }
42434
42435                 _gl.uniform2fv( location, uniform._array );
42436
42437             } else if ( type === "v3v" ) { // array of THREE.Vector3
42438
42439                 if ( uniform._array === undefined ) {
42440
42441                     uniform._array = new Float32Array( 3 * value.length );
42442
42443                 }
42444
42445                 for ( i = 0, il = value.length; i < il; i ++ ) {
42446
42447                     offset = i * 3;
42448
42449                     uniform._array[ offset ]      = value[ i ].x;
42450                     uniform._array[ offset + 1 ] = value[ i ].y;
42451                     uniform._array[ offset + 2 ] = value[ i ].z;
42452
42453                 }
42454
42455                 _gl.uniform3fv( location, uniform._array );
42456
42457             } else if ( type === "v4v" ) { // array of THREE.Vector4
42458
42459                 if ( uniform._array === undefined ) {
42460
42461                     uniform._array = new Float32Array( 4 * value.length );
42462
42463                 }
42464
42465                 for ( i = 0, il = value.length; i < il; i ++ ) {
42466
42467                     offset = i * 4;
42468
42469                     uniform._array[ offset ]      = value[ i ].x;
42470                     uniform._array[ offset + 1 ] = value[ i ].y;
42471                     uniform._array[ offset + 2 ] = value[ i ].z;
42472                     uniform._array[ offset + 3 ] = value[ i ].w;
42473
42474                 }
42475
42476                 _gl.uniform4fv( location, uniform._array );
42477
42478             } else if ( type === "m4") { // single THREE.Matrix4
42479
42480                 if ( uniform._array === undefined ) {
42481
42482                     uniform._array = new Float32Array( 16 );
42483
42484                 }
42485
42486                 value.flattenToArray( uniform._array );
42487                 _gl.uniformMatrix4fv( location, false, uniform._array );
42488
42489             } else if ( type === "m4v" ) { // array of THREE.Matrix4
42490
42491                 if ( uniform._array === undefined ) {
42492
42493                     uniform._array = new Float32Array( 16 * value.length );
42494
42495                 }
42496
42497                 for ( i = 0, il = value.length; i < il; i ++ ) {
42498
42499                     value[ i ].flattenToArrayOffset( uniform._array, i * 16 );
42500
42501                 }
42502
42503                 _gl.uniformMatrix4fv( location, false, uniform._array );
42504
42505             } else if ( type === "t" ) { // single THREE.Texture (2d or cube)
42506
42507                 texture = value;
42508                 textureUnit = getTextureUnit();
42509
42510                 _gl.uniform1i( location, textureUnit );
42511
42512                 if ( !texture ) continue;
42513
42514                 if ( texture.image instanceof Array && texture.image.length === 6 ) {
42515
42516                     setCubeTexture( texture, textureUnit );
42517
42518                 } else if ( texture instanceof THREE.WebGLRenderTargetCube ) {
42519
42520                     setCubeTextureDynamic( texture, textureUnit );
42521
42522                 } else {
42523
42524                     _this.setTexture( texture, textureUnit );
42525
42526                 }
42527
42528             } else if ( type === "tv" ) { // array of THREE.Texture (2d)
42529
42530                 if ( uniform._array === undefined ) {
42531
42532                     uniform._array = [];
42533
42534                 }
42535
42536                 for( i = 0, il = uniform.value.length; i < il; i ++ ) {
42537
42538                     uniform._array[ i ] = getTextureUnit();
42539
42540                 }
42541
42542                 _gl.uniform1iv( location, uniform._array );
42543
42544                 for( i = 0, il = uniform.value.length; i < il; i ++ ) {
42545
42546                     texture = uniform.value[ i ];
42547                     textureUnit = uniform._array[ i ];
42548
42549                     if ( !texture ) continue;
42550
42551                     _this.setTexture( texture, textureUnit );
42552
42553                 }
42554
42555             }
42556
42557         }
42558
42559     };
42560
42561     function setupMatrices ( object, camera ) {
42562
42563         object._modelViewMatrix.multiply( camera.matrixWorldInverse, object.matrixWorld );
42564
42565         object._normalMatrix.getInverse( object._modelViewMatrix );
42566         object._normalMatrix.transpose();
42567
42568     };
42569
42570     //
42571
42572     function setColorGamma( array, offset, color, intensitySq ) {
42573
42574         array[ offset ]     = color.r * color.r * intensitySq;
42575         array[ offset + 1 ] = color.g * color.g * intensitySq;
42576         array[ offset + 2 ] = color.b * color.b * intensitySq;
42577
42578     };
42579
42580     function setColorLinear( array, offset, color, intensity ) {
42581
42582         array[ offset ]     = color.r * intensity;
42583         array[ offset + 1 ] = color.g * intensity;
42584         array[ offset + 2 ] = color.b * intensity;
42585
42586     };
42587
42588     function setupLights ( program, lights ) {
42589
42590         var l, ll, light, n,
42591         r = 0, g = 0, b = 0,
42592         color, skyColor, groundColor,
42593         intensity,  intensitySq,
42594         position,
42595         distance,
42596
42597         zlights = _lights,
42598
42599         dirColors = zlights.directional.colors,
42600         dirPositions = zlights.directional.positions,
42601
42602         pointColors = zlights.point.colors,
42603         pointPositions = zlights.point.positions,
42604         pointDistances = zlights.point.distances,
42605
42606         spotColors = zlights.spot.colors,
42607         spotPositions = zlights.spot.positions,
42608         spotDistances = zlights.spot.distances,
42609         spotDirections = zlights.spot.directions,
42610         spotAngles = zlights.spot.angles,
42611         spotExponents = zlights.spot.exponents,
42612
42613         hemiSkyColors = zlights.hemi.skyColors,
42614         hemiGroundColors = zlights.hemi.groundColors,
42615         hemiPositions = zlights.hemi.positions,
42616
42617         dirLength = 0,
42618         pointLength = 0,
42619         spotLength = 0,
42620         hemiLength = 0,
42621
42622         dirOffset = 0,
42623         pointOffset = 0,
42624         spotOffset = 0,
42625         hemiOffset = 0;
42626
42627         for ( l = 0, ll = lights.length; l < ll; l ++ ) {
42628
42629             light = lights[ l ];
42630
42631             if ( light.onlyShadow || ! light.visible ) continue;
42632
42633             color = light.color;
42634             intensity = light.intensity;
42635             distance = light.distance;
42636
42637             if ( light instanceof THREE.AmbientLight ) {
42638
42639                 if ( _this.gammaInput ) {
42640
42641                     r += color.r * color.r;
42642                     g += color.g * color.g;
42643                     b += color.b * color.b;
42644
42645                 } else {
42646
42647                     r += color.r;
42648                     g += color.g;
42649                     b += color.b;
42650
42651                 }
42652
42653             } else if ( light instanceof THREE.DirectionalLight ) {
42654
42655                 dirOffset = dirLength * 3;
42656
42657                 if ( _this.gammaInput ) {
42658
42659                     setColorGamma( dirColors, dirOffset, color, intensity * intensity );
42660
42661                 } else {
42662
42663                     setColorLinear( dirColors, dirOffset, color, intensity );
42664
42665                 }
42666
42667                 _direction.copy( light.matrixWorld.getPosition() );
42668                 _direction.subSelf( light.target.matrixWorld.getPosition() );
42669                 _direction.normalize();
42670
42671                 dirPositions[ dirOffset ]     = _direction.x;
42672                 dirPositions[ dirOffset + 1 ] = _direction.y;
42673                 dirPositions[ dirOffset + 2 ] = _direction.z;
42674
42675                 dirLength += 1;
42676
42677             } else if( light instanceof THREE.PointLight ) {
42678
42679                 pointOffset = pointLength * 3;
42680
42681                 if ( _this.gammaInput ) {
42682
42683                     setColorGamma( pointColors, pointOffset, color, intensity * intensity );
42684
42685                 } else {
42686
42687                     setColorLinear( pointColors, pointOffset, color, intensity );
42688
42689                 }
42690
42691                 position = light.matrixWorld.getPosition();
42692
42693                 pointPositions[ pointOffset ]     = position.x;
42694                 pointPositions[ pointOffset + 1 ] = position.y;
42695                 pointPositions[ pointOffset + 2 ] = position.z;
42696
42697                 pointDistances[ pointLength ] = distance;
42698
42699                 pointLength += 1;
42700
42701             } else if( light instanceof THREE.SpotLight ) {
42702
42703                 spotOffset = spotLength * 3;
42704
42705                 if ( _this.gammaInput ) {
42706
42707                     setColorGamma( spotColors, spotOffset, color, intensity * intensity );
42708
42709                 } else {
42710
42711                     setColorLinear( spotColors, spotOffset, color, intensity );
42712
42713                 }
42714
42715                 position = light.matrixWorld.getPosition();
42716
42717                 spotPositions[ spotOffset ]     = position.x;
42718                 spotPositions[ spotOffset + 1 ] = position.y;
42719                 spotPositions[ spotOffset + 2 ] = position.z;
42720
42721                 spotDistances[ spotLength ] = distance;
42722
42723                 _direction.copy( position );
42724                 _direction.subSelf( light.target.matrixWorld.getPosition() );
42725                 _direction.normalize();
42726
42727                 spotDirections[ spotOffset ]     = _direction.x;
42728                 spotDirections[ spotOffset + 1 ] = _direction.y;
42729                 spotDirections[ spotOffset + 2 ] = _direction.z;
42730
42731                 spotAngles[ spotLength ] = Math.cos( light.angle );
42732                 spotExponents[ spotLength ] = light.exponent;
42733
42734                 spotLength += 1;
42735
42736             } else if ( light instanceof THREE.HemisphereLight ) {
42737
42738                 skyColor = light.color;
42739                 groundColor = light.groundColor;
42740
42741                 hemiOffset = hemiLength * 3;
42742
42743                 if ( _this.gammaInput ) {
42744
42745                     intensitySq = intensity * intensity;
42746
42747                     setColorGamma( hemiSkyColors, hemiOffset, skyColor, intensitySq );
42748                     setColorGamma( hemiGroundColors, hemiOffset, groundColor, intensitySq );
42749
42750                 } else {
42751
42752                     setColorLinear( hemiSkyColors, hemiOffset, skyColor, intensity );
42753                     setColorLinear( hemiGroundColors, hemiOffset, groundColor, intensity );
42754
42755                 }
42756
42757                 position = light.matrixWorld.getPosition();
42758
42759                 hemiPositions[ hemiOffset ]     = position.x;
42760                 hemiPositions[ hemiOffset + 1 ] = position.y;
42761                 hemiPositions[ hemiOffset + 2 ] = position.z;
42762
42763                 hemiLength += 1;
42764
42765             }
42766
42767         }
42768
42769         // null eventual remains from removed lights
42770         // (this is to avoid if in shader)
42771
42772         for ( l = dirLength * 3, ll = dirColors.length; l < ll; l ++ ) dirColors[ l ] = 0.0;
42773         for ( l = pointLength * 3, ll = pointColors.length; l < ll; l ++ ) pointColors[ l ] = 0.0;
42774         for ( l = spotLength * 3, ll = spotColors.length; l < ll; l ++ ) spotColors[ l ] = 0.0;
42775         for ( l = hemiLength * 3, ll = hemiSkyColors.length; l < ll; l ++ ) hemiSkyColors[ l ] = 0.0;
42776         for ( l = hemiLength * 3, ll = hemiGroundColors.length; l < ll; l ++ ) hemiGroundColors[ l ] = 0.0;
42777
42778         zlights.directional.length = dirLength;
42779         zlights.point.length = pointLength;
42780         zlights.spot.length = spotLength;
42781         zlights.hemi.length = hemiLength;
42782
42783         zlights.ambient[ 0 ] = r;
42784         zlights.ambient[ 1 ] = g;
42785         zlights.ambient[ 2 ] = b;
42786
42787     };
42788
42789     // GL state setting
42790
42791     this.setFaceCulling = function ( cullFace, frontFace ) {
42792
42793         if ( cullFace ) {
42794
42795             if ( !frontFace || frontFace === "ccw" ) {
42796
42797                 _gl.frontFace( _gl.CCW );
42798
42799             } else {
42800
42801                 _gl.frontFace( _gl.CW );
42802
42803             }
42804
42805             if( cullFace === "back" ) {
42806
42807                 _gl.cullFace( _gl.BACK );
42808
42809             } else if( cullFace === "front" ) {
42810
42811                 _gl.cullFace( _gl.FRONT );
42812
42813             } else {
42814
42815                 _gl.cullFace( _gl.FRONT_AND_BACK );
42816
42817             }
42818
42819             _gl.enable( _gl.CULL_FACE );
42820
42821         } else {
42822
42823             _gl.disable( _gl.CULL_FACE );
42824
42825         }
42826
42827     };
42828
42829     this.setMaterialFaces = function ( material ) {
42830
42831         var doubleSided = material.side === THREE.DoubleSide;
42832         var flipSided = material.side === THREE.BackSide;
42833
42834         if ( _oldDoubleSided !== doubleSided ) {
42835
42836             if ( doubleSided ) {
42837
42838                 _gl.disable( _gl.CULL_FACE );
42839
42840             } else {
42841
42842                 _gl.enable( _gl.CULL_FACE );
42843
42844             }
42845
42846             _oldDoubleSided = doubleSided;
42847
42848         }
42849
42850         if ( _oldFlipSided !== flipSided ) {
42851
42852             if ( flipSided ) {
42853
42854                 _gl.frontFace( _gl.CW );
42855
42856             } else {
42857
42858                 _gl.frontFace( _gl.CCW );
42859
42860             }
42861
42862             _oldFlipSided = flipSided;
42863
42864         }
42865
42866     };
42867
42868     this.setDepthTest = function ( depthTest ) {
42869
42870         if ( _oldDepthTest !== depthTest ) {
42871
42872             if ( depthTest ) {
42873
42874                 _gl.enable( _gl.DEPTH_TEST );
42875
42876             } else {
42877
42878                 _gl.disable( _gl.DEPTH_TEST );
42879
42880             }
42881
42882             _oldDepthTest = depthTest;
42883
42884         }
42885
42886     };
42887
42888     this.setDepthWrite = function ( depthWrite ) {
42889
42890         if ( _oldDepthWrite !== depthWrite ) {
42891
42892             _gl.depthMask( depthWrite );
42893             _oldDepthWrite = depthWrite;
42894
42895         }
42896
42897     };
42898
42899     function setLineWidth ( width ) {
42900
42901         if ( width !== _oldLineWidth ) {
42902
42903             _gl.lineWidth( width );
42904
42905             _oldLineWidth = width;
42906
42907         }
42908
42909     };
42910
42911     function setPolygonOffset ( polygonoffset, factor, units ) {
42912
42913         if ( _oldPolygonOffset !== polygonoffset ) {
42914
42915             if ( polygonoffset ) {
42916
42917                 _gl.enable( _gl.POLYGON_OFFSET_FILL );
42918
42919             } else {
42920
42921                 _gl.disable( _gl.POLYGON_OFFSET_FILL );
42922
42923             }
42924
42925             _oldPolygonOffset = polygonoffset;
42926
42927         }
42928
42929         if ( polygonoffset && ( _oldPolygonOffsetFactor !== factor || _oldPolygonOffsetUnits !== units ) ) {
42930
42931             _gl.polygonOffset( factor, units );
42932
42933             _oldPolygonOffsetFactor = factor;
42934             _oldPolygonOffsetUnits = units;
42935
42936         }
42937
42938     };
42939
42940     this.setBlending = function ( blending, blendEquation, blendSrc, blendDst ) {
42941
42942         if ( blending !== _oldBlending ) {
42943
42944             if ( blending === THREE.NoBlending ) {
42945
42946                 _gl.disable( _gl.BLEND );
42947
42948             } else if ( blending === THREE.AdditiveBlending ) {
42949
42950                 _gl.enable( _gl.BLEND );
42951                 _gl.blendEquation( _gl.FUNC_ADD );
42952                 _gl.blendFunc( _gl.SRC_ALPHA, _gl.ONE );
42953
42954             } else if ( blending === THREE.SubtractiveBlending ) {
42955
42956                 // TODO: Find blendFuncSeparate() combination
42957                 _gl.enable( _gl.BLEND );
42958                 _gl.blendEquation( _gl.FUNC_ADD );
42959                 _gl.blendFunc( _gl.ZERO, _gl.ONE_MINUS_SRC_COLOR );
42960
42961             } else if ( blending === THREE.MultiplyBlending ) {
42962
42963                 // TODO: Find blendFuncSeparate() combination
42964                 _gl.enable( _gl.BLEND );
42965                 _gl.blendEquation( _gl.FUNC_ADD );
42966                 _gl.blendFunc( _gl.ZERO, _gl.SRC_COLOR );
42967
42968             } else if ( blending === THREE.CustomBlending ) {
42969
42970                 _gl.enable( _gl.BLEND );
42971
42972             } else {
42973
42974                 _gl.enable( _gl.BLEND );
42975                 _gl.blendEquationSeparate( _gl.FUNC_ADD, _gl.FUNC_ADD );
42976                 _gl.blendFuncSeparate( _gl.SRC_ALPHA, _gl.ONE_MINUS_SRC_ALPHA, _gl.ONE, _gl.ONE_MINUS_SRC_ALPHA );
42977
42978             }
42979
42980             _oldBlending = blending;
42981
42982         }
42983
42984         if ( blending === THREE.CustomBlending ) {
42985
42986             if ( blendEquation !== _oldBlendEquation ) {
42987
42988                 _gl.blendEquation( paramThreeToGL( blendEquation ) );
42989
42990                 _oldBlendEquation = blendEquation;
42991
42992             }
42993
42994             if ( blendSrc !== _oldBlendSrc || blendDst !== _oldBlendDst ) {
42995
42996                 _gl.blendFunc( paramThreeToGL( blendSrc ), paramThreeToGL( blendDst ) );
42997
42998                 _oldBlendSrc = blendSrc;
42999                 _oldBlendDst = blendDst;
43000
43001             }
43002
43003         } else {
43004
43005             _oldBlendEquation = null;
43006             _oldBlendSrc = null;
43007             _oldBlendDst = null;
43008
43009         }
43010
43011     };
43012
43013     // Shaders
43014
43015     function buildProgram ( shaderID, fragmentShader, vertexShader, uniforms, attributes, parameters ) {
43016
43017         var p, pl, program, code;
43018         var chunks = [];
43019
43020         // Generate code
43021
43022         if ( shaderID ) {
43023
43024             chunks.push( shaderID );
43025
43026         } else {
43027
43028             chunks.push( fragmentShader );
43029             chunks.push( vertexShader );
43030
43031         }
43032
43033         for ( p in parameters ) {
43034
43035             chunks.push( p );
43036             chunks.push( parameters[ p ] );
43037
43038         }
43039
43040         code = chunks.join();
43041
43042         // Check if code has been already compiled
43043
43044         for ( p = 0, pl = _programs.length; p < pl; p ++ ) {
43045
43046             var programInfo = _programs[ p ];
43047
43048             if ( programInfo.code === code ) {
43049
43050                 // console.log( "Code already compiled." /*: \n\n" + code*/ );
43051
43052                 programInfo.usedTimes ++;
43053
43054                 return programInfo.program;
43055
43056             }
43057
43058         }
43059
43060         //console.log( "building new program " );
43061
43062         //
43063
43064         program = _gl.createProgram();
43065
43066         var prefix_vertex = [
43067
43068             "precision " + _precision + " float;",
43069
43070             _supportsVertexTextures ? "#define VERTEX_TEXTURES" : "",
43071
43072             _this.gammaInput ? "#define GAMMA_INPUT" : "",
43073             _this.gammaOutput ? "#define GAMMA_OUTPUT" : "",
43074             _this.physicallyBasedShading ? "#define PHYSICALLY_BASED_SHADING" : "",
43075
43076             "#define MAX_DIR_LIGHTS " + parameters.maxDirLights,
43077             "#define MAX_POINT_LIGHTS " + parameters.maxPointLights,
43078             "#define MAX_SPOT_LIGHTS " + parameters.maxSpotLights,
43079             "#define MAX_HEMI_LIGHTS " + parameters.maxHemiLights,
43080
43081             "#define MAX_SHADOWS " + parameters.maxShadows,
43082
43083             "#define MAX_BONES " + parameters.maxBones,
43084
43085             parameters.map ? "#define USE_MAP" : "",
43086             parameters.envMap ? "#define USE_ENVMAP" : "",
43087             parameters.lightMap ? "#define USE_LIGHTMAP" : "",
43088             parameters.bumpMap ? "#define USE_BUMPMAP" : "",
43089             parameters.normalMap ? "#define USE_NORMALMAP" : "",
43090             parameters.specularMap ? "#define USE_SPECULARMAP" : "",
43091             parameters.vertexColors ? "#define USE_COLOR" : "",
43092
43093             parameters.skinning ? "#define USE_SKINNING" : "",
43094             parameters.useVertexTexture ? "#define BONE_TEXTURE" : "",
43095             parameters.boneTextureWidth ? "#define N_BONE_PIXEL_X " + parameters.boneTextureWidth.toFixed( 1 ) : "",
43096             parameters.boneTextureHeight ? "#define N_BONE_PIXEL_Y " + parameters.boneTextureHeight.toFixed( 1 ) : "",
43097
43098             parameters.morphTargets ? "#define USE_MORPHTARGETS" : "",
43099             parameters.morphNormals ? "#define USE_MORPHNORMALS" : "",
43100             parameters.perPixel ? "#define PHONG_PER_PIXEL" : "",
43101             parameters.wrapAround ? "#define WRAP_AROUND" : "",
43102             parameters.doubleSided ? "#define DOUBLE_SIDED" : "",
43103             parameters.flipSided ? "#define FLIP_SIDED" : "",
43104
43105             parameters.shadowMapEnabled ? "#define USE_SHADOWMAP" : "",
43106             parameters.shadowMapSoft ? "#define SHADOWMAP_SOFT" : "",
43107             parameters.shadowMapDebug ? "#define SHADOWMAP_DEBUG" : "",
43108             parameters.shadowMapCascade ? "#define SHADOWMAP_CASCADE" : "",
43109
43110             parameters.sizeAttenuation ? "#define USE_SIZEATTENUATION" : "",
43111
43112             "uniform mat4 modelMatrix;",
43113             "uniform mat4 modelViewMatrix;",
43114             "uniform mat4 projectionMatrix;",
43115             "uniform mat4 viewMatrix;",
43116             "uniform mat3 normalMatrix;",
43117             "uniform vec3 cameraPosition;",
43118
43119             "attribute vec3 position;",
43120             "attribute vec3 normal;",
43121             "attribute vec2 uv;",
43122             "attribute vec2 uv2;",
43123
43124             "#ifdef USE_COLOR",
43125
43126                 "attribute vec3 color;",
43127
43128             "#endif",
43129
43130             "#ifdef USE_MORPHTARGETS",
43131
43132                 "attribute vec3 morphTarget0;",
43133                 "attribute vec3 morphTarget1;",
43134                 "attribute vec3 morphTarget2;",
43135                 "attribute vec3 morphTarget3;",
43136
43137                 "#ifdef USE_MORPHNORMALS",
43138
43139                     "attribute vec3 morphNormal0;",
43140                     "attribute vec3 morphNormal1;",
43141                     "attribute vec3 morphNormal2;",
43142                     "attribute vec3 morphNormal3;",
43143
43144                 "#else",
43145
43146                     "attribute vec3 morphTarget4;",
43147                     "attribute vec3 morphTarget5;",
43148                     "attribute vec3 morphTarget6;",
43149                     "attribute vec3 morphTarget7;",
43150
43151                 "#endif",
43152
43153             "#endif",
43154
43155             "#ifdef USE_SKINNING",
43156
43157                 "attribute vec4 skinIndex;",
43158                 "attribute vec4 skinWeight;",
43159
43160             "#endif",
43161
43162             ""
43163
43164         ].join("\n");
43165
43166         var prefix_fragment = [
43167
43168             "precision " + _precision + " float;",
43169
43170             ( parameters.bumpMap || parameters.normalMap ) ? "#extension GL_OES_standard_derivatives : enable" : "",
43171
43172             "#define MAX_DIR_LIGHTS " + parameters.maxDirLights,
43173             "#define MAX_POINT_LIGHTS " + parameters.maxPointLights,
43174             "#define MAX_SPOT_LIGHTS " + parameters.maxSpotLights,
43175             "#define MAX_HEMI_LIGHTS " + parameters.maxHemiLights,
43176
43177             "#define MAX_SHADOWS " + parameters.maxShadows,
43178
43179             parameters.alphaTest ? "#define ALPHATEST " + parameters.alphaTest: "",
43180
43181             _this.gammaInput ? "#define GAMMA_INPUT" : "",
43182             _this.gammaOutput ? "#define GAMMA_OUTPUT" : "",
43183             _this.physicallyBasedShading ? "#define PHYSICALLY_BASED_SHADING" : "",
43184
43185             ( parameters.useFog && parameters.fog ) ? "#define USE_FOG" : "",
43186             ( parameters.useFog && parameters.fog instanceof THREE.FogExp2 ) ? "#define FOG_EXP2" : "",
43187
43188             parameters.map ? "#define USE_MAP" : "",
43189             parameters.envMap ? "#define USE_ENVMAP" : "",
43190             parameters.lightMap ? "#define USE_LIGHTMAP" : "",
43191             parameters.bumpMap ? "#define USE_BUMPMAP" : "",
43192             parameters.normalMap ? "#define USE_NORMALMAP" : "",
43193             parameters.specularMap ? "#define USE_SPECULARMAP" : "",
43194             parameters.vertexColors ? "#define USE_COLOR" : "",
43195
43196             parameters.metal ? "#define METAL" : "",
43197             parameters.perPixel ? "#define PHONG_PER_PIXEL" : "",
43198             parameters.wrapAround ? "#define WRAP_AROUND" : "",
43199             parameters.doubleSided ? "#define DOUBLE_SIDED" : "",
43200             parameters.flipSided ? "#define FLIP_SIDED" : "",
43201
43202             parameters.shadowMapEnabled ? "#define USE_SHADOWMAP" : "",
43203             parameters.shadowMapSoft ? "#define SHADOWMAP_SOFT" : "",
43204             parameters.shadowMapDebug ? "#define SHADOWMAP_DEBUG" : "",
43205             parameters.shadowMapCascade ? "#define SHADOWMAP_CASCADE" : "",
43206
43207             "uniform mat4 viewMatrix;",
43208             "uniform vec3 cameraPosition;",
43209             ""
43210
43211         ].join("\n");
43212
43213         var glFragmentShader = getShader( "fragment", prefix_fragment + fragmentShader );
43214         var glVertexShader = getShader( "vertex", prefix_vertex + vertexShader );
43215
43216         _gl.attachShader( program, glVertexShader );
43217         _gl.attachShader( program, glFragmentShader );
43218
43219         _gl.linkProgram( program );
43220
43221         if ( !_gl.getProgramParameter( program, _gl.LINK_STATUS ) ) {
43222
43223             console.error( "Could not initialise shader\n" + "VALIDATE_STATUS: " + _gl.getProgramParameter( program, _gl.VALIDATE_STATUS ) + ", gl error [" + _gl.getError() + "]" );
43224
43225         }
43226
43227         // clean up
43228
43229         _gl.deleteShader( glFragmentShader );
43230         _gl.deleteShader( glVertexShader );
43231
43232         //console.log( prefix_fragment + fragmentShader );
43233         //console.log( prefix_vertex + vertexShader );
43234
43235         program.uniforms = {};
43236         program.attributes = {};
43237
43238         var identifiers, u, a, i;
43239
43240         // cache uniform locations
43241
43242         identifiers = [
43243
43244             'viewMatrix', 'modelViewMatrix', 'projectionMatrix', 'normalMatrix', 'modelMatrix', 'cameraPosition',
43245             'morphTargetInfluences'
43246
43247         ];
43248
43249         if ( parameters.useVertexTexture ) {
43250
43251             identifiers.push( 'boneTexture' );
43252
43253         } else {
43254
43255             identifiers.push( 'boneGlobalMatrices' );
43256
43257         }
43258
43259         for ( u in uniforms ) {
43260
43261             identifiers.push( u );
43262
43263         }
43264
43265         cacheUniformLocations( program, identifiers );
43266
43267         // cache attributes locations
43268
43269         identifiers = [
43270
43271             "position", "normal", "uv", "uv2", "tangent", "color",
43272             "skinIndex", "skinWeight"
43273
43274         ];
43275
43276         for ( i = 0; i < parameters.maxMorphTargets; i ++ ) {
43277
43278             identifiers.push( "morphTarget" + i );
43279
43280         }
43281
43282         for ( i = 0; i < parameters.maxMorphNormals; i ++ ) {
43283
43284             identifiers.push( "morphNormal" + i );
43285
43286         }
43287
43288         for ( a in attributes ) {
43289
43290             identifiers.push( a );
43291
43292         }
43293
43294         cacheAttributeLocations( program, identifiers );
43295
43296         program.id = _programs_counter ++;
43297
43298         _programs.push( { program: program, code: code, usedTimes: 1 } );
43299
43300         _this.info.memory.programs = _programs.length;
43301
43302         return program;
43303
43304     };
43305
43306     // Shader parameters cache
43307
43308     function cacheUniformLocations ( program, identifiers ) {
43309
43310         var i, l, id;
43311
43312         for( i = 0, l = identifiers.length; i < l; i ++ ) {
43313
43314             id = identifiers[ i ];
43315             program.uniforms[ id ] = _gl.getUniformLocation( program, id );
43316
43317         }
43318
43319     };
43320
43321     function cacheAttributeLocations ( program, identifiers ) {
43322
43323         var i, l, id;
43324
43325         for( i = 0, l = identifiers.length; i < l; i ++ ) {
43326
43327             id = identifiers[ i ];
43328             program.attributes[ id ] = _gl.getAttribLocation( program, id );
43329
43330         }
43331
43332     };
43333
43334     function addLineNumbers ( string ) {
43335
43336         var chunks = string.split( "\n" );
43337
43338         for ( var i = 0, il = chunks.length; i < il; i ++ ) {
43339
43340             // Chrome reports shader errors on lines
43341             // starting counting from 1
43342
43343             chunks[ i ] = ( i + 1 ) + ": " + chunks[ i ];
43344
43345         }
43346
43347         return chunks.join( "\n" );
43348
43349     };
43350
43351     function getShader ( type, string ) {
43352
43353         var shader;
43354
43355         if ( type === "fragment" ) {
43356
43357             shader = _gl.createShader( _gl.FRAGMENT_SHADER );
43358
43359         } else if ( type === "vertex" ) {
43360
43361             shader = _gl.createShader( _gl.VERTEX_SHADER );
43362
43363         }
43364
43365         _gl.shaderSource( shader, string );
43366         _gl.compileShader( shader );
43367
43368         if ( !_gl.getShaderParameter( shader, _gl.COMPILE_STATUS ) ) {
43369
43370             console.error( _gl.getShaderInfoLog( shader ) );
43371             console.error( addLineNumbers( string ) );
43372             return null;
43373
43374         }
43375
43376         return shader;
43377
43378     };
43379
43380     // Textures
43381
43382
43383     function isPowerOfTwo ( value ) {
43384
43385         return ( value & ( value - 1 ) ) === 0;
43386
43387     };
43388
43389     function setTextureParameters ( textureType, texture, isImagePowerOfTwo ) {
43390
43391         if ( isImagePowerOfTwo ) {
43392
43393             _gl.texParameteri( textureType, _gl.TEXTURE_WRAP_S, paramThreeToGL( texture.wrapS ) );
43394             _gl.texParameteri( textureType, _gl.TEXTURE_WRAP_T, paramThreeToGL( texture.wrapT ) );
43395
43396             _gl.texParameteri( textureType, _gl.TEXTURE_MAG_FILTER, paramThreeToGL( texture.magFilter ) );
43397             _gl.texParameteri( textureType, _gl.TEXTURE_MIN_FILTER, paramThreeToGL( texture.minFilter ) );
43398
43399         } else {
43400
43401             _gl.texParameteri( textureType, _gl.TEXTURE_WRAP_S, _gl.CLAMP_TO_EDGE );
43402             _gl.texParameteri( textureType, _gl.TEXTURE_WRAP_T, _gl.CLAMP_TO_EDGE );
43403
43404             _gl.texParameteri( textureType, _gl.TEXTURE_MAG_FILTER, filterFallback( texture.magFilter ) );
43405             _gl.texParameteri( textureType, _gl.TEXTURE_MIN_FILTER, filterFallback( texture.minFilter ) );
43406
43407         }
43408
43409         if ( _glExtensionTextureFilterAnisotropic && texture.type !== THREE.FloatType ) {
43410
43411             if ( texture.anisotropy > 1 || texture.__oldAnisotropy ) {
43412
43413                 _gl.texParameterf( textureType, _glExtensionTextureFilterAnisotropic.TEXTURE_MAX_ANISOTROPY_EXT, Math.min( texture.anisotropy, _maxAnisotropy ) );
43414                 texture.__oldAnisotropy = texture.anisotropy;
43415
43416             }
43417
43418         }
43419
43420     };
43421
43422     this.setTexture = function ( texture, slot ) {
43423
43424         if ( texture.needsUpdate ) {
43425
43426             if ( ! texture.__webglInit ) {
43427
43428                 texture.__webglInit = true;
43429                 texture.__webglTexture = _gl.createTexture();
43430
43431                 _this.info.memory.textures ++;
43432
43433             }
43434
43435             _gl.activeTexture( _gl.TEXTURE0 + slot );
43436             _gl.bindTexture( _gl.TEXTURE_2D, texture.__webglTexture );
43437
43438             _gl.pixelStorei( _gl.UNPACK_FLIP_Y_WEBGL, texture.flipY );
43439             _gl.pixelStorei( _gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, texture.premultiplyAlpha );
43440
43441             var image = texture.image,
43442             isImagePowerOfTwo = isPowerOfTwo( image.width ) && isPowerOfTwo( image.height ),
43443             glFormat = paramThreeToGL( texture.format ),
43444             glType = paramThreeToGL( texture.type );
43445
43446             setTextureParameters( _gl.TEXTURE_2D, texture, isImagePowerOfTwo );
43447
43448             if ( texture instanceof THREE.CompressedTexture ) {
43449
43450                 var mipmap, mipmaps = texture.mipmaps;
43451
43452                 for( var i = 0, il = mipmaps.length; i < il; i ++ ) {
43453
43454                     mipmap = mipmaps[ i ];
43455                     _gl.compressedTexImage2D( _gl.TEXTURE_2D, i, glFormat, mipmap.width, mipmap.height, 0, mipmap.data );
43456
43457                 }
43458
43459             } else if ( texture instanceof THREE.DataTexture ) {
43460
43461                 _gl.texImage2D( _gl.TEXTURE_2D, 0, glFormat, image.width, image.height, 0, glFormat, glType, image.data );
43462
43463             } else {
43464
43465                 _gl.texImage2D( _gl.TEXTURE_2D, 0, glFormat, glFormat, glType, texture.image );
43466
43467             }
43468
43469             if ( texture.generateMipmaps && isImagePowerOfTwo ) _gl.generateMipmap( _gl.TEXTURE_2D );
43470
43471             texture.needsUpdate = false;
43472
43473             if ( texture.onUpdate ) texture.onUpdate();
43474
43475         } else {
43476
43477             _gl.activeTexture( _gl.TEXTURE0 + slot );
43478             _gl.bindTexture( _gl.TEXTURE_2D, texture.__webglTexture );
43479
43480         }
43481
43482     };
43483
43484     function clampToMaxSize ( image, maxSize ) {
43485
43486         if ( image.width <= maxSize && image.height <= maxSize ) {
43487
43488             return image;
43489
43490         }
43491
43492         // Warning: Scaling through the canvas will only work with images that use
43493         // premultiplied alpha.
43494
43495         var maxDimension = Math.max( image.width, image.height );
43496         var newWidth = Math.floor( image.width * maxSize / maxDimension );
43497         var newHeight = Math.floor( image.height * maxSize / maxDimension );
43498
43499         var canvas = document.createElement( 'canvas' );
43500         canvas.width = newWidth;
43501         canvas.height = newHeight;
43502
43503         var ctx = canvas.getContext( "2d" );
43504         ctx.drawImage( image, 0, 0, image.width, image.height, 0, 0, newWidth, newHeight );
43505
43506         return canvas;
43507
43508     }
43509
43510     function setCubeTexture ( texture, slot ) {
43511
43512         if ( texture.image.length === 6 ) {
43513
43514             if ( texture.needsUpdate ) {
43515
43516                 if ( ! texture.image.__webglTextureCube ) {
43517
43518                     texture.image.__webglTextureCube = _gl.createTexture();
43519
43520                 }
43521
43522                 _gl.activeTexture( _gl.TEXTURE0 + slot );
43523                 _gl.bindTexture( _gl.TEXTURE_CUBE_MAP, texture.image.__webglTextureCube );
43524
43525                 _gl.pixelStorei( _gl.UNPACK_FLIP_Y_WEBGL, texture.flipY );
43526
43527                 var isCompressed = texture instanceof THREE.CompressedTexture;
43528
43529                 var cubeImage = [];
43530
43531                 for ( var i = 0; i < 6; i ++ ) {
43532
43533                     if ( _this.autoScaleCubemaps && ! isCompressed ) {
43534
43535                         cubeImage[ i ] = clampToMaxSize( texture.image[ i ], _maxCubemapSize );
43536
43537                     } else {
43538
43539                         cubeImage[ i ] = texture.image[ i ];
43540
43541                     }
43542
43543                 }
43544
43545                 var image = cubeImage[ 0 ],
43546                 isImagePowerOfTwo = isPowerOfTwo( image.width ) && isPowerOfTwo( image.height ),
43547                 glFormat = paramThreeToGL( texture.format ),
43548                 glType = paramThreeToGL( texture.type );
43549
43550                 setTextureParameters( _gl.TEXTURE_CUBE_MAP, texture, isImagePowerOfTwo );
43551
43552                 for ( var i = 0; i < 6; i ++ ) {
43553
43554                     if ( isCompressed ) {
43555
43556                         var mipmap, mipmaps = cubeImage[ i ].mipmaps;
43557
43558                         for( var j = 0, jl = mipmaps.length; j < jl; j ++ ) {
43559
43560                             mipmap = mipmaps[ j ];
43561                             _gl.compressedTexImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, j, glFormat, mipmap.width, mipmap.height, 0, mipmap.data );
43562
43563                         }
43564
43565                     } else {
43566
43567                         _gl.texImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, glFormat, glFormat, glType, cubeImage[ i ] );
43568
43569                     }
43570
43571                 }
43572
43573                 if ( texture.generateMipmaps && isImagePowerOfTwo ) {
43574
43575                     _gl.generateMipmap( _gl.TEXTURE_CUBE_MAP );
43576
43577                 }
43578
43579                 texture.needsUpdate = false;
43580
43581                 if ( texture.onUpdate ) texture.onUpdate();
43582
43583             } else {
43584
43585                 _gl.activeTexture( _gl.TEXTURE0 + slot );
43586                 _gl.bindTexture( _gl.TEXTURE_CUBE_MAP, texture.image.__webglTextureCube );
43587
43588             }
43589
43590         }
43591
43592     };
43593
43594     function setCubeTextureDynamic ( texture, slot ) {
43595
43596         _gl.activeTexture( _gl.TEXTURE0 + slot );
43597         _gl.bindTexture( _gl.TEXTURE_CUBE_MAP, texture.__webglTexture );
43598
43599     };
43600
43601     // Render targets
43602
43603     function setupFrameBuffer ( framebuffer, renderTarget, textureTarget ) {
43604
43605         _gl.bindFramebuffer( _gl.FRAMEBUFFER, framebuffer );
43606         _gl.framebufferTexture2D( _gl.FRAMEBUFFER, _gl.COLOR_ATTACHMENT0, textureTarget, renderTarget.__webglTexture, 0 );
43607
43608     };
43609
43610     function setupRenderBuffer ( renderbuffer, renderTarget  ) {
43611
43612         _gl.bindRenderbuffer( _gl.RENDERBUFFER, renderbuffer );
43613
43614         if ( renderTarget.depthBuffer && ! renderTarget.stencilBuffer ) {
43615
43616             _gl.renderbufferStorage( _gl.RENDERBUFFER, _gl.DEPTH_COMPONENT16, renderTarget.width, renderTarget.height );
43617             _gl.framebufferRenderbuffer( _gl.FRAMEBUFFER, _gl.DEPTH_ATTACHMENT, _gl.RENDERBUFFER, renderbuffer );
43618
43619         /* For some reason this is not working. Defaulting to RGBA4.
43620         } else if( ! renderTarget.depthBuffer && renderTarget.stencilBuffer ) {
43621
43622             _gl.renderbufferStorage( _gl.RENDERBUFFER, _gl.STENCIL_INDEX8, renderTarget.width, renderTarget.height );
43623             _gl.framebufferRenderbuffer( _gl.FRAMEBUFFER, _gl.STENCIL_ATTACHMENT, _gl.RENDERBUFFER, renderbuffer );
43624         */
43625         } else if( renderTarget.depthBuffer && renderTarget.stencilBuffer ) {
43626
43627             _gl.renderbufferStorage( _gl.RENDERBUFFER, _gl.DEPTH_STENCIL, renderTarget.width, renderTarget.height );
43628             _gl.framebufferRenderbuffer( _gl.FRAMEBUFFER, _gl.DEPTH_STENCIL_ATTACHMENT, _gl.RENDERBUFFER, renderbuffer );
43629
43630         } else {
43631
43632             _gl.renderbufferStorage( _gl.RENDERBUFFER, _gl.RGBA4, renderTarget.width, renderTarget.height );
43633
43634         }
43635
43636     };
43637
43638     this.setRenderTarget = function ( renderTarget ) {
43639
43640         var isCube = ( renderTarget instanceof THREE.WebGLRenderTargetCube );
43641
43642         if ( renderTarget && ! renderTarget.__webglFramebuffer ) {
43643
43644             if ( renderTarget.depthBuffer === undefined ) renderTarget.depthBuffer = true;
43645             if ( renderTarget.stencilBuffer === undefined ) renderTarget.stencilBuffer = true;
43646
43647             renderTarget.__webglTexture = _gl.createTexture();
43648
43649             // Setup texture, create render and frame buffers
43650
43651             var isTargetPowerOfTwo = isPowerOfTwo( renderTarget.width ) && isPowerOfTwo( renderTarget.height ),
43652                 glFormat = paramThreeToGL( renderTarget.format ),
43653                 glType = paramThreeToGL( renderTarget.type );
43654
43655             if ( isCube ) {
43656
43657                 renderTarget.__webglFramebuffer = [];
43658                 renderTarget.__webglRenderbuffer = [];
43659
43660                 _gl.bindTexture( _gl.TEXTURE_CUBE_MAP, renderTarget.__webglTexture );
43661                 setTextureParameters( _gl.TEXTURE_CUBE_MAP, renderTarget, isTargetPowerOfTwo );
43662
43663                 for ( var i = 0; i < 6; i ++ ) {
43664
43665                     renderTarget.__webglFramebuffer[ i ] = _gl.createFramebuffer();
43666                     renderTarget.__webglRenderbuffer[ i ] = _gl.createRenderbuffer();
43667
43668                     _gl.texImage2D( _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, glFormat, renderTarget.width, renderTarget.height, 0, glFormat, glType, null );
43669
43670                     setupFrameBuffer( renderTarget.__webglFramebuffer[ i ], renderTarget, _gl.TEXTURE_CUBE_MAP_POSITIVE_X + i );
43671                     setupRenderBuffer( renderTarget.__webglRenderbuffer[ i ], renderTarget );
43672
43673                 }
43674
43675                 if ( isTargetPowerOfTwo ) _gl.generateMipmap( _gl.TEXTURE_CUBE_MAP );
43676
43677             } else {
43678
43679                 renderTarget.__webglFramebuffer = _gl.createFramebuffer();
43680                 renderTarget.__webglRenderbuffer = _gl.createRenderbuffer();
43681
43682                 _gl.bindTexture( _gl.TEXTURE_2D, renderTarget.__webglTexture );
43683                 setTextureParameters( _gl.TEXTURE_2D, renderTarget, isTargetPowerOfTwo );
43684
43685                 _gl.texImage2D( _gl.TEXTURE_2D, 0, glFormat, renderTarget.width, renderTarget.height, 0, glFormat, glType, null );
43686
43687                 setupFrameBuffer( renderTarget.__webglFramebuffer, renderTarget, _gl.TEXTURE_2D );
43688                 setupRenderBuffer( renderTarget.__webglRenderbuffer, renderTarget );
43689
43690                 if ( isTargetPowerOfTwo ) _gl.generateMipmap( _gl.TEXTURE_2D );
43691
43692             }
43693
43694             // Release everything
43695
43696             if ( isCube ) {
43697
43698                 _gl.bindTexture( _gl.TEXTURE_CUBE_MAP, null );
43699
43700             } else {
43701
43702                 _gl.bindTexture( _gl.TEXTURE_2D, null );
43703
43704             }
43705
43706             _gl.bindRenderbuffer( _gl.RENDERBUFFER, null );
43707             _gl.bindFramebuffer( _gl.FRAMEBUFFER, null);
43708
43709         }
43710
43711         var framebuffer, width, height, vx, vy;
43712
43713         if ( renderTarget ) {
43714
43715             if ( isCube ) {
43716
43717                 framebuffer = renderTarget.__webglFramebuffer[ renderTarget.activeCubeFace ];
43718
43719             } else {
43720
43721                 framebuffer = renderTarget.__webglFramebuffer;
43722
43723             }
43724
43725             width = renderTarget.width;
43726             height = renderTarget.height;
43727
43728             vx = 0;
43729             vy = 0;
43730
43731         } else {
43732
43733             framebuffer = null;
43734
43735             width = _viewportWidth;
43736             height = _viewportHeight;
43737
43738             vx = _viewportX;
43739             vy = _viewportY;
43740
43741         }
43742
43743         if ( framebuffer !== _currentFramebuffer ) {
43744
43745             _gl.bindFramebuffer( _gl.FRAMEBUFFER, framebuffer );
43746             _gl.viewport( vx, vy, width, height );
43747
43748             _currentFramebuffer = framebuffer;
43749
43750         }
43751
43752         _currentWidth = width;
43753         _currentHeight = height;
43754
43755     };
43756
43757     function updateRenderTargetMipmap ( renderTarget ) {
43758
43759         if ( renderTarget instanceof THREE.WebGLRenderTargetCube ) {
43760
43761             _gl.bindTexture( _gl.TEXTURE_CUBE_MAP, renderTarget.__webglTexture );
43762             _gl.generateMipmap( _gl.TEXTURE_CUBE_MAP );
43763             _gl.bindTexture( _gl.TEXTURE_CUBE_MAP, null );
43764
43765         } else {
43766
43767             _gl.bindTexture( _gl.TEXTURE_2D, renderTarget.__webglTexture );
43768             _gl.generateMipmap( _gl.TEXTURE_2D );
43769             _gl.bindTexture( _gl.TEXTURE_2D, null );
43770
43771         }
43772
43773     };
43774
43775     // Fallback filters for non-power-of-2 textures
43776
43777     function filterFallback ( f ) {
43778
43779         if ( f === THREE.NearestFilter || f === THREE.NearestMipMapNearestFilter || f === THREE.NearestMipMapLinearFilter ) {
43780
43781             return _gl.NEAREST;
43782
43783         }
43784
43785         return _gl.LINEAR;
43786
43787     };
43788
43789     // Map three.js constants to WebGL constants
43790
43791     function paramThreeToGL ( p ) {
43792
43793         if ( p === THREE.RepeatWrapping ) return _gl.REPEAT;
43794         if ( p === THREE.ClampToEdgeWrapping ) return _gl.CLAMP_TO_EDGE;
43795         if ( p === THREE.MirroredRepeatWrapping ) return _gl.MIRRORED_REPEAT;
43796
43797         if ( p === THREE.NearestFilter ) return _gl.NEAREST;
43798         if ( p === THREE.NearestMipMapNearestFilter ) return _gl.NEAREST_MIPMAP_NEAREST;
43799         if ( p === THREE.NearestMipMapLinearFilter ) return _gl.NEAREST_MIPMAP_LINEAR;
43800
43801         if ( p === THREE.LinearFilter ) return _gl.LINEAR;
43802         if ( p === THREE.LinearMipMapNearestFilter ) return _gl.LINEAR_MIPMAP_NEAREST;
43803         if ( p === THREE.LinearMipMapLinearFilter ) return _gl.LINEAR_MIPMAP_LINEAR;
43804
43805         if ( p === THREE.UnsignedByteType ) return _gl.UNSIGNED_BYTE;
43806         if ( p === THREE.UnsignedShort4444Type ) return _gl.UNSIGNED_SHORT_4_4_4_4;
43807         if ( p === THREE.UnsignedShort5551Type ) return _gl.UNSIGNED_SHORT_5_5_5_1;
43808         if ( p === THREE.UnsignedShort565Type ) return _gl.UNSIGNED_SHORT_5_6_5;
43809
43810         if ( p === THREE.ByteType ) return _gl.BYTE;
43811         if ( p === THREE.ShortType ) return _gl.SHORT;
43812         if ( p === THREE.UnsignedShortType ) return _gl.UNSIGNED_SHORT;
43813         if ( p === THREE.IntType ) return _gl.INT;
43814         if ( p === THREE.UnsignedIntType ) return _gl.UNSIGNED_INT;
43815         if ( p === THREE.FloatType ) return _gl.FLOAT;
43816
43817         if ( p === THREE.AlphaFormat ) return _gl.ALPHA;
43818         if ( p === THREE.RGBFormat ) return _gl.RGB;
43819         if ( p === THREE.RGBAFormat ) return _gl.RGBA;
43820         if ( p === THREE.LuminanceFormat ) return _gl.LUMINANCE;
43821         if ( p === THREE.LuminanceAlphaFormat ) return _gl.LUMINANCE_ALPHA;
43822
43823         if ( p === THREE.AddEquation ) return _gl.FUNC_ADD;
43824         if ( p === THREE.SubtractEquation ) return _gl.FUNC_SUBTRACT;
43825         if ( p === THREE.ReverseSubtractEquation ) return _gl.FUNC_REVERSE_SUBTRACT;
43826
43827         if ( p === THREE.ZeroFactor ) return _gl.ZERO;
43828         if ( p === THREE.OneFactor ) return _gl.ONE;
43829         if ( p === THREE.SrcColorFactor ) return _gl.SRC_COLOR;
43830         if ( p === THREE.OneMinusSrcColorFactor ) return _gl.ONE_MINUS_SRC_COLOR;
43831         if ( p === THREE.SrcAlphaFactor ) return _gl.SRC_ALPHA;
43832         if ( p === THREE.OneMinusSrcAlphaFactor ) return _gl.ONE_MINUS_SRC_ALPHA;
43833         if ( p === THREE.DstAlphaFactor ) return _gl.DST_ALPHA;
43834         if ( p === THREE.OneMinusDstAlphaFactor ) return _gl.ONE_MINUS_DST_ALPHA;
43835
43836         if ( p === THREE.DstColorFactor ) return _gl.DST_COLOR;
43837         if ( p === THREE.OneMinusDstColorFactor ) return _gl.ONE_MINUS_DST_COLOR;
43838         if ( p === THREE.SrcAlphaSaturateFactor ) return _gl.SRC_ALPHA_SATURATE;
43839
43840         if ( _glExtensionCompressedTextureS3TC !== undefined ) {
43841
43842             if ( p === THREE.RGB_S3TC_DXT1_Format ) return _glExtensionCompressedTextureS3TC.COMPRESSED_RGB_S3TC_DXT1_EXT;
43843             if ( p === THREE.RGBA_S3TC_DXT1_Format ) return _glExtensionCompressedTextureS3TC.COMPRESSED_RGBA_S3TC_DXT1_EXT;
43844             if ( p === THREE.RGBA_S3TC_DXT3_Format ) return _glExtensionCompressedTextureS3TC.COMPRESSED_RGBA_S3TC_DXT3_EXT;
43845             if ( p === THREE.RGBA_S3TC_DXT5_Format ) return _glExtensionCompressedTextureS3TC.COMPRESSED_RGBA_S3TC_DXT5_EXT;
43846
43847         }
43848
43849         return 0;
43850
43851     };
43852
43853     // Allocations
43854
43855     function allocateBones ( object ) {
43856
43857         if ( _supportsBoneTextures && object && object.useVertexTexture ) {
43858
43859             return 1024;
43860
43861         } else {
43862
43863             // default for when object is not specified
43864             // ( for example when prebuilding shader
43865             //   to be used with multiple objects )
43866             //
43867             //     - leave some extra space for other uniforms
43868             //  - limit here is ANGLE's 254 max uniform vectors
43869             //    (up to 54 should be safe)
43870
43871             var nVertexUniforms = _gl.getParameter( _gl.MAX_VERTEX_UNIFORM_VECTORS );
43872             var nVertexMatrices = Math.floor( ( nVertexUniforms - 20 ) / 4 );
43873
43874             var maxBones = nVertexMatrices;
43875
43876             if ( object !== undefined && object instanceof THREE.SkinnedMesh ) {
43877
43878                 maxBones = Math.min( object.bones.length, maxBones );
43879
43880                 if ( maxBones < object.bones.length ) {
43881
43882                     console.warn( "WebGLRenderer: too many bones - " + object.bones.length + ", this GPU supports just " + maxBones + " (try OpenGL instead of ANGLE)" );
43883
43884                 }
43885
43886             }
43887
43888             return maxBones;
43889
43890         }
43891
43892     };
43893
43894     function allocateLights ( lights ) {
43895
43896         var l, ll, light, dirLights, pointLights, spotLights, hemiLights, maxDirLights, maxPointLights, maxSpotLights, maxHemiLights;
43897
43898         dirLights = pointLights = spotLights = hemiLights = maxDirLights = maxPointLights = maxSpotLights = maxHemiLights = 0;
43899
43900         for ( l = 0, ll = lights.length; l < ll; l ++ ) {
43901
43902             light = lights[ l ];
43903
43904             if ( light.onlyShadow ) continue;
43905
43906             if ( light instanceof THREE.DirectionalLight ) dirLights ++;
43907             if ( light instanceof THREE.PointLight ) pointLights ++;
43908             if ( light instanceof THREE.SpotLight ) spotLights ++;
43909             if ( light instanceof THREE.HemisphereLight ) hemiLights ++;
43910
43911         }
43912
43913         if ( ( pointLights + spotLights + dirLights + hemiLights) <= _maxLights ) {
43914
43915             maxDirLights = dirLights;
43916             maxPointLights = pointLights;
43917             maxSpotLights = spotLights;
43918             maxHemiLights = hemiLights;
43919
43920         } else {
43921
43922             maxDirLights = Math.ceil( _maxLights * dirLights / ( pointLights + dirLights ) );
43923             maxPointLights = _maxLights - maxDirLights;
43924
43925             // these are not really correct
43926
43927             maxSpotLights = maxPointLights;
43928             maxHemiLights = maxDirLights;
43929
43930         }
43931
43932         return { 'directional' : maxDirLights, 'point' : maxPointLights, 'spot': maxSpotLights, 'hemi': maxHemiLights };
43933
43934     };
43935
43936     function allocateShadows ( lights ) {
43937
43938         var l, ll, light, maxShadows = 0;
43939
43940         for ( l = 0, ll = lights.length; l < ll; l++ ) {
43941
43942             light = lights[ l ];
43943
43944             if ( ! light.castShadow ) continue;
43945
43946             if ( light instanceof THREE.SpotLight ) maxShadows ++;
43947             if ( light instanceof THREE.DirectionalLight && ! light.shadowCascade ) maxShadows ++;
43948
43949         }
43950
43951         return maxShadows;
43952
43953     };
43954
43955     // Initialization
43956
43957     function initGL () {
43958
43959         try {
43960
43961             if ( ! ( _gl = _canvas.getContext( 'experimental-webgl', { alpha: _alpha, premultipliedAlpha: _premultipliedAlpha, antialias: _antialias, stencil: _stencil, preserveDrawingBuffer: _preserveDrawingBuffer } ) ) ) {
43962
43963                 throw 'Error creating WebGL context.';
43964
43965             }
43966
43967         } catch ( error ) {
43968
43969             console.error( error );
43970
43971         }
43972
43973         _glExtensionTextureFloat = _gl.getExtension( 'OES_texture_float' );
43974         _glExtensionStandardDerivatives = _gl.getExtension( 'OES_standard_derivatives' );
43975
43976         _glExtensionTextureFilterAnisotropic = _gl.getExtension( 'EXT_texture_filter_anisotropic' ) ||
43977                                                _gl.getExtension( 'MOZ_EXT_texture_filter_anisotropic' ) ||
43978                                                _gl.getExtension( 'WEBKIT_EXT_texture_filter_anisotropic' );
43979
43980
43981         _glExtensionCompressedTextureS3TC = _gl.getExtension( 'WEBGL_compressed_texture_s3tc' ) ||
43982                                             _gl.getExtension( 'MOZ_WEBGL_compressed_texture_s3tc' ) ||
43983                                             _gl.getExtension( 'WEBKIT_WEBGL_compressed_texture_s3tc' );
43984
43985         if ( ! _glExtensionTextureFloat ) {
43986
43987             console.log( 'THREE.WebGLRenderer: Float textures not supported.' );
43988
43989         }
43990
43991         if ( ! _glExtensionStandardDerivatives ) {
43992
43993             console.log( 'THREE.WebGLRenderer: Standard derivatives not supported.' );
43994
43995         }
43996
43997         if ( ! _glExtensionTextureFilterAnisotropic ) {
43998
43999             console.log( 'THREE.WebGLRenderer: Anisotropic texture filtering not supported.' );
44000
44001         }
44002
44003         if ( ! _glExtensionCompressedTextureS3TC ) {
44004
44005             console.log( 'THREE.WebGLRenderer: S3TC compressed textures not supported.' );
44006
44007         }
44008
44009     };
44010
44011     function setDefaultGLState () {
44012
44013         _gl.clearColor( 0, 0, 0, 1 );
44014         _gl.clearDepth( 1 );
44015         _gl.clearStencil( 0 );
44016
44017         _gl.enable( _gl.DEPTH_TEST );
44018         _gl.depthFunc( _gl.LEQUAL );
44019
44020         _gl.frontFace( _gl.CCW );
44021         _gl.cullFace( _gl.BACK );
44022         _gl.enable( _gl.CULL_FACE );
44023
44024         _gl.enable( _gl.BLEND );
44025         _gl.blendEquation( _gl.FUNC_ADD );
44026         _gl.blendFunc( _gl.SRC_ALPHA, _gl.ONE_MINUS_SRC_ALPHA );
44027
44028         _gl.clearColor( _clearColor.r, _clearColor.g, _clearColor.b, _clearAlpha );
44029
44030     };
44031
44032     // default plugins (order is important)
44033
44034     this.shadowMapPlugin = new THREE.ShadowMapPlugin();
44035     this.addPrePlugin( this.shadowMapPlugin );
44036
44037     this.addPostPlugin( new THREE.SpritePlugin() );
44038     this.addPostPlugin( new THREE.LensFlarePlugin() );
44039
44040 };
44041 /**
44042  * @author szimek / https://github.com/szimek/
44043  * @author alteredq / http://alteredqualia.com/
44044  */
44045
44046 THREE.WebGLRenderTarget = function ( width, height, options ) {
44047
44048     this.width = width;
44049     this.height = height;
44050
44051     options = options || {};
44052
44053     this.wrapS = options.wrapS !== undefined ? options.wrapS : THREE.ClampToEdgeWrapping;
44054     this.wrapT = options.wrapT !== undefined ? options.wrapT : THREE.ClampToEdgeWrapping;
44055
44056     this.magFilter = options.magFilter !== undefined ? options.magFilter : THREE.LinearFilter;
44057     this.minFilter = options.minFilter !== undefined ? options.minFilter : THREE.LinearMipMapLinearFilter;
44058
44059     this.anisotropy = options.anisotropy !== undefined ? options.anisotropy : 1;
44060
44061     this.offset = new THREE.Vector2( 0, 0 );
44062     this.repeat = new THREE.Vector2( 1, 1 );
44063
44064     this.format = options.format !== undefined ? options.format : THREE.RGBAFormat;
44065     this.type = options.type !== undefined ? options.type : THREE.UnsignedByteType;
44066
44067     this.depthBuffer = options.depthBuffer !== undefined ? options.depthBuffer : true;
44068     this.stencilBuffer = options.stencilBuffer !== undefined ? options.stencilBuffer : true;
44069
44070     this.generateMipmaps = true;
44071
44072 };
44073
44074 THREE.WebGLRenderTarget.prototype.clone = function() {
44075
44076     var tmp = new THREE.WebGLRenderTarget( this.width, this.height );
44077
44078     tmp.wrapS = this.wrapS;
44079     tmp.wrapT = this.wrapT;
44080
44081     tmp.magFilter = this.magFilter;
44082     tmp.anisotropy = this.anisotropy;
44083
44084     tmp.minFilter = this.minFilter;
44085
44086     tmp.offset.copy( this.offset );
44087     tmp.repeat.copy( this.repeat );
44088
44089     tmp.format = this.format;
44090     tmp.type = this.type;
44091
44092     tmp.depthBuffer = this.depthBuffer;
44093     tmp.stencilBuffer = this.stencilBuffer;
44094
44095     tmp.generateMipmaps = this.generateMipmaps;
44096
44097     return tmp;
44098
44099 };
44100 /**
44101  * @author alteredq / http://alteredqualia.com
44102  */
44103
44104 THREE.WebGLRenderTargetCube = function ( width, height, options ) {
44105
44106     THREE.WebGLRenderTarget.call( this, width, height, options );
44107
44108     this.activeCubeFace = 0; // PX 0, NX 1, PY 2, NY 3, PZ 4, NZ 5
44109
44110 };
44111
44112 THREE.WebGLRenderTargetCube.prototype = Object.create( THREE.WebGLRenderTarget.prototype );
44113 /**
44114  * @author mrdoob / http://mrdoob.com/
44115  */
44116
44117 THREE.RenderableVertex = function () {
44118
44119     this.positionWorld = new THREE.Vector3();
44120     this.positionScreen = new THREE.Vector4();
44121
44122     this.visible = true;
44123
44124 };
44125
44126 THREE.RenderableVertex.prototype.copy = function ( vertex ) {
44127
44128     this.positionWorld.copy( vertex.positionWorld );
44129     this.positionScreen.copy( vertex.positionScreen );
44130
44131 }
44132 /**
44133  * @author mrdoob / http://mrdoob.com/
44134  */
44135
44136 THREE.RenderableFace3 = function () {
44137
44138     this.v1 = new THREE.RenderableVertex();
44139     this.v2 = new THREE.RenderableVertex();
44140     this.v3 = new THREE.RenderableVertex();
44141
44142     this.centroidWorld = new THREE.Vector3();
44143     this.centroidScreen = new THREE.Vector3();
44144
44145     this.normalWorld = new THREE.Vector3();
44146     this.vertexNormalsWorld = [ new THREE.Vector3(), new THREE.Vector3(), new THREE.Vector3() ];
44147     this.vertexNormalsLength = 0;
44148
44149     this.material = null;
44150     this.uvs = [[]];
44151
44152     this.z = null;
44153
44154 };
44155 /**
44156  * @author mrdoob / http://mrdoob.com/
44157  */
44158
44159 THREE.RenderableFace4 = function () {
44160
44161     this.v1 = new THREE.RenderableVertex();
44162     this.v2 = new THREE.RenderableVertex();
44163     this.v3 = new THREE.RenderableVertex();
44164     this.v4 = new THREE.RenderableVertex();
44165
44166     this.centroidWorld = new THREE.Vector3();
44167     this.centroidScreen = new THREE.Vector3();
44168
44169     this.normalWorld = new THREE.Vector3();
44170     this.vertexNormalsWorld = [ new THREE.Vector3(), new THREE.Vector3(), new THREE.Vector3(), new THREE.Vector3() ];
44171     this.vertexNormalsLength = 0;
44172
44173     this.material = null;
44174     this.uvs = [[]];
44175
44176     this.z = null;
44177
44178 };
44179 /**
44180  * @author mrdoob / http://mrdoob.com/
44181  */
44182
44183 THREE.RenderableObject = function () {
44184
44185     this.object = null;
44186     this.z = null;
44187
44188 };
44189 /**
44190  * @author mrdoob / http://mrdoob.com/
44191  */
44192
44193 THREE.RenderableParticle = function () {
44194
44195     this.object = null;
44196
44197     this.x = null;
44198     this.y = null;
44199     this.z = null;
44200
44201     this.rotation = null;
44202     this.scale = new THREE.Vector2();
44203
44204     this.material = null;
44205
44206 };
44207 /**
44208  * @author mrdoob / http://mrdoob.com/
44209  */
44210
44211 THREE.RenderableLine = function () {
44212
44213     this.z = null;
44214
44215     this.v1 = new THREE.RenderableVertex();
44216     this.v2 = new THREE.RenderableVertex();
44217
44218     this.material = null;
44219
44220 };
44221 /**
44222  * @author alteredq / http://alteredqualia.com/
44223  */
44224
44225 THREE.ColorUtils = {
44226
44227     adjustHSV : function ( color, h, s, v ) {
44228
44229         var hsv = THREE.ColorUtils.__hsv;
44230
44231         THREE.ColorUtils.rgbToHsv( color, hsv );
44232
44233         hsv.h = THREE.Math.clamp( hsv.h + h, 0, 1 );
44234         hsv.s = THREE.Math.clamp( hsv.s + s, 0, 1 );
44235         hsv.v = THREE.Math.clamp( hsv.v + v, 0, 1 );
44236
44237         color.setHSV( hsv.h, hsv.s, hsv.v );
44238
44239     },
44240
44241     // based on MochiKit implementation by Bob Ippolito
44242
44243     rgbToHsv : function ( color, hsv ) {
44244
44245         var r = color.r;
44246         var g = color.g;
44247         var b = color.b;
44248
44249         var max = Math.max( Math.max( r, g ), b );
44250         var min = Math.min( Math.min( r, g ), b );
44251
44252         var hue;
44253         var saturation;
44254         var value = max;
44255
44256         if ( min === max )    {
44257
44258             hue = 0;
44259             saturation = 0;
44260
44261         } else {
44262
44263             var delta = ( max - min );
44264             saturation = delta / max;
44265
44266             if ( r === max ) {
44267
44268                 hue = ( g - b ) / delta;
44269
44270             } else if ( g === max ) {
44271
44272                 hue = 2 + ( ( b - r ) / delta );
44273
44274             } else    {
44275
44276                 hue = 4 + ( ( r - g ) / delta );
44277             }
44278
44279             hue /= 6;
44280
44281             if ( hue < 0 ) {
44282
44283                 hue += 1;
44284
44285             }
44286
44287             if ( hue > 1 ) {
44288
44289                 hue -= 1;
44290
44291             }
44292
44293         }
44294
44295         if ( hsv === undefined ) {
44296
44297             hsv = { h: 0, s: 0, v: 0 };
44298
44299         }
44300
44301         hsv.h = hue;
44302         hsv.s = saturation;
44303         hsv.v = value;
44304
44305         return hsv;
44306
44307     }
44308
44309 };
44310
44311 THREE.ColorUtils.__hsv = { h: 0, s: 0, v: 0 };/**
44312  * @author mrdoob / http://mrdoob.com/
44313  * @author alteredq / http://alteredqualia.com/
44314  */
44315
44316 THREE.GeometryUtils = {
44317
44318     // Merge two geometries or geometry and geometry from object (using object's transform)
44319
44320     merge: function ( geometry1, object2 /* mesh | geometry */ ) {
44321
44322         var matrix, matrixRotation,
44323         vertexOffset = geometry1.vertices.length,
44324         uvPosition = geometry1.faceVertexUvs[ 0 ].length,
44325         geometry2 = object2 instanceof THREE.Mesh ? object2.geometry : object2,
44326         vertices1 = geometry1.vertices,
44327         vertices2 = geometry2.vertices,
44328         faces1 = geometry1.faces,
44329         faces2 = geometry2.faces,
44330         uvs1 = geometry1.faceVertexUvs[ 0 ],
44331         uvs2 = geometry2.faceVertexUvs[ 0 ];
44332
44333         var geo1MaterialsMap = {};
44334
44335         for ( var i = 0; i < geometry1.materials.length; i ++ ) {
44336
44337             var id = geometry1.materials[ i ].id;
44338
44339             geo1MaterialsMap[ id ] = i;
44340
44341         }
44342
44343         if ( object2 instanceof THREE.Mesh ) {
44344
44345             object2.matrixAutoUpdate && object2.updateMatrix();
44346
44347             matrix = object2.matrix;
44348             matrixRotation = new THREE.Matrix4();
44349             matrixRotation.extractRotation( matrix, object2.scale );
44350
44351         }
44352
44353         // vertices
44354
44355         for ( var i = 0, il = vertices2.length; i < il; i ++ ) {
44356
44357             var vertex = vertices2[ i ];
44358
44359             var vertexCopy = vertex.clone();
44360
44361             if ( matrix ) matrix.multiplyVector3( vertexCopy );
44362
44363             vertices1.push( vertexCopy );
44364
44365         }
44366
44367         // faces
44368
44369         for ( i = 0, il = faces2.length; i < il; i ++ ) {
44370
44371             var face = faces2[ i ], faceCopy, normal, color,
44372             faceVertexNormals = face.vertexNormals,
44373             faceVertexColors = face.vertexColors;
44374
44375             if ( face instanceof THREE.Face3 ) {
44376
44377                 faceCopy = new THREE.Face3( face.a + vertexOffset, face.b + vertexOffset, face.c + vertexOffset );
44378
44379             } else if ( face instanceof THREE.Face4 ) {
44380
44381                 faceCopy = new THREE.Face4( face.a + vertexOffset, face.b + vertexOffset, face.c + vertexOffset, face.d + vertexOffset );
44382
44383             }
44384
44385             faceCopy.normal.copy( face.normal );
44386
44387             if ( matrixRotation ) matrixRotation.multiplyVector3( faceCopy.normal );
44388
44389             for ( var j = 0, jl = faceVertexNormals.length; j < jl; j ++ ) {
44390
44391                 normal = faceVertexNormals[ j ].clone();
44392
44393                 if ( matrixRotation ) matrixRotation.multiplyVector3( normal );
44394
44395                 faceCopy.vertexNormals.push( normal );
44396
44397             }
44398
44399             faceCopy.color.copy( face.color );
44400
44401             for ( var j = 0, jl = faceVertexColors.length; j < jl; j ++ ) {
44402
44403                 color = faceVertexColors[ j ];
44404                 faceCopy.vertexColors.push( color.clone() );
44405
44406             }
44407
44408             if ( face.materialIndex !== undefined ) {
44409
44410                 var material2 = geometry2.materials[ face.materialIndex ];
44411                 var materialId2 = material2.id;
44412
44413                 var materialIndex = geo1MaterialsMap[ materialId2 ];
44414
44415                 if ( materialIndex === undefined ) {
44416
44417                     materialIndex = geometry1.materials.length;
44418                     geo1MaterialsMap[ materialId2 ] = materialIndex;
44419
44420                     geometry1.materials.push( material2 );
44421
44422                 }
44423
44424                 faceCopy.materialIndex = materialIndex;
44425
44426             }
44427
44428             faceCopy.centroid.copy( face.centroid );
44429             if ( matrix ) matrix.multiplyVector3( faceCopy.centroid );
44430
44431             faces1.push( faceCopy );
44432
44433         }
44434
44435         // uvs
44436
44437         for ( i = 0, il = uvs2.length; i < il; i ++ ) {
44438
44439             var uv = uvs2[ i ], uvCopy = [];
44440
44441             for ( var j = 0, jl = uv.length; j < jl; j ++ ) {
44442
44443                 uvCopy.push( new THREE.UV( uv[ j ].u, uv[ j ].v ) );
44444
44445             }
44446
44447             uvs1.push( uvCopy );
44448
44449         }
44450
44451     },
44452
44453     clone: function ( geometry ) {
44454
44455         var cloneGeo = new THREE.Geometry();
44456
44457         var i, il;
44458
44459         var vertices = geometry.vertices,
44460             faces = geometry.faces,
44461             uvs = geometry.faceVertexUvs[ 0 ];
44462
44463         // materials
44464
44465         if ( geometry.materials ) {
44466
44467             cloneGeo.materials = geometry.materials.slice();
44468
44469         }
44470
44471         // vertices
44472
44473         for ( i = 0, il = vertices.length; i < il; i ++ ) {
44474
44475             var vertex = vertices[ i ];
44476
44477             cloneGeo.vertices.push( vertex.clone() );
44478
44479         }
44480
44481         // faces
44482
44483         for ( i = 0, il = faces.length; i < il; i ++ ) {
44484
44485             var face = faces[ i ];
44486
44487             cloneGeo.faces.push( face.clone() );
44488
44489         }
44490
44491         // uvs
44492
44493         for ( i = 0, il = uvs.length; i < il; i ++ ) {
44494
44495             var uv = uvs[ i ], uvCopy = [];
44496
44497             for ( var j = 0, jl = uv.length; j < jl; j ++ ) {
44498
44499                 uvCopy.push( new THREE.UV( uv[ j ].u, uv[ j ].v ) );
44500
44501             }
44502
44503             cloneGeo.faceVertexUvs[ 0 ].push( uvCopy );
44504
44505         }
44506
44507         return cloneGeo;
44508
44509     },
44510
44511     // Get random point in triangle (via barycentric coordinates)
44512     //     (uniform distribution)
44513     //     http://www.cgafaq.info/wiki/Random_Point_In_Triangle
44514
44515     randomPointInTriangle: function ( vectorA, vectorB, vectorC ) {
44516
44517         var a, b, c,
44518             point = new THREE.Vector3(),
44519             tmp = THREE.GeometryUtils.__v1;
44520
44521         a = THREE.GeometryUtils.random();
44522         b = THREE.GeometryUtils.random();
44523
44524         if ( ( a + b ) > 1 ) {
44525
44526             a = 1 - a;
44527             b = 1 - b;
44528
44529         }
44530
44531         c = 1 - a - b;
44532
44533         point.copy( vectorA );
44534         point.multiplyScalar( a );
44535
44536         tmp.copy( vectorB );
44537         tmp.multiplyScalar( b );
44538
44539         point.addSelf( tmp );
44540
44541         tmp.copy( vectorC );
44542         tmp.multiplyScalar( c );
44543
44544         point.addSelf( tmp );
44545
44546         return point;
44547
44548     },
44549
44550     // Get random point in face (triangle / quad)
44551     // (uniform distribution)
44552
44553     randomPointInFace: function ( face, geometry, useCachedAreas ) {
44554
44555         var vA, vB, vC, vD;
44556
44557         if ( face instanceof THREE.Face3 ) {
44558
44559             vA = geometry.vertices[ face.a ];
44560             vB = geometry.vertices[ face.b ];
44561             vC = geometry.vertices[ face.c ];
44562
44563             return THREE.GeometryUtils.randomPointInTriangle( vA, vB, vC );
44564
44565         } else if ( face instanceof THREE.Face4 ) {
44566
44567             vA = geometry.vertices[ face.a ];
44568             vB = geometry.vertices[ face.b ];
44569             vC = geometry.vertices[ face.c ];
44570             vD = geometry.vertices[ face.d ];
44571
44572             var area1, area2;
44573
44574             if ( useCachedAreas ) {
44575
44576                 if ( face._area1 && face._area2 ) {
44577
44578                     area1 = face._area1;
44579                     area2 = face._area2;
44580
44581                 } else {
44582
44583                     area1 = THREE.GeometryUtils.triangleArea( vA, vB, vD );
44584                     area2 = THREE.GeometryUtils.triangleArea( vB, vC, vD );
44585
44586                     face._area1 = area1;
44587                     face._area2 = area2;
44588
44589                 }
44590
44591             } else {
44592
44593                 area1 = THREE.GeometryUtils.triangleArea( vA, vB, vD ),
44594                 area2 = THREE.GeometryUtils.triangleArea( vB, vC, vD );
44595
44596             }
44597
44598             var r = THREE.GeometryUtils.random() * ( area1 + area2 );
44599
44600             if ( r < area1 ) {
44601
44602                 return THREE.GeometryUtils.randomPointInTriangle( vA, vB, vD );
44603
44604             } else {
44605
44606                 return THREE.GeometryUtils.randomPointInTriangle( vB, vC, vD );
44607
44608             }
44609
44610         }
44611
44612     },
44613
44614     // Get uniformly distributed random points in mesh
44615     //     - create array with cumulative sums of face areas
44616     //  - pick random number from 0 to total area
44617     //  - find corresponding place in area array by binary search
44618     //    - get random point in face
44619
44620     randomPointsInGeometry: function ( geometry, n ) {
44621
44622         var face, i,
44623             faces = geometry.faces,
44624             vertices = geometry.vertices,
44625             il = faces.length,
44626             totalArea = 0,
44627             cumulativeAreas = [],
44628             vA, vB, vC, vD;
44629
44630         // precompute face areas
44631
44632         for ( i = 0; i < il; i ++ ) {
44633
44634             face = faces[ i ];
44635
44636             if ( face instanceof THREE.Face3 ) {
44637
44638                 vA = vertices[ face.a ];
44639                 vB = vertices[ face.b ];
44640                 vC = vertices[ face.c ];
44641
44642                 face._area = THREE.GeometryUtils.triangleArea( vA, vB, vC );
44643
44644             } else if ( face instanceof THREE.Face4 ) {
44645
44646                 vA = vertices[ face.a ];
44647                 vB = vertices[ face.b ];
44648                 vC = vertices[ face.c ];
44649                 vD = vertices[ face.d ];
44650
44651                 face._area1 = THREE.GeometryUtils.triangleArea( vA, vB, vD );
44652                 face._area2 = THREE.GeometryUtils.triangleArea( vB, vC, vD );
44653
44654                 face._area = face._area1 + face._area2;
44655
44656             }
44657
44658             totalArea += face._area;
44659
44660             cumulativeAreas[ i ] = totalArea;
44661
44662         }
44663
44664         // binary search cumulative areas array
44665
44666         function binarySearchIndices( value ) {
44667
44668             function binarySearch( start, end ) {
44669
44670                 // return closest larger index
44671                 // if exact number is not found
44672
44673                 if ( end < start )
44674                     return start;
44675
44676                 var mid = start + Math.floor( ( end - start ) / 2 );
44677
44678                 if ( cumulativeAreas[ mid ] > value ) {
44679
44680                     return binarySearch( start, mid - 1 );
44681
44682                 } else if ( cumulativeAreas[ mid ] < value ) {
44683
44684                     return binarySearch( mid + 1, end );
44685
44686                 } else {
44687
44688                     return mid;
44689
44690                 }
44691
44692             }
44693
44694             var result = binarySearch( 0, cumulativeAreas.length - 1 )
44695             return result;
44696
44697         }
44698
44699         // pick random face weighted by face area
44700
44701         var r, index,
44702             result = [];
44703
44704         var stats = {};
44705
44706         for ( i = 0; i < n; i ++ ) {
44707
44708             r = THREE.GeometryUtils.random() * totalArea;
44709
44710             index = binarySearchIndices( r );
44711
44712             result[ i ] = THREE.GeometryUtils.randomPointInFace( faces[ index ], geometry, true );
44713
44714             if ( ! stats[ index ] ) {
44715
44716                 stats[ index ] = 1;
44717
44718             } else {
44719
44720                 stats[ index ] += 1;
44721
44722             }
44723
44724         }
44725
44726         return result;
44727
44728     },
44729
44730     // Get triangle area (by Heron's formula)
44731     //     http://en.wikipedia.org/wiki/Heron%27s_formula
44732
44733     triangleArea: function ( vectorA, vectorB, vectorC ) {
44734
44735         var s, a, b, c,
44736             tmp = THREE.GeometryUtils.__v1;
44737
44738         tmp.sub( vectorA, vectorB );
44739         a = tmp.length();
44740
44741         tmp.sub( vectorA, vectorC );
44742         b = tmp.length();
44743
44744         tmp.sub( vectorB, vectorC );
44745         c = tmp.length();
44746
44747         s = 0.5 * ( a + b + c );
44748
44749         return Math.sqrt( s * ( s - a ) * ( s - b ) * ( s - c ) );
44750
44751     },
44752
44753     // Center geometry so that 0,0,0 is in center of bounding box
44754
44755     center: function ( geometry ) {
44756
44757         geometry.computeBoundingBox();
44758
44759         var bb = geometry.boundingBox;
44760
44761         var offset = new THREE.Vector3();
44762
44763         offset.add( bb.min, bb.max );
44764         offset.multiplyScalar( -0.5 );
44765
44766         geometry.applyMatrix( new THREE.Matrix4().makeTranslation( offset.x, offset.y, offset.z ) );
44767         geometry.computeBoundingBox();
44768
44769         return offset;
44770
44771     },
44772
44773     // Normalize UVs to be from <0,1>
44774     // (for now just the first set of UVs)
44775
44776     normalizeUVs: function ( geometry ) {
44777
44778         var uvSet = geometry.faceVertexUvs[ 0 ];
44779
44780         for ( var i = 0, il = uvSet.length; i < il; i ++ ) {
44781
44782             var uvs = uvSet[ i ];
44783
44784             for ( var j = 0, jl = uvs.length; j < jl; j ++ ) {
44785
44786                 // texture repeat
44787
44788                 if( uvs[ j ].u !== 1.0 ) uvs[ j ].u = uvs[ j ].u - Math.floor( uvs[ j ].u );
44789                 if( uvs[ j ].v !== 1.0 ) uvs[ j ].v = uvs[ j ].v - Math.floor( uvs[ j ].v );
44790
44791             }
44792
44793         }
44794
44795     },
44796
44797     triangulateQuads: function ( geometry ) {
44798
44799         var i, il, j, jl;
44800
44801         var faces = [];
44802         var faceUvs = [];
44803         var faceVertexUvs = [];
44804
44805         for ( i = 0, il = geometry.faceUvs.length; i < il; i ++ ) {
44806
44807             faceUvs[ i ] = [];
44808
44809         }
44810
44811         for ( i = 0, il = geometry.faceVertexUvs.length; i < il; i ++ ) {
44812
44813             faceVertexUvs[ i ] = [];
44814
44815         }
44816
44817         for ( i = 0, il = geometry.faces.length; i < il; i ++ ) {
44818
44819             var face = geometry.faces[ i ];
44820
44821             if ( face instanceof THREE.Face4 ) {
44822
44823                 var a = face.a;
44824                 var b = face.b;
44825                 var c = face.c;
44826                 var d = face.d;
44827
44828                 var triA = new THREE.Face3();
44829                 var triB = new THREE.Face3();
44830
44831                 triA.color.copy( face.color );
44832                 triB.color.copy( face.color );
44833
44834                 triA.materialIndex = face.materialIndex;
44835                 triB.materialIndex = face.materialIndex;
44836
44837                 triA.a = a;
44838                 triA.b = b;
44839                 triA.c = d;
44840
44841                 triB.a = b;
44842                 triB.b = c;
44843                 triB.c = d;
44844
44845                 if ( face.vertexColors.length === 4 ) {
44846
44847                     triA.vertexColors[ 0 ] = face.vertexColors[ 0 ].clone();
44848                     triA.vertexColors[ 1 ] = face.vertexColors[ 1 ].clone();
44849                     triA.vertexColors[ 2 ] = face.vertexColors[ 3 ].clone();
44850
44851                     triB.vertexColors[ 0 ] = face.vertexColors[ 1 ].clone();
44852                     triB.vertexColors[ 1 ] = face.vertexColors[ 2 ].clone();
44853                     triB.vertexColors[ 2 ] = face.vertexColors[ 3 ].clone();
44854
44855                 }
44856
44857                 faces.push( triA, triB );
44858
44859                 for ( j = 0, jl = geometry.faceVertexUvs.length; j < jl; j ++ ) {
44860
44861                     if ( geometry.faceVertexUvs[ j ].length ) {
44862
44863                         var uvs = geometry.faceVertexUvs[ j ][ i ];
44864
44865                         var uvA = uvs[ 0 ];
44866                         var uvB = uvs[ 1 ];
44867                         var uvC = uvs[ 2 ];
44868                         var uvD = uvs[ 3 ];
44869
44870                         var uvsTriA = [ uvA.clone(), uvB.clone(), uvD.clone() ];
44871                         var uvsTriB = [ uvB.clone(), uvC.clone(), uvD.clone() ];
44872
44873                         faceVertexUvs[ j ].push( uvsTriA, uvsTriB );
44874
44875                     }
44876
44877                 }
44878
44879                 for ( j = 0, jl = geometry.faceUvs.length; j < jl; j ++ ) {
44880
44881                     if ( geometry.faceUvs[ j ].length ) {
44882
44883                         var faceUv = geometry.faceUvs[ j ][ i ];
44884
44885                         faceUvs[ j ].push( faceUv, faceUv );
44886
44887                     }
44888
44889                 }
44890
44891             } else {
44892
44893                 faces.push( face );
44894
44895                 for ( j = 0, jl = geometry.faceUvs.length; j < jl; j ++ ) {
44896
44897                     faceUvs[ j ].push( geometry.faceUvs[ j ][ i ] );
44898
44899                 }
44900
44901                 for ( j = 0, jl = geometry.faceVertexUvs.length; j < jl; j ++ ) {
44902
44903                     faceVertexUvs[ j ].push( geometry.faceVertexUvs[ j ][ i ] );
44904
44905                 }
44906
44907             }
44908
44909         }
44910
44911         geometry.faces = faces;
44912         geometry.faceUvs = faceUvs;
44913         geometry.faceVertexUvs = faceVertexUvs;
44914
44915         geometry.computeCentroids();
44916         geometry.computeFaceNormals();
44917         geometry.computeVertexNormals();
44918
44919         if ( geometry.hasTangents ) geometry.computeTangents();
44920
44921     },
44922
44923     // Make all faces use unique vertices
44924     // so that each face can be separated from others
44925
44926     explode: function( geometry ) {
44927
44928         var vertices = [];
44929
44930         for ( var i = 0, il = geometry.faces.length; i < il; i ++ ) {
44931
44932             var n = vertices.length;
44933
44934             var face = geometry.faces[ i ];
44935
44936             if ( face instanceof THREE.Face4 ) {
44937
44938                 var a = face.a;
44939                 var b = face.b;
44940                 var c = face.c;
44941                 var d = face.d;
44942
44943                 var va = geometry.vertices[ a ];
44944                 var vb = geometry.vertices[ b ];
44945                 var vc = geometry.vertices[ c ];
44946                 var vd = geometry.vertices[ d ];
44947
44948                 vertices.push( va.clone() );
44949                 vertices.push( vb.clone() );
44950                 vertices.push( vc.clone() );
44951                 vertices.push( vd.clone() );
44952
44953                 face.a = n;
44954                 face.b = n + 1;
44955                 face.c = n + 2;
44956                 face.d = n + 3;
44957
44958             } else {
44959
44960                 var a = face.a;
44961                 var b = face.b;
44962                 var c = face.c;
44963
44964                 var va = geometry.vertices[ a ];
44965                 var vb = geometry.vertices[ b ];
44966                 var vc = geometry.vertices[ c ];
44967
44968                 vertices.push( va.clone() );
44969                 vertices.push( vb.clone() );
44970                 vertices.push( vc.clone() );
44971
44972                 face.a = n;
44973                 face.b = n + 1;
44974                 face.c = n + 2;
44975
44976             }
44977
44978         }
44979
44980         geometry.vertices = vertices;
44981         delete geometry.__tmpVertices;
44982
44983     },
44984
44985     // Break faces with edges longer than maxEdgeLength
44986     // - not recursive
44987
44988     tessellate: function ( geometry, maxEdgeLength ) {
44989
44990         var i, il, face,
44991         a, b, c, d,
44992         va, vb, vc, vd,
44993         dab, dbc, dac, dcd, dad,
44994         m, m1, m2,
44995         vm, vm1, vm2,
44996         vnm, vnm1, vnm2,
44997         vcm, vcm1, vcm2,
44998         triA, triB,
44999         quadA, quadB,
45000         edge;
45001
45002         var faces = [];
45003         var faceVertexUvs = [];
45004
45005         for ( i = 0, il = geometry.faceVertexUvs.length; i < il; i ++ ) {
45006
45007             faceVertexUvs[ i ] = [];
45008
45009         }
45010
45011         for ( i = 0, il = geometry.faces.length; i < il; i ++ ) {
45012
45013             face = geometry.faces[ i ];
45014
45015             if ( face instanceof THREE.Face3 ) {
45016
45017                 a = face.a;
45018                 b = face.b;
45019                 c = face.c;
45020
45021                 va = geometry.vertices[ a ];
45022                 vb = geometry.vertices[ b ];
45023                 vc = geometry.vertices[ c ];
45024
45025                 dab = va.distanceTo( vb );
45026                 dbc = vb.distanceTo( vc );
45027                 dac = va.distanceTo( vc );
45028
45029                 if ( dab > maxEdgeLength || dbc > maxEdgeLength || dac > maxEdgeLength ) {
45030
45031                     m = geometry.vertices.length;
45032
45033                     triA = face.clone();
45034                     triB = face.clone();
45035
45036                     if ( dab >= dbc && dab >= dac ) {
45037
45038                         vm = va.clone();
45039                         vm.lerpSelf( vb, 0.5 );
45040
45041                         triA.a = a;
45042                         triA.b = m;
45043                         triA.c = c;
45044
45045                         triB.a = m;
45046                         triB.b = b;
45047                         triB.c = c;
45048
45049                         if ( face.vertexNormals.length === 3 ) {
45050
45051                             vnm = face.vertexNormals[ 0 ].clone();
45052                             vnm.lerpSelf( face.vertexNormals[ 1 ], 0.5 );
45053
45054                             triA.vertexNormals[ 1 ].copy( vnm );
45055                             triB.vertexNormals[ 0 ].copy( vnm );
45056
45057                         }
45058
45059                         if ( face.vertexColors.length === 3 ) {
45060
45061                             vcm = face.vertexColors[ 0 ].clone();
45062                             vcm.lerpSelf( face.vertexColors[ 1 ], 0.5 );
45063
45064                             triA.vertexColors[ 1 ].copy( vcm );
45065                             triB.vertexColors[ 0 ].copy( vcm );
45066
45067                         }
45068
45069                         edge = 0;
45070
45071                     } else if ( dbc >= dab && dbc >= dac ) {
45072
45073                         vm = vb.clone();
45074                         vm.lerpSelf( vc, 0.5 );
45075
45076                         triA.a = a;
45077                         triA.b = b;
45078                         triA.c = m;
45079
45080                         triB.a = m;
45081                         triB.b = c;
45082                         triB.c = a;
45083
45084                         if ( face.vertexNormals.length === 3 ) {
45085
45086                             vnm = face.vertexNormals[ 1 ].clone();
45087                             vnm.lerpSelf( face.vertexNormals[ 2 ], 0.5 );
45088
45089                             triA.vertexNormals[ 2 ].copy( vnm );
45090
45091                             triB.vertexNormals[ 0 ].copy( vnm );
45092                             triB.vertexNormals[ 1 ].copy( face.vertexNormals[ 2 ] );
45093                             triB.vertexNormals[ 2 ].copy( face.vertexNormals[ 0 ] );
45094
45095                         }
45096
45097                         if ( face.vertexColors.length === 3 ) {
45098
45099                             vcm = face.vertexColors[ 1 ].clone();
45100                             vcm.lerpSelf( face.vertexColors[ 2 ], 0.5 );
45101
45102                             triA.vertexColors[ 2 ].copy( vcm );
45103
45104                             triB.vertexColors[ 0 ].copy( vcm );
45105                             triB.vertexColors[ 1 ].copy( face.vertexColors[ 2 ] );
45106                             triB.vertexColors[ 2 ].copy( face.vertexColors[ 0 ] );
45107
45108                         }
45109
45110                         edge = 1;
45111
45112                     } else {
45113
45114                         vm = va.clone();
45115                         vm.lerpSelf( vc, 0.5 );
45116
45117                         triA.a = a;
45118                         triA.b = b;
45119                         triA.c = m;
45120
45121                         triB.a = m;
45122                         triB.b = b;
45123                         triB.c = c;
45124
45125                         if ( face.vertexNormals.length === 3 ) {
45126
45127                             vnm = face.vertexNormals[ 0 ].clone();
45128                             vnm.lerpSelf( face.vertexNormals[ 2 ], 0.5 );
45129
45130                             triA.vertexNormals[ 2 ].copy( vnm );
45131                             triB.vertexNormals[ 0 ].copy( vnm );
45132
45133                         }
45134
45135                         if ( face.vertexColors.length === 3 ) {
45136
45137                             vcm = face.vertexColors[ 0 ].clone();
45138                             vcm.lerpSelf( face.vertexColors[ 2 ], 0.5 );
45139
45140                             triA.vertexColors[ 2 ].copy( vcm );
45141                             triB.vertexColors[ 0 ].copy( vcm );
45142
45143                         }
45144
45145                         edge = 2;
45146
45147                     }
45148
45149                     faces.push( triA, triB );
45150                     geometry.vertices.push( vm );
45151
45152                     var j, jl, uvs, uvA, uvB, uvC, uvM, uvsTriA, uvsTriB;
45153
45154                     for ( j = 0, jl = geometry.faceVertexUvs.length; j < jl; j ++ ) {
45155
45156                         if ( geometry.faceVertexUvs[ j ].length ) {
45157
45158                             uvs = geometry.faceVertexUvs[ j ][ i ];
45159
45160                             uvA = uvs[ 0 ];
45161                             uvB = uvs[ 1 ];
45162                             uvC = uvs[ 2 ];
45163
45164                             // AB
45165
45166                             if ( edge === 0 ) {
45167
45168                                 uvM = uvA.clone();
45169                                 uvM.lerpSelf( uvB, 0.5 );
45170
45171                                 uvsTriA = [ uvA.clone(), uvM.clone(), uvC.clone() ];
45172                                 uvsTriB = [ uvM.clone(), uvB.clone(), uvC.clone() ];
45173
45174                             // BC
45175
45176                             } else if ( edge === 1 ) {
45177
45178                                 uvM = uvB.clone();
45179                                 uvM.lerpSelf( uvC, 0.5 );
45180
45181                                 uvsTriA = [ uvA.clone(), uvB.clone(), uvM.clone() ];
45182                                 uvsTriB = [ uvM.clone(), uvC.clone(), uvA.clone() ];
45183
45184                             // AC
45185
45186                             } else {
45187
45188                                 uvM = uvA.clone();
45189                                 uvM.lerpSelf( uvC, 0.5 );
45190
45191                                 uvsTriA = [ uvA.clone(), uvB.clone(), uvM.clone() ];
45192                                 uvsTriB = [ uvM.clone(), uvB.clone(), uvC.clone() ];
45193
45194                             }
45195
45196                             faceVertexUvs[ j ].push( uvsTriA, uvsTriB );
45197
45198                         }
45199
45200                     }
45201
45202                 } else {
45203
45204                     faces.push( face );
45205
45206                     for ( j = 0, jl = geometry.faceVertexUvs.length; j < jl; j ++ ) {
45207
45208                         faceVertexUvs[ j ].push( geometry.faceVertexUvs[ j ][ i ] );
45209
45210                     }
45211
45212                 }
45213
45214             } else {
45215
45216                 a = face.a;
45217                 b = face.b;
45218                 c = face.c;
45219                 d = face.d;
45220
45221                 va = geometry.vertices[ a ];
45222                 vb = geometry.vertices[ b ];
45223                 vc = geometry.vertices[ c ];
45224                 vd = geometry.vertices[ d ];
45225
45226                 dab = va.distanceTo( vb );
45227                 dbc = vb.distanceTo( vc );
45228                 dcd = vc.distanceTo( vd );
45229                 dad = va.distanceTo( vd );
45230
45231                 if ( dab > maxEdgeLength || dbc > maxEdgeLength || dcd > maxEdgeLength || dad > maxEdgeLength ) {
45232
45233                     m1 = geometry.vertices.length;
45234                     m2 = geometry.vertices.length + 1;
45235
45236                     quadA = face.clone();
45237                     quadB = face.clone();
45238
45239                     if ( ( dab >= dbc && dab >= dcd && dab >= dad ) || ( dcd >= dbc && dcd >= dab && dcd >= dad ) ) {
45240
45241                         vm1 = va.clone();
45242                         vm1.lerpSelf( vb, 0.5 );
45243
45244                         vm2 = vc.clone();
45245                         vm2.lerpSelf( vd, 0.5 );
45246
45247                         quadA.a = a;
45248                         quadA.b = m1;
45249                         quadA.c = m2;
45250                         quadA.d = d;
45251
45252                         quadB.a = m1;
45253                         quadB.b = b;
45254                         quadB.c = c;
45255                         quadB.d = m2;
45256
45257                         if ( face.vertexNormals.length === 4 ) {
45258
45259                             vnm1 = face.vertexNormals[ 0 ].clone();
45260                             vnm1.lerpSelf( face.vertexNormals[ 1 ], 0.5 );
45261
45262                             vnm2 = face.vertexNormals[ 2 ].clone();
45263                             vnm2.lerpSelf( face.vertexNormals[ 3 ], 0.5 );
45264
45265                             quadA.vertexNormals[ 1 ].copy( vnm1 );
45266                             quadA.vertexNormals[ 2 ].copy( vnm2 );
45267
45268                             quadB.vertexNormals[ 0 ].copy( vnm1 );
45269                             quadB.vertexNormals[ 3 ].copy( vnm2 );
45270
45271                         }
45272
45273                         if ( face.vertexColors.length === 4 ) {
45274
45275                             vcm1 = face.vertexColors[ 0 ].clone();
45276                             vcm1.lerpSelf( face.vertexColors[ 1 ], 0.5 );
45277
45278                             vcm2 = face.vertexColors[ 2 ].clone();
45279                             vcm2.lerpSelf( face.vertexColors[ 3 ], 0.5 );
45280
45281                             quadA.vertexColors[ 1 ].copy( vcm1 );
45282                             quadA.vertexColors[ 2 ].copy( vcm2 );
45283
45284                             quadB.vertexColors[ 0 ].copy( vcm1 );
45285                             quadB.vertexColors[ 3 ].copy( vcm2 );
45286
45287                         }
45288
45289                         edge = 0;
45290
45291                     } else {
45292
45293                         vm1 = vb.clone();
45294                         vm1.lerpSelf( vc, 0.5 );
45295
45296                         vm2 = vd.clone();
45297                         vm2.lerpSelf( va, 0.5 );
45298
45299                         quadA.a = a;
45300                         quadA.b = b;
45301                         quadA.c = m1;
45302                         quadA.d = m2;
45303
45304                         quadB.a = m2;
45305                         quadB.b = m1;
45306                         quadB.c = c;
45307                         quadB.d = d;
45308
45309                         if ( face.vertexNormals.length === 4 ) {
45310
45311                             vnm1 = face.vertexNormals[ 1 ].clone();
45312                             vnm1.lerpSelf( face.vertexNormals[ 2 ], 0.5 );
45313
45314                             vnm2 = face.vertexNormals[ 3 ].clone();
45315                             vnm2.lerpSelf( face.vertexNormals[ 0 ], 0.5 );
45316
45317                             quadA.vertexNormals[ 2 ].copy( vnm1 );
45318                             quadA.vertexNormals[ 3 ].copy( vnm2 );
45319
45320                             quadB.vertexNormals[ 0 ].copy( vnm2 );
45321                             quadB.vertexNormals[ 1 ].copy( vnm1 );
45322
45323                         }
45324
45325                         if ( face.vertexColors.length === 4 ) {
45326
45327                             vcm1 = face.vertexColors[ 1 ].clone();
45328                             vcm1.lerpSelf( face.vertexColors[ 2 ], 0.5 );
45329
45330                             vcm2 = face.vertexColors[ 3 ].clone();
45331                             vcm2.lerpSelf( face.vertexColors[ 0 ], 0.5 );
45332
45333                             quadA.vertexColors[ 2 ].copy( vcm1 );
45334                             quadA.vertexColors[ 3 ].copy( vcm2 );
45335
45336                             quadB.vertexColors[ 0 ].copy( vcm2 );
45337                             quadB.vertexColors[ 1 ].copy( vcm1 );
45338
45339                         }
45340
45341                         edge = 1;
45342
45343                     }
45344
45345                     faces.push( quadA, quadB );
45346                     geometry.vertices.push( vm1, vm2 );
45347
45348                     var j, jl, uvs, uvA, uvB, uvC, uvD, uvM1, uvM2, uvsQuadA, uvsQuadB;
45349
45350                     for ( j = 0, jl = geometry.faceVertexUvs.length; j < jl; j ++ ) {
45351
45352                         if ( geometry.faceVertexUvs[ j ].length ) {
45353
45354                             uvs = geometry.faceVertexUvs[ j ][ i ];
45355
45356                             uvA = uvs[ 0 ];
45357                             uvB = uvs[ 1 ];
45358                             uvC = uvs[ 2 ];
45359                             uvD = uvs[ 3 ];
45360
45361                             // AB + CD
45362
45363                             if ( edge === 0 ) {
45364
45365                                 uvM1 = uvA.clone();
45366                                 uvM1.lerpSelf( uvB, 0.5 );
45367
45368                                 uvM2 = uvC.clone();
45369                                 uvM2.lerpSelf( uvD, 0.5 );
45370
45371                                 uvsQuadA = [ uvA.clone(), uvM1.clone(), uvM2.clone(), uvD.clone() ];
45372                                 uvsQuadB = [ uvM1.clone(), uvB.clone(), uvC.clone(), uvM2.clone() ];
45373
45374                             // BC + AD
45375
45376                             } else {
45377
45378                                 uvM1 = uvB.clone();
45379                                 uvM1.lerpSelf( uvC, 0.5 );
45380
45381                                 uvM2 = uvD.clone();
45382                                 uvM2.lerpSelf( uvA, 0.5 );
45383
45384                                 uvsQuadA = [ uvA.clone(), uvB.clone(), uvM1.clone(), uvM2.clone() ];
45385                                 uvsQuadB = [ uvM2.clone(), uvM1.clone(), uvC.clone(), uvD.clone() ];
45386
45387                             }
45388
45389                             faceVertexUvs[ j ].push( uvsQuadA, uvsQuadB );
45390
45391                         }
45392
45393                     }
45394
45395                 } else {
45396
45397                     faces.push( face );
45398
45399                     for ( j = 0, jl = geometry.faceVertexUvs.length; j < jl; j ++ ) {
45400
45401                         faceVertexUvs[ j ].push( geometry.faceVertexUvs[ j ][ i ] );
45402
45403                     }
45404
45405                 }
45406
45407             }
45408
45409         }
45410
45411         geometry.faces = faces;
45412         geometry.faceVertexUvs = faceVertexUvs;
45413
45414     }
45415
45416 };
45417
45418 THREE.GeometryUtils.random = THREE.Math.random16;
45419
45420 THREE.GeometryUtils.__v1 = new THREE.Vector3();
45421 /**
45422  * @author alteredq / http://alteredqualia.com/
45423  * @author mrdoob / http://mrdoob.com/
45424  */
45425
45426 THREE.ImageUtils = {
45427
45428     crossOrigin: 'anonymous',
45429
45430     loadTexture: function ( url, mapping, onLoad, onError ) {
45431
45432         var image = new Image();
45433         var texture = new THREE.Texture( image, mapping );
45434
45435         var loader = new THREE.ImageLoader();
45436
45437         loader.addEventListener( 'load', function ( event ) {
45438
45439             texture.image = event.content;
45440             texture.needsUpdate = true;
45441
45442             if ( onLoad ) onLoad( texture );
45443
45444         } );
45445
45446         loader.addEventListener( 'error', function ( event ) {
45447
45448             if ( onError ) onError( event.message );
45449
45450         } );
45451
45452         loader.crossOrigin = this.crossOrigin;
45453         loader.load( url, image );
45454
45455         return texture;
45456
45457     },
45458
45459     loadCompressedTexture: function ( url, mapping, onLoad, onError ) {
45460
45461         var texture = new THREE.CompressedTexture();
45462         texture.mapping = mapping;
45463
45464         var request = new XMLHttpRequest();
45465
45466         request.onload = function () {
45467
45468             var buffer = request.response;
45469             var dds = THREE.ImageUtils.parseDDS( buffer, true );
45470
45471             texture.format = dds.format;
45472
45473             texture.mipmaps = dds.mipmaps;
45474             texture.image.width = dds.width;
45475             texture.image.height = dds.height;
45476
45477             // gl.generateMipmap fails for compressed textures
45478             // mipmaps must be embedded in the DDS file
45479             // or texture filters must not use mipmapping
45480
45481             texture.generateMipmaps = false;
45482
45483             texture.needsUpdate = true;
45484
45485             if ( onLoad ) onLoad( texture );
45486
45487         }
45488
45489         request.onerror = onError;
45490
45491         request.open( 'GET', url, true );
45492         request.responseType = "arraybuffer";
45493         request.send( null );
45494
45495         return texture;
45496
45497     },
45498
45499     loadTextureCube: function ( array, mapping, onLoad, onError ) {
45500
45501         var images = [];
45502         images.loadCount = 0;
45503
45504         var texture = new THREE.Texture();
45505         texture.image = images;
45506         if ( mapping !== undefined ) texture.mapping = mapping;
45507
45508         // no flipping needed for cube textures
45509
45510         texture.flipY = false;
45511
45512         for ( var i = 0, il = array.length; i < il; ++ i ) {
45513
45514             var cubeImage = new Image();
45515             images[ i ] = cubeImage;
45516
45517             cubeImage.onload = function () {
45518
45519                 images.loadCount += 1;
45520
45521                 if ( images.loadCount === 6 ) {
45522
45523                     texture.needsUpdate = true;
45524                     if ( onLoad ) onLoad();
45525
45526                 }
45527
45528             };
45529
45530             cubeImage.onerror = onError;
45531
45532             cubeImage.crossOrigin = this.crossOrigin;
45533             cubeImage.src = array[ i ];
45534
45535         }
45536
45537         return texture;
45538
45539     },
45540
45541     loadCompressedTextureCube: function ( array, mapping, onLoad, onError ) {
45542
45543         var images = [];
45544         images.loadCount = 0;
45545
45546         var texture = new THREE.CompressedTexture();
45547         texture.image = images;
45548         if ( mapping !== undefined ) texture.mapping = mapping;
45549
45550         // no flipping for cube textures
45551         // (also flipping doesn't work for compressed textures )
45552
45553         texture.flipY = false;
45554
45555         // can't generate mipmaps for compressed textures
45556         // mips must be embedded in DDS files
45557
45558         texture.generateMipmaps = false;
45559
45560         var generateCubeFaceCallback = function ( rq, img ) {
45561
45562             return function () {
45563
45564                 var buffer = rq.response;
45565                 var dds = THREE.ImageUtils.parseDDS( buffer, true );
45566
45567                 img.format = dds.format;
45568
45569                 img.mipmaps = dds.mipmaps;
45570                 img.width = dds.width;
45571                 img.height = dds.height;
45572
45573                 images.loadCount += 1;
45574
45575                 if ( images.loadCount === 6 ) {
45576
45577                     texture.format = dds.format;
45578                     texture.needsUpdate = true;
45579                     if ( onLoad ) onLoad();
45580
45581                 }
45582
45583             }
45584
45585         }
45586
45587         for ( var i = 0, il = array.length; i < il; ++ i ) {
45588
45589             var cubeImage = {};
45590             images[ i ] = cubeImage;
45591
45592             var request = new XMLHttpRequest();
45593
45594             request.onload = generateCubeFaceCallback( request, cubeImage );
45595             request.onerror = onError;
45596
45597             var url = array[ i ];
45598
45599             request.open( 'GET', url, true );
45600             request.responseType = "arraybuffer";
45601             request.send( null );
45602
45603         }
45604
45605         return texture;
45606
45607     },
45608
45609     parseDDS: function ( buffer, loadMipmaps ) {
45610
45611         var dds = { mipmaps: [], width: 0, height: 0, format: null, mipmapCount: 1 };
45612
45613         // Adapted from @toji's DDS utils
45614         //    https://github.com/toji/webgl-texture-utils/blob/master/texture-util/dds.js
45615
45616         // All values and structures referenced from:
45617         // http://msdn.microsoft.com/en-us/library/bb943991.aspx/
45618
45619         var DDS_MAGIC = 0x20534444;
45620
45621         var DDSD_CAPS = 0x1,
45622             DDSD_HEIGHT = 0x2,
45623             DDSD_WIDTH = 0x4,
45624             DDSD_PITCH = 0x8,
45625             DDSD_PIXELFORMAT = 0x1000,
45626             DDSD_MIPMAPCOUNT = 0x20000,
45627             DDSD_LINEARSIZE = 0x80000,
45628             DDSD_DEPTH = 0x800000;
45629
45630         var DDSCAPS_COMPLEX = 0x8,
45631             DDSCAPS_MIPMAP = 0x400000,
45632             DDSCAPS_TEXTURE = 0x1000;
45633
45634         var DDSCAPS2_CUBEMAP = 0x200,
45635             DDSCAPS2_CUBEMAP_POSITIVEX = 0x400,
45636             DDSCAPS2_CUBEMAP_NEGATIVEX = 0x800,
45637             DDSCAPS2_CUBEMAP_POSITIVEY = 0x1000,
45638             DDSCAPS2_CUBEMAP_NEGATIVEY = 0x2000,
45639             DDSCAPS2_CUBEMAP_POSITIVEZ = 0x4000,
45640             DDSCAPS2_CUBEMAP_NEGATIVEZ = 0x8000,
45641             DDSCAPS2_VOLUME = 0x200000;
45642
45643         var DDPF_ALPHAPIXELS = 0x1,
45644             DDPF_ALPHA = 0x2,
45645             DDPF_FOURCC = 0x4,
45646             DDPF_RGB = 0x40,
45647             DDPF_YUV = 0x200,
45648             DDPF_LUMINANCE = 0x20000;
45649
45650         function fourCCToInt32( value ) {
45651
45652             return value.charCodeAt(0) +
45653                 (value.charCodeAt(1) << 8) +
45654                 (value.charCodeAt(2) << 16) +
45655                 (value.charCodeAt(3) << 24);
45656
45657         }
45658
45659         function int32ToFourCC( value ) {
45660
45661             return String.fromCharCode(
45662                 value & 0xff,
45663                 (value >> 8) & 0xff,
45664                 (value >> 16) & 0xff,
45665                 (value >> 24) & 0xff
45666             );
45667         }
45668
45669         var FOURCC_DXT1 = fourCCToInt32("DXT1");
45670         var FOURCC_DXT3 = fourCCToInt32("DXT3");
45671         var FOURCC_DXT5 = fourCCToInt32("DXT5");
45672
45673         var headerLengthInt = 31; // The header length in 32 bit ints
45674
45675         // Offsets into the header array
45676
45677         var off_magic = 0;
45678
45679         var off_size = 1;
45680         var off_flags = 2;
45681         var off_height = 3;
45682         var off_width = 4;
45683
45684         var off_mipmapCount = 7;
45685
45686         var off_pfFlags = 20;
45687         var off_pfFourCC = 21;
45688
45689         // Parse header
45690
45691         var header = new Int32Array( buffer, 0, headerLengthInt );
45692
45693         if ( header[ off_magic ] !== DDS_MAGIC ) {
45694
45695             console.error( "ImageUtils.parseDDS(): Invalid magic number in DDS header" );
45696             return dds;
45697
45698         }
45699
45700         if ( ! header[ off_pfFlags ] & DDPF_FOURCC ) {
45701
45702             console.error( "ImageUtils.parseDDS(): Unsupported format, must contain a FourCC code" );
45703             return dds;
45704
45705         }
45706
45707         var blockBytes;
45708
45709         var fourCC = header[ off_pfFourCC ];
45710
45711         switch ( fourCC ) {
45712
45713             case FOURCC_DXT1:
45714
45715                 blockBytes = 8;
45716                 dds.format = THREE.RGB_S3TC_DXT1_Format;
45717                 break;
45718
45719             case FOURCC_DXT3:
45720
45721                 blockBytes = 16;
45722                 dds.format = THREE.RGBA_S3TC_DXT3_Format;
45723                 break;
45724
45725             case FOURCC_DXT5:
45726
45727                 blockBytes = 16;
45728                 dds.format = THREE.RGBA_S3TC_DXT5_Format;
45729                 break;
45730
45731             default:
45732
45733                 console.error( "ImageUtils.parseDDS(): Unsupported FourCC code: ", int32ToFourCC( fourCC ) );
45734                 return dds;
45735
45736         }
45737
45738         dds.mipmapCount = 1;
45739
45740         if ( header[ off_flags ] & DDSD_MIPMAPCOUNT && loadMipmaps !== false ) {
45741
45742             dds.mipmapCount = Math.max( 1, header[ off_mipmapCount ] );
45743
45744         }
45745
45746         dds.width = header[ off_width ];
45747         dds.height = header[ off_height ];
45748
45749         var dataOffset = header[ off_size ] + 4;
45750
45751         // Extract mipmaps buffers
45752
45753         var width = dds.width;
45754         var height = dds.height;
45755
45756         for ( var i = 0; i < dds.mipmapCount; i ++ ) {
45757
45758             var dataLength = Math.max( 4, width ) / 4 * Math.max( 4, height ) / 4 * blockBytes;
45759             var byteArray = new Uint8Array( buffer, dataOffset, dataLength );
45760
45761             var mipmap = { "data": byteArray, "width": width, "height": height };
45762             dds.mipmaps.push( mipmap );
45763
45764             dataOffset += dataLength;
45765
45766             width = Math.max( width * 0.5, 1 );
45767             height = Math.max( height * 0.5, 1 );
45768
45769         }
45770
45771         return dds;
45772
45773     },
45774
45775     getNormalMap: function ( image, depth ) {
45776
45777         // Adapted from http://www.paulbrunt.co.uk/lab/heightnormal/
45778
45779         var cross = function ( a, b ) {
45780
45781             return [ a[ 1 ] * b[ 2 ] - a[ 2 ] * b[ 1 ], a[ 2 ] * b[ 0 ] - a[ 0 ] * b[ 2 ], a[ 0 ] * b[ 1 ] - a[ 1 ] * b[ 0 ] ];
45782
45783         }
45784
45785         var subtract = function ( a, b ) {
45786
45787             return [ a[ 0 ] - b[ 0 ], a[ 1 ] - b[ 1 ], a[ 2 ] - b[ 2 ] ];
45788
45789         }
45790
45791         var normalize = function ( a ) {
45792
45793             var l = Math.sqrt( a[ 0 ] * a[ 0 ] + a[ 1 ] * a[ 1 ] + a[ 2 ] * a[ 2 ] );
45794             return [ a[ 0 ] / l, a[ 1 ] / l, a[ 2 ] / l ];
45795
45796         }
45797
45798         depth = depth | 1;
45799
45800         var width = image.width;
45801         var height = image.height;
45802
45803         var canvas = document.createElement( 'canvas' );
45804         canvas.width = width;
45805         canvas.height = height;
45806
45807         var context = canvas.getContext( '2d' );
45808         context.drawImage( image, 0, 0 );
45809
45810         var data = context.getImageData( 0, 0, width, height ).data;
45811         var imageData = context.createImageData( width, height );
45812         var output = imageData.data;
45813
45814         for ( var x = 0; x < width; x ++ ) {
45815
45816             for ( var y = 0; y < height; y ++ ) {
45817
45818                 var ly = y - 1 < 0 ? 0 : y - 1;
45819                 var uy = y + 1 > height - 1 ? height - 1 : y + 1;
45820                 var lx = x - 1 < 0 ? 0 : x - 1;
45821                 var ux = x + 1 > width - 1 ? width - 1 : x + 1;
45822
45823                 var points = [];
45824                 var origin = [ 0, 0, data[ ( y * width + x ) * 4 ] / 255 * depth ];
45825                 points.push( [ - 1, 0, data[ ( y * width + lx ) * 4 ] / 255 * depth ] );
45826                 points.push( [ - 1, - 1, data[ ( ly * width + lx ) * 4 ] / 255 * depth ] );
45827                 points.push( [ 0, - 1, data[ ( ly * width + x ) * 4 ] / 255 * depth ] );
45828                 points.push( [  1, - 1, data[ ( ly * width + ux ) * 4 ] / 255 * depth ] );
45829                 points.push( [ 1, 0, data[ ( y * width + ux ) * 4 ] / 255 * depth ] );
45830                 points.push( [ 1, 1, data[ ( uy * width + ux ) * 4 ] / 255 * depth ] );
45831                 points.push( [ 0, 1, data[ ( uy * width + x ) * 4 ] / 255 * depth ] );
45832                 points.push( [ - 1, 1, data[ ( uy * width + lx ) * 4 ] / 255 * depth ] );
45833
45834                 var normals = [];
45835                 var num_points = points.length;
45836
45837                 for ( var i = 0; i < num_points; i ++ ) {
45838
45839                     var v1 = points[ i ];
45840                     var v2 = points[ ( i + 1 ) % num_points ];
45841                     v1 = subtract( v1, origin );
45842                     v2 = subtract( v2, origin );
45843                     normals.push( normalize( cross( v1, v2 ) ) );
45844
45845                 }
45846
45847                 var normal = [ 0, 0, 0 ];
45848
45849                 for ( var i = 0; i < normals.length; i ++ ) {
45850
45851                     normal[ 0 ] += normals[ i ][ 0 ];
45852                     normal[ 1 ] += normals[ i ][ 1 ];
45853                     normal[ 2 ] += normals[ i ][ 2 ];
45854
45855                 }
45856
45857                 normal[ 0 ] /= normals.length;
45858                 normal[ 1 ] /= normals.length;
45859                 normal[ 2 ] /= normals.length;
45860
45861                 var idx = ( y * width + x ) * 4;
45862
45863                 output[ idx ] = ( ( normal[ 0 ] + 1.0 ) / 2.0 * 255 ) | 0;
45864                 output[ idx + 1 ] = ( ( normal[ 1 ] + 1.0 ) / 2.0 * 255 ) | 0;
45865                 output[ idx + 2 ] = ( normal[ 2 ] * 255 ) | 0;
45866                 output[ idx + 3 ] = 255;
45867
45868             }
45869
45870         }
45871
45872         context.putImageData( imageData, 0, 0 );
45873
45874         return canvas;
45875
45876     },
45877
45878     generateDataTexture: function ( width, height, color ) {
45879
45880         var size = width * height;
45881         var data = new Uint8Array( 3 * size );
45882
45883         var r = Math.floor( color.r * 255 );
45884         var g = Math.floor( color.g * 255 );
45885         var b = Math.floor( color.b * 255 );
45886
45887         for ( var i = 0; i < size; i ++ ) {
45888
45889             data[ i * 3 ]       = r;
45890             data[ i * 3 + 1 ] = g;
45891             data[ i * 3 + 2 ] = b;
45892
45893         }
45894
45895         var texture = new THREE.DataTexture( data, width, height, THREE.RGBFormat );
45896         texture.needsUpdate = true;
45897
45898         return texture;
45899
45900     }
45901
45902 };
45903 /**
45904  * @author alteredq / http://alteredqualia.com/
45905  */
45906
45907 THREE.SceneUtils = {
45908
45909     showHierarchy : function ( root, visible ) {
45910
45911         THREE.SceneUtils.traverseHierarchy( root, function( node ) { node.visible = visible; } );
45912
45913     },
45914
45915     traverseHierarchy : function ( root, callback ) {
45916
45917         var n, i, l = root.children.length;
45918
45919         for ( i = 0; i < l; i ++ ) {
45920
45921             n = root.children[ i ];
45922
45923             callback( n );
45924
45925             THREE.SceneUtils.traverseHierarchy( n, callback );
45926
45927         }
45928
45929     },
45930
45931     createMultiMaterialObject : function ( geometry, materials ) {
45932
45933         var i, il = materials.length,
45934             group = new THREE.Object3D();
45935
45936         for ( i = 0; i < il; i ++ ) {
45937
45938             var object = new THREE.Mesh( geometry, materials[ i ] );
45939             group.add( object );
45940
45941         }
45942
45943         return group;
45944
45945     },
45946
45947     cloneObject: function ( source ) {
45948
45949         var object;
45950
45951         // subclass specific properties
45952         // (must process in order from more specific subclasses to more abstract classes)
45953
45954         if ( source instanceof THREE.MorphAnimMesh ) {
45955
45956             object = new THREE.MorphAnimMesh( source.geometry, source.material );
45957
45958             object.duration = source.duration;
45959             object.mirroredLoop = source.mirroredLoop;
45960             object.time = source.time;
45961
45962             object.lastKeyframe = source.lastKeyframe;
45963             object.currentKeyframe = source.currentKeyframe;
45964
45965             object.direction = source.direction;
45966             object.directionBackwards = source.directionBackwards;
45967
45968         } else if ( source instanceof THREE.SkinnedMesh ) {
45969
45970             object = new THREE.SkinnedMesh( source.geometry, source.material, source.useVertexTexture );
45971
45972         } else if ( source instanceof THREE.Mesh ) {
45973
45974             object = new THREE.Mesh( source.geometry, source.material );
45975
45976         } else if ( source instanceof THREE.Line ) {
45977
45978             object = new THREE.Line( source.geometry, source.material, source.type );
45979
45980         } else if ( source instanceof THREE.Ribbon ) {
45981
45982             object = new THREE.Ribbon( source.geometry, source.material );
45983
45984         } else if ( source instanceof THREE.ParticleSystem ) {
45985
45986             object = new THREE.ParticleSystem( source.geometry, source.material );
45987             object.sortParticles = source.sortParticles;
45988
45989         } else if ( source instanceof THREE.Particle ) {
45990
45991             object = new THREE.Particle( source.material );
45992
45993         } else if ( source instanceof THREE.Sprite ) {
45994
45995             object = new THREE.Sprite( {} );
45996
45997             object.color.copy( source.color );
45998             object.map = source.map;
45999             object.blending = source.blending;
46000
46001             object.useScreenCoordinates = source.useScreenCoordinates;
46002             object.mergeWith3D = source.mergeWith3D;
46003             object.affectedByDistance = source.affectedByDistance;
46004             object.scaleByViewport = source.scaleByViewport;
46005             object.alignment = source.alignment;
46006
46007             object.rotation3d.copy( source.rotation3d );
46008             object.rotation = source.rotation;
46009             object.opacity = source.opacity;
46010
46011             object.uvOffset.copy( source.uvOffset );
46012             object.uvScale.copy( source.uvScale);
46013
46014         } else if ( source instanceof THREE.LOD ) {
46015
46016             object = new THREE.LOD();
46017
46018         /*
46019         } else if ( source instanceof THREE.MarchingCubes ) {
46020
46021             object = new THREE.MarchingCubes( source.resolution, source.material );
46022             object.field.set( source.field );
46023             object.isolation = source.isolation;
46024         */
46025
46026         } else if ( source instanceof THREE.Object3D ) {
46027
46028             object = new THREE.Object3D();
46029
46030         }
46031
46032         // base class properties
46033
46034         object.name = source.name;
46035
46036         object.parent = source.parent;
46037
46038         object.up.copy( source.up );
46039
46040         object.position.copy( source.position );
46041
46042         // because of Sprite madness
46043
46044         if ( object.rotation instanceof THREE.Vector3 )
46045             object.rotation.copy( source.rotation );
46046
46047         object.eulerOrder = source.eulerOrder;
46048
46049         object.scale.copy( source.scale );
46050
46051         object.dynamic = source.dynamic;
46052
46053         object.renderDepth = source.renderDepth;
46054
46055         object.rotationAutoUpdate = source.rotationAutoUpdate;
46056
46057         object.matrix.copy( source.matrix );
46058         object.matrixWorld.copy( source.matrixWorld );
46059         object.matrixRotationWorld.copy( source.matrixRotationWorld );
46060
46061         object.matrixAutoUpdate = source.matrixAutoUpdate;
46062         object.matrixWorldNeedsUpdate = source.matrixWorldNeedsUpdate;
46063
46064         object.quaternion.copy( source.quaternion );
46065         object.useQuaternion = source.useQuaternion;
46066
46067         object.boundRadius = source.boundRadius;
46068         object.boundRadiusScale = source.boundRadiusScale;
46069
46070         object.visible = source.visible;
46071
46072         object.castShadow = source.castShadow;
46073         object.receiveShadow = source.receiveShadow;
46074
46075         object.frustumCulled = source.frustumCulled;
46076
46077         // children
46078
46079         for ( var i = 0; i < source.children.length; i ++ ) {
46080
46081             var child = THREE.SceneUtils.cloneObject( source.children[ i ] );
46082             object.children[ i ] = child;
46083
46084             child.parent = object;
46085
46086         }
46087
46088         // LODs need to be patched separately to use cloned children
46089
46090         if ( source instanceof THREE.LOD ) {
46091
46092             for ( var i = 0; i < source.LODs.length; i ++ ) {
46093
46094                 var lod = source.LODs[ i ];
46095                 object.LODs[ i ] = { visibleAtDistance: lod.visibleAtDistance, object3D: object.children[ i ] };
46096
46097             }
46098
46099         }
46100
46101         return object;
46102
46103     },
46104
46105     detach : function ( child, parent, scene ) {
46106
46107         child.applyMatrix( parent.matrixWorld );
46108         parent.remove( child );
46109         scene.add( child );
46110
46111     },
46112
46113     attach: function ( child, scene, parent ) {
46114
46115         var matrixWorldInverse = new THREE.Matrix4();
46116         matrixWorldInverse.getInverse( parent.matrixWorld );
46117         child.applyMatrix( matrixWorldInverse );
46118
46119         scene.remove( child );
46120         parent.add( child );
46121
46122     }
46123
46124 };
46125 /**
46126  * @author alteredq / http://alteredqualia.com/
46127  * @author mrdoob / http://mrdoob.com/
46128  *
46129  * ShaderUtils currently contains:
46130  *
46131  *    fresnel
46132  *    normal
46133  *     cube
46134  *
46135  */
46136
46137 if ( THREE.WebGLRenderer ) {
46138
46139 THREE.ShaderUtils = {
46140
46141     lib: {
46142
46143         /* -------------------------------------------------------------------------
46144         //    Fresnel shader
46145         //    - based on Nvidia Cg tutorial
46146          ------------------------------------------------------------------------- */
46147
46148         'fresnel': {
46149
46150             uniforms: {
46151
46152                 "mRefractionRatio": { type: "f", value: 1.02 },
46153                 "mFresnelBias": { type: "f", value: 0.1 },
46154                 "mFresnelPower": { type: "f", value: 2.0 },
46155                 "mFresnelScale": { type: "f", value: 1.0 },
46156                 "tCube": { type: "t", value: null }
46157
46158             },
46159
46160             fragmentShader: [
46161
46162                 "uniform samplerCube tCube;",
46163
46164                 "varying vec3 vReflect;",
46165                 "varying vec3 vRefract[3];",
46166                 "varying float vReflectionFactor;",
46167
46168                 "void main() {",
46169
46170                     "vec4 reflectedColor = textureCube( tCube, vec3( -vReflect.x, vReflect.yz ) );",
46171                     "vec4 refractedColor = vec4( 1.0, 1.0, 1.0, 1.0 );",
46172
46173                     "refractedColor.r = textureCube( tCube, vec3( -vRefract[0].x, vRefract[0].yz ) ).r;",
46174                     "refractedColor.g = textureCube( tCube, vec3( -vRefract[1].x, vRefract[1].yz ) ).g;",
46175                     "refractedColor.b = textureCube( tCube, vec3( -vRefract[2].x, vRefract[2].yz ) ).b;",
46176                     "refractedColor.a = 1.0;",
46177
46178                     "gl_FragColor = mix( refractedColor, reflectedColor, clamp( vReflectionFactor, 0.0, 1.0 ) );",
46179
46180                 "}"
46181
46182             ].join("\n"),
46183
46184             vertexShader: [
46185
46186                 "uniform float mRefractionRatio;",
46187                 "uniform float mFresnelBias;",
46188                 "uniform float mFresnelScale;",
46189                 "uniform float mFresnelPower;",
46190
46191                 "varying vec3 vReflect;",
46192                 "varying vec3 vRefract[3];",
46193                 "varying float vReflectionFactor;",
46194
46195                 "void main() {",
46196
46197                     "vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );",
46198                     "vec4 mPosition = modelMatrix * vec4( position, 1.0 );",
46199
46200                     "vec3 nWorld = normalize( mat3( modelMatrix[0].xyz, modelMatrix[1].xyz, modelMatrix[2].xyz ) * normal );",
46201
46202                     "vec3 I = mPosition.xyz - cameraPosition;",
46203
46204                     "vReflect = reflect( I, nWorld );",
46205                     "vRefract[0] = refract( normalize( I ), nWorld, mRefractionRatio );",
46206                     "vRefract[1] = refract( normalize( I ), nWorld, mRefractionRatio * 0.99 );",
46207                     "vRefract[2] = refract( normalize( I ), nWorld, mRefractionRatio * 0.98 );",
46208                     "vReflectionFactor = mFresnelBias + mFresnelScale * pow( 1.0 + dot( normalize( I ), nWorld ), mFresnelPower );",
46209
46210                     "gl_Position = projectionMatrix * mvPosition;",
46211
46212                 "}"
46213
46214             ].join("\n")
46215
46216         },
46217
46218         /* -------------------------------------------------------------------------
46219         //    Normal map shader
46220         //        - Blinn-Phong
46221         //        - normal + diffuse + specular + AO + displacement + reflection + shadow maps
46222         //        - point and directional lights (use with "lights: true" material option)
46223          ------------------------------------------------------------------------- */
46224
46225         'normal' : {
46226
46227             uniforms: THREE.UniformsUtils.merge( [
46228
46229                 THREE.UniformsLib[ "fog" ],
46230                 THREE.UniformsLib[ "lights" ],
46231                 THREE.UniformsLib[ "shadowmap" ],
46232
46233                 {
46234
46235                 "enableAO"          : { type: "i", value: 0 },
46236                 "enableDiffuse"      : { type: "i", value: 0 },
46237                 "enableSpecular"  : { type: "i", value: 0 },
46238                 "enableReflection": { type: "i", value: 0 },
46239                 "enableDisplacement": { type: "i", value: 0 },
46240
46241                 "tDisplacement": { type: "t", value: null }, // must go first as this is vertex texture
46242                 "tDiffuse"       : { type: "t", value: null },
46243                 "tCube"           : { type: "t", value: null },
46244                 "tNormal"       : { type: "t", value: null },
46245                 "tSpecular"       : { type: "t", value: null },
46246                 "tAO"           : { type: "t", value: null },
46247
46248                 "uNormalScale": { type: "v2", value: new THREE.Vector2( 1, 1 ) },
46249
46250                 "uDisplacementBias": { type: "f", value: 0.0 },
46251                 "uDisplacementScale": { type: "f", value: 1.0 },
46252
46253                 "uDiffuseColor": { type: "c", value: new THREE.Color( 0xffffff ) },
46254                 "uSpecularColor": { type: "c", value: new THREE.Color( 0x111111 ) },
46255                 "uAmbientColor": { type: "c", value: new THREE.Color( 0xffffff ) },
46256                 "uShininess": { type: "f", value: 30 },
46257                 "uOpacity": { type: "f", value: 1 },
46258
46259                 "useRefract": { type: "i", value: 0 },
46260                 "uRefractionRatio": { type: "f", value: 0.98 },
46261                 "uReflectivity": { type: "f", value: 0.5 },
46262
46263                 "uOffset" : { type: "v2", value: new THREE.Vector2( 0, 0 ) },
46264                 "uRepeat" : { type: "v2", value: new THREE.Vector2( 1, 1 ) },
46265
46266                 "wrapRGB"  : { type: "v3", value: new THREE.Vector3( 1, 1, 1 ) }
46267
46268                 }
46269
46270             ] ),
46271
46272             fragmentShader: [
46273
46274                 "uniform vec3 uAmbientColor;",
46275                 "uniform vec3 uDiffuseColor;",
46276                 "uniform vec3 uSpecularColor;",
46277                 "uniform float uShininess;",
46278                 "uniform float uOpacity;",
46279
46280                 "uniform bool enableDiffuse;",
46281                 "uniform bool enableSpecular;",
46282                 "uniform bool enableAO;",
46283                 "uniform bool enableReflection;",
46284
46285                 "uniform sampler2D tDiffuse;",
46286                 "uniform sampler2D tNormal;",
46287                 "uniform sampler2D tSpecular;",
46288                 "uniform sampler2D tAO;",
46289
46290                 "uniform samplerCube tCube;",
46291
46292                 "uniform vec2 uNormalScale;",
46293
46294                 "uniform bool useRefract;",
46295                 "uniform float uRefractionRatio;",
46296                 "uniform float uReflectivity;",
46297
46298                 "varying vec3 vTangent;",
46299                 "varying vec3 vBinormal;",
46300                 "varying vec3 vNormal;",
46301                 "varying vec2 vUv;",
46302
46303                 "uniform vec3 ambientLightColor;",
46304
46305                 "#if MAX_DIR_LIGHTS > 0",
46306
46307                     "uniform vec3 directionalLightColor[ MAX_DIR_LIGHTS ];",
46308                     "uniform vec3 directionalLightDirection[ MAX_DIR_LIGHTS ];",
46309
46310                 "#endif",
46311
46312                 "#if MAX_HEMI_LIGHTS > 0",
46313
46314                     "uniform vec3 hemisphereLightSkyColor[ MAX_HEMI_LIGHTS ];",
46315                     "uniform vec3 hemisphereLightGroundColor[ MAX_HEMI_LIGHTS ];",
46316                     "uniform vec3 hemisphereLightPosition[ MAX_HEMI_LIGHTS ];",
46317
46318                 "#endif",
46319
46320                 "#if MAX_POINT_LIGHTS > 0",
46321
46322                     "uniform vec3 pointLightColor[ MAX_POINT_LIGHTS ];",
46323                     "uniform vec3 pointLightPosition[ MAX_POINT_LIGHTS ];",
46324                     "uniform float pointLightDistance[ MAX_POINT_LIGHTS ];",
46325
46326                 "#endif",
46327
46328                 "#if MAX_SPOT_LIGHTS > 0",
46329
46330                     "uniform vec3 spotLightColor[ MAX_SPOT_LIGHTS ];",
46331                     "uniform vec3 spotLightPosition[ MAX_SPOT_LIGHTS ];",
46332                     "uniform vec3 spotLightDirection[ MAX_SPOT_LIGHTS ];",
46333                     "uniform float spotLightAngle[ MAX_SPOT_LIGHTS ];",
46334                     "uniform float spotLightExponent[ MAX_SPOT_LIGHTS ];",
46335                     "uniform float spotLightDistance[ MAX_SPOT_LIGHTS ];",
46336
46337                 "#endif",
46338
46339                 "#ifdef WRAP_AROUND",
46340
46341                     "uniform vec3 wrapRGB;",
46342
46343                 "#endif",
46344
46345                 "varying vec3 vWorldPosition;",
46346                 "varying vec3 vViewPosition;",
46347
46348                 THREE.ShaderChunk[ "shadowmap_pars_fragment" ],
46349                 THREE.ShaderChunk[ "fog_pars_fragment" ],
46350
46351                 "void main() {",
46352
46353                     "gl_FragColor = vec4( vec3( 1.0 ), uOpacity );",
46354
46355                     "vec3 specularTex = vec3( 1.0 );",
46356
46357                     "vec3 normalTex = texture2D( tNormal, vUv ).xyz * 2.0 - 1.0;",
46358                     "normalTex.xy *= uNormalScale;",
46359                     "normalTex = normalize( normalTex );",
46360
46361                     "if( enableDiffuse ) {",
46362
46363                         "#ifdef GAMMA_INPUT",
46364
46365                             "vec4 texelColor = texture2D( tDiffuse, vUv );",
46366                             "texelColor.xyz *= texelColor.xyz;",
46367
46368                             "gl_FragColor = gl_FragColor * texelColor;",
46369
46370                         "#else",
46371
46372                             "gl_FragColor = gl_FragColor * texture2D( tDiffuse, vUv );",
46373
46374                         "#endif",
46375
46376                     "}",
46377
46378                     "if( enableAO ) {",
46379
46380                         "#ifdef GAMMA_INPUT",
46381
46382                             "vec4 aoColor = texture2D( tAO, vUv );",
46383                             "aoColor.xyz *= aoColor.xyz;",
46384
46385                             "gl_FragColor.xyz = gl_FragColor.xyz * aoColor.xyz;",
46386
46387                         "#else",
46388
46389                             "gl_FragColor.xyz = gl_FragColor.xyz * texture2D( tAO, vUv ).xyz;",
46390
46391                         "#endif",
46392
46393                     "}",
46394
46395                     "if( enableSpecular )",
46396                         "specularTex = texture2D( tSpecular, vUv ).xyz;",
46397
46398                     "mat3 tsb = mat3( normalize( vTangent ), normalize( vBinormal ), normalize( vNormal ) );",
46399                     "vec3 finalNormal = tsb * normalTex;",
46400
46401                     "#ifdef FLIP_SIDED",
46402
46403                         "finalNormal = -finalNormal;",
46404
46405                     "#endif",
46406
46407                     "vec3 normal = normalize( finalNormal );",
46408                     "vec3 viewPosition = normalize( vViewPosition );",
46409
46410                     // point lights
46411
46412                     "#if MAX_POINT_LIGHTS > 0",
46413
46414                         "vec3 pointDiffuse = vec3( 0.0 );",
46415                         "vec3 pointSpecular = vec3( 0.0 );",
46416
46417                         "for ( int i = 0; i < MAX_POINT_LIGHTS; i ++ ) {",
46418
46419                             "vec4 lPosition = viewMatrix * vec4( pointLightPosition[ i ], 1.0 );",
46420                             "vec3 pointVector = lPosition.xyz + vViewPosition.xyz;",
46421
46422                             "float pointDistance = 1.0;",
46423                             "if ( pointLightDistance[ i ] > 0.0 )",
46424                                 "pointDistance = 1.0 - min( ( length( pointVector ) / pointLightDistance[ i ] ), 1.0 );",
46425
46426                             "pointVector = normalize( pointVector );",
46427
46428                             // diffuse
46429
46430                             "#ifdef WRAP_AROUND",
46431
46432                                 "float pointDiffuseWeightFull = max( dot( normal, pointVector ), 0.0 );",
46433                                 "float pointDiffuseWeightHalf = max( 0.5 * dot( normal, pointVector ) + 0.5, 0.0 );",
46434
46435                                 "vec3 pointDiffuseWeight = mix( vec3 ( pointDiffuseWeightFull ), vec3( pointDiffuseWeightHalf ), wrapRGB );",
46436
46437                             "#else",
46438
46439                                 "float pointDiffuseWeight = max( dot( normal, pointVector ), 0.0 );",
46440
46441                             "#endif",
46442
46443                             "pointDiffuse += pointDistance * pointLightColor[ i ] * uDiffuseColor * pointDiffuseWeight;",
46444
46445                             // specular
46446
46447                             "vec3 pointHalfVector = normalize( pointVector + viewPosition );",
46448                             "float pointDotNormalHalf = max( dot( normal, pointHalfVector ), 0.0 );",
46449                             "float pointSpecularWeight = specularTex.r * max( pow( pointDotNormalHalf, uShininess ), 0.0 );",
46450
46451                             "#ifdef PHYSICALLY_BASED_SHADING",
46452
46453                                 // 2.0 => 2.0001 is hack to work around ANGLE bug
46454
46455                                 "float specularNormalization = ( uShininess + 2.0001 ) / 8.0;",
46456
46457                                 "vec3 schlick = uSpecularColor + vec3( 1.0 - uSpecularColor ) * pow( 1.0 - dot( pointVector, pointHalfVector ), 5.0 );",
46458                                 "pointSpecular += schlick * pointLightColor[ i ] * pointSpecularWeight * pointDiffuseWeight * pointDistance * specularNormalization;",
46459
46460                             "#else",
46461
46462                                 "pointSpecular += pointDistance * pointLightColor[ i ] * uSpecularColor * pointSpecularWeight * pointDiffuseWeight;",
46463
46464                             "#endif",
46465
46466                         "}",
46467
46468                     "#endif",
46469
46470                     // spot lights
46471
46472                     "#if MAX_SPOT_LIGHTS > 0",
46473
46474                         "vec3 spotDiffuse = vec3( 0.0 );",
46475                         "vec3 spotSpecular = vec3( 0.0 );",
46476
46477                         "for ( int i = 0; i < MAX_SPOT_LIGHTS; i ++ ) {",
46478
46479                             "vec4 lPosition = viewMatrix * vec4( spotLightPosition[ i ], 1.0 );",
46480                             "vec3 spotVector = lPosition.xyz + vViewPosition.xyz;",
46481
46482                             "float spotDistance = 1.0;",
46483                             "if ( spotLightDistance[ i ] > 0.0 )",
46484                                 "spotDistance = 1.0 - min( ( length( spotVector ) / spotLightDistance[ i ] ), 1.0 );",
46485
46486                             "spotVector = normalize( spotVector );",
46487
46488                             "float spotEffect = dot( spotLightDirection[ i ], normalize( spotLightPosition[ i ] - vWorldPosition ) );",
46489
46490                             "if ( spotEffect > spotLightAngle[ i ] ) {",
46491
46492                                 "spotEffect = pow( spotEffect, spotLightExponent[ i ] );",
46493
46494                                 // diffuse
46495
46496                                 "#ifdef WRAP_AROUND",
46497
46498                                     "float spotDiffuseWeightFull = max( dot( normal, spotVector ), 0.0 );",
46499                                     "float spotDiffuseWeightHalf = max( 0.5 * dot( normal, spotVector ) + 0.5, 0.0 );",
46500
46501                                     "vec3 spotDiffuseWeight = mix( vec3 ( spotDiffuseWeightFull ), vec3( spotDiffuseWeightHalf ), wrapRGB );",
46502
46503                                 "#else",
46504
46505                                     "float spotDiffuseWeight = max( dot( normal, spotVector ), 0.0 );",
46506
46507                                 "#endif",
46508
46509                                 "spotDiffuse += spotDistance * spotLightColor[ i ] * uDiffuseColor * spotDiffuseWeight * spotEffect;",
46510
46511                                 // specular
46512
46513                                 "vec3 spotHalfVector = normalize( spotVector + viewPosition );",
46514                                 "float spotDotNormalHalf = max( dot( normal, spotHalfVector ), 0.0 );",
46515                                 "float spotSpecularWeight = specularTex.r * max( pow( spotDotNormalHalf, uShininess ), 0.0 );",
46516
46517                                 "#ifdef PHYSICALLY_BASED_SHADING",
46518
46519                                     // 2.0 => 2.0001 is hack to work around ANGLE bug
46520
46521                                     "float specularNormalization = ( uShininess + 2.0001 ) / 8.0;",
46522
46523                                     "vec3 schlick = uSpecularColor + vec3( 1.0 - uSpecularColor ) * pow( 1.0 - dot( spotVector, spotHalfVector ), 5.0 );",
46524                                     "spotSpecular += schlick * spotLightColor[ i ] * spotSpecularWeight * spotDiffuseWeight * spotDistance * specularNormalization * spotEffect;",
46525
46526                                 "#else",
46527
46528                                     "spotSpecular += spotDistance * spotLightColor[ i ] * uSpecularColor * spotSpecularWeight * spotDiffuseWeight * spotEffect;",
46529
46530                                 "#endif",
46531
46532                             "}",
46533
46534                         "}",
46535
46536                     "#endif",
46537
46538                     // directional lights
46539
46540                     "#if MAX_DIR_LIGHTS > 0",
46541
46542                         "vec3 dirDiffuse = vec3( 0.0 );",
46543                         "vec3 dirSpecular = vec3( 0.0 );",
46544
46545                         "for( int i = 0; i < MAX_DIR_LIGHTS; i++ ) {",
46546
46547                             "vec4 lDirection = viewMatrix * vec4( directionalLightDirection[ i ], 0.0 );",
46548                             "vec3 dirVector = normalize( lDirection.xyz );",
46549
46550                             // diffuse
46551
46552                             "#ifdef WRAP_AROUND",
46553
46554                                 "float directionalLightWeightingFull = max( dot( normal, dirVector ), 0.0 );",
46555                                 "float directionalLightWeightingHalf = max( 0.5 * dot( normal, dirVector ) + 0.5, 0.0 );",
46556
46557                                 "vec3 dirDiffuseWeight = mix( vec3( directionalLightWeightingFull ), vec3( directionalLightWeightingHalf ), wrapRGB );",
46558
46559                             "#else",
46560
46561                                 "float dirDiffuseWeight = max( dot( normal, dirVector ), 0.0 );",
46562
46563                             "#endif",
46564
46565                             "dirDiffuse += directionalLightColor[ i ] * uDiffuseColor * dirDiffuseWeight;",
46566
46567                             // specular
46568
46569                             "vec3 dirHalfVector = normalize( dirVector + viewPosition );",
46570                             "float dirDotNormalHalf = max( dot( normal, dirHalfVector ), 0.0 );",
46571                             "float dirSpecularWeight = specularTex.r * max( pow( dirDotNormalHalf, uShininess ), 0.0 );",
46572
46573                             "#ifdef PHYSICALLY_BASED_SHADING",
46574
46575                                 // 2.0 => 2.0001 is hack to work around ANGLE bug
46576
46577                                 "float specularNormalization = ( uShininess + 2.0001 ) / 8.0;",
46578
46579                                 "vec3 schlick = uSpecularColor + vec3( 1.0 - uSpecularColor ) * pow( 1.0 - dot( dirVector, dirHalfVector ), 5.0 );",
46580                                 "dirSpecular += schlick * directionalLightColor[ i ] * dirSpecularWeight * dirDiffuseWeight * specularNormalization;",
46581
46582                             "#else",
46583
46584                                 "dirSpecular += directionalLightColor[ i ] * uSpecularColor * dirSpecularWeight * dirDiffuseWeight;",
46585
46586                             "#endif",
46587
46588                         "}",
46589
46590                     "#endif",
46591
46592                     // hemisphere lights
46593
46594                     "#if MAX_HEMI_LIGHTS > 0",
46595
46596                         "vec3 hemiDiffuse  = vec3( 0.0 );",
46597                         "vec3 hemiSpecular = vec3( 0.0 );" ,
46598
46599                         "for( int i = 0; i < MAX_HEMI_LIGHTS; i ++ ) {",
46600
46601                             "vec4 lPosition = viewMatrix * vec4( hemisphereLightPosition[ i ], 1.0 );",
46602                             "vec3 lVector = normalize( lPosition.xyz + vViewPosition.xyz );",
46603
46604                             // diffuse
46605
46606                             "float dotProduct = dot( normal, lVector );",
46607                             "float hemiDiffuseWeight = 0.5 * dotProduct + 0.5;",
46608
46609                             "vec3 hemiColor = mix( hemisphereLightGroundColor[ i ], hemisphereLightSkyColor[ i ], hemiDiffuseWeight );",
46610
46611                             "hemiDiffuse += uDiffuseColor * hemiColor;",
46612
46613                             // specular (sky light)
46614
46615
46616                             "vec3 hemiHalfVectorSky = normalize( lVector + viewPosition );",
46617                             "float hemiDotNormalHalfSky = 0.5 * dot( normal, hemiHalfVectorSky ) + 0.5;",
46618                             "float hemiSpecularWeightSky = specularTex.r * max( pow( hemiDotNormalHalfSky, uShininess ), 0.0 );",
46619
46620                             // specular (ground light)
46621
46622                             "vec3 lVectorGround = normalize( -lPosition.xyz + vViewPosition.xyz );",
46623
46624                             "vec3 hemiHalfVectorGround = normalize( lVectorGround + viewPosition );",
46625                             "float hemiDotNormalHalfGround = 0.5 * dot( normal, hemiHalfVectorGround ) + 0.5;",
46626                             "float hemiSpecularWeightGround = specularTex.r * max( pow( hemiDotNormalHalfGround, uShininess ), 0.0 );",
46627
46628                             "#ifdef PHYSICALLY_BASED_SHADING",
46629
46630                                 "float dotProductGround = dot( normal, lVectorGround );",
46631
46632                                 // 2.0 => 2.0001 is hack to work around ANGLE bug
46633
46634                                 "float specularNormalization = ( uShininess + 2.0001 ) / 8.0;",
46635
46636                                 "vec3 schlickSky = uSpecularColor + vec3( 1.0 - uSpecularColor ) * pow( 1.0 - dot( lVector, hemiHalfVectorSky ), 5.0 );",
46637                                 "vec3 schlickGround = uSpecularColor + vec3( 1.0 - uSpecularColor ) * pow( 1.0 - dot( lVectorGround, hemiHalfVectorGround ), 5.0 );",
46638                                 "hemiSpecular += hemiColor * specularNormalization * ( schlickSky * hemiSpecularWeightSky * max( dotProduct, 0.0 ) + schlickGround * hemiSpecularWeightGround * max( dotProductGround, 0.0 ) );",
46639
46640                             "#else",
46641
46642                                 "hemiSpecular += uSpecularColor * hemiColor * ( hemiSpecularWeightSky + hemiSpecularWeightGround ) * hemiDiffuseWeight;",
46643
46644                             "#endif",
46645
46646                         "}",
46647
46648                     "#endif",
46649
46650                     // all lights contribution summation
46651
46652                     "vec3 totalDiffuse = vec3( 0.0 );",
46653                     "vec3 totalSpecular = vec3( 0.0 );",
46654
46655                     "#if MAX_DIR_LIGHTS > 0",
46656
46657                         "totalDiffuse += dirDiffuse;",
46658                         "totalSpecular += dirSpecular;",
46659
46660                     "#endif",
46661
46662                     "#if MAX_HEMI_LIGHTS > 0",
46663
46664                         "totalDiffuse += hemiDiffuse;",
46665                         "totalSpecular += hemiSpecular;",
46666
46667                     "#endif",
46668
46669                     "#if MAX_POINT_LIGHTS > 0",
46670
46671                         "totalDiffuse += pointDiffuse;",
46672                         "totalSpecular += pointSpecular;",
46673
46674                     "#endif",
46675
46676                     "#if MAX_SPOT_LIGHTS > 0",
46677
46678                         "totalDiffuse += spotDiffuse;",
46679                         "totalSpecular += spotSpecular;",
46680
46681                     "#endif",
46682
46683                     "#ifdef METAL",
46684
46685                         "gl_FragColor.xyz = gl_FragColor.xyz * ( totalDiffuse + ambientLightColor * uAmbientColor + totalSpecular );",
46686
46687                     "#else",
46688
46689                         "gl_FragColor.xyz = gl_FragColor.xyz * ( totalDiffuse + ambientLightColor * uAmbientColor ) + totalSpecular;",
46690
46691                     "#endif",
46692
46693                     "if ( enableReflection ) {",
46694
46695                         "vec3 vReflect;",
46696                         "vec3 cameraToVertex = normalize( vWorldPosition - cameraPosition );",
46697
46698                         "if ( useRefract ) {",
46699
46700                             "vReflect = refract( cameraToVertex, normal, uRefractionRatio );",
46701
46702                         "} else {",
46703
46704                             "vReflect = reflect( cameraToVertex, normal );",
46705
46706                         "}",
46707
46708                         "vec4 cubeColor = textureCube( tCube, vec3( -vReflect.x, vReflect.yz ) );",
46709
46710                         "#ifdef GAMMA_INPUT",
46711
46712                             "cubeColor.xyz *= cubeColor.xyz;",
46713
46714                         "#endif",
46715
46716                         "gl_FragColor.xyz = mix( gl_FragColor.xyz, cubeColor.xyz, specularTex.r * uReflectivity );",
46717
46718                     "}",
46719
46720                     THREE.ShaderChunk[ "shadowmap_fragment" ],
46721                     THREE.ShaderChunk[ "linear_to_gamma_fragment" ],
46722                     THREE.ShaderChunk[ "fog_fragment" ],
46723
46724                 "}"
46725
46726             ].join("\n"),
46727
46728             vertexShader: [
46729
46730                 "attribute vec4 tangent;",
46731
46732                 "uniform vec2 uOffset;",
46733                 "uniform vec2 uRepeat;",
46734
46735                 "uniform bool enableDisplacement;",
46736
46737                 "#ifdef VERTEX_TEXTURES",
46738
46739                     "uniform sampler2D tDisplacement;",
46740                     "uniform float uDisplacementScale;",
46741                     "uniform float uDisplacementBias;",
46742
46743                 "#endif",
46744
46745                 "varying vec3 vTangent;",
46746                 "varying vec3 vBinormal;",
46747                 "varying vec3 vNormal;",
46748                 "varying vec2 vUv;",
46749
46750                 "varying vec3 vWorldPosition;",
46751                 "varying vec3 vViewPosition;",
46752
46753                 THREE.ShaderChunk[ "skinning_pars_vertex" ],
46754                 THREE.ShaderChunk[ "shadowmap_pars_vertex" ],
46755
46756                 "void main() {",
46757
46758                     THREE.ShaderChunk[ "skinbase_vertex" ],
46759                     THREE.ShaderChunk[ "skinnormal_vertex" ],
46760
46761                     // normal, tangent and binormal vectors
46762
46763                     "#ifdef USE_SKINNING",
46764
46765                         "vNormal = normalMatrix * skinnedNormal.xyz;",
46766
46767                         "vec4 skinnedTangent = skinMatrix * vec4( tangent.xyz, 0.0 );",
46768                         "vTangent = normalMatrix * skinnedTangent.xyz;",
46769
46770                     "#else",
46771
46772                         "vNormal = normalMatrix * normal;",
46773                         "vTangent = normalMatrix * tangent.xyz;",
46774
46775                     "#endif",
46776
46777                     "vBinormal = cross( vNormal, vTangent ) * tangent.w;",
46778
46779                     "vUv = uv * uRepeat + uOffset;",
46780
46781                     // displacement mapping
46782
46783                     "vec3 displacedPosition;",
46784
46785                     "#ifdef VERTEX_TEXTURES",
46786
46787                         "if ( enableDisplacement ) {",
46788
46789                             "vec3 dv = texture2D( tDisplacement, uv ).xyz;",
46790                             "float df = uDisplacementScale * dv.x + uDisplacementBias;",
46791                             "displacedPosition = position + normalize( normal ) * df;",
46792
46793                         "} else {",
46794
46795                             "#ifdef USE_SKINNING",
46796
46797                                 "vec4 skinVertex = vec4( position, 1.0 );",
46798
46799                                 "vec4 skinned  = boneMatX * skinVertex * skinWeight.x;",
46800                                 "skinned       += boneMatY * skinVertex * skinWeight.y;",
46801
46802                                 "displacedPosition  = skinned.xyz;",
46803
46804                             "#else",
46805
46806                                 "displacedPosition = position;",
46807
46808                             "#endif",
46809
46810                         "}",
46811
46812                     "#else",
46813
46814                         "#ifdef USE_SKINNING",
46815
46816                             "vec4 skinVertex = vec4( position, 1.0 );",
46817
46818                             "vec4 skinned  = boneMatX * skinVertex * skinWeight.x;",
46819                             "skinned       += boneMatY * skinVertex * skinWeight.y;",
46820
46821                             "displacedPosition  = skinned.xyz;",
46822
46823                         "#else",
46824
46825                             "displacedPosition = position;",
46826
46827                         "#endif",
46828
46829                     "#endif",
46830
46831                     //
46832
46833                     "vec4 mvPosition = modelViewMatrix * vec4( displacedPosition, 1.0 );",
46834                     "vec4 mPosition = modelMatrix * vec4( displacedPosition, 1.0 );",
46835
46836                     "gl_Position = projectionMatrix * mvPosition;",
46837
46838                     //
46839
46840                     "vWorldPosition = mPosition.xyz;",
46841                     "vViewPosition = -mvPosition.xyz;",
46842
46843                     // shadows
46844
46845                     "#ifdef USE_SHADOWMAP",
46846
46847                         "for( int i = 0; i < MAX_SHADOWS; i ++ ) {",
46848
46849                             "vShadowCoord[ i ] = shadowMatrix[ i ] * mPosition;",
46850
46851                         "}",
46852
46853                     "#endif",
46854
46855                 "}"
46856
46857             ].join("\n")
46858
46859         },
46860
46861         /* -------------------------------------------------------------------------
46862         //    Cube map shader
46863          ------------------------------------------------------------------------- */
46864
46865         'cube': {
46866
46867             uniforms: { "tCube": { type: "t", value: null },
46868                         "tFlip": { type: "f", value: -1 } },
46869
46870             vertexShader: [
46871
46872                 "varying vec3 vViewPosition;",
46873
46874                 "void main() {",
46875
46876                     "vec4 mPosition = modelMatrix * vec4( position, 1.0 );",
46877                     "vViewPosition = cameraPosition - mPosition.xyz;",
46878
46879                     "gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );",
46880
46881                 "}"
46882
46883             ].join("\n"),
46884
46885             fragmentShader: [
46886
46887                 "uniform samplerCube tCube;",
46888                 "uniform float tFlip;",
46889
46890                 "varying vec3 vViewPosition;",
46891
46892                 "void main() {",
46893
46894                     "vec3 wPos = cameraPosition - vViewPosition;",
46895                     "gl_FragColor = textureCube( tCube, vec3( tFlip * wPos.x, wPos.yz ) );",
46896
46897                 "}"
46898
46899             ].join("\n")
46900
46901         }
46902
46903     }
46904
46905 };
46906
46907 };
46908 /**
46909  * @author zz85 / http://www.lab4games.net/zz85/blog
46910  * @author alteredq / http://alteredqualia.com/
46911  *
46912  * For Text operations in three.js (See TextGeometry)
46913  *
46914  * It uses techniques used in:
46915  *
46916  *     typeface.js and canvastext
46917  *         For converting fonts and rendering with javascript
46918  *        http://typeface.neocracy.org
46919  *
46920  *    Triangulation ported from AS3
46921  *        Simple Polygon Triangulation
46922  *        http://actionsnippet.com/?p=1462
46923  *
46924  *     A Method to triangulate shapes with holes
46925  *        http://www.sakri.net/blog/2009/06/12/an-approach-to-triangulating-polygons-with-holes/
46926  *
46927  */
46928
46929 THREE.FontUtils = {
46930
46931     faces : {},
46932
46933     // Just for now. face[weight][style]
46934
46935     face : "helvetiker",
46936     weight: "normal",
46937     style : "normal",
46938     size : 150,
46939     divisions : 10,
46940
46941     getFace : function() {
46942
46943         return this.faces[ this.face ][ this.weight ][ this.style ];
46944
46945     },
46946
46947     loadFace : function( data ) {
46948
46949         var family = data.familyName.toLowerCase();
46950
46951         var ThreeFont = this;
46952
46953         ThreeFont.faces[ family ] = ThreeFont.faces[ family ] || {};
46954
46955         ThreeFont.faces[ family ][ data.cssFontWeight ] = ThreeFont.faces[ family ][ data.cssFontWeight ] || {};
46956         ThreeFont.faces[ family ][ data.cssFontWeight ][ data.cssFontStyle ] = data;
46957
46958         var face = ThreeFont.faces[ family ][ data.cssFontWeight ][ data.cssFontStyle ] = data;
46959
46960         return data;
46961
46962     },
46963
46964     drawText : function( text ) {
46965
46966         var characterPts = [], allPts = [];
46967
46968         // RenderText
46969
46970         var i, p,
46971             face = this.getFace(),
46972             scale = this.size / face.resolution,
46973             offset = 0,
46974             chars = String( text ).split( '' ),
46975             length = chars.length;
46976
46977         var fontPaths = [];
46978
46979         for ( i = 0; i < length; i ++ ) {
46980
46981             var path = new THREE.Path();
46982
46983             var ret = this.extractGlyphPoints( chars[ i ], face, scale, offset, path );
46984             offset += ret.offset;
46985
46986             fontPaths.push( ret.path );
46987
46988         }
46989
46990         // get the width
46991
46992         var width = offset / 2;
46993         //
46994         // for ( p = 0; p < allPts.length; p++ ) {
46995         //
46996         //     allPts[ p ].x -= width;
46997         //
46998         // }
46999
47000         //var extract = this.extractPoints( allPts, characterPts );
47001         //extract.contour = allPts;
47002
47003         //extract.paths = fontPaths;
47004         //extract.offset = width;
47005
47006         return { paths : fontPaths, offset : width };
47007
47008     },
47009
47010
47011
47012
47013     extractGlyphPoints : function( c, face, scale, offset, path ) {
47014
47015         var pts = [];
47016
47017         var i, i2, divisions,
47018             outline, action, length,
47019             scaleX, scaleY,
47020             x, y, cpx, cpy, cpx0, cpy0, cpx1, cpy1, cpx2, cpy2,
47021             laste,
47022             glyph = face.glyphs[ c ] || face.glyphs[ '?' ];
47023
47024         if ( !glyph ) return;
47025
47026         if ( glyph.o ) {
47027
47028             outline = glyph._cachedOutline || ( glyph._cachedOutline = glyph.o.split( ' ' ) );
47029             length = outline.length;
47030
47031             scaleX = scale;
47032             scaleY = scale;
47033
47034             for ( i = 0; i < length; ) {
47035
47036                 action = outline[ i ++ ];
47037
47038                 //console.log( action );
47039
47040                 switch( action ) {
47041
47042                 case 'm':
47043
47044                     // Move To
47045
47046                     x = outline[ i++ ] * scaleX + offset;
47047                     y = outline[ i++ ] * scaleY;
47048
47049                     path.moveTo( x, y );
47050                     break;
47051
47052                 case 'l':
47053
47054                     // Line To
47055
47056                     x = outline[ i++ ] * scaleX + offset;
47057                     y = outline[ i++ ] * scaleY;
47058                     path.lineTo(x,y);
47059                     break;
47060
47061                 case 'q':
47062
47063                     // QuadraticCurveTo
47064
47065                     cpx  = outline[ i++ ] * scaleX + offset;
47066                     cpy  = outline[ i++ ] * scaleY;
47067                     cpx1 = outline[ i++ ] * scaleX + offset;
47068                     cpy1 = outline[ i++ ] * scaleY;
47069
47070                     path.quadraticCurveTo(cpx1, cpy1, cpx, cpy);
47071
47072                     laste = pts[ pts.length - 1 ];
47073
47074                     if ( laste ) {
47075
47076                         cpx0 = laste.x;
47077                         cpy0 = laste.y;
47078
47079                         for ( i2 = 1, divisions = this.divisions; i2 <= divisions; i2 ++ ) {
47080
47081                             var t = i2 / divisions;
47082                             var tx = THREE.Shape.Utils.b2( t, cpx0, cpx1, cpx );
47083                             var ty = THREE.Shape.Utils.b2( t, cpy0, cpy1, cpy );
47084                       }
47085
47086                   }
47087
47088                   break;
47089
47090                 case 'b':
47091
47092                     // Cubic Bezier Curve
47093
47094                     cpx  = outline[ i++ ] *  scaleX + offset;
47095                     cpy  = outline[ i++ ] *  scaleY;
47096                     cpx1 = outline[ i++ ] *  scaleX + offset;
47097                     cpy1 = outline[ i++ ] * -scaleY;
47098                     cpx2 = outline[ i++ ] *  scaleX + offset;
47099                     cpy2 = outline[ i++ ] * -scaleY;
47100
47101                     path.bezierCurveTo( cpx, cpy, cpx1, cpy1, cpx2, cpy2 );
47102
47103                     laste = pts[ pts.length - 1 ];
47104
47105                     if ( laste ) {
47106
47107                         cpx0 = laste.x;
47108                         cpy0 = laste.y;
47109
47110                         for ( i2 = 1, divisions = this.divisions; i2 <= divisions; i2 ++ ) {
47111
47112                             var t = i2 / divisions;
47113                             var tx = THREE.Shape.Utils.b3( t, cpx0, cpx1, cpx2, cpx );
47114                             var ty = THREE.Shape.Utils.b3( t, cpy0, cpy1, cpy2, cpy );
47115
47116                         }
47117
47118                     }
47119
47120                     break;
47121
47122                 }
47123
47124             }
47125         }
47126
47127
47128
47129         return { offset: glyph.ha*scale, path:path};
47130     }
47131
47132 };
47133
47134
47135 THREE.FontUtils.generateShapes = function( text, parameters ) {
47136
47137     // Parameters
47138
47139     parameters = parameters || {};
47140
47141     var size = parameters.size !== undefined ? parameters.size : 100;
47142     var curveSegments = parameters.curveSegments !== undefined ? parameters.curveSegments: 4;
47143
47144     var font = parameters.font !== undefined ? parameters.font : "helvetiker";
47145     var weight = parameters.weight !== undefined ? parameters.weight : "normal";
47146     var style = parameters.style !== undefined ? parameters.style : "normal";
47147
47148     THREE.FontUtils.size = size;
47149     THREE.FontUtils.divisions = curveSegments;
47150
47151     THREE.FontUtils.face = font;
47152     THREE.FontUtils.weight = weight;
47153     THREE.FontUtils.style = style;
47154
47155     // Get a Font data json object
47156
47157     var data = THREE.FontUtils.drawText( text );
47158
47159     var paths = data.paths;
47160     var shapes = [];
47161
47162     for ( var p = 0, pl = paths.length; p < pl; p ++ ) {
47163
47164         Array.prototype.push.apply( shapes, paths[ p ].toShapes() );
47165
47166     }
47167
47168     return shapes;
47169
47170 };
47171
47172
47173 /**
47174  * This code is a quick port of code written in C++ which was submitted to
47175  * flipcode.com by John W. Ratcliff  // July 22, 2000
47176  * See original code and more information here:
47177  * http://www.flipcode.com/archives/Efficient_Polygon_Triangulation.shtml
47178  *
47179  * ported to actionscript by Zevan Rosser
47180  * www.actionsnippet.com
47181  *
47182  * ported to javascript by Joshua Koo
47183  * http://www.lab4games.net/zz85/blog
47184  *
47185  */
47186
47187
47188 ( function( namespace ) {
47189
47190     var EPSILON = 0.0000000001;
47191
47192     // takes in an contour array and returns
47193
47194     var process = function( contour, indices ) {
47195
47196         var n = contour.length;
47197
47198         if ( n < 3 ) return null;
47199
47200         var result = [],
47201             verts = [],
47202             vertIndices = [];
47203
47204         /* we want a counter-clockwise polygon in verts */
47205
47206         var u, v, w;
47207
47208         if ( area( contour ) > 0.0 ) {
47209
47210             for ( v = 0; v < n; v++ ) verts[ v ] = v;
47211
47212         } else {
47213
47214             for ( v = 0; v < n; v++ ) verts[ v ] = ( n - 1 ) - v;
47215
47216         }
47217
47218         var nv = n;
47219
47220         /*  remove nv - 2 vertices, creating 1 triangle every time */
47221
47222         var count = 2 * nv;   /* error detection */
47223
47224         for( v = nv - 1; nv > 2; ) {
47225
47226             /* if we loop, it is probably a non-simple polygon */
47227
47228             if ( ( count-- ) <= 0 ) {
47229
47230                 //** Triangulate: ERROR - probable bad polygon!
47231
47232                 //throw ( "Warning, unable to triangulate polygon!" );
47233                 //return null;
47234                 // Sometimes warning is fine, especially polygons are triangulated in reverse.
47235                 console.log( "Warning, unable to triangulate polygon!" );
47236
47237                 if ( indices ) return vertIndices;
47238                 return result;
47239
47240             }
47241
47242             /* three consecutive vertices in current polygon, <u,v,w> */
47243
47244             u = v;          if ( nv <= u ) u = 0;     /* previous */
47245             v = u + 1;  if ( nv <= v ) v = 0;     /* new v    */
47246             w = v + 1;  if ( nv <= w ) w = 0;     /* next     */
47247
47248             if ( snip( contour, u, v, w, nv, verts ) ) {
47249
47250                 var a, b, c, s, t;
47251
47252                 /* true names of the vertices */
47253
47254                 a = verts[ u ];
47255                 b = verts[ v ];
47256                 c = verts[ w ];
47257
47258                 /* output Triangle */
47259
47260                 /*
47261                 result.push( contour[ a ] );
47262                 result.push( contour[ b ] );
47263                 result.push( contour[ c ] );
47264                 */
47265                 result.push( [ contour[ a ],
47266                     contour[ b ],
47267                     contour[ c ] ] );
47268
47269
47270                 vertIndices.push( [ verts[ u ], verts[ v ], verts[ w ] ] );
47271
47272                 /* remove v from the remaining polygon */
47273
47274                 for( s = v, t = v + 1; t < nv; s++, t++ ) {
47275
47276                     verts[ s ] = verts[ t ];
47277
47278                 }
47279
47280                 nv--;
47281
47282                 /* reset error detection counter */
47283
47284                 count = 2 * nv;
47285
47286             }
47287
47288         }
47289
47290         if ( indices ) return vertIndices;
47291         return result;
47292
47293     };
47294
47295     // calculate area of the contour polygon
47296
47297     var area = function ( contour ) {
47298
47299         var n = contour.length;
47300         var a = 0.0;
47301
47302         for( var p = n - 1, q = 0; q < n; p = q++ ) {
47303
47304             a += contour[ p ].x * contour[ q ].y - contour[ q ].x * contour[ p ].y;
47305
47306         }
47307
47308         return a * 0.5;
47309
47310     };
47311
47312     // see if p is inside triangle abc
47313
47314     var insideTriangle = function( ax, ay,
47315                                    bx, by,
47316                                    cx, cy,
47317                                    px, py ) {
47318
47319           var aX, aY, bX, bY;
47320           var cX, cY, apx, apy;
47321           var bpx, bpy, cpx, cpy;
47322           var cCROSSap, bCROSScp, aCROSSbp;
47323
47324           aX = cx - bx;  aY = cy - by;
47325           bX = ax - cx;  bY = ay - cy;
47326           cX = bx - ax;  cY = by - ay;
47327           apx= px  -ax;  apy= py - ay;
47328           bpx= px - bx;  bpy= py - by;
47329           cpx= px - cx;  cpy= py - cy;
47330
47331           aCROSSbp = aX*bpy - aY*bpx;
47332           cCROSSap = cX*apy - cY*apx;
47333           bCROSScp = bX*cpy - bY*cpx;
47334
47335           return ( (aCROSSbp >= 0.0) && (bCROSScp >= 0.0) && (cCROSSap >= 0.0) );
47336
47337     };
47338
47339
47340     var snip = function ( contour, u, v, w, n, verts ) {
47341
47342         var p;
47343         var ax, ay, bx, by;
47344         var cx, cy, px, py;
47345
47346         ax = contour[ verts[ u ] ].x;
47347         ay = contour[ verts[ u ] ].y;
47348
47349         bx = contour[ verts[ v ] ].x;
47350         by = contour[ verts[ v ] ].y;
47351
47352         cx = contour[ verts[ w ] ].x;
47353         cy = contour[ verts[ w ] ].y;
47354
47355         if ( EPSILON > (((bx-ax)*(cy-ay)) - ((by-ay)*(cx-ax))) ) return false;
47356
47357             for ( p = 0; p < n; p++ ) {
47358
47359                 if( (p == u) || (p == v) || (p == w) ) continue;
47360
47361                 px = contour[ verts[ p ] ].x
47362                 py = contour[ verts[ p ] ].y
47363
47364                 if ( insideTriangle( ax, ay, bx, by, cx, cy, px, py ) ) return false;
47365
47366           }
47367
47368           return true;
47369
47370     };
47371
47372
47373     namespace.Triangulate = process;
47374     namespace.Triangulate.area = area;
47375
47376     return namespace;
47377
47378 })(THREE.FontUtils);
47379
47380 // To use the typeface.js face files, hook up the API
47381 self._typeface_js = { faces: THREE.FontUtils.faces, loadFace: THREE.FontUtils.loadFace };/**
47382  * @author zz85 / http://www.lab4games.net/zz85/blog
47383  * Extensible curve object
47384  *
47385  * Some common of Curve methods
47386  * .getPoint(t), getTangent(t)
47387  * .getPointAt(u), getTagentAt(u)
47388  * .getPoints(), .getSpacedPoints()
47389  * .getLength()
47390  * .updateArcLengths()
47391  *
47392  * This file contains following classes:
47393  *
47394  * -- 2d classes --
47395  * THREE.Curve
47396  * THREE.LineCurve
47397  * THREE.QuadraticBezierCurve
47398  * THREE.CubicBezierCurve
47399  * THREE.SplineCurve
47400  * THREE.ArcCurve
47401  * THREE.EllipseCurve
47402  *
47403  * -- 3d classes --
47404  * THREE.LineCurve3
47405  * THREE.QuadraticBezierCurve3
47406  * THREE.CubicBezierCurve3
47407  * THREE.SplineCurve3
47408  * THREE.ClosedSplineCurve3
47409  *
47410  * A series of curves can be represented as a THREE.CurvePath
47411  *
47412  **/
47413
47414 /**************************************************************
47415  *    Abstract Curve base class
47416  **************************************************************/
47417
47418 THREE.Curve = function () {
47419
47420 };
47421
47422 // Virtual base class method to overwrite and implement in subclasses
47423 //    - t [0 .. 1]
47424
47425 THREE.Curve.prototype.getPoint = function ( t ) {
47426
47427     console.log( "Warning, getPoint() not implemented!" );
47428     return null;
47429
47430 };
47431
47432 // Get point at relative position in curve according to arc length
47433 // - u [0 .. 1]
47434
47435 THREE.Curve.prototype.getPointAt = function ( u ) {
47436
47437     var t = this.getUtoTmapping( u );
47438     return this.getPoint( t );
47439
47440 };
47441
47442 // Get sequence of points using getPoint( t )
47443
47444 THREE.Curve.prototype.getPoints = function ( divisions ) {
47445
47446     if ( !divisions ) divisions = 5;
47447
47448     var d, pts = [];
47449
47450     for ( d = 0; d <= divisions; d ++ ) {
47451
47452         pts.push( this.getPoint( d / divisions ) );
47453
47454     }
47455
47456     return pts;
47457
47458 };
47459
47460 // Get sequence of points using getPointAt( u )
47461
47462 THREE.Curve.prototype.getSpacedPoints = function ( divisions ) {
47463
47464     if ( !divisions ) divisions = 5;
47465
47466     var d, pts = [];
47467
47468     for ( d = 0; d <= divisions; d ++ ) {
47469
47470         pts.push( this.getPointAt( d / divisions ) );
47471
47472     }
47473
47474     return pts;
47475
47476 };
47477
47478 // Get total curve arc length
47479
47480 THREE.Curve.prototype.getLength = function () {
47481
47482     var lengths = this.getLengths();
47483     return lengths[ lengths.length - 1 ];
47484
47485 };
47486
47487 // Get list of cumulative segment lengths
47488
47489 THREE.Curve.prototype.getLengths = function ( divisions ) {
47490
47491     if ( !divisions ) divisions = (this.__arcLengthDivisions) ? (this.__arcLengthDivisions): 200;
47492
47493     if ( this.cacheArcLengths
47494         && ( this.cacheArcLengths.length == divisions + 1 )
47495         && !this.needsUpdate) {
47496
47497         //console.log( "cached", this.cacheArcLengths );
47498         return this.cacheArcLengths;
47499
47500     }
47501
47502     this.needsUpdate = false;
47503
47504     var cache = [];
47505     var current, last = this.getPoint( 0 );
47506     var p, sum = 0;
47507
47508     cache.push( 0 );
47509
47510     for ( p = 1; p <= divisions; p ++ ) {
47511
47512         current = this.getPoint ( p / divisions );
47513         sum += current.distanceTo( last );
47514         cache.push( sum );
47515         last = current;
47516
47517     }
47518
47519     this.cacheArcLengths = cache;
47520
47521     return cache; // { sums: cache, sum:sum }; Sum is in the last element.
47522
47523 };
47524
47525
47526 THREE.Curve.prototype.updateArcLengths = function() {
47527     this.needsUpdate = true;
47528     this.getLengths();
47529 };
47530
47531 // Given u ( 0 .. 1 ), get a t to find p. This gives you points which are equi distance
47532
47533 THREE.Curve.prototype.getUtoTmapping = function ( u, distance ) {
47534
47535     var arcLengths = this.getLengths();
47536
47537     var i = 0, il = arcLengths.length;
47538
47539     var targetArcLength; // The targeted u distance value to get
47540
47541     if ( distance ) {
47542
47543         targetArcLength = distance;
47544
47545     } else {
47546
47547         targetArcLength = u * arcLengths[ il - 1 ];
47548
47549     }
47550
47551     //var time = Date.now();
47552
47553     // binary search for the index with largest value smaller than target u distance
47554
47555     var low = 0, high = il - 1, comparison;
47556
47557     while ( low <= high ) {
47558
47559         i = Math.floor( low + ( high - low ) / 2 ); // less likely to overflow, though probably not issue here, JS doesn't really have integers, all numbers are floats
47560
47561         comparison = arcLengths[ i ] - targetArcLength;
47562
47563         if ( comparison < 0 ) {
47564
47565             low = i + 1;
47566             continue;
47567
47568         } else if ( comparison > 0 ) {
47569
47570             high = i - 1;
47571             continue;
47572
47573         } else {
47574
47575             high = i;
47576             break;
47577
47578             // DONE
47579
47580         }
47581
47582     }
47583
47584     i = high;
47585
47586     //console.log('b' , i, low, high, Date.now()- time);
47587
47588     if ( arcLengths[ i ] == targetArcLength ) {
47589
47590         var t = i / ( il - 1 );
47591         return t;
47592
47593     }
47594
47595     // we could get finer grain at lengths, or use simple interpolatation between two points
47596
47597     var lengthBefore = arcLengths[ i ];
47598     var lengthAfter = arcLengths[ i + 1 ];
47599
47600     var segmentLength = lengthAfter - lengthBefore;
47601
47602     // determine where we are between the 'before' and 'after' points
47603
47604     var segmentFraction = ( targetArcLength - lengthBefore ) / segmentLength;
47605
47606     // add that fractional amount to t
47607
47608     var t = ( i + segmentFraction ) / ( il -1 );
47609
47610     return t;
47611
47612 };
47613
47614
47615 // In 2D space, there are actually 2 normal vectors,
47616 // and in 3D space, infinte
47617 // TODO this should be depreciated.
47618 THREE.Curve.prototype.getNormalVector = function( t ) {
47619
47620     var vec = this.getTangent( t );
47621
47622     return new THREE.Vector2( -vec.y , vec.x );
47623
47624 };
47625
47626 // Returns a unit vector tangent at t
47627 // In case any sub curve does not implement its tangent / normal finding,
47628 // we get 2 points with a small delta and find a gradient of the 2 points
47629 // which seems to make a reasonable approximation
47630
47631 THREE.Curve.prototype.getTangent = function( t ) {
47632
47633     var delta = 0.0001;
47634     var t1 = t - delta;
47635     var t2 = t + delta;
47636
47637     // Capping in case of danger
47638
47639     if ( t1 < 0 ) t1 = 0;
47640     if ( t2 > 1 ) t2 = 1;
47641
47642     var pt1 = this.getPoint( t1 );
47643     var pt2 = this.getPoint( t2 );
47644
47645     var vec = pt2.clone().subSelf(pt1);
47646     return vec.normalize();
47647
47648 };
47649
47650
47651 THREE.Curve.prototype.getTangentAt = function ( u ) {
47652
47653     var t = this.getUtoTmapping( u );
47654     return this.getTangent( t );
47655
47656 };
47657
47658 /**************************************************************
47659  *    Line
47660  **************************************************************/
47661
47662 THREE.LineCurve = function ( v1, v2 ) {
47663
47664     this.v1 = v1;
47665     this.v2 = v2;
47666
47667 };
47668
47669 THREE.LineCurve.prototype = Object.create( THREE.Curve.prototype );
47670
47671 THREE.LineCurve.prototype.getPoint = function ( t ) {
47672
47673     var point = this.v2.clone().subSelf(this.v1);
47674     point.multiplyScalar( t ).addSelf( this.v1 );
47675
47676     return point;
47677
47678 };
47679
47680 // Line curve is linear, so we can overwrite default getPointAt
47681
47682 THREE.LineCurve.prototype.getPointAt = function ( u ) {
47683
47684     return this.getPoint( u );
47685
47686 };
47687
47688 THREE.LineCurve.prototype.getTangent = function( t ) {
47689
47690     var tangent = this.v2.clone().subSelf(this.v1);
47691
47692     return tangent.normalize();
47693
47694 };
47695
47696 /**************************************************************
47697  *    Quadratic Bezier curve
47698  **************************************************************/
47699
47700
47701 THREE.QuadraticBezierCurve = function ( v0, v1, v2 ) {
47702
47703     this.v0 = v0;
47704     this.v1 = v1;
47705     this.v2 = v2;
47706
47707 };
47708
47709 THREE.QuadraticBezierCurve.prototype = Object.create( THREE.Curve.prototype );
47710
47711
47712 THREE.QuadraticBezierCurve.prototype.getPoint = function ( t ) {
47713
47714     var tx, ty;
47715
47716     tx = THREE.Shape.Utils.b2( t, this.v0.x, this.v1.x, this.v2.x );
47717     ty = THREE.Shape.Utils.b2( t, this.v0.y, this.v1.y, this.v2.y );
47718
47719     return new THREE.Vector2( tx, ty );
47720
47721 };
47722
47723
47724 THREE.QuadraticBezierCurve.prototype.getTangent = function( t ) {
47725
47726     var tx, ty;
47727
47728     tx = THREE.Curve.Utils.tangentQuadraticBezier( t, this.v0.x, this.v1.x, this.v2.x );
47729     ty = THREE.Curve.Utils.tangentQuadraticBezier( t, this.v0.y, this.v1.y, this.v2.y );
47730
47731     // returns unit vector
47732
47733     var tangent = new THREE.Vector2( tx, ty );
47734     tangent.normalize();
47735
47736     return tangent;
47737
47738 };
47739
47740
47741 /**************************************************************
47742  *    Cubic Bezier curve
47743  **************************************************************/
47744
47745 THREE.CubicBezierCurve = function ( v0, v1, v2, v3 ) {
47746
47747     this.v0 = v0;
47748     this.v1 = v1;
47749     this.v2 = v2;
47750     this.v3 = v3;
47751
47752 };
47753
47754 THREE.CubicBezierCurve.prototype = Object.create( THREE.Curve.prototype );
47755
47756 THREE.CubicBezierCurve.prototype.getPoint = function ( t ) {
47757
47758     var tx, ty;
47759
47760     tx = THREE.Shape.Utils.b3( t, this.v0.x, this.v1.x, this.v2.x, this.v3.x );
47761     ty = THREE.Shape.Utils.b3( t, this.v0.y, this.v1.y, this.v2.y, this.v3.y );
47762
47763     return new THREE.Vector2( tx, ty );
47764
47765 };
47766
47767 THREE.CubicBezierCurve.prototype.getTangent = function( t ) {
47768
47769     var tx, ty;
47770
47771     tx = THREE.Curve.Utils.tangentCubicBezier( t, this.v0.x, this.v1.x, this.v2.x, this.v3.x );
47772     ty = THREE.Curve.Utils.tangentCubicBezier( t, this.v0.y, this.v1.y, this.v2.y, this.v3.y );
47773
47774     var tangent = new THREE.Vector2( tx, ty );
47775     tangent.normalize();
47776
47777     return tangent;
47778
47779 };
47780
47781
47782 /**************************************************************
47783  *    Spline curve
47784  **************************************************************/
47785
47786 THREE.SplineCurve = function ( points /* array of Vector2 */ ) {
47787
47788     this.points = (points == undefined) ? [] : points;
47789
47790 };
47791
47792 THREE.SplineCurve.prototype = Object.create( THREE.Curve.prototype );
47793
47794 THREE.SplineCurve.prototype.getPoint = function ( t ) {
47795
47796     var v = new THREE.Vector2();
47797     var c = [];
47798     var points = this.points, point, intPoint, weight;
47799     point = ( points.length - 1 ) * t;
47800
47801     intPoint = Math.floor( point );
47802     weight = point - intPoint;
47803
47804     c[ 0 ] = intPoint == 0 ? intPoint : intPoint - 1;
47805     c[ 1 ] = intPoint;
47806     c[ 2 ] = intPoint  > points.length - 2 ? points.length -1 : intPoint + 1;
47807     c[ 3 ] = intPoint  > points.length - 3 ? points.length -1 : intPoint + 2;
47808
47809     v.x = THREE.Curve.Utils.interpolate( points[ c[ 0 ] ].x, points[ c[ 1 ] ].x, points[ c[ 2 ] ].x, points[ c[ 3 ] ].x, weight );
47810     v.y = THREE.Curve.Utils.interpolate( points[ c[ 0 ] ].y, points[ c[ 1 ] ].y, points[ c[ 2 ] ].y, points[ c[ 3 ] ].y, weight );
47811
47812     return v;
47813
47814 };
47815
47816 /**************************************************************
47817  *    Ellipse curve
47818  **************************************************************/
47819
47820 THREE.EllipseCurve = function ( aX, aY, xRadius, yRadius,
47821                             aStartAngle, aEndAngle,
47822                             aClockwise ) {
47823
47824     this.aX = aX;
47825     this.aY = aY;
47826
47827     this.xRadius = xRadius;
47828     this.yRadius = yRadius;
47829
47830     this.aStartAngle = aStartAngle;
47831     this.aEndAngle = aEndAngle;
47832
47833     this.aClockwise = aClockwise;
47834
47835 };
47836
47837 THREE.EllipseCurve.prototype = Object.create( THREE.Curve.prototype );
47838
47839 THREE.EllipseCurve.prototype.getPoint = function ( t ) {
47840
47841     var deltaAngle = this.aEndAngle - this.aStartAngle;
47842
47843     if ( !this.aClockwise ) {
47844
47845         t = 1 - t;
47846
47847     }
47848
47849     var angle = this.aStartAngle + t * deltaAngle;
47850
47851     var tx = this.aX + this.xRadius * Math.cos( angle );
47852     var ty = this.aY + this.yRadius * Math.sin( angle );
47853
47854     return new THREE.Vector2( tx, ty );
47855
47856 };
47857
47858 /**************************************************************
47859  *    Arc curve
47860  **************************************************************/
47861
47862 THREE.ArcCurve = function ( aX, aY, aRadius, aStartAngle, aEndAngle, aClockwise ) {
47863
47864     THREE.EllipseCurve.call( this, aX, aY, aRadius, aRadius, aStartAngle, aEndAngle, aClockwise );
47865 };
47866
47867 THREE.ArcCurve.prototype = Object.create( THREE.EllipseCurve.prototype );
47868
47869
47870 /**************************************************************
47871  *    Utils
47872  **************************************************************/
47873
47874 THREE.Curve.Utils = {
47875
47876     tangentQuadraticBezier: function ( t, p0, p1, p2 ) {
47877
47878         return 2 * ( 1 - t ) * ( p1 - p0 ) + 2 * t * ( p2 - p1 );
47879
47880     },
47881
47882     // Puay Bing, thanks for helping with this derivative!
47883
47884     tangentCubicBezier: function (t, p0, p1, p2, p3 ) {
47885
47886         return -3 * p0 * (1 - t) * (1 - t)  +
47887             3 * p1 * (1 - t) * (1-t) - 6 *t *p1 * (1-t) +
47888             6 * t *  p2 * (1-t) - 3 * t * t * p2 +
47889             3 * t * t * p3;
47890     },
47891
47892
47893     tangentSpline: function ( t, p0, p1, p2, p3 ) {
47894
47895         // To check if my formulas are correct
47896
47897         var h00 = 6 * t * t - 6 * t;     // derived from 2t^3 − 3t^2 + 1
47898         var h10 = 3 * t * t - 4 * t + 1; // t^3 − 2t^2 + t
47899         var h01 = -6 * t * t + 6 * t;     // − 2t3 + 3t2
47900         var h11 = 3 * t * t - 2 * t;    // t3 − t2
47901
47902         return h00 + h10 + h01 + h11;
47903
47904     },
47905
47906     // Catmull-Rom
47907
47908     interpolate: function( p0, p1, p2, p3, t ) {
47909
47910         var v0 = ( p2 - p0 ) * 0.5;
47911         var v1 = ( p3 - p1 ) * 0.5;
47912         var t2 = t * t;
47913         var t3 = t * t2;
47914         return ( 2 * p1 - 2 * p2 + v0 + v1 ) * t3 + ( - 3 * p1 + 3 * p2 - 2 * v0 - v1 ) * t2 + v0 * t + p1;
47915
47916     }
47917
47918 };
47919
47920
47921 // TODO: Transformation for Curves?
47922
47923 /**************************************************************
47924  *    3D Curves
47925  **************************************************************/
47926
47927 // A Factory method for creating new curve subclasses
47928
47929 THREE.Curve.create = function ( constructor, getPointFunc ) {
47930
47931     constructor.prototype = Object.create( THREE.Curve.prototype );
47932     constructor.prototype.getPoint = getPointFunc;
47933
47934     return constructor;
47935
47936 };
47937
47938
47939 /**************************************************************
47940  *    Line3D
47941  **************************************************************/
47942
47943 THREE.LineCurve3 = THREE.Curve.create(
47944
47945     function ( v1, v2 ) {
47946
47947         this.v1 = v1;
47948         this.v2 = v2;
47949
47950     },
47951
47952     function ( t ) {
47953
47954         var r = new THREE.Vector3();
47955
47956
47957         r.sub( this.v2, this.v1 ); // diff
47958         r.multiplyScalar( t );
47959         r.addSelf( this.v1 );
47960
47961         return r;
47962
47963     }
47964
47965 );
47966
47967
47968 /**************************************************************
47969  *    Quadratic Bezier 3D curve
47970  **************************************************************/
47971
47972 THREE.QuadraticBezierCurve3 = THREE.Curve.create(
47973
47974     function ( v0, v1, v2 ) {
47975
47976         this.v0 = v0;
47977         this.v1 = v1;
47978         this.v2 = v2;
47979
47980     },
47981
47982     function ( t ) {
47983
47984         var tx, ty, tz;
47985
47986         tx = THREE.Shape.Utils.b2( t, this.v0.x, this.v1.x, this.v2.x );
47987         ty = THREE.Shape.Utils.b2( t, this.v0.y, this.v1.y, this.v2.y );
47988         tz = THREE.Shape.Utils.b2( t, this.v0.z, this.v1.z, this.v2.z );
47989
47990         return new THREE.Vector3( tx, ty, tz );
47991
47992     }
47993
47994 );
47995
47996
47997
47998 /**************************************************************
47999  *    Cubic Bezier 3D curve
48000  **************************************************************/
48001
48002 THREE.CubicBezierCurve3 = THREE.Curve.create(
48003
48004     function ( v0, v1, v2, v3 ) {
48005
48006         this.v0 = v0;
48007         this.v1 = v1;
48008         this.v2 = v2;
48009         this.v3 = v3;
48010
48011     },
48012
48013     function ( t ) {
48014
48015         var tx, ty, tz;
48016
48017         tx = THREE.Shape.Utils.b3( t, this.v0.x, this.v1.x, this.v2.x, this.v3.x );
48018         ty = THREE.Shape.Utils.b3( t, this.v0.y, this.v1.y, this.v2.y, this.v3.y );
48019         tz = THREE.Shape.Utils.b3( t, this.v0.z, this.v1.z, this.v2.z, this.v3.z );
48020
48021         return new THREE.Vector3( tx, ty, tz );
48022
48023     }
48024
48025 );
48026
48027
48028
48029 /**************************************************************
48030  *    Spline 3D curve
48031  **************************************************************/
48032
48033
48034 THREE.SplineCurve3 = THREE.Curve.create(
48035
48036     function ( points /* array of Vector3 */) {
48037
48038         this.points = (points == undefined) ? [] : points;
48039
48040     },
48041
48042     function ( t ) {
48043
48044         var v = new THREE.Vector3();
48045         var c = [];
48046         var points = this.points, point, intPoint, weight;
48047         point = ( points.length - 1 ) * t;
48048
48049         intPoint = Math.floor( point );
48050         weight = point - intPoint;
48051
48052         c[ 0 ] = intPoint == 0 ? intPoint : intPoint - 1;
48053         c[ 1 ] = intPoint;
48054         c[ 2 ] = intPoint  > points.length - 2 ? points.length - 1 : intPoint + 1;
48055         c[ 3 ] = intPoint  > points.length - 3 ? points.length - 1 : intPoint + 2;
48056
48057         var pt0 = points[ c[0] ],
48058             pt1 = points[ c[1] ],
48059             pt2 = points[ c[2] ],
48060             pt3 = points[ c[3] ];
48061
48062         v.x = THREE.Curve.Utils.interpolate(pt0.x, pt1.x, pt2.x, pt3.x, weight);
48063         v.y = THREE.Curve.Utils.interpolate(pt0.y, pt1.y, pt2.y, pt3.y, weight);
48064         v.z = THREE.Curve.Utils.interpolate(pt0.z, pt1.z, pt2.z, pt3.z, weight);
48065
48066         return v;
48067
48068     }
48069
48070 );
48071
48072
48073 // THREE.SplineCurve3.prototype.getTangent = function(t) {
48074 //         var v = new THREE.Vector3();
48075 //         var c = [];
48076 //         var points = this.points, point, intPoint, weight;
48077 //         point = ( points.length - 1 ) * t;
48078
48079 //         intPoint = Math.floor( point );
48080 //         weight = point - intPoint;
48081
48082 //         c[ 0 ] = intPoint == 0 ? intPoint : intPoint - 1;
48083 //         c[ 1 ] = intPoint;
48084 //         c[ 2 ] = intPoint  > points.length - 2 ? points.length - 1 : intPoint + 1;
48085 //         c[ 3 ] = intPoint  > points.length - 3 ? points.length - 1 : intPoint + 2;
48086
48087 //         var pt0 = points[ c[0] ],
48088 //             pt1 = points[ c[1] ],
48089 //             pt2 = points[ c[2] ],
48090 //             pt3 = points[ c[3] ];
48091
48092 //     // t = weight;
48093 //     v.x = THREE.Curve.Utils.tangentSpline( t, pt0.x, pt1.x, pt2.x, pt3.x );
48094 //     v.y = THREE.Curve.Utils.tangentSpline( t, pt0.y, pt1.y, pt2.y, pt3.y );
48095 //     v.z = THREE.Curve.Utils.tangentSpline( t, pt0.z, pt1.z, pt2.z, pt3.z );
48096
48097 //     return v;
48098
48099 // }
48100
48101 /**************************************************************
48102  *    Closed Spline 3D curve
48103  **************************************************************/
48104
48105
48106 THREE.ClosedSplineCurve3 = THREE.Curve.create(
48107
48108     function ( points /* array of Vector3 */) {
48109
48110         this.points = (points == undefined) ? [] : points;
48111
48112     },
48113
48114     function ( t ) {
48115
48116         var v = new THREE.Vector3();
48117         var c = [];
48118         var points = this.points, point, intPoint, weight;
48119         point = ( points.length - 0 ) * t;
48120             // This needs to be from 0-length +1
48121
48122         intPoint = Math.floor( point );
48123         weight = point - intPoint;
48124
48125         intPoint += intPoint > 0 ? 0 : ( Math.floor( Math.abs( intPoint ) / points.length ) + 1 ) * points.length;
48126         c[ 0 ] = ( intPoint - 1 ) % points.length;
48127         c[ 1 ] = ( intPoint ) % points.length;
48128         c[ 2 ] = ( intPoint + 1 ) % points.length;
48129         c[ 3 ] = ( intPoint + 2 ) % points.length;
48130
48131         v.x = THREE.Curve.Utils.interpolate( points[ c[ 0 ] ].x, points[ c[ 1 ] ].x, points[ c[ 2 ] ].x, points[ c[ 3 ] ].x, weight );
48132         v.y = THREE.Curve.Utils.interpolate( points[ c[ 0 ] ].y, points[ c[ 1 ] ].y, points[ c[ 2 ] ].y, points[ c[ 3 ] ].y, weight );
48133         v.z = THREE.Curve.Utils.interpolate( points[ c[ 0 ] ].z, points[ c[ 1 ] ].z, points[ c[ 2 ] ].z, points[ c[ 3 ] ].z, weight );
48134
48135         return v;
48136
48137     }
48138
48139 );
48140 /**
48141  * @author zz85 / http://www.lab4games.net/zz85/blog
48142  *
48143  **/
48144
48145 /**************************************************************
48146  *    Curved Path - a curve path is simply a array of connected
48147  *  curves, but retains the api of a curve
48148  **************************************************************/
48149
48150 THREE.CurvePath = function () {
48151
48152     this.curves = [];
48153     this.bends = [];
48154
48155     this.autoClose = false; // Automatically closes the path
48156 };
48157
48158 THREE.CurvePath.prototype = Object.create( THREE.Curve.prototype );
48159
48160 THREE.CurvePath.prototype.add = function ( curve ) {
48161
48162     this.curves.push( curve );
48163
48164 };
48165
48166 THREE.CurvePath.prototype.checkConnection = function() {
48167     // TODO
48168     // If the ending of curve is not connected to the starting
48169     // or the next curve, then, this is not a real path
48170 };
48171
48172 THREE.CurvePath.prototype.closePath = function() {
48173     // TODO Test
48174     // and verify for vector3 (needs to implement equals)
48175     // Add a line curve if start and end of lines are not connected
48176     var startPoint = this.curves[0].getPoint(0);
48177     var endPoint = this.curves[this.curves.length-1].getPoint(1);
48178
48179     if (!startPoint.equals(endPoint)) {
48180         this.curves.push( new THREE.LineCurve(endPoint, startPoint) );
48181     }
48182
48183 };
48184
48185 // To get accurate point with reference to
48186 // entire path distance at time t,
48187 // following has to be done:
48188
48189 // 1. Length of each sub path have to be known
48190 // 2. Locate and identify type of curve
48191 // 3. Get t for the curve
48192 // 4. Return curve.getPointAt(t')
48193
48194 THREE.CurvePath.prototype.getPoint = function( t ) {
48195
48196     var d = t * this.getLength();
48197     var curveLengths = this.getCurveLengths();
48198     var i = 0, diff, curve;
48199
48200     // To think about boundaries points.
48201
48202     while ( i < curveLengths.length ) {
48203
48204         if ( curveLengths[ i ] >= d ) {
48205
48206             diff = curveLengths[ i ] - d;
48207             curve = this.curves[ i ];
48208
48209             var u = 1 - diff / curve.getLength();
48210
48211             return curve.getPointAt( u );
48212
48213             break;
48214         }
48215
48216         i ++;
48217
48218     }
48219
48220     return null;
48221
48222     // loop where sum != 0, sum > d , sum+1 <d
48223
48224 };
48225
48226 /*
48227 THREE.CurvePath.prototype.getTangent = function( t ) {
48228 };*/
48229
48230
48231 // We cannot use the default THREE.Curve getPoint() with getLength() because in
48232 // THREE.Curve, getLength() depends on getPoint() but in THREE.CurvePath
48233 // getPoint() depends on getLength
48234
48235 THREE.CurvePath.prototype.getLength = function() {
48236
48237     var lens = this.getCurveLengths();
48238     return lens[ lens.length - 1 ];
48239
48240 };
48241
48242 // Compute lengths and cache them
48243 // We cannot overwrite getLengths() because UtoT mapping uses it.
48244
48245 THREE.CurvePath.prototype.getCurveLengths = function() {
48246
48247     // We use cache values if curves and cache array are same length
48248
48249     if ( this.cacheLengths && this.cacheLengths.length == this.curves.length ) {
48250
48251         return this.cacheLengths;
48252
48253     };
48254
48255     // Get length of subsurve
48256     // Push sums into cached array
48257
48258     var lengths = [], sums = 0;
48259     var i, il = this.curves.length;
48260
48261     for ( i = 0; i < il; i ++ ) {
48262
48263         sums += this.curves[ i ].getLength();
48264         lengths.push( sums );
48265
48266     }
48267
48268     this.cacheLengths = lengths;
48269
48270     return lengths;
48271
48272 };
48273
48274
48275
48276 // Returns min and max coordinates, as well as centroid
48277
48278 THREE.CurvePath.prototype.getBoundingBox = function () {
48279
48280     var points = this.getPoints();
48281
48282     var maxX, maxY, maxZ;
48283     var minX, minY, minZ;
48284
48285     maxX = maxY = Number.NEGATIVE_INFINITY;
48286     minX = minY = Number.POSITIVE_INFINITY;
48287
48288     var p, i, il, sum;
48289
48290     var v3 = points[0] instanceof THREE.Vector3;
48291
48292     sum = v3 ? new THREE.Vector3() : new THREE.Vector2();
48293
48294     for ( i = 0, il = points.length; i < il; i ++ ) {
48295
48296         p = points[ i ];
48297
48298         if ( p.x > maxX ) maxX = p.x;
48299         else if ( p.x < minX ) minX = p.x;
48300
48301         if ( p.y > maxY ) maxY = p.y;
48302         else if ( p.y < minY ) minY = p.y;
48303
48304         if (v3) {
48305
48306             if ( p.z > maxZ ) maxZ = p.z;
48307             else if ( p.z < minZ ) minZ = p.z;
48308
48309         }
48310
48311         sum.addSelf( p );
48312
48313     }
48314
48315     var ret = {
48316
48317         minX: minX,
48318         minY: minY,
48319         maxX: maxX,
48320         maxY: maxY,
48321         centroid: sum.divideScalar( il )
48322
48323     };
48324
48325     if (v3) {
48326
48327         ret.maxZ = maxZ;
48328         ret.minZ = minZ;
48329
48330     }
48331
48332     return ret;
48333
48334 };
48335
48336 /**************************************************************
48337  *    Create Geometries Helpers
48338  **************************************************************/
48339
48340 /// Generate geometry from path points (for Line or ParticleSystem objects)
48341
48342 THREE.CurvePath.prototype.createPointsGeometry = function( divisions ) {
48343
48344     var pts = this.getPoints( divisions, true );
48345     return this.createGeometry( pts );
48346
48347 };
48348
48349 // Generate geometry from equidistance sampling along the path
48350
48351 THREE.CurvePath.prototype.createSpacedPointsGeometry = function( divisions ) {
48352
48353     var pts = this.getSpacedPoints( divisions, true );
48354     return this.createGeometry( pts );
48355
48356 };
48357
48358 THREE.CurvePath.prototype.createGeometry = function( points ) {
48359
48360     var geometry = new THREE.Geometry();
48361
48362     for ( var i = 0; i < points.length; i ++ ) {
48363
48364         geometry.vertices.push( new THREE.Vector3( points[ i ].x, points[ i ].y, points[ i ].z || 0) );
48365
48366     }
48367
48368     return geometry;
48369
48370 };
48371
48372
48373 /**************************************************************
48374  *    Bend / Wrap Helper Methods
48375  **************************************************************/
48376
48377 // Wrap path / Bend modifiers?
48378
48379 THREE.CurvePath.prototype.addWrapPath = function ( bendpath ) {
48380
48381     this.bends.push( bendpath );
48382
48383 };
48384
48385 THREE.CurvePath.prototype.getTransformedPoints = function( segments, bends ) {
48386
48387     var oldPts = this.getPoints( segments ); // getPoints getSpacedPoints
48388     var i, il;
48389
48390     if ( !bends ) {
48391
48392         bends = this.bends;
48393
48394     }
48395
48396     for ( i = 0, il = bends.length; i < il; i ++ ) {
48397
48398         oldPts = this.getWrapPoints( oldPts, bends[ i ] );
48399
48400     }
48401
48402     return oldPts;
48403
48404 };
48405
48406 THREE.CurvePath.prototype.getTransformedSpacedPoints = function( segments, bends ) {
48407
48408     var oldPts = this.getSpacedPoints( segments );
48409
48410     var i, il;
48411
48412     if ( !bends ) {
48413
48414         bends = this.bends;
48415
48416     }
48417
48418     for ( i = 0, il = bends.length; i < il; i ++ ) {
48419
48420         oldPts = this.getWrapPoints( oldPts, bends[ i ] );
48421
48422     }
48423
48424     return oldPts;
48425
48426 };
48427
48428 // This returns getPoints() bend/wrapped around the contour of a path.
48429 // Read http://www.planetclegg.com/projects/WarpingTextToSplines.html
48430
48431 THREE.CurvePath.prototype.getWrapPoints = function ( oldPts, path ) {
48432
48433     var bounds = this.getBoundingBox();
48434
48435     var i, il, p, oldX, oldY, xNorm;
48436
48437     for ( i = 0, il = oldPts.length; i < il; i ++ ) {
48438
48439         p = oldPts[ i ];
48440
48441         oldX = p.x;
48442         oldY = p.y;
48443
48444         xNorm = oldX / bounds.maxX;
48445
48446         // If using actual distance, for length > path, requires line extrusions
48447         //xNorm = path.getUtoTmapping(xNorm, oldX); // 3 styles. 1) wrap stretched. 2) wrap stretch by arc length 3) warp by actual distance
48448
48449         xNorm = path.getUtoTmapping( xNorm, oldX );
48450
48451         // check for out of bounds?
48452
48453         var pathPt = path.getPoint( xNorm );
48454         var normal = path.getNormalVector( xNorm ).multiplyScalar( oldY );
48455
48456         p.x = pathPt.x + normal.x;
48457         p.y = pathPt.y + normal.y;
48458
48459     }
48460
48461     return oldPts;
48462
48463 };
48464
48465 /**
48466  * @author alteredq / http://alteredqualia.com/
48467  */
48468
48469 THREE.Gyroscope = function () {
48470
48471     THREE.Object3D.call( this );
48472
48473 };
48474
48475 THREE.Gyroscope.prototype = Object.create( THREE.Object3D.prototype );
48476
48477 THREE.Gyroscope.prototype.updateMatrixWorld = function ( force ) {
48478
48479     this.matrixAutoUpdate && this.updateMatrix();
48480
48481     // update matrixWorld
48482
48483     if ( this.matrixWorldNeedsUpdate || force ) {
48484
48485         if ( this.parent ) {
48486
48487             this.matrixWorld.multiply( this.parent.matrixWorld, this.matrix );
48488
48489             this.matrixWorld.decompose( this.translationWorld, this.rotationWorld, this.scaleWorld );
48490             this.matrix.decompose( this.translationObject, this.rotationObject, this.scaleObject );
48491
48492             this.matrixWorld.compose( this.translationWorld, this.rotationObject, this.scaleWorld );
48493
48494
48495         } else {
48496
48497             this.matrixWorld.copy( this.matrix );
48498
48499         }
48500
48501
48502         this.matrixWorldNeedsUpdate = false;
48503
48504         force = true;
48505
48506     }
48507
48508     // update children
48509
48510     for ( var i = 0, l = this.children.length; i < l; i ++ ) {
48511
48512         this.children[ i ].updateMatrixWorld( force );
48513
48514     }
48515
48516 };
48517
48518 THREE.Gyroscope.prototype.translationWorld = new THREE.Vector3();
48519 THREE.Gyroscope.prototype.translationObject = new THREE.Vector3();
48520 THREE.Gyroscope.prototype.rotationWorld = new THREE.Quaternion();
48521 THREE.Gyroscope.prototype.rotationObject = new THREE.Quaternion();
48522 THREE.Gyroscope.prototype.scaleWorld = new THREE.Vector3();
48523 THREE.Gyroscope.prototype.scaleObject = new THREE.Vector3();
48524
48525 /**
48526  * @author zz85 / http://www.lab4games.net/zz85/blog
48527  * Creates free form 2d path using series of points, lines or curves.
48528  *
48529  **/
48530
48531 THREE.Path = function ( points ) {
48532
48533     THREE.CurvePath.call(this);
48534
48535     this.actions = [];
48536
48537     if ( points ) {
48538
48539         this.fromPoints( points );
48540
48541     }
48542
48543 };
48544
48545 THREE.Path.prototype = Object.create( THREE.CurvePath.prototype );
48546
48547 THREE.PathActions = {
48548
48549     MOVE_TO: 'moveTo',
48550     LINE_TO: 'lineTo',
48551     QUADRATIC_CURVE_TO: 'quadraticCurveTo', // Bezier quadratic curve
48552     BEZIER_CURVE_TO: 'bezierCurveTo',         // Bezier cubic curve
48553     CSPLINE_THRU: 'splineThru',                // Catmull-rom spline
48554     ARC: 'arc',                                // Circle
48555     ELLIPSE: 'ellipse'
48556 };
48557
48558 // TODO Clean up PATH API
48559
48560 // Create path using straight lines to connect all points
48561 // - vectors: array of Vector2
48562
48563 THREE.Path.prototype.fromPoints = function ( vectors ) {
48564
48565     this.moveTo( vectors[ 0 ].x, vectors[ 0 ].y );
48566
48567     for ( var v = 1, vlen = vectors.length; v < vlen; v ++ ) {
48568
48569         this.lineTo( vectors[ v ].x, vectors[ v ].y );
48570
48571     };
48572
48573 };
48574
48575 // startPath() endPath()?
48576
48577 THREE.Path.prototype.moveTo = function ( x, y ) {
48578
48579     var args = Array.prototype.slice.call( arguments );
48580     this.actions.push( { action: THREE.PathActions.MOVE_TO, args: args } );
48581
48582 };
48583
48584 THREE.Path.prototype.lineTo = function ( x, y ) {
48585
48586     var args = Array.prototype.slice.call( arguments );
48587
48588     var lastargs = this.actions[ this.actions.length - 1 ].args;
48589
48590     var x0 = lastargs[ lastargs.length - 2 ];
48591     var y0 = lastargs[ lastargs.length - 1 ];
48592
48593     var curve = new THREE.LineCurve( new THREE.Vector2( x0, y0 ), new THREE.Vector2( x, y ) );
48594     this.curves.push( curve );
48595
48596     this.actions.push( { action: THREE.PathActions.LINE_TO, args: args } );
48597
48598 };
48599
48600 THREE.Path.prototype.quadraticCurveTo = function( aCPx, aCPy, aX, aY ) {
48601
48602     var args = Array.prototype.slice.call( arguments );
48603
48604     var lastargs = this.actions[ this.actions.length - 1 ].args;
48605
48606     var x0 = lastargs[ lastargs.length - 2 ];
48607     var y0 = lastargs[ lastargs.length - 1 ];
48608
48609     var curve = new THREE.QuadraticBezierCurve( new THREE.Vector2( x0, y0 ),
48610                                                 new THREE.Vector2( aCPx, aCPy ),
48611                                                 new THREE.Vector2( aX, aY ) );
48612     this.curves.push( curve );
48613
48614     this.actions.push( { action: THREE.PathActions.QUADRATIC_CURVE_TO, args: args } );
48615
48616 };
48617
48618 THREE.Path.prototype.bezierCurveTo = function( aCP1x, aCP1y,
48619                                                aCP2x, aCP2y,
48620                                                aX, aY ) {
48621
48622     var args = Array.prototype.slice.call( arguments );
48623
48624     var lastargs = this.actions[ this.actions.length - 1 ].args;
48625
48626     var x0 = lastargs[ lastargs.length - 2 ];
48627     var y0 = lastargs[ lastargs.length - 1 ];
48628
48629     var curve = new THREE.CubicBezierCurve( new THREE.Vector2( x0, y0 ),
48630                                             new THREE.Vector2( aCP1x, aCP1y ),
48631                                             new THREE.Vector2( aCP2x, aCP2y ),
48632                                             new THREE.Vector2( aX, aY ) );
48633     this.curves.push( curve );
48634
48635     this.actions.push( { action: THREE.PathActions.BEZIER_CURVE_TO, args: args } );
48636
48637 };
48638
48639 THREE.Path.prototype.splineThru = function( pts /*Array of Vector*/ ) {
48640
48641     var args = Array.prototype.slice.call( arguments );
48642     var lastargs = this.actions[ this.actions.length - 1 ].args;
48643
48644     var x0 = lastargs[ lastargs.length - 2 ];
48645     var y0 = lastargs[ lastargs.length - 1 ];
48646 //---
48647     var npts = [ new THREE.Vector2( x0, y0 ) ];
48648     Array.prototype.push.apply( npts, pts );
48649
48650     var curve = new THREE.SplineCurve( npts );
48651     this.curves.push( curve );
48652
48653     this.actions.push( { action: THREE.PathActions.CSPLINE_THRU, args: args } );
48654
48655 };
48656
48657 // FUTURE: Change the API or follow canvas API?
48658
48659 THREE.Path.prototype.arc = function ( aX, aY, aRadius,
48660                                       aStartAngle, aEndAngle, aClockwise ) {
48661
48662     var lastargs = this.actions[ this.actions.length - 1].args;
48663     var x0 = lastargs[ lastargs.length - 2 ];
48664     var y0 = lastargs[ lastargs.length - 1 ];
48665
48666     this.absarc(aX + x0, aY + y0, aRadius,
48667         aStartAngle, aEndAngle, aClockwise );
48668
48669  };
48670
48671  THREE.Path.prototype.absarc = function ( aX, aY, aRadius,
48672                                       aStartAngle, aEndAngle, aClockwise ) {
48673     this.absellipse(aX, aY, aRadius, aRadius, aStartAngle, aEndAngle, aClockwise);
48674  };
48675
48676 THREE.Path.prototype.ellipse = function ( aX, aY, xRadius, yRadius,
48677                                       aStartAngle, aEndAngle, aClockwise ) {
48678
48679     var lastargs = this.actions[ this.actions.length - 1].args;
48680     var x0 = lastargs[ lastargs.length - 2 ];
48681     var y0 = lastargs[ lastargs.length - 1 ];
48682
48683     this.absellipse(aX + x0, aY + y0, xRadius, yRadius,
48684         aStartAngle, aEndAngle, aClockwise );
48685
48686  };
48687
48688
48689 THREE.Path.prototype.absellipse = function ( aX, aY, xRadius, yRadius,
48690                                       aStartAngle, aEndAngle, aClockwise ) {
48691
48692     var args = Array.prototype.slice.call( arguments );
48693     var curve = new THREE.EllipseCurve( aX, aY, xRadius, yRadius,
48694                                     aStartAngle, aEndAngle, aClockwise );
48695     this.curves.push( curve );
48696
48697     var lastPoint = curve.getPoint(aClockwise ? 1 : 0);
48698     args.push(lastPoint.x);
48699     args.push(lastPoint.y);
48700
48701     this.actions.push( { action: THREE.PathActions.ELLIPSE, args: args } );
48702
48703  };
48704
48705 THREE.Path.prototype.getSpacedPoints = function ( divisions, closedPath ) {
48706
48707     if ( ! divisions ) divisions = 40;
48708
48709     var points = [];
48710
48711     for ( var i = 0; i < divisions; i ++ ) {
48712
48713         points.push( this.getPoint( i / divisions ) );
48714
48715         //if( !this.getPoint( i / divisions ) ) throw "DIE";
48716
48717     }
48718
48719     // if ( closedPath ) {
48720     //
48721     //     points.push( points[ 0 ] );
48722     //
48723     // }
48724
48725     return points;
48726
48727 };
48728
48729 /* Return an array of vectors based on contour of the path */
48730
48731 THREE.Path.prototype.getPoints = function( divisions, closedPath ) {
48732
48733     if (this.useSpacedPoints) {
48734         console.log('tata');
48735         return this.getSpacedPoints( divisions, closedPath );
48736     }
48737
48738     divisions = divisions || 12;
48739
48740     var points = [];
48741
48742     var i, il, item, action, args;
48743     var cpx, cpy, cpx2, cpy2, cpx1, cpy1, cpx0, cpy0,
48744         laste, j,
48745         t, tx, ty;
48746
48747     for ( i = 0, il = this.actions.length; i < il; i ++ ) {
48748
48749         item = this.actions[ i ];
48750
48751         action = item.action;
48752         args = item.args;
48753
48754         switch( action ) {
48755
48756         case THREE.PathActions.MOVE_TO:
48757
48758             points.push( new THREE.Vector2( args[ 0 ], args[ 1 ] ) );
48759
48760             break;
48761
48762         case THREE.PathActions.LINE_TO:
48763
48764             points.push( new THREE.Vector2( args[ 0 ], args[ 1 ] ) );
48765
48766             break;
48767
48768         case THREE.PathActions.QUADRATIC_CURVE_TO:
48769
48770             cpx  = args[ 2 ];
48771             cpy  = args[ 3 ];
48772
48773             cpx1 = args[ 0 ];
48774             cpy1 = args[ 1 ];
48775
48776             if ( points.length > 0 ) {
48777
48778                 laste = points[ points.length - 1 ];
48779
48780                 cpx0 = laste.x;
48781                 cpy0 = laste.y;
48782
48783             } else {
48784
48785                 laste = this.actions[ i - 1 ].args;
48786
48787                 cpx0 = laste[ laste.length - 2 ];
48788                 cpy0 = laste[ laste.length - 1 ];
48789
48790             }
48791
48792             for ( j = 1; j <= divisions; j ++ ) {
48793
48794                 t = j / divisions;
48795
48796                 tx = THREE.Shape.Utils.b2( t, cpx0, cpx1, cpx );
48797                 ty = THREE.Shape.Utils.b2( t, cpy0, cpy1, cpy );
48798
48799                 points.push( new THREE.Vector2( tx, ty ) );
48800
48801               }
48802
48803             break;
48804
48805         case THREE.PathActions.BEZIER_CURVE_TO:
48806
48807             cpx  = args[ 4 ];
48808             cpy  = args[ 5 ];
48809
48810             cpx1 = args[ 0 ];
48811             cpy1 = args[ 1 ];
48812
48813             cpx2 = args[ 2 ];
48814             cpy2 = args[ 3 ];
48815
48816             if ( points.length > 0 ) {
48817
48818                 laste = points[ points.length - 1 ];
48819
48820                 cpx0 = laste.x;
48821                 cpy0 = laste.y;
48822
48823             } else {
48824
48825                 laste = this.actions[ i - 1 ].args;
48826
48827                 cpx0 = laste[ laste.length - 2 ];
48828                 cpy0 = laste[ laste.length - 1 ];
48829
48830             }
48831
48832
48833             for ( j = 1; j <= divisions; j ++ ) {
48834
48835                 t = j / divisions;
48836
48837                 tx = THREE.Shape.Utils.b3( t, cpx0, cpx1, cpx2, cpx );
48838                 ty = THREE.Shape.Utils.b3( t, cpy0, cpy1, cpy2, cpy );
48839
48840                 points.push( new THREE.Vector2( tx, ty ) );
48841
48842             }
48843
48844             break;
48845
48846         case THREE.PathActions.CSPLINE_THRU:
48847
48848             laste = this.actions[ i - 1 ].args;
48849
48850             var last = new THREE.Vector2( laste[ laste.length - 2 ], laste[ laste.length - 1 ] );
48851             var spts = [ last ];
48852
48853             var n = divisions * args[ 0 ].length;
48854
48855             spts = spts.concat( args[ 0 ] );
48856
48857             var spline = new THREE.SplineCurve( spts );
48858
48859             for ( j = 1; j <= n; j ++ ) {
48860
48861                 points.push( spline.getPointAt( j / n ) ) ;
48862
48863             }
48864
48865             break;
48866
48867         case THREE.PathActions.ARC:
48868
48869             var aX = args[ 0 ], aY = args[ 1 ],
48870                 aRadius = args[ 2 ],
48871                 aStartAngle = args[ 3 ], aEndAngle = args[ 4 ],
48872                 aClockwise = !!args[ 5 ];
48873
48874             var deltaAngle = aEndAngle - aStartAngle;
48875             var angle;
48876             var tdivisions = divisions * 2;
48877
48878             for ( j = 1; j <= tdivisions; j ++ ) {
48879
48880                 t = j / tdivisions;
48881
48882                 if ( ! aClockwise ) {
48883
48884                     t = 1 - t;
48885
48886                 }
48887
48888                 angle = aStartAngle + t * deltaAngle;
48889
48890                 tx = aX + aRadius * Math.cos( angle );
48891                 ty = aY + aRadius * Math.sin( angle );
48892
48893                 //console.log('t', t, 'angle', angle, 'tx', tx, 'ty', ty);
48894
48895                 points.push( new THREE.Vector2( tx, ty ) );
48896
48897             }
48898
48899             //console.log(points);
48900
48901           break;
48902
48903         case THREE.PathActions.ELLIPSE:
48904
48905             var aX = args[ 0 ], aY = args[ 1 ],
48906                 xRadius = args[ 2 ],
48907                 yRadius = args[ 3 ],
48908                 aStartAngle = args[ 4 ], aEndAngle = args[ 5 ],
48909                 aClockwise = !!args[ 6 ];
48910
48911
48912             var deltaAngle = aEndAngle - aStartAngle;
48913             var angle;
48914             var tdivisions = divisions * 2;
48915
48916             for ( j = 1; j <= tdivisions; j ++ ) {
48917
48918                 t = j / tdivisions;
48919
48920                 if ( ! aClockwise ) {
48921
48922                     t = 1 - t;
48923
48924                 }
48925
48926                 angle = aStartAngle + t * deltaAngle;
48927
48928                 tx = aX + xRadius * Math.cos( angle );
48929                 ty = aY + yRadius * Math.sin( angle );
48930
48931                 //console.log('t', t, 'angle', angle, 'tx', tx, 'ty', ty);
48932
48933                 points.push( new THREE.Vector2( tx, ty ) );
48934
48935             }
48936
48937             //console.log(points);
48938
48939           break;
48940
48941         } // end switch
48942
48943     }
48944
48945
48946
48947     // Normalize to remove the closing point by default.
48948     var lastPoint = points[ points.length - 1];
48949     var EPSILON = 0.0000000001;
48950     if ( Math.abs(lastPoint.x - points[ 0 ].x) < EPSILON &&
48951              Math.abs(lastPoint.y - points[ 0 ].y) < EPSILON)
48952         points.splice( points.length - 1, 1);
48953     if ( closedPath ) {
48954
48955         points.push( points[ 0 ] );
48956
48957     }
48958
48959     return points;
48960
48961 };
48962
48963 // Breaks path into shapes
48964
48965 THREE.Path.prototype.toShapes = function() {
48966
48967     var i, il, item, action, args;
48968
48969     var subPaths = [], lastPath = new THREE.Path();
48970
48971     for ( i = 0, il = this.actions.length; i < il; i ++ ) {
48972
48973         item = this.actions[ i ];
48974
48975         args = item.args;
48976         action = item.action;
48977
48978         if ( action == THREE.PathActions.MOVE_TO ) {
48979
48980             if ( lastPath.actions.length != 0 ) {
48981
48982                 subPaths.push( lastPath );
48983                 lastPath = new THREE.Path();
48984
48985             }
48986
48987         }
48988
48989         lastPath[ action ].apply( lastPath, args );
48990
48991     }
48992
48993     if ( lastPath.actions.length != 0 ) {
48994
48995         subPaths.push( lastPath );
48996
48997     }
48998
48999     // console.log(subPaths);
49000
49001     if ( subPaths.length == 0 ) return [];
49002
49003     var tmpPath, tmpShape, shapes = [];
49004
49005     var holesFirst = !THREE.Shape.Utils.isClockWise( subPaths[ 0 ].getPoints() );
49006     // console.log("Holes first", holesFirst);
49007
49008     if ( subPaths.length == 1) {
49009         tmpPath = subPaths[0];
49010         tmpShape = new THREE.Shape();
49011         tmpShape.actions = tmpPath.actions;
49012         tmpShape.curves = tmpPath.curves;
49013         shapes.push( tmpShape );
49014         return shapes;
49015     };
49016
49017     if ( holesFirst ) {
49018
49019         tmpShape = new THREE.Shape();
49020
49021         for ( i = 0, il = subPaths.length; i < il; i ++ ) {
49022
49023             tmpPath = subPaths[ i ];
49024
49025             if ( THREE.Shape.Utils.isClockWise( tmpPath.getPoints() ) ) {
49026
49027                 tmpShape.actions = tmpPath.actions;
49028                 tmpShape.curves = tmpPath.curves;
49029
49030                 shapes.push( tmpShape );
49031                 tmpShape = new THREE.Shape();
49032
49033                 //console.log('cw', i);
49034
49035             } else {
49036
49037                 tmpShape.holes.push( tmpPath );
49038
49039                 //console.log('ccw', i);
49040
49041             }
49042
49043         }
49044
49045     } else {
49046
49047         // Shapes first
49048
49049         for ( i = 0, il = subPaths.length; i < il; i ++ ) {
49050
49051             tmpPath = subPaths[ i ];
49052
49053             if ( THREE.Shape.Utils.isClockWise( tmpPath.getPoints() ) ) {
49054
49055
49056                 if ( tmpShape ) shapes.push( tmpShape );
49057
49058                 tmpShape = new THREE.Shape();
49059                 tmpShape.actions = tmpPath.actions;
49060                 tmpShape.curves = tmpPath.curves;
49061
49062             } else {
49063
49064                 tmpShape.holes.push( tmpPath );
49065
49066             }
49067
49068         }
49069
49070         shapes.push( tmpShape );
49071
49072     }
49073
49074     //console.log("shape", shapes);
49075
49076     return shapes;
49077
49078 };
49079 /**
49080  * @author zz85 / http://www.lab4games.net/zz85/blog
49081  * Defines a 2d shape plane using paths.
49082  **/
49083
49084 // STEP 1 Create a path.
49085 // STEP 2 Turn path into shape.
49086 // STEP 3 ExtrudeGeometry takes in Shape/Shapes
49087 // STEP 3a - Extract points from each shape, turn to vertices
49088 // STEP 3b - Triangulate each shape, add faces.
49089
49090 THREE.Shape = function ( ) {
49091
49092     THREE.Path.apply( this, arguments );
49093     this.holes = [];
49094
49095 };
49096
49097 THREE.Shape.prototype = Object.create( THREE.Path.prototype );
49098
49099 // Convenience method to return ExtrudeGeometry
49100
49101 THREE.Shape.prototype.extrude = function ( options ) {
49102
49103     var extruded = new THREE.ExtrudeGeometry( this, options );
49104     return extruded;
49105
49106 };
49107
49108 // Convenience method to return ShapeGeometry
49109
49110 THREE.Shape.prototype.makeGeometry = function ( options ) {
49111
49112     var geometry = new THREE.ShapeGeometry( this, options );
49113     return geometry;
49114
49115 };
49116
49117 // Get points of holes
49118
49119 THREE.Shape.prototype.getPointsHoles = function ( divisions ) {
49120
49121     var i, il = this.holes.length, holesPts = [];
49122
49123     for ( i = 0; i < il; i ++ ) {
49124
49125         holesPts[ i ] = this.holes[ i ].getTransformedPoints( divisions, this.bends );
49126
49127     }
49128
49129     return holesPts;
49130
49131 };
49132
49133 // Get points of holes (spaced by regular distance)
49134
49135 THREE.Shape.prototype.getSpacedPointsHoles = function ( divisions ) {
49136
49137     var i, il = this.holes.length, holesPts = [];
49138
49139     for ( i = 0; i < il; i ++ ) {
49140
49141         holesPts[ i ] = this.holes[ i ].getTransformedSpacedPoints( divisions, this.bends );
49142
49143     }
49144
49145     return holesPts;
49146
49147 };
49148
49149
49150 // Get points of shape and holes (keypoints based on segments parameter)
49151
49152 THREE.Shape.prototype.extractAllPoints = function ( divisions ) {
49153
49154     return {
49155
49156         shape: this.getTransformedPoints( divisions ),
49157         holes: this.getPointsHoles( divisions )
49158
49159     };
49160
49161 };
49162
49163 THREE.Shape.prototype.extractPoints = function ( divisions ) {
49164
49165     if (this.useSpacedPoints) {
49166         return this.extractAllSpacedPoints(divisions);
49167     }
49168
49169     return this.extractAllPoints(divisions);
49170
49171 };
49172
49173 //
49174 // THREE.Shape.prototype.extractAllPointsWithBend = function ( divisions, bend ) {
49175 //
49176 //     return {
49177 //
49178 //         shape: this.transform( bend, divisions ),
49179 //         holes: this.getPointsHoles( divisions, bend )
49180 //
49181 //     };
49182 //
49183 // };
49184
49185 // Get points of shape and holes (spaced by regular distance)
49186
49187 THREE.Shape.prototype.extractAllSpacedPoints = function ( divisions ) {
49188
49189     return {
49190
49191         shape: this.getTransformedSpacedPoints( divisions ),
49192         holes: this.getSpacedPointsHoles( divisions )
49193
49194     };
49195
49196 };
49197
49198 /**************************************************************
49199  *    Utils
49200  **************************************************************/
49201
49202 THREE.Shape.Utils = {
49203
49204     /*
49205         contour - array of vector2 for contour
49206         holes   - array of array of vector2
49207     */
49208
49209     removeHoles: function ( contour, holes ) {
49210
49211         var shape = contour.concat(); // work on this shape
49212         var allpoints = shape.concat();
49213
49214         /* For each isolated shape, find the closest points and break to the hole to allow triangulation */
49215
49216
49217         var prevShapeVert, nextShapeVert,
49218             prevHoleVert, nextHoleVert,
49219             holeIndex, shapeIndex,
49220             shapeId, shapeGroup,
49221             h, h2,
49222             hole, shortest, d,
49223             p, pts1, pts2,
49224             tmpShape1, tmpShape2,
49225             tmpHole1, tmpHole2,
49226             verts = [];
49227
49228         for ( h = 0; h < holes.length; h ++ ) {
49229
49230             hole = holes[ h ];
49231
49232             /*
49233             shapeholes[ h ].concat(); // preserves original
49234             holes.push( hole );
49235             */
49236
49237             Array.prototype.push.apply( allpoints, hole );
49238
49239             shortest = Number.POSITIVE_INFINITY;
49240
49241
49242             // Find the shortest pair of pts between shape and hole
49243
49244             // Note: Actually, I'm not sure now if we could optimize this to be faster than O(m*n)
49245             // Using distanceToSquared() intead of distanceTo() should speed a little
49246             // since running square roots operations are reduced.
49247
49248             for ( h2 = 0; h2 < hole.length; h2 ++ ) {
49249
49250                 pts1 = hole[ h2 ];
49251                 var dist = [];
49252
49253                 for ( p = 0; p < shape.length; p++ ) {
49254
49255                     pts2 = shape[ p ];
49256                     d = pts1.distanceToSquared( pts2 );
49257                     dist.push( d );
49258
49259                     if ( d < shortest ) {
49260
49261                         shortest = d;
49262                         holeIndex = h2;
49263                         shapeIndex = p;
49264
49265                     }
49266
49267                 }
49268
49269             }
49270
49271             //console.log("shortest", shortest, dist);
49272
49273             prevShapeVert = ( shapeIndex - 1 ) >= 0 ? shapeIndex - 1 : shape.length - 1;
49274             prevHoleVert = ( holeIndex - 1 ) >= 0 ? holeIndex - 1 : hole.length - 1;
49275
49276             var areaapts = [
49277
49278                 hole[ holeIndex ],
49279                 shape[ shapeIndex ],
49280                 shape[ prevShapeVert ]
49281
49282             ];
49283
49284             var areaa = THREE.FontUtils.Triangulate.area( areaapts );
49285
49286             var areabpts = [
49287
49288                 hole[ holeIndex ],
49289                 hole[ prevHoleVert ],
49290                 shape[ shapeIndex ]
49291
49292             ];
49293
49294             var areab = THREE.FontUtils.Triangulate.area( areabpts );
49295
49296             var shapeOffset = 1;
49297             var holeOffset = -1;
49298
49299             var oldShapeIndex = shapeIndex, oldHoleIndex = holeIndex;
49300             shapeIndex += shapeOffset;
49301             holeIndex += holeOffset;
49302
49303             if ( shapeIndex < 0 ) { shapeIndex += shape.length;  }
49304             shapeIndex %= shape.length;
49305
49306             if ( holeIndex < 0 ) { holeIndex += hole.length;  }
49307             holeIndex %= hole.length;
49308
49309             prevShapeVert = ( shapeIndex - 1 ) >= 0 ? shapeIndex - 1 : shape.length - 1;
49310             prevHoleVert = ( holeIndex - 1 ) >= 0 ? holeIndex - 1 : hole.length - 1;
49311
49312             areaapts = [
49313
49314                 hole[ holeIndex ],
49315                 shape[ shapeIndex ],
49316                 shape[ prevShapeVert ]
49317
49318             ];
49319
49320             var areaa2 = THREE.FontUtils.Triangulate.area( areaapts );
49321
49322             areabpts = [
49323
49324                 hole[ holeIndex ],
49325                 hole[ prevHoleVert ],
49326                 shape[ shapeIndex ]
49327
49328             ];
49329
49330             var areab2 = THREE.FontUtils.Triangulate.area( areabpts );
49331             //console.log(areaa,areab ,areaa2,areab2, ( areaa + areab ),  ( areaa2 + areab2 ));
49332
49333             if ( ( areaa + areab ) > ( areaa2 + areab2 ) ) {
49334
49335                 // In case areas are not correct.
49336                 //console.log("USE THIS");
49337
49338                 shapeIndex = oldShapeIndex;
49339                 holeIndex = oldHoleIndex ;
49340
49341                 if ( shapeIndex < 0 ) { shapeIndex += shape.length;  }
49342                 shapeIndex %= shape.length;
49343
49344                 if ( holeIndex < 0 ) { holeIndex += hole.length;  }
49345                 holeIndex %= hole.length;
49346
49347                 prevShapeVert = ( shapeIndex - 1 ) >= 0 ? shapeIndex - 1 : shape.length - 1;
49348                 prevHoleVert = ( holeIndex - 1 ) >= 0 ? holeIndex - 1 : hole.length - 1;
49349
49350             } else {
49351
49352                 //console.log("USE THAT ")
49353
49354             }
49355
49356             tmpShape1 = shape.slice( 0, shapeIndex );
49357             tmpShape2 = shape.slice( shapeIndex );
49358             tmpHole1 = hole.slice( holeIndex );
49359             tmpHole2 = hole.slice( 0, holeIndex );
49360
49361             // Should check orders here again?
49362
49363             var trianglea = [
49364
49365                 hole[ holeIndex ],
49366                 shape[ shapeIndex ],
49367                 shape[ prevShapeVert ]
49368
49369             ];
49370
49371             var triangleb = [
49372
49373                 hole[ holeIndex ] ,
49374                 hole[ prevHoleVert ],
49375                 shape[ shapeIndex ]
49376
49377             ];
49378
49379             verts.push( trianglea );
49380             verts.push( triangleb );
49381
49382             shape = tmpShape1.concat( tmpHole1 ).concat( tmpHole2 ).concat( tmpShape2 );
49383
49384         }
49385
49386         return {
49387
49388             shape:shape,         /* shape with no holes */
49389             isolatedPts: verts, /* isolated faces */
49390             allpoints: allpoints
49391
49392         }
49393
49394
49395     },
49396
49397     triangulateShape: function ( contour, holes ) {
49398
49399         var shapeWithoutHoles = THREE.Shape.Utils.removeHoles( contour, holes );
49400
49401         var shape = shapeWithoutHoles.shape,
49402             allpoints = shapeWithoutHoles.allpoints,
49403             isolatedPts = shapeWithoutHoles.isolatedPts;
49404
49405         var triangles = THREE.FontUtils.Triangulate( shape, false ); // True returns indices for points of spooled shape
49406
49407         // To maintain reference to old shape, one must match coordinates, or offset the indices from original arrays. It's probably easier to do the first.
49408
49409         //console.log( "triangles",triangles, triangles.length );
49410         //console.log( "allpoints",allpoints, allpoints.length );
49411
49412         var i, il, f, face,
49413             key, index,
49414             allPointsMap = {},
49415             isolatedPointsMap = {};
49416
49417         // prepare all points map
49418
49419         for ( i = 0, il = allpoints.length; i < il; i ++ ) {
49420
49421             key = allpoints[ i ].x + ":" + allpoints[ i ].y;
49422
49423             if ( allPointsMap[ key ] !== undefined ) {
49424
49425                 console.log( "Duplicate point", key );
49426
49427             }
49428
49429             allPointsMap[ key ] = i;
49430
49431         }
49432
49433         // check all face vertices against all points map
49434
49435         for ( i = 0, il = triangles.length; i < il; i ++ ) {
49436
49437             face = triangles[ i ];
49438
49439             for ( f = 0; f < 3; f ++ ) {
49440
49441                 key = face[ f ].x + ":" + face[ f ].y;
49442
49443                 index = allPointsMap[ key ];
49444
49445                 if ( index !== undefined ) {
49446
49447                     face[ f ] = index;
49448
49449                 }
49450
49451             }
49452
49453         }
49454
49455         // check isolated points vertices against all points map
49456
49457         for ( i = 0, il = isolatedPts.length; i < il; i ++ ) {
49458
49459             face = isolatedPts[ i ];
49460
49461             for ( f = 0; f < 3; f ++ ) {
49462
49463                 key = face[ f ].x + ":" + face[ f ].y;
49464
49465                 index = allPointsMap[ key ];
49466
49467                 if ( index !== undefined ) {
49468
49469                     face[ f ] = index;
49470
49471                 }
49472
49473             }
49474
49475         }
49476
49477         return triangles.concat( isolatedPts );
49478
49479     }, // end triangulate shapes
49480
49481     /*
49482     triangulate2 : function( pts, holes ) {
49483
49484         // For use with Poly2Tri.js
49485
49486         var allpts = pts.concat();
49487         var shape = [];
49488         for (var p in pts) {
49489             shape.push(new js.poly2tri.Point(pts[p].x, pts[p].y));
49490         }
49491
49492         var swctx = new js.poly2tri.SweepContext(shape);
49493
49494         for (var h in holes) {
49495             var aHole = holes[h];
49496             var newHole = []
49497             for (i in aHole) {
49498                 newHole.push(new js.poly2tri.Point(aHole[i].x, aHole[i].y));
49499                 allpts.push(aHole[i]);
49500             }
49501             swctx.AddHole(newHole);
49502         }
49503
49504         var find;
49505         var findIndexForPt = function (pt) {
49506             find = new THREE.Vector2(pt.x, pt.y);
49507             var p;
49508             for (p=0, pl = allpts.length; p<pl; p++) {
49509                 if (allpts[p].equals(find)) return p;
49510             }
49511             return -1;
49512         };
49513
49514         // triangulate
49515         js.poly2tri.sweep.Triangulate(swctx);
49516
49517         var triangles =  swctx.GetTriangles();
49518         var tr ;
49519         var facesPts = [];
49520         for (var t in triangles) {
49521             tr =  triangles[t];
49522             facesPts.push([
49523                 findIndexForPt(tr.GetPoint(0)),
49524                 findIndexForPt(tr.GetPoint(1)),
49525                 findIndexForPt(tr.GetPoint(2))
49526                     ]);
49527         }
49528
49529
49530     //    console.log(facesPts);
49531     //    console.log("triangles", triangles.length, triangles);
49532
49533         // Returns array of faces with 3 element each
49534     return facesPts;
49535     },
49536 */
49537
49538     isClockWise: function ( pts ) {
49539
49540         return THREE.FontUtils.Triangulate.area( pts ) < 0;
49541
49542     },
49543
49544     // Bezier Curves formulas obtained from
49545     // http://en.wikipedia.org/wiki/B%C3%A9zier_curve
49546
49547     // Quad Bezier Functions
49548
49549     b2p0: function ( t, p ) {
49550
49551         var k = 1 - t;
49552         return k * k * p;
49553
49554     },
49555
49556     b2p1: function ( t, p ) {
49557
49558         return 2 * ( 1 - t ) * t * p;
49559
49560     },
49561
49562     b2p2: function ( t, p ) {
49563
49564         return t * t * p;
49565
49566     },
49567
49568     b2: function ( t, p0, p1, p2 ) {
49569
49570         return this.b2p0( t, p0 ) + this.b2p1( t, p1 ) + this.b2p2( t, p2 );
49571
49572     },
49573
49574     // Cubic Bezier Functions
49575
49576     b3p0: function ( t, p ) {
49577
49578         var k = 1 - t;
49579         return k * k * k * p;
49580
49581     },
49582
49583     b3p1: function ( t, p ) {
49584
49585         var k = 1 - t;
49586         return 3 * k * k * t * p;
49587
49588     },
49589
49590     b3p2: function ( t, p ) {
49591
49592         var k = 1 - t;
49593         return 3 * k * t * t * p;
49594
49595     },
49596
49597     b3p3: function ( t, p ) {
49598
49599         return t * t * t * p;
49600
49601     },
49602
49603     b3: function ( t, p0, p1, p2, p3 ) {
49604
49605         return this.b3p0( t, p0 ) + this.b3p1( t, p1 ) + this.b3p2( t, p2 ) +  this.b3p3( t, p3 );
49606
49607     }
49608
49609 };
49610
49611 /**
49612  * @author mikael emtinger / http://gomo.se/
49613  */
49614
49615 THREE.AnimationHandler = (function() {
49616
49617     var playing = [];
49618     var library = {};
49619     var that    = {};
49620
49621
49622     //--- update ---
49623
49624     that.update = function( deltaTimeMS ) {
49625
49626         for( var i = 0; i < playing.length; i ++ )
49627             playing[ i ].update( deltaTimeMS );
49628
49629     };
49630
49631
49632     //--- add ---
49633
49634     that.addToUpdate = function( animation ) {
49635
49636         if ( playing.indexOf( animation ) === -1 )
49637             playing.push( animation );
49638
49639     };
49640
49641
49642     //--- remove ---
49643
49644     that.removeFromUpdate = function( animation ) {
49645
49646         var index = playing.indexOf( animation );
49647
49648         if( index !== -1 )
49649             playing.splice( index, 1 );
49650
49651     };
49652
49653
49654     //--- add ---
49655
49656     that.add = function( data ) {
49657
49658         if ( library[ data.name ] !== undefined )
49659             console.log( "THREE.AnimationHandler.add: Warning! " + data.name + " already exists in library. Overwriting." );
49660
49661         library[ data.name ] = data;
49662         initData( data );
49663
49664     };
49665
49666
49667     //--- get ---
49668
49669     that.get = function( name ) {
49670
49671         if ( typeof name === "string" ) {
49672
49673             if ( library[ name ] ) {
49674
49675                 return library[ name ];
49676
49677             } else {
49678
49679                 console.log( "THREE.AnimationHandler.get: Couldn't find animation " + name );
49680                 return null;
49681
49682             }
49683
49684         } else {
49685
49686             // todo: add simple tween library
49687
49688         }
49689
49690     };
49691
49692     //--- parse ---
49693
49694     that.parse = function( root ) {
49695
49696         // setup hierarchy
49697
49698         var hierarchy = [];
49699
49700         if ( root instanceof THREE.SkinnedMesh ) {
49701
49702             for( var b = 0; b < root.bones.length; b++ ) {
49703
49704                 hierarchy.push( root.bones[ b ] );
49705
49706             }
49707
49708         } else {
49709
49710             parseRecurseHierarchy( root, hierarchy );
49711
49712         }
49713
49714         return hierarchy;
49715
49716     };
49717
49718     var parseRecurseHierarchy = function( root, hierarchy ) {
49719
49720         hierarchy.push( root );
49721
49722         for( var c = 0; c < root.children.length; c++ )
49723             parseRecurseHierarchy( root.children[ c ], hierarchy );
49724
49725     }
49726
49727
49728     //--- init data ---
49729
49730     var initData = function( data ) {
49731
49732         if( data.initialized === true )
49733             return;
49734
49735
49736         // loop through all keys
49737
49738         for( var h = 0; h < data.hierarchy.length; h ++ ) {
49739
49740             for( var k = 0; k < data.hierarchy[ h ].keys.length; k ++ ) {
49741
49742                 // remove minus times
49743
49744                 if( data.hierarchy[ h ].keys[ k ].time < 0 )
49745                     data.hierarchy[ h ].keys[ k ].time = 0;
49746
49747
49748                 // create quaternions
49749
49750                 if( data.hierarchy[ h ].keys[ k ].rot !== undefined &&
49751                  !( data.hierarchy[ h ].keys[ k ].rot instanceof THREE.Quaternion ) ) {
49752
49753                     var quat = data.hierarchy[ h ].keys[ k ].rot;
49754                     data.hierarchy[ h ].keys[ k ].rot = new THREE.Quaternion( quat[0], quat[1], quat[2], quat[3] );
49755
49756                 }
49757
49758             }
49759
49760
49761             // prepare morph target keys
49762
49763             if( data.hierarchy[ h ].keys.length && data.hierarchy[ h ].keys[ 0 ].morphTargets !== undefined ) {
49764
49765                 // get all used
49766
49767                 var usedMorphTargets = {};
49768
49769                 for ( var k = 0; k < data.hierarchy[ h ].keys.length; k ++ ) {
49770
49771                     for ( var m = 0; m < data.hierarchy[ h ].keys[ k ].morphTargets.length; m ++ ) {
49772
49773                         var morphTargetName = data.hierarchy[ h ].keys[ k ].morphTargets[ m ];
49774                         usedMorphTargets[ morphTargetName ] = -1;
49775
49776                     }
49777
49778                 }
49779
49780                 data.hierarchy[ h ].usedMorphTargets = usedMorphTargets;
49781
49782
49783                 // set all used on all frames
49784
49785                 for ( var k = 0; k < data.hierarchy[ h ].keys.length; k ++ ) {
49786
49787                     var influences = {};
49788
49789                     for ( var morphTargetName in usedMorphTargets ) {
49790
49791                         for ( var m = 0; m < data.hierarchy[ h ].keys[ k ].morphTargets.length; m ++ ) {
49792
49793                             if ( data.hierarchy[ h ].keys[ k ].morphTargets[ m ] === morphTargetName ) {
49794
49795                                 influences[ morphTargetName ] = data.hierarchy[ h ].keys[ k ].morphTargetsInfluences[ m ];
49796                                 break;
49797
49798                             }
49799
49800                         }
49801
49802                         if ( m === data.hierarchy[ h ].keys[ k ].morphTargets.length ) {
49803
49804                             influences[ morphTargetName ] = 0;
49805
49806                         }
49807
49808                     }
49809
49810                     data.hierarchy[ h ].keys[ k ].morphTargetsInfluences = influences;
49811
49812                 }
49813
49814             }
49815
49816
49817             // remove all keys that are on the same time
49818
49819             for ( var k = 1; k < data.hierarchy[ h ].keys.length; k ++ ) {
49820
49821                 if ( data.hierarchy[ h ].keys[ k ].time === data.hierarchy[ h ].keys[ k - 1 ].time ) {
49822
49823                     data.hierarchy[ h ].keys.splice( k, 1 );
49824                     k --;
49825
49826                 }
49827
49828             }
49829
49830
49831             // set index
49832
49833             for ( var k = 0; k < data.hierarchy[ h ].keys.length; k ++ ) {
49834
49835                 data.hierarchy[ h ].keys[ k ].index = k;
49836
49837             }
49838
49839         }
49840
49841
49842         // JIT
49843
49844         var lengthInFrames = parseInt( data.length * data.fps, 10 );
49845
49846         data.JIT = {};
49847         data.JIT.hierarchy = [];
49848
49849         for( var h = 0; h < data.hierarchy.length; h ++ )
49850             data.JIT.hierarchy.push( new Array( lengthInFrames ) );
49851
49852
49853         // done
49854
49855         data.initialized = true;
49856
49857     };
49858
49859
49860     // interpolation types
49861
49862     that.LINEAR = 0;
49863     that.CATMULLROM = 1;
49864     that.CATMULLROM_FORWARD = 2;
49865
49866     return that;
49867
49868 }());
49869 /**
49870  * @author mikael emtinger / http://gomo.se/
49871  * @author mrdoob / http://mrdoob.com/
49872  * @author alteredq / http://alteredqualia.com/
49873  */
49874
49875 THREE.Animation = function ( root, name, interpolationType ) {
49876
49877     this.root = root;
49878     this.data = THREE.AnimationHandler.get( name );
49879     this.hierarchy = THREE.AnimationHandler.parse( root );
49880
49881     this.currentTime = 0;
49882     this.timeScale = 1;
49883
49884     this.isPlaying = false;
49885     this.isPaused = true;
49886     this.loop = true;
49887
49888     this.interpolationType = interpolationType !== undefined ? interpolationType : THREE.AnimationHandler.LINEAR;
49889
49890     this.points = [];
49891     this.target = new THREE.Vector3();
49892
49893 };
49894
49895 THREE.Animation.prototype.play = function ( loop, startTimeMS ) {
49896
49897     if ( this.isPlaying === false ) {
49898
49899         this.isPlaying = true;
49900         this.loop = loop !== undefined ? loop : true;
49901         this.currentTime = startTimeMS !== undefined ? startTimeMS : 0;
49902
49903         // reset key cache
49904
49905         var h, hl = this.hierarchy.length,
49906             object;
49907
49908         for ( h = 0; h < hl; h ++ ) {
49909
49910             object = this.hierarchy[ h ];
49911
49912             if ( this.interpolationType !== THREE.AnimationHandler.CATMULLROM_FORWARD ) {
49913
49914                 object.useQuaternion = true;
49915
49916             }
49917
49918             object.matrixAutoUpdate = true;
49919
49920             if ( object.animationCache === undefined ) {
49921
49922                 object.animationCache = {};
49923                 object.animationCache.prevKey = { pos: 0, rot: 0, scl: 0 };
49924                 object.animationCache.nextKey = { pos: 0, rot: 0, scl: 0 };
49925                 object.animationCache.originalMatrix = object instanceof THREE.Bone ? object.skinMatrix : object.matrix;
49926
49927             }
49928
49929             var prevKey = object.animationCache.prevKey;
49930             var nextKey = object.animationCache.nextKey;
49931
49932             prevKey.pos = this.data.hierarchy[ h ].keys[ 0 ];
49933             prevKey.rot = this.data.hierarchy[ h ].keys[ 0 ];
49934             prevKey.scl = this.data.hierarchy[ h ].keys[ 0 ];
49935
49936             nextKey.pos = this.getNextKeyWith( "pos", h, 1 );
49937             nextKey.rot = this.getNextKeyWith( "rot", h, 1 );
49938             nextKey.scl = this.getNextKeyWith( "scl", h, 1 );
49939
49940         }
49941
49942         this.update( 0 );
49943
49944     }
49945
49946     this.isPaused = false;
49947
49948     THREE.AnimationHandler.addToUpdate( this );
49949
49950 };
49951
49952
49953 THREE.Animation.prototype.pause = function() {
49954
49955     if ( this.isPaused === true ) {
49956
49957         THREE.AnimationHandler.addToUpdate( this );
49958
49959     } else {
49960
49961         THREE.AnimationHandler.removeFromUpdate( this );
49962
49963     }
49964
49965     this.isPaused = !this.isPaused;
49966
49967 };
49968
49969
49970 THREE.Animation.prototype.stop = function() {
49971
49972     this.isPlaying = false;
49973     this.isPaused  = false;
49974     THREE.AnimationHandler.removeFromUpdate( this );
49975
49976 };
49977
49978
49979 THREE.Animation.prototype.update = function ( deltaTimeMS ) {
49980
49981     // early out
49982
49983     if ( this.isPlaying === false ) return;
49984
49985
49986     // vars
49987
49988     var types = [ "pos", "rot", "scl" ];
49989     var type;
49990     var scale;
49991     var vector;
49992     var prevXYZ, nextXYZ;
49993     var prevKey, nextKey;
49994     var object;
49995     var animationCache;
49996     var frame;
49997     var JIThierarchy = this.data.JIT.hierarchy;
49998     var currentTime, unloopedCurrentTime;
49999     var currentPoint, forwardPoint, angle;
50000
50001
50002     this.currentTime += deltaTimeMS * this.timeScale;
50003
50004     unloopedCurrentTime = this.currentTime;
50005     currentTime = this.currentTime = this.currentTime % this.data.length;
50006     frame = parseInt( Math.min( currentTime * this.data.fps, this.data.length * this.data.fps ), 10 );
50007
50008
50009     for ( var h = 0, hl = this.hierarchy.length; h < hl; h ++ ) {
50010
50011         object = this.hierarchy[ h ];
50012         animationCache = object.animationCache;
50013
50014         // loop through pos/rot/scl
50015
50016         for ( var t = 0; t < 3; t ++ ) {
50017
50018             // get keys
50019
50020             type    = types[ t ];
50021             prevKey = animationCache.prevKey[ type ];
50022             nextKey = animationCache.nextKey[ type ];
50023
50024             // switch keys?
50025
50026             if ( nextKey.time <= unloopedCurrentTime ) {
50027
50028                 // did we loop?
50029
50030                 if ( currentTime < unloopedCurrentTime ) {
50031
50032                     if ( this.loop ) {
50033
50034                         prevKey = this.data.hierarchy[ h ].keys[ 0 ];
50035                         nextKey = this.getNextKeyWith( type, h, 1 );
50036
50037                         while( nextKey.time < currentTime ) {
50038
50039                             prevKey = nextKey;
50040                             nextKey = this.getNextKeyWith( type, h, nextKey.index + 1 );
50041
50042                         }
50043
50044                     } else {
50045
50046                         this.stop();
50047                         return;
50048
50049                     }
50050
50051                 } else {
50052
50053                     do {
50054
50055                         prevKey = nextKey;
50056                         nextKey = this.getNextKeyWith( type, h, nextKey.index + 1 );
50057
50058                     } while( nextKey.time < currentTime )
50059
50060                 }
50061
50062                 animationCache.prevKey[ type ] = prevKey;
50063                 animationCache.nextKey[ type ] = nextKey;
50064
50065             }
50066
50067
50068             object.matrixAutoUpdate = true;
50069             object.matrixWorldNeedsUpdate = true;
50070
50071             scale = ( currentTime - prevKey.time ) / ( nextKey.time - prevKey.time );
50072             prevXYZ = prevKey[ type ];
50073             nextXYZ = nextKey[ type ];
50074
50075
50076             // check scale error
50077
50078             if ( scale < 0 || scale > 1 ) {
50079
50080                 console.log( "THREE.Animation.update: Warning! Scale out of bounds:" + scale + " on bone " + h );
50081                 scale = scale < 0 ? 0 : 1;
50082
50083             }
50084
50085             // interpolate
50086
50087             if ( type === "pos" ) {
50088
50089                 vector = object.position;
50090
50091                 if ( this.interpolationType === THREE.AnimationHandler.LINEAR ) {
50092
50093                     vector.x = prevXYZ[ 0 ] + ( nextXYZ[ 0 ] - prevXYZ[ 0 ] ) * scale;
50094                     vector.y = prevXYZ[ 1 ] + ( nextXYZ[ 1 ] - prevXYZ[ 1 ] ) * scale;
50095                     vector.z = prevXYZ[ 2 ] + ( nextXYZ[ 2 ] - prevXYZ[ 2 ] ) * scale;
50096
50097                 } else if ( this.interpolationType === THREE.AnimationHandler.CATMULLROM ||
50098                             this.interpolationType === THREE.AnimationHandler.CATMULLROM_FORWARD ) {
50099
50100                     this.points[ 0 ] = this.getPrevKeyWith( "pos", h, prevKey.index - 1 )[ "pos" ];
50101                     this.points[ 1 ] = prevXYZ;
50102                     this.points[ 2 ] = nextXYZ;
50103                     this.points[ 3 ] = this.getNextKeyWith( "pos", h, nextKey.index + 1 )[ "pos" ];
50104
50105                     scale = scale * 0.33 + 0.33;
50106
50107                     currentPoint = this.interpolateCatmullRom( this.points, scale );
50108
50109                     vector.x = currentPoint[ 0 ];
50110                     vector.y = currentPoint[ 1 ];
50111                     vector.z = currentPoint[ 2 ];
50112
50113                     if ( this.interpolationType === THREE.AnimationHandler.CATMULLROM_FORWARD ) {
50114
50115                         forwardPoint = this.interpolateCatmullRom( this.points, scale * 1.01 );
50116
50117                         this.target.set( forwardPoint[ 0 ], forwardPoint[ 1 ], forwardPoint[ 2 ] );
50118                         this.target.subSelf( vector );
50119                         this.target.y = 0;
50120                         this.target.normalize();
50121
50122                         angle = Math.atan2( this.target.x, this.target.z );
50123                         object.rotation.set( 0, angle, 0 );
50124
50125                     }
50126
50127                 }
50128
50129             } else if ( type === "rot" ) {
50130
50131                 THREE.Quaternion.slerp( prevXYZ, nextXYZ, object.quaternion, scale );
50132
50133             } else if ( type === "scl" ) {
50134
50135                 vector = object.scale;
50136
50137                 vector.x = prevXYZ[ 0 ] + ( nextXYZ[ 0 ] - prevXYZ[ 0 ] ) * scale;
50138                 vector.y = prevXYZ[ 1 ] + ( nextXYZ[ 1 ] - prevXYZ[ 1 ] ) * scale;
50139                 vector.z = prevXYZ[ 2 ] + ( nextXYZ[ 2 ] - prevXYZ[ 2 ] ) * scale;
50140
50141             }
50142
50143         }
50144
50145     }
50146
50147 };
50148
50149 // Catmull-Rom spline
50150
50151 THREE.Animation.prototype.interpolateCatmullRom = function ( points, scale ) {
50152
50153     var c = [], v3 = [],
50154     point, intPoint, weight, w2, w3,
50155     pa, pb, pc, pd;
50156
50157     point = ( points.length - 1 ) * scale;
50158     intPoint = Math.floor( point );
50159     weight = point - intPoint;
50160
50161     c[ 0 ] = intPoint === 0 ? intPoint : intPoint - 1;
50162     c[ 1 ] = intPoint;
50163     c[ 2 ] = intPoint > points.length - 2 ? intPoint : intPoint + 1;
50164     c[ 3 ] = intPoint > points.length - 3 ? intPoint : intPoint + 2;
50165
50166     pa = points[ c[ 0 ] ];
50167     pb = points[ c[ 1 ] ];
50168     pc = points[ c[ 2 ] ];
50169     pd = points[ c[ 3 ] ];
50170
50171     w2 = weight * weight;
50172     w3 = weight * w2;
50173
50174     v3[ 0 ] = this.interpolate( pa[ 0 ], pb[ 0 ], pc[ 0 ], pd[ 0 ], weight, w2, w3 );
50175     v3[ 1 ] = this.interpolate( pa[ 1 ], pb[ 1 ], pc[ 1 ], pd[ 1 ], weight, w2, w3 );
50176     v3[ 2 ] = this.interpolate( pa[ 2 ], pb[ 2 ], pc[ 2 ], pd[ 2 ], weight, w2, w3 );
50177
50178     return v3;
50179
50180 };
50181
50182 THREE.Animation.prototype.interpolate = function ( p0, p1, p2, p3, t, t2, t3 ) {
50183
50184     var v0 = ( p2 - p0 ) * 0.5,
50185         v1 = ( p3 - p1 ) * 0.5;
50186
50187     return ( 2 * ( p1 - p2 ) + v0 + v1 ) * t3 + ( - 3 * ( p1 - p2 ) - 2 * v0 - v1 ) * t2 + v0 * t + p1;
50188
50189 };
50190
50191
50192
50193 // Get next key with
50194
50195 THREE.Animation.prototype.getNextKeyWith = function ( type, h, key ) {
50196
50197     var keys = this.data.hierarchy[ h ].keys;
50198
50199     if ( this.interpolationType === THREE.AnimationHandler.CATMULLROM ||
50200          this.interpolationType === THREE.AnimationHandler.CATMULLROM_FORWARD ) {
50201
50202         key = key < keys.length - 1 ? key : keys.length - 1;
50203
50204     } else {
50205
50206         key = key % keys.length;
50207
50208     }
50209
50210     for ( ; key < keys.length; key++ ) {
50211
50212         if ( keys[ key ][ type ] !== undefined ) {
50213
50214             return keys[ key ];
50215
50216         }
50217
50218     }
50219
50220     return this.data.hierarchy[ h ].keys[ 0 ];
50221
50222 };
50223
50224 // Get previous key with
50225
50226 THREE.Animation.prototype.getPrevKeyWith = function ( type, h, key ) {
50227
50228     var keys = this.data.hierarchy[ h ].keys;
50229
50230     if ( this.interpolationType === THREE.AnimationHandler.CATMULLROM ||
50231          this.interpolationType === THREE.AnimationHandler.CATMULLROM_FORWARD ) {
50232
50233         key = key > 0 ? key : 0;
50234
50235     } else {
50236
50237         key = key >= 0 ? key : key + keys.length;
50238
50239     }
50240
50241
50242     for ( ; key >= 0; key -- ) {
50243
50244         if ( keys[ key ][ type ] !== undefined ) {
50245
50246             return keys[ key ];
50247
50248         }
50249
50250     }
50251
50252     return this.data.hierarchy[ h ].keys[ keys.length - 1 ];
50253
50254 };
50255 /**
50256  * @author mikael emtinger / http://gomo.se/
50257  * @author mrdoob / http://mrdoob.com/
50258  * @author alteredq / http://alteredqualia.com/
50259  * @author khang duong
50260  * @author erik kitson
50261  */
50262
50263 THREE.KeyFrameAnimation = function( root, data, JITCompile ) {
50264
50265     this.root = root;
50266     this.data = THREE.AnimationHandler.get( data );
50267     this.hierarchy = THREE.AnimationHandler.parse( root );
50268     this.currentTime = 0;
50269     this.timeScale = 0.001;
50270     this.isPlaying = false;
50271     this.isPaused = true;
50272     this.loop = true;
50273     this.JITCompile = JITCompile !== undefined ? JITCompile : true;
50274
50275     // initialize to first keyframes
50276
50277     for ( var h = 0, hl = this.hierarchy.length; h < hl; h++ ) {
50278
50279         var keys = this.data.hierarchy[h].keys,
50280             sids = this.data.hierarchy[h].sids,
50281             obj = this.hierarchy[h];
50282
50283         if ( keys.length && sids ) {
50284
50285             for ( var s = 0; s < sids.length; s++ ) {
50286
50287                 var sid = sids[ s ],
50288                     next = this.getNextKeyWith( sid, h, 0 );
50289
50290                 if ( next ) {
50291
50292                     next.apply( sid );
50293
50294                 }
50295
50296             }
50297
50298             obj.matrixAutoUpdate = false;
50299             this.data.hierarchy[h].node.updateMatrix();
50300             obj.matrixWorldNeedsUpdate = true;
50301
50302         }
50303
50304     }
50305
50306 };
50307
50308 // Play
50309
50310 THREE.KeyFrameAnimation.prototype.play = function( loop, startTimeMS ) {
50311
50312     if( !this.isPlaying ) {
50313
50314         this.isPlaying = true;
50315         this.loop = loop !== undefined ? loop : true;
50316         this.currentTime = startTimeMS !== undefined ? startTimeMS : 0;
50317         this.startTimeMs = startTimeMS;
50318         this.startTime = 10000000;
50319         this.endTime = -this.startTime;
50320
50321
50322         // reset key cache
50323
50324         var h, hl = this.hierarchy.length,
50325             object,
50326             node;
50327
50328         for ( h = 0; h < hl; h++ ) {
50329
50330             object = this.hierarchy[ h ];
50331             node = this.data.hierarchy[ h ];
50332             object.useQuaternion = true;
50333
50334             if ( node.animationCache === undefined ) {
50335
50336                 node.animationCache = {};
50337                 node.animationCache.prevKey = null;
50338                 node.animationCache.nextKey = null;
50339                 node.animationCache.originalMatrix = object instanceof THREE.Bone ? object.skinMatrix : object.matrix;
50340
50341             }
50342
50343             var keys = this.data.hierarchy[h].keys;
50344
50345             if (keys.length) {
50346
50347                 node.animationCache.prevKey = keys[ 0 ];
50348                 node.animationCache.nextKey = keys[ 1 ];
50349
50350                 this.startTime = Math.min( keys[0].time, this.startTime );
50351                 this.endTime = Math.max( keys[keys.length - 1].time, this.endTime );
50352
50353             }
50354
50355         }
50356
50357         this.update( 0 );
50358
50359     }
50360
50361     this.isPaused = false;
50362
50363     THREE.AnimationHandler.addToUpdate( this );
50364
50365 };
50366
50367
50368
50369 // Pause
50370
50371 THREE.KeyFrameAnimation.prototype.pause = function() {
50372
50373     if( this.isPaused ) {
50374
50375         THREE.AnimationHandler.addToUpdate( this );
50376
50377     } else {
50378
50379         THREE.AnimationHandler.removeFromUpdate( this );
50380
50381     }
50382
50383     this.isPaused = !this.isPaused;
50384
50385 };
50386
50387
50388 // Stop
50389
50390 THREE.KeyFrameAnimation.prototype.stop = function() {
50391
50392     this.isPlaying = false;
50393     this.isPaused  = false;
50394     THREE.AnimationHandler.removeFromUpdate( this );
50395
50396
50397     // reset JIT matrix and remove cache
50398
50399     for ( var h = 0; h < this.data.hierarchy.length; h++ ) {
50400
50401         var obj = this.hierarchy[ h ];
50402         var node = this.data.hierarchy[ h ];
50403
50404         if ( node.animationCache !== undefined ) {
50405
50406             var original = node.animationCache.originalMatrix;
50407
50408             if( obj instanceof THREE.Bone ) {
50409
50410                 original.copy( obj.skinMatrix );
50411                 obj.skinMatrix = original;
50412
50413             } else {
50414
50415                 original.copy( obj.matrix );
50416                 obj.matrix = original;
50417
50418             }
50419
50420             delete node.animationCache;
50421
50422         }
50423
50424     }
50425
50426 };
50427
50428
50429 // Update
50430
50431 THREE.KeyFrameAnimation.prototype.update = function( deltaTimeMS ) {
50432
50433     // early out
50434
50435     if( !this.isPlaying ) return;
50436
50437
50438     // vars
50439
50440     var prevKey, nextKey;
50441     var object;
50442     var node;
50443     var frame;
50444     var JIThierarchy = this.data.JIT.hierarchy;
50445     var currentTime, unloopedCurrentTime;
50446     var looped;
50447
50448
50449     // update
50450
50451     this.currentTime += deltaTimeMS * this.timeScale;
50452
50453     unloopedCurrentTime = this.currentTime;
50454     currentTime         = this.currentTime = this.currentTime % this.data.length;
50455
50456     // if looped around, the current time should be based on the startTime
50457     if ( currentTime < this.startTimeMs ) {
50458
50459         currentTime = this.currentTime = this.startTimeMs + currentTime;
50460
50461     }
50462
50463     frame               = parseInt( Math.min( currentTime * this.data.fps, this.data.length * this.data.fps ), 10 );
50464     looped                 = currentTime < unloopedCurrentTime;
50465
50466     if ( looped && !this.loop ) {
50467
50468         // Set the animation to the last keyframes and stop
50469         for ( var h = 0, hl = this.hierarchy.length; h < hl; h++ ) {
50470
50471             var keys = this.data.hierarchy[h].keys,
50472                 sids = this.data.hierarchy[h].sids,
50473                 end = keys.length-1,
50474                 obj = this.hierarchy[h];
50475
50476             if ( keys.length ) {
50477
50478                 for ( var s = 0; s < sids.length; s++ ) {
50479
50480                     var sid = sids[ s ],
50481                         prev = this.getPrevKeyWith( sid, h, end );
50482
50483                     if ( prev ) {
50484                         prev.apply( sid );
50485
50486                     }
50487
50488                 }
50489
50490                 this.data.hierarchy[h].node.updateMatrix();
50491                 obj.matrixWorldNeedsUpdate = true;
50492
50493             }
50494
50495         }
50496
50497         this.stop();
50498         return;
50499
50500     }
50501
50502     // check pre-infinity
50503     if ( currentTime < this.startTime ) {
50504
50505         return;
50506
50507     }
50508
50509     // update
50510
50511     for ( var h = 0, hl = this.hierarchy.length; h < hl; h++ ) {
50512
50513         object = this.hierarchy[ h ];
50514         node = this.data.hierarchy[ h ];
50515
50516         var keys = node.keys,
50517             animationCache = node.animationCache;
50518
50519         // use JIT?
50520
50521         if ( this.JITCompile && JIThierarchy[ h ][ frame ] !== undefined ) {
50522
50523             if( object instanceof THREE.Bone ) {
50524
50525                 object.skinMatrix = JIThierarchy[ h ][ frame ];
50526                 object.matrixWorldNeedsUpdate = false;
50527
50528             } else {
50529
50530                 object.matrix = JIThierarchy[ h ][ frame ];
50531                 object.matrixWorldNeedsUpdate = true;
50532
50533             }
50534
50535         // use interpolation
50536
50537         } else if ( keys.length ) {
50538
50539             // make sure so original matrix and not JIT matrix is set
50540
50541             if ( this.JITCompile && animationCache ) {
50542
50543                 if( object instanceof THREE.Bone ) {
50544
50545                     object.skinMatrix = animationCache.originalMatrix;
50546
50547                 } else {
50548
50549                     object.matrix = animationCache.originalMatrix;
50550
50551                 }
50552
50553             }
50554
50555             prevKey = animationCache.prevKey;
50556             nextKey = animationCache.nextKey;
50557
50558             if ( prevKey && nextKey ) {
50559
50560                 // switch keys?
50561
50562                 if ( nextKey.time <= unloopedCurrentTime ) {
50563
50564                     // did we loop?
50565
50566                     if ( looped && this.loop ) {
50567
50568                         prevKey = keys[ 0 ];
50569                         nextKey = keys[ 1 ];
50570
50571                         while ( nextKey.time < currentTime ) {
50572
50573                             prevKey = nextKey;
50574                             nextKey = keys[ prevKey.index + 1 ];
50575
50576                         }
50577
50578                     } else if ( !looped ) {
50579
50580                         var lastIndex = keys.length - 1;
50581
50582                         while ( nextKey.time < currentTime && nextKey.index !== lastIndex ) {
50583
50584                             prevKey = nextKey;
50585                             nextKey = keys[ prevKey.index + 1 ];
50586
50587                         }
50588
50589                     }
50590
50591                     animationCache.prevKey = prevKey;
50592                     animationCache.nextKey = nextKey;
50593
50594                 }
50595                 if(nextKey.time >= currentTime)
50596                     prevKey.interpolate( nextKey, currentTime );
50597                 else
50598                     prevKey.interpolate( nextKey, nextKey.time);
50599
50600             }
50601
50602             this.data.hierarchy[h].node.updateMatrix();
50603             object.matrixWorldNeedsUpdate = true;
50604
50605         }
50606
50607     }
50608
50609     // update JIT?
50610
50611     if ( this.JITCompile ) {
50612
50613         if ( JIThierarchy[ 0 ][ frame ] === undefined ) {
50614
50615             this.hierarchy[ 0 ].updateMatrixWorld( true );
50616
50617             for ( var h = 0; h < this.hierarchy.length; h++ ) {
50618
50619                 if( this.hierarchy[ h ] instanceof THREE.Bone ) {
50620
50621                     JIThierarchy[ h ][ frame ] = this.hierarchy[ h ].skinMatrix.clone();
50622
50623                 } else {
50624
50625                     JIThierarchy[ h ][ frame ] = this.hierarchy[ h ].matrix.clone();
50626
50627                 }
50628
50629             }
50630
50631         }
50632
50633     }
50634
50635 };
50636
50637 // Get next key with
50638
50639 THREE.KeyFrameAnimation.prototype.getNextKeyWith = function( sid, h, key ) {
50640
50641     var keys = this.data.hierarchy[ h ].keys;
50642     key = key % keys.length;
50643
50644     for ( ; key < keys.length; key++ ) {
50645
50646         if ( keys[ key ].hasTarget( sid ) ) {
50647
50648             return keys[ key ];
50649
50650         }
50651
50652     }
50653
50654     return keys[ 0 ];
50655
50656 };
50657
50658 // Get previous key with
50659
50660 THREE.KeyFrameAnimation.prototype.getPrevKeyWith = function( sid, h, key ) {
50661
50662     var keys = this.data.hierarchy[ h ].keys;
50663     key = key >= 0 ? key : key + keys.length;
50664
50665     for ( ; key >= 0; key-- ) {
50666
50667         if ( keys[ key ].hasTarget( sid ) ) {
50668
50669             return keys[ key ];
50670
50671         }
50672
50673     }
50674
50675     return keys[ keys.length - 1 ];
50676
50677 };
50678 /**
50679  * Camera for rendering cube maps
50680  *    - renders scene into axis-aligned cube
50681  *
50682  * @author alteredq / http://alteredqualia.com/
50683  */
50684
50685 THREE.CubeCamera = function ( near, far, cubeResolution ) {
50686
50687     THREE.Object3D.call( this );
50688
50689     var fov = 90, aspect = 1;
50690
50691     var cameraPX = new THREE.PerspectiveCamera( fov, aspect, near, far );
50692     cameraPX.up.set( 0, -1, 0 );
50693     cameraPX.lookAt( new THREE.Vector3( 1, 0, 0 ) );
50694     this.add( cameraPX );
50695
50696     var cameraNX = new THREE.PerspectiveCamera( fov, aspect, near, far );
50697     cameraNX.up.set( 0, -1, 0 );
50698     cameraNX.lookAt( new THREE.Vector3( -1, 0, 0 ) );
50699     this.add( cameraNX );
50700
50701     var cameraPY = new THREE.PerspectiveCamera( fov, aspect, near, far );
50702     cameraPY.up.set( 0, 0, 1 );
50703     cameraPY.lookAt( new THREE.Vector3( 0, 1, 0 ) );
50704     this.add( cameraPY );
50705
50706     var cameraNY = new THREE.PerspectiveCamera( fov, aspect, near, far );
50707     cameraNY.up.set( 0, 0, -1 );
50708     cameraNY.lookAt( new THREE.Vector3( 0, -1, 0 ) );
50709     this.add( cameraNY );
50710
50711     var cameraPZ = new THREE.PerspectiveCamera( fov, aspect, near, far );
50712     cameraPZ.up.set( 0, -1, 0 );
50713     cameraPZ.lookAt( new THREE.Vector3( 0, 0, 1 ) );
50714     this.add( cameraPZ );
50715
50716     var cameraNZ = new THREE.PerspectiveCamera( fov, aspect, near, far );
50717     cameraNZ.up.set( 0, -1, 0 );
50718     cameraNZ.lookAt( new THREE.Vector3( 0, 0, -1 ) );
50719     this.add( cameraNZ );
50720
50721     this.renderTarget = new THREE.WebGLRenderTargetCube( cubeResolution, cubeResolution, { format: THREE.RGBFormat, magFilter: THREE.LinearFilter, minFilter: THREE.LinearFilter } );
50722
50723     this.updateCubeMap = function ( renderer, scene ) {
50724
50725         var renderTarget = this.renderTarget;
50726         var generateMipmaps = renderTarget.generateMipmaps;
50727
50728         renderTarget.generateMipmaps = false;
50729
50730         renderTarget.activeCubeFace = 0;
50731         renderer.render( scene, cameraPX, renderTarget );
50732
50733         renderTarget.activeCubeFace = 1;
50734         renderer.render( scene, cameraNX, renderTarget );
50735
50736         renderTarget.activeCubeFace = 2;
50737         renderer.render( scene, cameraPY, renderTarget );
50738
50739         renderTarget.activeCubeFace = 3;
50740         renderer.render( scene, cameraNY, renderTarget );
50741
50742         renderTarget.activeCubeFace = 4;
50743         renderer.render( scene, cameraPZ, renderTarget );
50744
50745         renderTarget.generateMipmaps = generateMipmaps;
50746
50747         renderTarget.activeCubeFace = 5;
50748         renderer.render( scene, cameraNZ, renderTarget );
50749
50750     };
50751
50752 };
50753
50754 THREE.CubeCamera.prototype = Object.create( THREE.Object3D.prototype );
50755 /*
50756  *    @author zz85 / http://twitter.com/blurspline / http://www.lab4games.net/zz85/blog
50757  *
50758  *    A general perpose camera, for setting FOV, Lens Focal Length,
50759  *        and switching between perspective and orthographic views easily.
50760  *        Use this only if you do not wish to manage
50761  *        both a Orthographic and Perspective Camera
50762  *
50763  */
50764
50765
50766 THREE.CombinedCamera = function ( width, height, fov, near, far, orthoNear, orthoFar ) {
50767
50768     THREE.Camera.call( this );
50769
50770     this.fov = fov;
50771
50772     this.left = -width / 2;
50773     this.right = width / 2
50774     this.top = height / 2;
50775     this.bottom = -height / 2;
50776
50777     // We could also handle the projectionMatrix internally, but just wanted to test nested camera objects
50778
50779     this.cameraO = new THREE.OrthographicCamera( width / - 2, width / 2, height / 2, height / - 2,     orthoNear, orthoFar );
50780     this.cameraP = new THREE.PerspectiveCamera( fov, width / height, near, far );
50781
50782     this.zoom = 1;
50783
50784     this.toPerspective();
50785
50786     var aspect = width/height;
50787
50788 };
50789
50790 THREE.CombinedCamera.prototype = Object.create( THREE.Camera.prototype );
50791
50792 THREE.CombinedCamera.prototype.toPerspective = function () {
50793
50794     // Switches to the Perspective Camera
50795
50796     this.near = this.cameraP.near;
50797     this.far = this.cameraP.far;
50798
50799     this.cameraP.fov =  this.fov / this.zoom ;
50800
50801     this.cameraP.updateProjectionMatrix();
50802
50803     this.projectionMatrix = this.cameraP.projectionMatrix;
50804
50805     this.inPerspectiveMode = true;
50806     this.inOrthographicMode = false;
50807
50808 };
50809
50810 THREE.CombinedCamera.prototype.toOrthographic = function () {
50811
50812     // Switches to the Orthographic camera estimating viewport from Perspective
50813
50814     var fov = this.fov;
50815     var aspect = this.cameraP.aspect;
50816     var near = this.cameraP.near;
50817     var far = this.cameraP.far;
50818
50819     // The size that we set is the mid plane of the viewing frustum
50820
50821     var hyperfocus = ( near + far ) / 2;
50822
50823     var halfHeight = Math.tan( fov / 2 ) * hyperfocus;
50824     var planeHeight = 2 * halfHeight;
50825     var planeWidth = planeHeight * aspect;
50826     var halfWidth = planeWidth / 2;
50827
50828     halfHeight /= this.zoom;
50829     halfWidth /= this.zoom;
50830
50831     this.cameraO.left = -halfWidth;
50832     this.cameraO.right = halfWidth;
50833     this.cameraO.top = halfHeight;
50834     this.cameraO.bottom = -halfHeight;
50835
50836     // this.cameraO.left = -farHalfWidth;
50837     // this.cameraO.right = farHalfWidth;
50838     // this.cameraO.top = farHalfHeight;
50839     // this.cameraO.bottom = -farHalfHeight;
50840
50841     // this.cameraO.left = this.left / this.zoom;
50842     // this.cameraO.right = this.right / this.zoom;
50843     // this.cameraO.top = this.top / this.zoom;
50844     // this.cameraO.bottom = this.bottom / this.zoom;
50845
50846     this.cameraO.updateProjectionMatrix();
50847
50848     this.near = this.cameraO.near;
50849     this.far = this.cameraO.far;
50850     this.projectionMatrix = this.cameraO.projectionMatrix;
50851
50852     this.inPerspectiveMode = false;
50853     this.inOrthographicMode = true;
50854
50855 };
50856
50857
50858 THREE.CombinedCamera.prototype.setSize = function( width, height ) {
50859
50860     this.cameraP.aspect = width / height;
50861     this.left = -width / 2;
50862     this.right = width / 2
50863     this.top = height / 2;
50864     this.bottom = -height / 2;
50865
50866 };
50867
50868
50869 THREE.CombinedCamera.prototype.setFov = function( fov ) {
50870
50871     this.fov = fov;
50872
50873     if ( this.inPerspectiveMode ) {
50874
50875         this.toPerspective();
50876
50877     } else {
50878
50879         this.toOrthographic();
50880
50881     }
50882
50883 };
50884
50885 // For mantaining similar API with PerspectiveCamera
50886
50887 THREE.CombinedCamera.prototype.updateProjectionMatrix = function() {
50888
50889     if ( this.inPerspectiveMode ) {
50890
50891         this.toPerspective();
50892
50893     } else {
50894
50895         this.toPerspective();
50896         this.toOrthographic();
50897
50898     }
50899
50900 };
50901
50902 /*
50903 * Uses Focal Length (in mm) to estimate and set FOV
50904 * 35mm (fullframe) camera is used if frame size is not specified;
50905 * Formula based on http://www.bobatkins.com/photography/technical/field_of_view.html
50906 */
50907 THREE.CombinedCamera.prototype.setLens = function ( focalLength, frameHeight ) {
50908
50909     if ( frameHeight === undefined ) frameHeight = 24;
50910
50911     var fov = 2 * Math.atan( frameHeight / ( focalLength * 2 ) ) * ( 180 / Math.PI );
50912
50913     this.setFov( fov );
50914
50915     return fov;
50916 };
50917
50918
50919 THREE.CombinedCamera.prototype.setZoom = function( zoom ) {
50920
50921     this.zoom = zoom;
50922
50923     if ( this.inPerspectiveMode ) {
50924
50925         this.toPerspective();
50926
50927     } else {
50928
50929         this.toOrthographic();
50930
50931     }
50932
50933 };
50934
50935 THREE.CombinedCamera.prototype.toFrontView = function() {
50936
50937     this.rotation.x = 0;
50938     this.rotation.y = 0;
50939     this.rotation.z = 0;
50940
50941     // should we be modifing the matrix instead?
50942
50943     this.rotationAutoUpdate = false;
50944
50945 };
50946
50947 THREE.CombinedCamera.prototype.toBackView = function() {
50948
50949     this.rotation.x = 0;
50950     this.rotation.y = Math.PI;
50951     this.rotation.z = 0;
50952     this.rotationAutoUpdate = false;
50953
50954 };
50955
50956 THREE.CombinedCamera.prototype.toLeftView = function() {
50957
50958     this.rotation.x = 0;
50959     this.rotation.y = - Math.PI / 2;
50960     this.rotation.z = 0;
50961     this.rotationAutoUpdate = false;
50962
50963 };
50964
50965 THREE.CombinedCamera.prototype.toRightView = function() {
50966
50967     this.rotation.x = 0;
50968     this.rotation.y = Math.PI / 2;
50969     this.rotation.z = 0;
50970     this.rotationAutoUpdate = false;
50971
50972 };
50973
50974 THREE.CombinedCamera.prototype.toTopView = function() {
50975
50976     this.rotation.x = - Math.PI / 2;
50977     this.rotation.y = 0;
50978     this.rotation.z = 0;
50979     this.rotationAutoUpdate = false;
50980
50981 };
50982
50983 THREE.CombinedCamera.prototype.toBottomView = function() {
50984
50985     this.rotation.x = Math.PI / 2;
50986     this.rotation.y = 0;
50987     this.rotation.z = 0;
50988     this.rotationAutoUpdate = false;
50989
50990 };
50991
50992 /**
50993  * @author mrdoob / http://mrdoob.com/
50994  * @author alteredq / http://alteredqualia.com/
50995  * @author paulirish / http://paulirish.com/
50996  */
50997
50998 THREE.FirstPersonControls = function ( object, domElement ) {
50999
51000     this.object = object;
51001     this.target = new THREE.Vector3( 0, 0, 0 );
51002
51003     this.domElement = ( domElement !== undefined ) ? domElement : document;
51004
51005     this.movementSpeed = 1.0;
51006     this.lookSpeed = 0.005;
51007
51008     this.lookVertical = true;
51009     this.autoForward = false;
51010     // this.invertVertical = false;
51011
51012     this.activeLook = true;
51013
51014     this.heightSpeed = false;
51015     this.heightCoef = 1.0;
51016     this.heightMin = 0.0;
51017     this.heightMax = 1.0;
51018
51019     this.constrainVertical = false;
51020     this.verticalMin = 0;
51021     this.verticalMax = Math.PI;
51022
51023     this.autoSpeedFactor = 0.0;
51024
51025     this.mouseX = 0;
51026     this.mouseY = 0;
51027
51028     this.lat = 0;
51029     this.lon = 0;
51030     this.phi = 0;
51031     this.theta = 0;
51032
51033     this.moveForward = false;
51034     this.moveBackward = false;
51035     this.moveLeft = false;
51036     this.moveRight = false;
51037     this.freeze = false;
51038
51039     this.mouseDragOn = false;
51040
51041     this.viewHalfX = 0;
51042     this.viewHalfY = 0;
51043
51044     if ( this.domElement !== document ) {
51045
51046         this.domElement.setAttribute( 'tabindex', -1 );
51047
51048     }
51049
51050     //
51051
51052     this.handleResize = function () {
51053
51054         if ( this.domElement === document ) {
51055
51056             this.viewHalfX = window.innerWidth / 2;
51057             this.viewHalfY = window.innerHeight / 2;
51058
51059         } else {
51060
51061             this.viewHalfX = this.domElement.offsetWidth / 2;
51062             this.viewHalfY = this.domElement.offsetHeight / 2;
51063
51064         }
51065
51066     };
51067
51068     this.onMouseDown = function ( event ) {
51069
51070         if ( this.domElement !== document ) {
51071
51072             this.domElement.focus();
51073
51074         }
51075
51076         event.preventDefault();
51077         event.stopPropagation();
51078
51079         if ( this.activeLook ) {
51080
51081             switch ( event.button ) {
51082
51083                 case 0: this.moveForward = true; break;
51084                 case 2: this.moveBackward = true; break;
51085
51086             }
51087
51088         }
51089
51090         this.mouseDragOn = true;
51091
51092     };
51093
51094     this.onMouseUp = function ( event ) {
51095
51096         event.preventDefault();
51097         event.stopPropagation();
51098
51099         if ( this.activeLook ) {
51100
51101             switch ( event.button ) {
51102
51103                 case 0: this.moveForward = false; break;
51104                 case 2: this.moveBackward = false; break;
51105
51106             }
51107
51108         }
51109
51110         this.mouseDragOn = false;
51111
51112     };
51113
51114     this.onMouseMove = function ( event ) {
51115
51116         if ( this.domElement === document ) {
51117
51118             this.mouseX = event.pageX - this.viewHalfX;
51119             this.mouseY = event.pageY - this.viewHalfY;
51120
51121         } else {
51122
51123             this.mouseX = event.pageX - this.domElement.offsetLeft - this.viewHalfX;
51124             this.mouseY = event.pageY - this.domElement.offsetTop - this.viewHalfY;
51125
51126         }
51127
51128     };
51129
51130     this.onKeyDown = function ( event ) {
51131
51132         //event.preventDefault();
51133
51134         switch ( event.keyCode ) {
51135
51136             case 38: /*up*/
51137             case 87: /*W*/ this.moveForward = true; break;
51138
51139             case 37: /*left*/
51140             case 65: /*A*/ this.moveLeft = true; break;
51141
51142             case 40: /*down*/
51143             case 83: /*S*/ this.moveBackward = true; break;
51144
51145             case 39: /*right*/
51146             case 68: /*D*/ this.moveRight = true; break;
51147
51148             case 82: /*R*/ this.moveUp = true; break;
51149             case 70: /*F*/ this.moveDown = true; break;
51150
51151             case 81: /*Q*/ this.freeze = !this.freeze; break;
51152
51153         }
51154
51155     };
51156
51157     this.onKeyUp = function ( event ) {
51158
51159         switch( event.keyCode ) {
51160
51161             case 38: /*up*/
51162             case 87: /*W*/ this.moveForward = false; break;
51163
51164             case 37: /*left*/
51165             case 65: /*A*/ this.moveLeft = false; break;
51166
51167             case 40: /*down*/
51168             case 83: /*S*/ this.moveBackward = false; break;
51169
51170             case 39: /*right*/
51171             case 68: /*D*/ this.moveRight = false; break;
51172
51173             case 82: /*R*/ this.moveUp = false; break;
51174             case 70: /*F*/ this.moveDown = false; break;
51175
51176         }
51177
51178     };
51179
51180     this.update = function( delta ) {
51181         var actualMoveSpeed = 0;
51182
51183         if ( this.freeze ) {
51184
51185             return;
51186
51187         } else {
51188
51189             if ( this.heightSpeed ) {
51190
51191                 var y = THREE.Math.clamp( this.object.position.y, this.heightMin, this.heightMax );
51192                 var heightDelta = y - this.heightMin;
51193
51194                 this.autoSpeedFactor = delta * ( heightDelta * this.heightCoef );
51195
51196             } else {
51197
51198                 this.autoSpeedFactor = 0.0;
51199
51200             }
51201
51202             actualMoveSpeed = delta * this.movementSpeed;
51203
51204             if ( this.moveForward || ( this.autoForward && !this.moveBackward ) ) this.object.translateZ( - ( actualMoveSpeed + this.autoSpeedFactor ) );
51205             if ( this.moveBackward ) this.object.translateZ( actualMoveSpeed );
51206
51207             if ( this.moveLeft ) this.object.translateX( - actualMoveSpeed );
51208             if ( this.moveRight ) this.object.translateX( actualMoveSpeed );
51209
51210             if ( this.moveUp ) this.object.translateY( actualMoveSpeed );
51211             if ( this.moveDown ) this.object.translateY( - actualMoveSpeed );
51212
51213             var actualLookSpeed = delta * this.lookSpeed;
51214
51215             if ( !this.activeLook ) {
51216
51217                 actualLookSpeed = 0;
51218
51219             }
51220
51221             this.lon += this.mouseX * actualLookSpeed;
51222             if( this.lookVertical ) this.lat -= this.mouseY * actualLookSpeed; // * this.invertVertical?-1:1;
51223
51224             this.lat = Math.max( - 85, Math.min( 85, this.lat ) );
51225             this.phi = ( 90 - this.lat ) * Math.PI / 180;
51226             this.theta = this.lon * Math.PI / 180;
51227
51228             var targetPosition = this.target,
51229                 position = this.object.position;
51230
51231             targetPosition.x = position.x + 100 * Math.sin( this.phi ) * Math.cos( this.theta );
51232             targetPosition.y = position.y + 100 * Math.cos( this.phi );
51233             targetPosition.z = position.z + 100 * Math.sin( this.phi ) * Math.sin( this.theta );
51234
51235         }
51236
51237         var verticalLookRatio = 1;
51238
51239         if ( this.constrainVertical ) {
51240
51241             verticalLookRatio = Math.PI / ( this.verticalMax - this.verticalMin );
51242
51243         }
51244
51245         this.lon += this.mouseX * actualLookSpeed;
51246         if( this.lookVertical ) this.lat -= this.mouseY * actualLookSpeed * verticalLookRatio;
51247
51248         this.lat = Math.max( - 85, Math.min( 85, this.lat ) );
51249         this.phi = ( 90 - this.lat ) * Math.PI / 180;
51250
51251         this.theta = this.lon * Math.PI / 180;
51252
51253         if ( this.constrainVertical ) {
51254
51255             this.phi = THREE.Math.mapLinear( this.phi, 0, Math.PI, this.verticalMin, this.verticalMax );
51256
51257         }
51258
51259         var targetPosition = this.target,
51260             position = this.object.position;
51261
51262         targetPosition.x = position.x + 100 * Math.sin( this.phi ) * Math.cos( this.theta );
51263         targetPosition.y = position.y + 100 * Math.cos( this.phi );
51264         targetPosition.z = position.z + 100 * Math.sin( this.phi ) * Math.sin( this.theta );
51265
51266         this.object.lookAt( targetPosition );
51267
51268     };
51269
51270
51271     this.domElement.addEventListener( 'contextmenu', function ( event ) { event.preventDefault(); }, false );
51272
51273     this.domElement.addEventListener( 'mousemove', bind( this, this.onMouseMove ), false );
51274     this.domElement.addEventListener( 'mousedown', bind( this, this.onMouseDown ), false );
51275     this.domElement.addEventListener( 'mouseup', bind( this, this.onMouseUp ), false );
51276     this.domElement.addEventListener( 'keydown', bind( this, this.onKeyDown ), false );
51277     this.domElement.addEventListener( 'keyup', bind( this, this.onKeyUp ), false );
51278
51279     function bind( scope, fn ) {
51280
51281         return function () {
51282
51283             fn.apply( scope, arguments );
51284
51285         };
51286
51287     };
51288
51289     this.handleResize();
51290
51291 };
51292 /**
51293  * @author alteredq / http://alteredqualia.com/
51294  */
51295
51296 THREE.PathControls = function ( object, domElement ) {
51297
51298     this.object = object;
51299     this.domElement = ( domElement !== undefined ) ? domElement : document;
51300
51301     this.id = "PathControls" + THREE.PathControlsIdCounter ++;
51302
51303     // API
51304
51305     this.duration = 10 * 1000; // milliseconds
51306     this.waypoints = [];
51307
51308     this.useConstantSpeed = true;
51309     this.resamplingCoef = 50;
51310
51311     this.debugPath = new THREE.Object3D();
51312     this.debugDummy = new THREE.Object3D();
51313
51314     this.animationParent = new THREE.Object3D();
51315
51316     this.lookSpeed = 0.005;
51317     this.lookVertical = true;
51318     this.lookHorizontal = true;
51319     this.verticalAngleMap   = { srcRange: [ 0, 2 * Math.PI ], dstRange: [ 0, 2 * Math.PI ] };
51320     this.horizontalAngleMap = { srcRange: [ 0, 2 * Math.PI ], dstRange: [ 0, 2 * Math.PI ] };
51321
51322     // internals
51323
51324     this.target = new THREE.Object3D();
51325
51326     this.mouseX = 0;
51327     this.mouseY = 0;
51328
51329     this.lat = 0;
51330     this.lon = 0;
51331
51332     this.phi = 0;
51333     this.theta = 0;
51334
51335     var PI2 = Math.PI * 2,
51336         PI180 = Math.PI / 180;
51337
51338     this.viewHalfX = 0;
51339     this.viewHalfY = 0;
51340
51341     if ( this.domElement !== document ) {
51342
51343         this.domElement.setAttribute( 'tabindex', -1 );
51344
51345     }
51346
51347     // methods
51348
51349     this.handleResize = function () {
51350
51351         if ( this.domElement === document ) {
51352
51353             this.viewHalfX = window.innerWidth / 2;
51354             this.viewHalfY = window.innerHeight / 2;
51355
51356         } else {
51357
51358             this.viewHalfX = this.domElement.offsetWidth / 2;
51359             this.viewHalfY = this.domElement.offsetHeight / 2;
51360
51361         }
51362
51363     };
51364
51365     this.update = function ( delta ) {
51366
51367         var srcRange, dstRange;
51368
51369         if( this.lookHorizontal ) this.lon += this.mouseX * this.lookSpeed * delta;
51370         if( this.lookVertical )   this.lat -= this.mouseY * this.lookSpeed * delta;
51371
51372         this.lon = Math.max( 0, Math.min( 360, this.lon ) );
51373         this.lat = Math.max( - 85, Math.min( 85, this.lat ) );
51374
51375         this.phi = ( 90 - this.lat ) * PI180;
51376         this.theta = this.lon * PI180;
51377
51378         this.phi = normalize_angle_rad( this.phi );
51379
51380         // constrain vertical look angle
51381
51382         srcRange = this.verticalAngleMap.srcRange;
51383         dstRange = this.verticalAngleMap.dstRange;
51384
51385         var tmpPhi = THREE.Math.mapLinear( this.phi, srcRange[ 0 ], srcRange[ 1 ], dstRange[ 0 ], dstRange[ 1 ] );
51386         var tmpPhiFullRange = dstRange[ 1 ] - dstRange[ 0 ];
51387         var tmpPhiNormalized = ( tmpPhi - dstRange[ 0 ] ) / tmpPhiFullRange;
51388
51389         this.phi = QuadraticEaseInOut( tmpPhiNormalized ) * tmpPhiFullRange + dstRange[ 0 ];
51390
51391         // constrain horizontal look angle
51392
51393         srcRange = this.horizontalAngleMap.srcRange;
51394         dstRange = this.horizontalAngleMap.dstRange;
51395
51396         var tmpTheta = THREE.Math.mapLinear( this.theta, srcRange[ 0 ], srcRange[ 1 ], dstRange[ 0 ], dstRange[ 1 ] );
51397         var tmpThetaFullRange = dstRange[ 1 ] - dstRange[ 0 ];
51398         var tmpThetaNormalized = ( tmpTheta - dstRange[ 0 ] ) / tmpThetaFullRange;
51399
51400         this.theta = QuadraticEaseInOut( tmpThetaNormalized ) * tmpThetaFullRange + dstRange[ 0 ];
51401
51402         var targetPosition = this.target.position,
51403             position = this.object.position;
51404
51405         targetPosition.x = 100 * Math.sin( this.phi ) * Math.cos( this.theta );
51406         targetPosition.y = 100 * Math.cos( this.phi );
51407         targetPosition.z = 100 * Math.sin( this.phi ) * Math.sin( this.theta );
51408
51409         this.object.lookAt( this.target.position );
51410
51411     };
51412
51413     this.onMouseMove = function ( event ) {
51414
51415         if ( this.domElement === document ) {
51416
51417             this.mouseX = event.pageX - this.viewHalfX;
51418             this.mouseY = event.pageY - this.viewHalfY;
51419
51420         } else {
51421
51422             this.mouseX = event.pageX - this.domElement.offsetLeft - this.viewHalfX;
51423             this.mouseY = event.pageY - this.domElement.offsetTop - this.viewHalfY;
51424
51425         }
51426
51427     };
51428
51429     // utils
51430
51431     function normalize_angle_rad( a ) {
51432
51433         var b = a % PI2;
51434         return b >= 0 ? b : b + PI2;
51435
51436     };
51437
51438     function distance( a, b ) {
51439
51440         var dx = a[ 0 ] - b[ 0 ],
51441             dy = a[ 1 ] - b[ 1 ],
51442             dz = a[ 2 ] - b[ 2 ];
51443
51444         return Math.sqrt( dx * dx + dy * dy + dz * dz );
51445
51446     };
51447
51448     function QuadraticEaseInOut ( k ) {
51449
51450         if ( ( k *= 2 ) < 1 ) return 0.5 * k * k;
51451         return - 0.5 * ( --k * ( k - 2 ) - 1 );
51452
51453     };
51454
51455     function bind( scope, fn ) {
51456
51457         return function () {
51458
51459             fn.apply( scope, arguments );
51460
51461         };
51462
51463     };
51464
51465     function initAnimationPath( parent, spline, name, duration ) {
51466
51467         var animationData = {
51468
51469            name: name,
51470            fps: 0.6,
51471            length: duration,
51472
51473            hierarchy: []
51474
51475         };
51476
51477         var i,
51478             parentAnimation, childAnimation,
51479             path = spline.getControlPointsArray(),
51480             sl = spline.getLength(),
51481             pl = path.length,
51482             t = 0,
51483             first = 0,
51484             last  = pl - 1;
51485
51486         parentAnimation = { parent: -1, keys: [] };
51487         parentAnimation.keys[ first ] = { time: 0,        pos: path[ first ], rot: [ 0, 0, 0, 1 ], scl: [ 1, 1, 1 ] };
51488         parentAnimation.keys[ last  ] = { time: duration, pos: path[ last ],  rot: [ 0, 0, 0, 1 ], scl: [ 1, 1, 1 ] };
51489
51490         for ( i = 1; i < pl - 1; i++ ) {
51491
51492             // real distance (approximation via linear segments)
51493
51494             t = duration * sl.chunks[ i ] / sl.total;
51495
51496             // equal distance
51497
51498             //t = duration * ( i / pl );
51499
51500             // linear distance
51501
51502             //t += duration * distance( path[ i ], path[ i - 1 ] ) / sl.total;
51503
51504             parentAnimation.keys[ i ] = { time: t, pos: path[ i ] };
51505
51506         }
51507
51508         animationData.hierarchy[ 0 ] = parentAnimation;
51509
51510         THREE.AnimationHandler.add( animationData );
51511
51512         return new THREE.Animation( parent, name, THREE.AnimationHandler.CATMULLROM_FORWARD, false );
51513
51514     };
51515
51516
51517     function createSplineGeometry( spline, n_sub ) {
51518
51519         var i, index, position,
51520             geometry = new THREE.Geometry();
51521
51522         for ( i = 0; i < spline.points.length * n_sub; i ++ ) {
51523
51524             index = i / ( spline.points.length * n_sub );
51525             position = spline.getPoint( index );
51526
51527             geometry.vertices[ i ] = new THREE.Vector3( position.x, position.y, position.z );
51528
51529         }
51530
51531         return geometry;
51532
51533     };
51534
51535     function createPath( parent, spline ) {
51536
51537         var lineGeo = createSplineGeometry( spline, 10 ),
51538             particleGeo = createSplineGeometry( spline, 10 ),
51539             lineMat = new THREE.LineBasicMaterial( { color: 0xff0000, linewidth: 3 } ),
51540             lineObj = new THREE.Line( lineGeo, lineMat ),
51541             particleObj = new THREE.ParticleSystem( particleGeo, new THREE.ParticleBasicMaterial( { color: 0xffaa00, size: 3 } ) );
51542
51543         lineObj.scale.set( 1, 1, 1 );
51544         parent.add( lineObj );
51545
51546         particleObj.scale.set( 1, 1, 1 );
51547         parent.add( particleObj );
51548
51549         var waypoint,
51550             geo = new THREE.SphereGeometry( 1, 16, 8 ),
51551             mat = new THREE.MeshBasicMaterial( { color: 0x00ff00 } );
51552
51553         for ( var i = 0; i < spline.points.length; i ++ ) {
51554
51555             waypoint = new THREE.Mesh( geo, mat );
51556             waypoint.position.copy( spline.points[ i ] );
51557             parent.add( waypoint );
51558
51559         }
51560
51561     };
51562
51563     this.init = function ( ) {
51564
51565         // constructor
51566
51567         this.spline = new THREE.Spline();
51568         this.spline.initFromArray( this.waypoints );
51569
51570         if ( this.useConstantSpeed ) {
51571
51572             this.spline.reparametrizeByArcLength( this.resamplingCoef );
51573
51574         }
51575
51576         if ( this.createDebugDummy ) {
51577
51578             var dummyParentMaterial = new THREE.MeshLambertMaterial( { color: 0x0077ff } ),
51579             dummyChildMaterial  = new THREE.MeshLambertMaterial( { color: 0x00ff00 } ),
51580             dummyParentGeo = new THREE.CubeGeometry( 10, 10, 20 ),
51581             dummyChildGeo  = new THREE.CubeGeometry( 2, 2, 10 );
51582
51583             this.animationParent = new THREE.Mesh( dummyParentGeo, dummyParentMaterial );
51584
51585             var dummyChild = new THREE.Mesh( dummyChildGeo, dummyChildMaterial );
51586             dummyChild.position.set( 0, 10, 0 );
51587
51588             this.animation = initAnimationPath( this.animationParent, this.spline, this.id, this.duration );
51589
51590             this.animationParent.add( this.object );
51591             this.animationParent.add( this.target );
51592             this.animationParent.add( dummyChild );
51593
51594         } else {
51595
51596             this.animation = initAnimationPath( this.animationParent, this.spline, this.id, this.duration );
51597             this.animationParent.add( this.target );
51598             this.animationParent.add( this.object );
51599
51600         }
51601
51602         if ( this.createDebugPath ) {
51603
51604             createPath( this.debugPath, this.spline );
51605
51606         }
51607
51608         this.domElement.addEventListener( 'mousemove', bind( this, this.onMouseMove ), false );
51609
51610     };
51611
51612     this.handleResize();
51613
51614 };
51615
51616 THREE.PathControlsIdCounter = 0;
51617 /**
51618  * @author James Baicoianu / http://www.baicoianu.com/
51619  */
51620
51621 THREE.FlyControls = function ( object, domElement ) {
51622
51623     this.object = object;
51624
51625     this.domElement = ( domElement !== undefined ) ? domElement : document;
51626     if ( domElement ) this.domElement.setAttribute( 'tabindex', -1 );
51627
51628     // API
51629
51630     this.movementSpeed = 1.0;
51631     this.rollSpeed = 0.005;
51632
51633     this.dragToLook = false;
51634     this.autoForward = false;
51635
51636     // disable default target object behavior
51637
51638     this.object.useQuaternion = true;
51639
51640     // internals
51641
51642     this.tmpQuaternion = new THREE.Quaternion();
51643
51644     this.mouseStatus = 0;
51645
51646     this.moveState = { up: 0, down: 0, left: 0, right: 0, forward: 0, back: 0, pitchUp: 0, pitchDown: 0, yawLeft: 0, yawRight: 0, rollLeft: 0, rollRight: 0 };
51647     this.moveVector = new THREE.Vector3( 0, 0, 0 );
51648     this.rotationVector = new THREE.Vector3( 0, 0, 0 );
51649
51650     this.handleEvent = function ( event ) {
51651
51652         if ( typeof this[ event.type ] == 'function' ) {
51653
51654             this[ event.type ]( event );
51655
51656         }
51657
51658     };
51659
51660     this.keydown = function( event ) {
51661
51662         if ( event.altKey ) {
51663
51664             return;
51665
51666         }
51667
51668         //event.preventDefault();
51669
51670         switch ( event.keyCode ) {
51671
51672             case 16: /* shift */ this.movementSpeedMultiplier = .1; break;
51673
51674             case 87: /*W*/ this.moveState.forward = 1; break;
51675             case 83: /*S*/ this.moveState.back = 1; break;
51676
51677             case 65: /*A*/ this.moveState.left = 1; break;
51678             case 68: /*D*/ this.moveState.right = 1; break;
51679
51680             case 82: /*R*/ this.moveState.up = 1; break;
51681             case 70: /*F*/ this.moveState.down = 1; break;
51682
51683             case 38: /*up*/ this.moveState.pitchUp = 1; break;
51684             case 40: /*down*/ this.moveState.pitchDown = 1; break;
51685
51686             case 37: /*left*/ this.moveState.yawLeft = 1; break;
51687             case 39: /*right*/ this.moveState.yawRight = 1; break;
51688
51689             case 81: /*Q*/ this.moveState.rollLeft = 1; break;
51690             case 69: /*E*/ this.moveState.rollRight = 1; break;
51691
51692         }
51693
51694         this.updateMovementVector();
51695         this.updateRotationVector();
51696
51697     };
51698
51699     this.keyup = function( event ) {
51700
51701         switch( event.keyCode ) {
51702
51703             case 16: /* shift */ this.movementSpeedMultiplier = 1; break;
51704
51705             case 87: /*W*/ this.moveState.forward = 0; break;
51706             case 83: /*S*/ this.moveState.back = 0; break;
51707
51708             case 65: /*A*/ this.moveState.left = 0; break;
51709             case 68: /*D*/ this.moveState.right = 0; break;
51710
51711             case 82: /*R*/ this.moveState.up = 0; break;
51712             case 70: /*F*/ this.moveState.down = 0; break;
51713
51714             case 38: /*up*/ this.moveState.pitchUp = 0; break;
51715             case 40: /*down*/ this.moveState.pitchDown = 0; break;
51716
51717             case 37: /*left*/ this.moveState.yawLeft = 0; break;
51718             case 39: /*right*/ this.moveState.yawRight = 0; break;
51719
51720             case 81: /*Q*/ this.moveState.rollLeft = 0; break;
51721             case 69: /*E*/ this.moveState.rollRight = 0; break;
51722
51723         }
51724
51725         this.updateMovementVector();
51726         this.updateRotationVector();
51727
51728     };
51729
51730     this.mousedown = function( event ) {
51731
51732         if ( this.domElement !== document ) {
51733
51734             this.domElement.focus();
51735
51736         }
51737
51738         event.preventDefault();
51739         event.stopPropagation();
51740
51741         if ( this.dragToLook ) {
51742
51743             this.mouseStatus ++;
51744
51745         } else {
51746
51747             switch ( event.button ) {
51748
51749                 case 0: this.object.moveForward = true; break;
51750                 case 2: this.object.moveBackward = true; break;
51751
51752             }
51753
51754         }
51755
51756     };
51757
51758     this.mousemove = function( event ) {
51759
51760         if ( !this.dragToLook || this.mouseStatus > 0 ) {
51761
51762             var container = this.getContainerDimensions();
51763             var halfWidth  = container.size[ 0 ] / 2;
51764             var halfHeight = container.size[ 1 ] / 2;
51765
51766             this.moveState.yawLeft   = - ( ( event.pageX - container.offset[ 0 ] ) - halfWidth  ) / halfWidth;
51767             this.moveState.pitchDown =   ( ( event.pageY - container.offset[ 1 ] ) - halfHeight ) / halfHeight;
51768
51769             this.updateRotationVector();
51770
51771         }
51772
51773     };
51774
51775     this.mouseup = function( event ) {
51776
51777         event.preventDefault();
51778         event.stopPropagation();
51779
51780         if ( this.dragToLook ) {
51781
51782             this.mouseStatus --;
51783
51784             this.moveState.yawLeft = this.moveState.pitchDown = 0;
51785
51786         } else {
51787
51788             switch ( event.button ) {
51789
51790                 case 0: this.moveForward = false; break;
51791                 case 2: this.moveBackward = false; break;
51792
51793             }
51794
51795         }
51796
51797         this.updateRotationVector();
51798
51799     };
51800
51801     this.update = function( delta ) {
51802
51803         var moveMult = delta * this.movementSpeed;
51804         var rotMult = delta * this.rollSpeed;
51805
51806         this.object.translateX( this.moveVector.x * moveMult );
51807         this.object.translateY( this.moveVector.y * moveMult );
51808         this.object.translateZ( this.moveVector.z * moveMult );
51809
51810         this.tmpQuaternion.set( this.rotationVector.x * rotMult, this.rotationVector.y * rotMult, this.rotationVector.z * rotMult, 1 ).normalize();
51811         this.object.quaternion.multiplySelf( this.tmpQuaternion );
51812
51813         this.object.matrix.setPosition( this.object.position );
51814         this.object.matrix.setRotationFromQuaternion( this.object.quaternion );
51815         this.object.matrixWorldNeedsUpdate = true;
51816
51817
51818     };
51819
51820     this.updateMovementVector = function() {
51821
51822         var forward = ( this.moveState.forward || ( this.autoForward && !this.moveState.back ) ) ? 1 : 0;
51823
51824         this.moveVector.x = ( -this.moveState.left    + this.moveState.right );
51825         this.moveVector.y = ( -this.moveState.down    + this.moveState.up );
51826         this.moveVector.z = ( -forward + this.moveState.back );
51827
51828         //console.log( 'move:', [ this.moveVector.x, this.moveVector.y, this.moveVector.z ] );
51829
51830     };
51831
51832     this.updateRotationVector = function() {
51833
51834         this.rotationVector.x = ( -this.moveState.pitchDown + this.moveState.pitchUp );
51835         this.rotationVector.y = ( -this.moveState.yawRight  + this.moveState.yawLeft );
51836         this.rotationVector.z = ( -this.moveState.rollRight + this.moveState.rollLeft );
51837
51838         //console.log( 'rotate:', [ this.rotationVector.x, this.rotationVector.y, this.rotationVector.z ] );
51839
51840     };
51841
51842     this.getContainerDimensions = function() {
51843
51844         if ( this.domElement != document ) {
51845
51846             return {
51847                 size    : [ this.domElement.offsetWidth, this.domElement.offsetHeight ],
51848                 offset    : [ this.domElement.offsetLeft,  this.domElement.offsetTop ]
51849             };
51850
51851         } else {
51852
51853             return {
51854                 size    : [ window.innerWidth, window.innerHeight ],
51855                 offset    : [ 0, 0 ]
51856             };
51857
51858         }
51859
51860     };
51861
51862     function bind( scope, fn ) {
51863
51864         return function () {
51865
51866             fn.apply( scope, arguments );
51867
51868         };
51869
51870     };
51871
51872     this.domElement.addEventListener( 'mousemove', bind( this, this.mousemove ), false );
51873     this.domElement.addEventListener( 'mousedown', bind( this, this.mousedown ), false );
51874     this.domElement.addEventListener( 'mouseup',   bind( this, this.mouseup ), false );
51875
51876     this.domElement.addEventListener( 'keydown', bind( this, this.keydown ), false );
51877     this.domElement.addEventListener( 'keyup',   bind( this, this.keyup ), false );
51878
51879     this.updateMovementVector();
51880     this.updateRotationVector();
51881
51882 };
51883 /**
51884  * @author mikael emtinger / http://gomo.se/
51885  * @author alteredq / http://alteredqualia.com/
51886  */
51887
51888 THREE.RollControls = function ( object, domElement ) {
51889
51890     this.object = object;
51891     this.domElement = ( domElement !== undefined ) ? domElement : document;
51892
51893     // API
51894
51895     this.mouseLook = true;
51896     this.autoForward = false;
51897
51898     this.lookSpeed = 1;
51899     this.movementSpeed = 1;
51900     this.rollSpeed = 1;
51901
51902     this.constrainVertical = [ -0.9, 0.9 ];
51903
51904     // disable default target object behavior
51905
51906     this.object.matrixAutoUpdate = false;
51907
51908     // internals
51909
51910     this.forward = new THREE.Vector3( 0, 0, 1 );
51911     this.roll = 0;
51912
51913     var xTemp = new THREE.Vector3();
51914     var yTemp = new THREE.Vector3();
51915     var zTemp = new THREE.Vector3();
51916     var rollMatrix = new THREE.Matrix4();
51917
51918     var doRoll = false, rollDirection = 1, forwardSpeed = 0, sideSpeed = 0, upSpeed = 0;
51919
51920     var mouseX = 0, mouseY = 0;
51921
51922     var windowHalfX = 0;
51923     var windowHalfY = 0;
51924
51925     //
51926
51927     this.handleResize = function () {
51928
51929         windowHalfX = window.innerWidth / 2;
51930         windowHalfY = window.innerHeight / 2;
51931
51932     };
51933
51934     // custom update
51935
51936     this.update = function ( delta ) {
51937
51938         if ( this.mouseLook ) {
51939
51940             var actualLookSpeed = delta * this.lookSpeed;
51941
51942             this.rotateHorizontally( actualLookSpeed * mouseX );
51943             this.rotateVertically( actualLookSpeed * mouseY );
51944
51945         }
51946
51947         var actualSpeed = delta * this.movementSpeed;
51948         var forwardOrAuto = ( forwardSpeed > 0 || ( this.autoForward && ! ( forwardSpeed < 0 ) ) ) ? 1 : forwardSpeed;
51949
51950         this.object.translateZ( -actualSpeed * forwardOrAuto );
51951         this.object.translateX( actualSpeed * sideSpeed );
51952         this.object.translateY( actualSpeed * upSpeed );
51953
51954         if( doRoll ) {
51955
51956             this.roll += this.rollSpeed * delta * rollDirection;
51957
51958         }
51959
51960         // cap forward up / down
51961
51962         if( this.forward.y > this.constrainVertical[ 1 ] ) {
51963
51964             this.forward.y = this.constrainVertical[ 1 ];
51965             this.forward.normalize();
51966
51967         } else if( this.forward.y < this.constrainVertical[ 0 ] ) {
51968
51969             this.forward.y = this.constrainVertical[ 0 ];
51970             this.forward.normalize();
51971
51972         }
51973
51974
51975         // construct unrolled camera matrix
51976
51977         zTemp.copy( this.forward );
51978         yTemp.set( 0, 1, 0 );
51979
51980         xTemp.cross( yTemp, zTemp ).normalize();
51981         yTemp.cross( zTemp, xTemp ).normalize();
51982
51983         this.object.matrix.elements[0] = xTemp.x; this.object.matrix.elements[4] = yTemp.x; this.object.matrix.elements[8] = zTemp.x;
51984         this.object.matrix.elements[1] = xTemp.y; this.object.matrix.elements[5] = yTemp.y; this.object.matrix.elements[9] = zTemp.y;
51985         this.object.matrix.elements[2] = xTemp.z; this.object.matrix.elements[6] = yTemp.z; this.object.matrix.elements[10] = zTemp.z;
51986
51987         // calculate roll matrix
51988
51989         rollMatrix.identity();
51990         rollMatrix.elements[0] = Math.cos( this.roll ); rollMatrix.elements[4] = -Math.sin( this.roll );
51991         rollMatrix.elements[1] = Math.sin( this.roll ); rollMatrix.elements[5] =  Math.cos( this.roll );
51992
51993         // multiply camera with roll
51994
51995         this.object.matrix.multiplySelf( rollMatrix );
51996         this.object.matrixWorldNeedsUpdate = true;
51997
51998         // set position
51999
52000         this.object.matrix.elements[12] = this.object.position.x;
52001         this.object.matrix.elements[13] = this.object.position.y;
52002         this.object.matrix.elements[14] = this.object.position.z;
52003
52004
52005     };
52006
52007     this.translateX = function ( distance ) {
52008
52009         this.object.position.x += this.object.matrix.elements[0] * distance;
52010         this.object.position.y += this.object.matrix.elements[1] * distance;
52011         this.object.position.z += this.object.matrix.elements[2] * distance;
52012
52013     };
52014
52015     this.translateY = function ( distance ) {
52016
52017         this.object.position.x += this.object.matrix.elements[4] * distance;
52018         this.object.position.y += this.object.matrix.elements[5] * distance;
52019         this.object.position.z += this.object.matrix.elements[6] * distance;
52020
52021     };
52022
52023     this.translateZ = function ( distance ) {
52024
52025         this.object.position.x -= this.object.matrix.elements[8] * distance;
52026         this.object.position.y -= this.object.matrix.elements[9] * distance;
52027         this.object.position.z -= this.object.matrix.elements[10] * distance;
52028
52029     };
52030
52031
52032     this.rotateHorizontally = function ( amount ) {
52033
52034         // please note that the amount is NOT degrees, but a scale value
52035
52036         xTemp.set( this.object.matrix.elements[0], this.object.matrix.elements[1], this.object.matrix.elements[2] );
52037         xTemp.multiplyScalar( amount );
52038
52039         this.forward.subSelf( xTemp );
52040         this.forward.normalize();
52041
52042     };
52043
52044     this.rotateVertically = function ( amount ) {
52045
52046         // please note that the amount is NOT degrees, but a scale value
52047
52048         yTemp.set( this.object.matrix.elements[4], this.object.matrix.elements[5], this.object.matrix.elements[6] );
52049         yTemp.multiplyScalar( amount );
52050
52051         this.forward.addSelf( yTemp );
52052         this.forward.normalize();
52053
52054     };
52055
52056     function onKeyDown( event ) {
52057
52058         //event.preventDefault();
52059
52060         switch ( event.keyCode ) {
52061
52062             case 38: /*up*/
52063             case 87: /*W*/ forwardSpeed = 1; break;
52064
52065             case 37: /*left*/
52066             case 65: /*A*/ sideSpeed = -1; break;
52067
52068             case 40: /*down*/
52069             case 83: /*S*/ forwardSpeed = -1; break;
52070
52071             case 39: /*right*/
52072             case 68: /*D*/ sideSpeed = 1; break;
52073
52074             case 81: /*Q*/ doRoll = true; rollDirection = 1; break;
52075             case 69: /*E*/ doRoll = true; rollDirection = -1; break;
52076
52077             case 82: /*R*/ upSpeed = 1; break;
52078             case 70: /*F*/ upSpeed = -1; break;
52079
52080         }
52081
52082     };
52083
52084     function onKeyUp( event ) {
52085
52086         switch( event.keyCode ) {
52087
52088             case 38: /*up*/
52089             case 87: /*W*/ forwardSpeed = 0; break;
52090
52091             case 37: /*left*/
52092             case 65: /*A*/ sideSpeed = 0; break;
52093
52094             case 40: /*down*/
52095             case 83: /*S*/ forwardSpeed = 0; break;
52096
52097             case 39: /*right*/
52098             case 68: /*D*/ sideSpeed = 0; break;
52099
52100             case 81: /*Q*/ doRoll = false; break;
52101             case 69: /*E*/ doRoll = false; break;
52102
52103             case 82: /*R*/ upSpeed = 0; break;
52104             case 70: /*F*/ upSpeed = 0; break;
52105
52106         }
52107
52108     };
52109
52110     function onMouseMove( event ) {
52111
52112         mouseX = ( event.clientX - windowHalfX ) / window.innerWidth;
52113         mouseY = ( event.clientY - windowHalfY ) / window.innerHeight;
52114
52115     };
52116
52117     function onMouseDown ( event ) {
52118
52119         event.preventDefault();
52120         event.stopPropagation();
52121
52122         switch ( event.button ) {
52123
52124             case 0: forwardSpeed = 1; break;
52125             case 2: forwardSpeed = -1; break;
52126
52127         }
52128
52129     };
52130
52131     function onMouseUp ( event ) {
52132
52133         event.preventDefault();
52134         event.stopPropagation();
52135
52136         switch ( event.button ) {
52137
52138             case 0: forwardSpeed = 0; break;
52139             case 2: forwardSpeed = 0; break;
52140
52141         }
52142
52143     };
52144
52145     this.domElement.addEventListener( 'contextmenu', function ( event ) { event.preventDefault(); }, false );
52146
52147     this.domElement.addEventListener( 'mousemove', onMouseMove, false );
52148     this.domElement.addEventListener( 'mousedown', onMouseDown, false );
52149     this.domElement.addEventListener( 'mouseup', onMouseUp, false );
52150     this.domElement.addEventListener( 'keydown', onKeyDown, false );
52151     this.domElement.addEventListener( 'keyup', onKeyUp, false );
52152
52153     this.handleResize();
52154
52155 };
52156 /**
52157  * @author Eberhard Graether / http://egraether.com/
52158  */
52159
52160 THREE.TrackballControls = function ( object, domElement ) {
52161
52162     THREE.EventTarget.call( this );
52163
52164     var _this = this,
52165     STATE = { NONE : -1, ROTATE : 0, ZOOM : 1, PAN : 2 };
52166
52167     this.object = object;
52168     this.domElement = ( domElement !== undefined ) ? domElement : document;
52169
52170     // API
52171
52172     this.enabled = true;
52173
52174     this.screen = { width: 0, height: 0, offsetLeft: 0, offsetTop: 0 };
52175     this.radius = ( this.screen.width + this.screen.height ) / 4;
52176
52177     this.rotateSpeed = 1.0;
52178     this.zoomSpeed = 1.2;
52179     this.panSpeed = 0.3;
52180
52181     this.noRotate = false;
52182     this.noZoom = false;
52183     this.noPan = false;
52184
52185     this.staticMoving = false;
52186     this.dynamicDampingFactor = 0.2;
52187
52188     this.minDistance = 0;
52189     this.maxDistance = Infinity;
52190
52191     this.keys = [ 65 /*A*/, 83 /*S*/, 68 /*D*/ ];
52192
52193     // internals
52194
52195     this.target = new THREE.Vector3();
52196
52197     var lastPosition = new THREE.Vector3();
52198
52199     var _keyPressed = false,
52200     _state = STATE.NONE,
52201
52202     _eye = new THREE.Vector3(),
52203
52204     _rotateStart = new THREE.Vector3(),
52205     _rotateEnd = new THREE.Vector3(),
52206
52207     _zoomStart = new THREE.Vector2(),
52208     _zoomEnd = new THREE.Vector2(),
52209
52210     _panStart = new THREE.Vector2(),
52211     _panEnd = new THREE.Vector2();
52212
52213     // events
52214
52215     var changeEvent = { type: 'change' };
52216
52217
52218     // methods
52219
52220     this.handleResize = function () {
52221
52222         this.screen.width = window.innerWidth;
52223         this.screen.height = window.innerHeight;
52224
52225         this.screen.offsetLeft = 0;
52226         this.screen.offsetTop = 0;
52227
52228         this.radius = ( this.screen.width + this.screen.height ) / 4;
52229     };
52230
52231     this.handleEvent = function ( event ) {
52232
52233         if ( typeof this[ event.type ] == 'function' ) {
52234
52235             this[ event.type ]( event );
52236
52237         }
52238
52239     };
52240
52241     this.getMouseOnScreen = function ( clientX, clientY ) {
52242
52243         return new THREE.Vector2(
52244             ( clientX - _this.screen.offsetLeft ) / _this.radius * 0.5,
52245             ( clientY - _this.screen.offsetTop ) / _this.radius * 0.5
52246         );
52247
52248     };
52249
52250     this.getMouseProjectionOnBall = function ( clientX, clientY ) {
52251
52252         var mouseOnBall = new THREE.Vector3(
52253             ( clientX - _this.screen.width * 0.5 - _this.screen.offsetLeft ) / _this.radius,
52254             ( _this.screen.height * 0.5 + _this.screen.offsetTop - clientY ) / _this.radius,
52255             0.0
52256         );
52257
52258         var length = mouseOnBall.length();
52259
52260         if ( length > 1.0 ) {
52261
52262             mouseOnBall.normalize();
52263
52264         } else {
52265
52266             mouseOnBall.z = Math.sqrt( 1.0 - length * length );
52267
52268         }
52269
52270         _eye.copy( _this.object.position ).subSelf( _this.target );
52271
52272         var projection = _this.object.up.clone().setLength( mouseOnBall.y );
52273         projection.addSelf( _this.object.up.clone().crossSelf( _eye ).setLength( mouseOnBall.x ) );
52274         projection.addSelf( _eye.setLength( mouseOnBall.z ) );
52275
52276         return projection;
52277
52278     };
52279
52280     this.rotateCamera = function () {
52281
52282         var angle = Math.acos( _rotateStart.dot( _rotateEnd ) / _rotateStart.length() / _rotateEnd.length() );
52283
52284         if ( angle ) {
52285
52286             var axis = ( new THREE.Vector3() ).cross( _rotateStart, _rotateEnd ).normalize(),
52287                 quaternion = new THREE.Quaternion();
52288
52289             angle *= _this.rotateSpeed;
52290
52291             quaternion.setFromAxisAngle( axis, -angle );
52292
52293             quaternion.multiplyVector3( _eye );
52294             quaternion.multiplyVector3( _this.object.up );
52295
52296             quaternion.multiplyVector3( _rotateEnd );
52297
52298             if ( _this.staticMoving ) {
52299
52300                 _rotateStart.copy( _rotateEnd );
52301
52302             } else {
52303
52304                 quaternion.setFromAxisAngle( axis, angle * ( _this.dynamicDampingFactor - 1.0 ) );
52305                 quaternion.multiplyVector3( _rotateStart );
52306
52307             }
52308
52309         }
52310
52311     };
52312
52313     this.zoomCamera = function () {
52314
52315         var factor = 1.0 + ( _zoomEnd.y - _zoomStart.y ) * _this.zoomSpeed;
52316
52317         if ( factor !== 1.0 && factor > 0.0 ) {
52318
52319             _eye.multiplyScalar( factor );
52320
52321             if ( _this.staticMoving ) {
52322
52323                 _zoomStart.copy( _zoomEnd );
52324
52325             } else {
52326
52327                 _zoomStart.y += ( _zoomEnd.y - _zoomStart.y ) * this.dynamicDampingFactor;
52328
52329             }
52330
52331         }
52332
52333     };
52334
52335     this.panCamera = function () {
52336
52337         var mouseChange = _panEnd.clone().subSelf( _panStart );
52338
52339         if ( mouseChange.lengthSq() ) {
52340
52341             mouseChange.multiplyScalar( _eye.length() * _this.panSpeed );
52342
52343             var pan = _eye.clone().crossSelf( _this.object.up ).setLength( mouseChange.x );
52344             pan.addSelf( _this.object.up.clone().setLength( mouseChange.y ) );
52345
52346             _this.object.position.addSelf( pan );
52347             _this.target.addSelf( pan );
52348
52349             if ( _this.staticMoving ) {
52350
52351                 _panStart = _panEnd;
52352
52353             } else {
52354
52355                 _panStart.addSelf( mouseChange.sub( _panEnd, _panStart ).multiplyScalar( _this.dynamicDampingFactor ) );
52356
52357             }
52358
52359         }
52360
52361     };
52362
52363     this.checkDistances = function () {
52364
52365         if ( !_this.noZoom || !_this.noPan ) {
52366
52367             if ( _this.object.position.lengthSq() > _this.maxDistance * _this.maxDistance ) {
52368
52369                 _this.object.position.setLength( _this.maxDistance );
52370
52371             }
52372
52373             if ( _eye.lengthSq() < _this.minDistance * _this.minDistance ) {
52374
52375                 _this.object.position.add( _this.target, _eye.setLength( _this.minDistance ) );
52376
52377             }
52378
52379         }
52380
52381     };
52382
52383     this.update = function () {
52384
52385         _eye.copy( _this.object.position ).subSelf( _this.target );
52386
52387         if ( !_this.noRotate ) {
52388
52389             _this.rotateCamera();
52390
52391         }
52392
52393         if ( !_this.noZoom ) {
52394
52395             _this.zoomCamera();
52396
52397         }
52398
52399         if ( !_this.noPan ) {
52400
52401             _this.panCamera();
52402
52403         }
52404
52405         _this.object.position.add( _this.target, _eye );
52406
52407         _this.checkDistances();
52408
52409         _this.object.lookAt( _this.target );
52410
52411         if ( lastPosition.distanceToSquared( _this.object.position ) > 0 ) {
52412
52413             _this.dispatchEvent( changeEvent );
52414
52415             lastPosition.copy( _this.object.position );
52416
52417         }
52418
52419     };
52420
52421     // listeners
52422
52423     function keydown( event ) {
52424
52425         if ( ! _this.enabled ) return;
52426
52427         //event.preventDefault();
52428
52429         if ( _state !== STATE.NONE ) {
52430
52431             return;
52432
52433         } else if ( event.keyCode === _this.keys[ STATE.ROTATE ] && !_this.noRotate ) {
52434
52435             _state = STATE.ROTATE;
52436
52437         } else if ( event.keyCode === _this.keys[ STATE.ZOOM ] && !_this.noZoom ) {
52438
52439             _state = STATE.ZOOM;
52440
52441         } else if ( event.keyCode === _this.keys[ STATE.PAN ] && !_this.noPan ) {
52442
52443             _state = STATE.PAN;
52444
52445         }
52446
52447         if ( _state !== STATE.NONE ) {
52448
52449             _keyPressed = true;
52450
52451         }
52452
52453     }
52454
52455     function keyup( event ) {
52456
52457         if ( ! _this.enabled ) return;
52458
52459         if ( _state !== STATE.NONE ) {
52460
52461             _state = STATE.NONE;
52462
52463         }
52464
52465     }
52466
52467     function mousedown( event ) {
52468
52469         if ( ! _this.enabled ) return;
52470
52471         event.preventDefault();
52472         event.stopPropagation();
52473
52474         if ( _state === STATE.NONE ) {
52475
52476             _state = event.button;
52477
52478             if ( _state === STATE.ROTATE && !_this.noRotate ) {
52479
52480                 _rotateStart = _rotateEnd = _this.getMouseProjectionOnBall( event.clientX, event.clientY );
52481
52482             } else if ( _state === STATE.ZOOM && !_this.noZoom ) {
52483
52484                 _zoomStart = _zoomEnd = _this.getMouseOnScreen( event.clientX, event.clientY );
52485
52486             } else if ( !this.noPan ) {
52487
52488                 _panStart = _panEnd = _this.getMouseOnScreen( event.clientX, event.clientY );
52489
52490             }
52491
52492         }
52493
52494     }
52495
52496     function mousemove( event ) {
52497
52498         if ( ! _this.enabled ) return;
52499
52500         if ( _keyPressed ) {
52501
52502             _rotateStart = _rotateEnd = _this.getMouseProjectionOnBall( event.clientX, event.clientY );
52503             _zoomStart = _zoomEnd = _this.getMouseOnScreen( event.clientX, event.clientY );
52504             _panStart = _panEnd = _this.getMouseOnScreen( event.clientX, event.clientY );
52505
52506             _keyPressed = false;
52507
52508         }
52509
52510         if ( _state === STATE.NONE ) {
52511
52512             return;
52513
52514         } else if ( _state === STATE.ROTATE && !_this.noRotate ) {
52515
52516             _rotateEnd = _this.getMouseProjectionOnBall( event.clientX, event.clientY );
52517
52518         } else if ( _state === STATE.ZOOM && !_this.noZoom ) {
52519
52520             _zoomEnd = _this.getMouseOnScreen( event.clientX, event.clientY );
52521
52522         } else if ( _state === STATE.PAN && !_this.noPan ) {
52523
52524             _panEnd = _this.getMouseOnScreen( event.clientX, event.clientY );
52525
52526         }
52527
52528     }
52529
52530     function mouseup( event ) {
52531
52532         if ( ! _this.enabled ) return;
52533
52534         event.preventDefault();
52535         event.stopPropagation();
52536
52537         _state = STATE.NONE;
52538
52539     }
52540
52541     function mousewheel( event ) {
52542
52543         if ( ! _this.enabled ) return;
52544
52545         event.preventDefault();
52546         event.stopPropagation();
52547
52548         var delta = 0;
52549
52550         if ( event.wheelDelta ) { // WebKit / Opera / Explorer 9
52551
52552             delta = event.wheelDelta / 40;
52553
52554         } else if ( event.detail ) { // Firefox
52555
52556             delta = - event.detail / 3;
52557
52558         }
52559
52560         _zoomStart.y += ( 1 / delta ) * 0.05;
52561
52562     }
52563
52564     this.domElement.addEventListener( 'contextmenu', function ( event ) { event.preventDefault(); }, false );
52565
52566     this.domElement.addEventListener( 'mousemove', mousemove, false );
52567     this.domElement.addEventListener( 'mousedown', mousedown, false );
52568     this.domElement.addEventListener( 'mouseup', mouseup, false );
52569     this.domElement.addEventListener( 'DOMMouseScroll', mousewheel, false );
52570     this.domElement.addEventListener( 'mousewheel', mousewheel, false );
52571
52572     window.addEventListener( 'keydown', keydown, false );
52573     window.addEventListener( 'keyup', keyup, false );
52574
52575     this.handleResize();
52576
52577 };
52578 /**
52579  * @author qiao / https://github.com/qiao
52580  * @author mrdoob / http://mrdoob.com
52581  * @author alteredq / http://alteredqualia.com/
52582  */
52583
52584 THREE.OrbitControls = function ( object, domElement ) {
52585
52586     THREE.EventTarget.call( this );
52587
52588     this.object = object;
52589     this.domElement = ( domElement !== undefined ) ? domElement : document;
52590
52591     // API
52592
52593     this.center = new THREE.Vector3();
52594
52595     this.userZoom = true;
52596     this.userZoomSpeed = 1.0;
52597
52598     this.userRotate = true;
52599     this.userRotateSpeed = 1.0;
52600
52601     this.autoRotate = false;
52602     this.autoRotateSpeed = 2.0; // 30 seconds per round when fps is 60
52603
52604     // internals
52605
52606     var scope = this;
52607
52608     var EPS = 0.000001;
52609     var PIXELS_PER_ROUND = 1800;
52610
52611     var rotateStart = new THREE.Vector2();
52612     var rotateEnd = new THREE.Vector2();
52613     var rotateDelta = new THREE.Vector2();
52614
52615     var zoomStart = new THREE.Vector2();
52616     var zoomEnd = new THREE.Vector2();
52617     var zoomDelta = new THREE.Vector2();
52618
52619     var phiDelta = 0;
52620     var thetaDelta = 0;
52621     var scale = 1;
52622
52623     var lastPosition = new THREE.Vector3();
52624
52625     var STATE = { NONE : -1, ROTATE : 0, ZOOM : 1 };
52626     var state = STATE.NONE;
52627
52628     // events
52629
52630     var changeEvent = { type: 'change' };
52631
52632
52633     this.rotateLeft = function ( angle ) {
52634
52635         if ( angle === undefined ) {
52636
52637             angle = getAutoRotationAngle();
52638
52639         }
52640
52641         thetaDelta -= angle;
52642
52643     };
52644
52645     this.rotateRight = function ( angle ) {
52646
52647         if ( angle === undefined ) {
52648
52649             angle = getAutoRotationAngle();
52650
52651         }
52652
52653         thetaDelta += angle;
52654
52655     };
52656
52657     this.rotateUp = function ( angle ) {
52658
52659         if ( angle === undefined ) {
52660
52661             angle = getAutoRotationAngle();
52662
52663         }
52664
52665         phiDelta -= angle;
52666
52667     };
52668
52669     this.rotateDown = function ( angle ) {
52670
52671         if ( angle === undefined ) {
52672
52673             angle = getAutoRotationAngle();
52674
52675         }
52676
52677         phiDelta += angle;
52678
52679     };
52680
52681     this.zoomIn = function ( zoomScale ) {
52682
52683         if ( zoomScale === undefined ) {
52684
52685             zoomScale = getZoomScale();
52686
52687         }
52688
52689         scale /= zoomScale;
52690
52691     };
52692
52693     this.zoomOut = function ( zoomScale ) {
52694
52695         if ( zoomScale === undefined ) {
52696
52697             zoomScale = getZoomScale();
52698
52699         }
52700
52701         scale *= zoomScale;
52702
52703     };
52704
52705     this.update = function () {
52706
52707         var position = this.object.position;
52708         var offset = position.clone().subSelf( this.center )
52709
52710         // angle from z-axis around y-axis
52711
52712         var theta = Math.atan2( offset.x, offset.z );
52713
52714         // angle from y-axis
52715
52716         var phi = Math.atan2( Math.sqrt( offset.x * offset.x + offset.z * offset.z ), offset.y );
52717
52718         if ( this.autoRotate ) {
52719
52720             this.rotateLeft( getAutoRotationAngle() );
52721
52722         }
52723
52724         theta += thetaDelta;
52725         phi += phiDelta;
52726
52727         // restrict phi to be betwee EPS and PI-EPS
52728
52729         phi = Math.max( EPS, Math.min( Math.PI - EPS, phi ) );
52730
52731         var radius = offset.length();
52732         offset.x = radius * Math.sin( phi ) * Math.sin( theta );
52733         offset.y = radius * Math.cos( phi );
52734         offset.z = radius * Math.sin( phi ) * Math.cos( theta );
52735         offset.multiplyScalar( scale );
52736
52737         position.copy( this.center ).addSelf( offset );
52738
52739         this.object.lookAt( this.center );
52740
52741         thetaDelta = 0;
52742         phiDelta = 0;
52743         scale = 1;
52744
52745         if ( lastPosition.distanceTo( this.object.position ) > 0 ) {
52746
52747             this.dispatchEvent( changeEvent );
52748
52749             lastPosition.copy( this.object.position );
52750
52751         }
52752
52753     };
52754
52755
52756     function getAutoRotationAngle() {
52757
52758         return 2 * Math.PI / 60 / 60 * scope.autoRotateSpeed;
52759
52760     }
52761
52762     function getZoomScale() {
52763
52764         return Math.pow( 0.95, scope.userZoomSpeed );
52765
52766     }
52767
52768     function onMouseDown( event ) {
52769
52770         if ( !scope.userRotate ) return;
52771
52772         event.preventDefault();
52773
52774         if ( event.button === 0 || event.button === 2 ) {
52775
52776             state = STATE.ROTATE;
52777
52778             rotateStart.set( event.clientX, event.clientY );
52779
52780         } else if ( event.button === 1 ) {
52781
52782             state = STATE.ZOOM;
52783
52784             zoomStart.set( event.clientX, event.clientY );
52785
52786         }
52787
52788         document.addEventListener( 'mousemove', onMouseMove, false );
52789         document.addEventListener( 'mouseup', onMouseUp, false );
52790
52791     }
52792
52793     function onMouseMove( event ) {
52794
52795         event.preventDefault();
52796
52797         if ( state === STATE.ROTATE ) {
52798
52799             rotateEnd.set( event.clientX, event.clientY );
52800             rotateDelta.sub( rotateEnd, rotateStart );
52801
52802             scope.rotateLeft( 2 * Math.PI * rotateDelta.x / PIXELS_PER_ROUND * scope.userRotateSpeed );
52803             scope.rotateUp( 2 * Math.PI * rotateDelta.y / PIXELS_PER_ROUND * scope.userRotateSpeed );
52804
52805             rotateStart.copy( rotateEnd );
52806
52807         } else if ( state === STATE.ZOOM ) {
52808
52809             zoomEnd.set( event.clientX, event.clientY );
52810             zoomDelta.sub( zoomEnd, zoomStart );
52811
52812             if ( zoomDelta.y > 0 ) {
52813
52814                 scope.zoomIn();
52815
52816             } else {
52817
52818                 scope.zoomOut();
52819
52820             }
52821
52822             zoomStart.copy( zoomEnd );
52823
52824         }
52825
52826     }
52827
52828     function onMouseUp( event ) {
52829
52830         if ( ! scope.userRotate ) return;
52831
52832         document.removeEventListener( 'mousemove', onMouseMove, false );
52833         document.removeEventListener( 'mouseup', onMouseUp, false );
52834
52835         state = STATE.NONE;
52836
52837     }
52838
52839     function onMouseWheel( event ) {
52840
52841         if ( ! scope.userZoom ) return;
52842
52843         if ( event.wheelDelta > 0 ) {
52844
52845             scope.zoomOut();
52846
52847         } else {
52848
52849             scope.zoomIn();
52850
52851         }
52852
52853     }
52854
52855     this.domElement.addEventListener( 'contextmenu', function ( event ) { event.preventDefault(); }, false );
52856     this.domElement.addEventListener( 'mousedown', onMouseDown, false );
52857     this.domElement.addEventListener( 'mousewheel', onMouseWheel, false );
52858
52859 };
52860 /**
52861  * @author hughes
52862  */
52863
52864 THREE.CircleGeometry = function ( radius, segments, thetaStart, thetaLength ) {
52865
52866     THREE.Geometry.call( this );
52867
52868     radius = radius || 50;
52869
52870     thetaStart = thetaStart !== undefined ? thetaStart : 0;
52871     thetaLength = thetaLength !== undefined ? thetaLength : Math.PI * 2;
52872     segments = segments !== undefined ? Math.max( 3, segments ) : 8;
52873
52874     var i, uvs = [],
52875     center = new THREE.Vector3(), centerUV = new THREE.UV( 0.5, 0.5 );
52876
52877     this.vertices.push(center);
52878     uvs.push( centerUV );
52879
52880     for ( i = 0; i <= segments; i ++ ) {
52881
52882         var vertex = new THREE.Vector3();
52883
52884         vertex.x = radius * Math.cos( thetaStart + i / segments * thetaLength );
52885         vertex.y = radius * Math.sin( thetaStart + i / segments * thetaLength );
52886
52887         this.vertices.push( vertex );
52888         uvs.push( new THREE.UV( ( vertex.x / radius + 1 ) / 2, - ( vertex.y / radius + 1 ) / 2 + 1 ) );
52889
52890     }
52891
52892     var n = new THREE.Vector3( 0, 0, -1 );
52893
52894     for ( i = 1; i <= segments; i ++ ) {
52895
52896         var v1 = i;
52897         var v2 = i + 1 ;
52898         var v3 = 0;
52899
52900         this.faces.push( new THREE.Face3( v1, v2, v3, [ n, n, n ] ) );
52901         this.faceVertexUvs[ 0 ].push( [ uvs[ i ], uvs[ i + 1 ], centerUV ] );
52902
52903     }
52904
52905     this.computeCentroids();
52906     this.computeFaceNormals();
52907
52908     this.boundingSphere = { radius: radius };
52909
52910 };
52911
52912 THREE.CircleGeometry.prototype = Object.create( THREE.Geometry.prototype );
52913 /**
52914  * @author mrdoob / http://mrdoob.com/
52915  * based on http://papervision3d.googlecode.com/svn/trunk/as3/trunk/src/org/papervision3d/objects/primitives/Cube.as
52916  */
52917
52918 THREE.CubeGeometry = function ( width, height, depth, segmentsWidth, segmentsHeight, segmentsDepth, materials, sides ) {
52919
52920     THREE.Geometry.call( this );
52921
52922     var scope = this,
52923     width_half = width / 2,
52924     height_half = height / 2,
52925     depth_half = depth / 2;
52926
52927     var mpx, mpy, mpz, mnx, mny, mnz;
52928
52929     if ( materials !== undefined ) {
52930
52931         if ( materials instanceof Array ) {
52932
52933             this.materials = materials;
52934
52935         } else {
52936
52937             this.materials = [];
52938
52939             for ( var i = 0; i < 6; i ++ ) {
52940
52941                 this.materials.push( materials );
52942
52943             }
52944
52945         }
52946
52947         mpx = 0; mnx = 1; mpy = 2; mny = 3; mpz = 4; mnz = 5;
52948
52949     } else {
52950
52951         this.materials = [];
52952
52953     }
52954
52955     this.sides = { px: true, nx: true, py: true, ny: true, pz: true, nz: true };
52956
52957     if ( sides != undefined ) {
52958
52959         for ( var s in sides ) {
52960
52961             if ( this.sides[ s ] !== undefined ) {
52962
52963                 this.sides[ s ] = sides[ s ];
52964
52965             }
52966
52967         }
52968
52969     }
52970
52971     this.sides.px && buildPlane( 'z', 'y', - 1, - 1, depth, height, width_half, mpx ); // px
52972     this.sides.nx && buildPlane( 'z', 'y',   1, - 1, depth, height, - width_half, mnx ); // nx
52973     this.sides.py && buildPlane( 'x', 'z',   1,   1, width, depth, height_half, mpy ); // py
52974     this.sides.ny && buildPlane( 'x', 'z',   1, - 1, width, depth, - height_half, mny ); // ny
52975     this.sides.pz && buildPlane( 'x', 'y',   1, - 1, width, height, depth_half, mpz ); // pz
52976     this.sides.nz && buildPlane( 'x', 'y', - 1, - 1, width, height, - depth_half, mnz ); // nz
52977
52978     function buildPlane( u, v, udir, vdir, width, height, depth, material ) {
52979
52980         var w, ix, iy,
52981         gridX = segmentsWidth || 1,
52982         gridY = segmentsHeight || 1,
52983         width_half = width / 2,
52984         height_half = height / 2,
52985         offset = scope.vertices.length;
52986
52987         if ( ( u === 'x' && v === 'y' ) || ( u === 'y' && v === 'x' ) ) {
52988
52989             w = 'z';
52990
52991         } else if ( ( u === 'x' && v === 'z' ) || ( u === 'z' && v === 'x' ) ) {
52992
52993             w = 'y';
52994             gridY = segmentsDepth || 1;
52995
52996         } else if ( ( u === 'z' && v === 'y' ) || ( u === 'y' && v === 'z' ) ) {
52997
52998             w = 'x';
52999             gridX = segmentsDepth || 1;
53000
53001         }
53002
53003         var gridX1 = gridX + 1,
53004         gridY1 = gridY + 1,
53005         segment_width = width / gridX,
53006         segment_height = height / gridY,
53007         normal = new THREE.Vector3();
53008
53009         normal[ w ] = depth > 0 ? 1 : - 1;
53010
53011         for ( iy = 0; iy < gridY1; iy ++ ) {
53012
53013             for ( ix = 0; ix < gridX1; ix ++ ) {
53014
53015                 var vector = new THREE.Vector3();
53016                 vector[ u ] = ( ix * segment_width - width_half ) * udir;
53017                 vector[ v ] = ( iy * segment_height - height_half ) * vdir;
53018                 vector[ w ] = depth;
53019
53020                 scope.vertices.push( vector );
53021
53022             }
53023
53024         }
53025
53026         for ( iy = 0; iy < gridY; iy++ ) {
53027
53028             for ( ix = 0; ix < gridX; ix++ ) {
53029
53030                 var a = ix + gridX1 * iy;
53031                 var b = ix + gridX1 * ( iy + 1 );
53032                 var c = ( ix + 1 ) + gridX1 * ( iy + 1 );
53033                 var d = ( ix + 1 ) + gridX1 * iy;
53034
53035                 var face = new THREE.Face4( a + offset, b + offset, c + offset, d + offset );
53036                 face.normal.copy( normal );
53037                 face.vertexNormals.push( normal.clone(), normal.clone(), normal.clone(), normal.clone() );
53038                 face.materialIndex = material;
53039
53040                 scope.faces.push( face );
53041                 scope.faceVertexUvs[ 0 ].push( [
53042                             new THREE.UV( ix / gridX, 1 - iy / gridY ),
53043                             new THREE.UV( ix / gridX, 1 - ( iy + 1 ) / gridY ),
53044                             new THREE.UV( ( ix + 1 ) / gridX, 1- ( iy + 1 ) / gridY ),
53045                             new THREE.UV( ( ix + 1 ) / gridX, 1 - iy / gridY )
53046                         ] );
53047
53048             }
53049
53050         }
53051
53052     }
53053
53054     this.computeCentroids();
53055     this.mergeVertices();
53056
53057 };
53058
53059 THREE.CubeGeometry.prototype = Object.create( THREE.Geometry.prototype );
53060 /**
53061  * @author mrdoob / http://mrdoob.com/
53062  */
53063
53064 THREE.CylinderGeometry = function ( radiusTop, radiusBottom, height, segmentsRadius, segmentsHeight, openEnded ) {
53065
53066     THREE.Geometry.call( this );
53067
53068     radiusTop = radiusTop !== undefined ? radiusTop : 20;
53069     radiusBottom = radiusBottom !== undefined ? radiusBottom : 20;
53070     height = height !== undefined ? height : 100;
53071
53072     var heightHalf = height / 2;
53073     var segmentsX = segmentsRadius || 8;
53074     var segmentsY = segmentsHeight || 1;
53075
53076     var x, y, vertices = [], uvs = [];
53077
53078     for ( y = 0; y <= segmentsY; y ++ ) {
53079
53080         var verticesRow = [];
53081         var uvsRow = [];
53082
53083         var v = y / segmentsY;
53084         var radius = v * ( radiusBottom - radiusTop ) + radiusTop;
53085
53086         for ( x = 0; x <= segmentsX; x ++ ) {
53087
53088             var u = x / segmentsX;
53089
53090             var vertex = new THREE.Vector3();
53091             vertex.x = radius * Math.sin( u * Math.PI * 2 );
53092             vertex.y = - v * height + heightHalf;
53093             vertex.z = radius * Math.cos( u * Math.PI * 2 );
53094
53095             this.vertices.push( vertex );
53096
53097             verticesRow.push( this.vertices.length - 1 );
53098             uvsRow.push( new THREE.UV( u, 1 - v ) );
53099
53100         }
53101
53102         vertices.push( verticesRow );
53103         uvs.push( uvsRow );
53104
53105     }
53106
53107     var tanTheta = ( radiusBottom - radiusTop ) / height;
53108     var na, nb;
53109
53110     for ( x = 0; x < segmentsX; x ++ ) {
53111
53112         if ( radiusTop !== 0 ) {
53113
53114             na = this.vertices[ vertices[ 0 ][ x ] ].clone();
53115             nb = this.vertices[ vertices[ 0 ][ x + 1 ] ].clone();
53116
53117         } else {
53118
53119             na = this.vertices[ vertices[ 1 ][ x ] ].clone();
53120             nb = this.vertices[ vertices[ 1 ][ x + 1 ] ].clone();
53121
53122         }
53123
53124         na.setY( Math.sqrt( na.x * na.x + na.z * na.z ) * tanTheta ).normalize();
53125         nb.setY( Math.sqrt( nb.x * nb.x + nb.z * nb.z ) * tanTheta ).normalize();
53126
53127         for ( y = 0; y < segmentsY; y ++ ) {
53128
53129             var v1 = vertices[ y ][ x ];
53130             var v2 = vertices[ y + 1 ][ x ];
53131             var v3 = vertices[ y + 1 ][ x + 1 ];
53132             var v4 = vertices[ y ][ x + 1 ];
53133
53134             var n1 = na.clone();
53135             var n2 = na.clone();
53136             var n3 = nb.clone();
53137             var n4 = nb.clone();
53138
53139             var uv1 = uvs[ y ][ x ].clone();
53140             var uv2 = uvs[ y + 1 ][ x ].clone();
53141             var uv3 = uvs[ y + 1 ][ x + 1 ].clone();
53142             var uv4 = uvs[ y ][ x + 1 ].clone();
53143
53144             this.faces.push( new THREE.Face4( v1, v2, v3, v4, [ n1, n2, n3, n4 ] ) );
53145             this.faceVertexUvs[ 0 ].push( [ uv1, uv2, uv3, uv4 ] );
53146
53147         }
53148
53149     }
53150
53151     // top cap
53152
53153     if ( !openEnded && radiusTop > 0 ) {
53154
53155         this.vertices.push( new THREE.Vector3( 0, heightHalf, 0 ) );
53156
53157         for ( x = 0; x < segmentsX; x ++ ) {
53158
53159             var v1 = vertices[ 0 ][ x ];
53160             var v2 = vertices[ 0 ][ x + 1 ];
53161             var v3 = this.vertices.length - 1;
53162
53163             var n1 = new THREE.Vector3( 0, 1, 0 );
53164             var n2 = new THREE.Vector3( 0, 1, 0 );
53165             var n3 = new THREE.Vector3( 0, 1, 0 );
53166
53167             var uv1 = uvs[ 0 ][ x ].clone();
53168             var uv2 = uvs[ 0 ][ x + 1 ].clone();
53169             var uv3 = new THREE.UV( uv2.u, 0 );
53170
53171             this.faces.push( new THREE.Face3( v1, v2, v3, [ n1, n2, n3 ] ) );
53172             this.faceVertexUvs[ 0 ].push( [ uv1, uv2, uv3 ] );
53173
53174         }
53175
53176     }
53177
53178     // bottom cap
53179
53180     if ( !openEnded && radiusBottom > 0 ) {
53181
53182         this.vertices.push( new THREE.Vector3( 0, - heightHalf, 0 ) );
53183
53184         for ( x = 0; x < segmentsX; x ++ ) {
53185
53186             var v1 = vertices[ y ][ x + 1 ];
53187             var v2 = vertices[ y ][ x ];
53188             var v3 = this.vertices.length - 1;
53189
53190             var n1 = new THREE.Vector3( 0, - 1, 0 );
53191             var n2 = new THREE.Vector3( 0, - 1, 0 );
53192             var n3 = new THREE.Vector3( 0, - 1, 0 );
53193
53194             var uv1 = uvs[ y ][ x + 1 ].clone();
53195             var uv2 = uvs[ y ][ x ].clone();
53196             var uv3 = new THREE.UV( uv2.u, 1 );
53197
53198             this.faces.push( new THREE.Face3( v1, v2, v3, [ n1, n2, n3 ] ) );
53199             this.faceVertexUvs[ 0 ].push( [ uv1, uv2, uv3 ] );
53200
53201         }
53202
53203     }
53204
53205     this.computeCentroids();
53206     this.computeFaceNormals();
53207
53208 }
53209
53210 THREE.CylinderGeometry.prototype = Object.create( THREE.Geometry.prototype );
53211 /**
53212  * @author zz85 / http://www.lab4games.net/zz85/blog
53213  *
53214  * Creates extruded geometry from a path shape.
53215  *
53216  * parameters = {
53217  *
53218  *  size: <float>, // size of the text
53219  *  height: <float>, // thickness to extrude text
53220  *  curveSegments: <int>, // number of points on the curves
53221  *  steps: <int>, // number of points for z-side extrusions / used for subdividing segements of extrude spline too
53222  *  amount: <int>, // Amount
53223  *
53224  *  bevelEnabled: <bool>, // turn on bevel
53225  *  bevelThickness: <float>, // how deep into text bevel goes
53226  *  bevelSize: <float>, // how far from text outline is bevel
53227  *  bevelSegments: <int>, // number of bevel layers
53228  *
53229  *  extrudePath: <THREE.CurvePath> // 3d spline path to extrude shape along. (creates Frames if .frames aren't defined)
53230  *  frames: <THREE.TubeGeometry.FrenetFrames> // containing arrays of tangents, normals, binormals
53231  *
53232  *  material: <int> // material index for front and back faces
53233  *  extrudeMaterial: <int> // material index for extrusion and beveled faces
53234  *  uvGenerator: <Object> // object that provides UV generator functions
53235  *
53236  * }
53237  **/
53238
53239 THREE.ExtrudeGeometry = function ( shapes, options ) {
53240
53241     if ( typeof( shapes ) === "undefined" ) {
53242         shapes = [];
53243         return;
53244     }
53245
53246     THREE.Geometry.call( this );
53247
53248     shapes = shapes instanceof Array ? shapes : [ shapes ];
53249
53250     this.shapebb = shapes[ shapes.length - 1 ].getBoundingBox();
53251
53252     this.addShapeList( shapes, options );
53253
53254     this.computeCentroids();
53255     this.computeFaceNormals();
53256
53257     // can't really use automatic vertex normals
53258     // as then front and back sides get smoothed too
53259     // should do separate smoothing just for sides
53260
53261     //this.computeVertexNormals();
53262
53263     //console.log( "took", ( Date.now() - startTime ) );
53264
53265 };
53266
53267 THREE.ExtrudeGeometry.prototype = Object.create( THREE.Geometry.prototype );
53268
53269 THREE.ExtrudeGeometry.prototype.addShapeList = function ( shapes, options ) {
53270     var sl = shapes.length;
53271
53272     for ( var s = 0; s < sl; s ++ ) {
53273         var shape = shapes[ s ];
53274         this.addShape( shape, options );
53275     }
53276 };
53277
53278 THREE.ExtrudeGeometry.prototype.addShape = function ( shape, options ) {
53279
53280     var amount = options.amount !== undefined ? options.amount : 100;
53281
53282     var bevelThickness = options.bevelThickness !== undefined ? options.bevelThickness : 6; // 10
53283     var bevelSize = options.bevelSize !== undefined ? options.bevelSize : bevelThickness - 2; // 8
53284     var bevelSegments = options.bevelSegments !== undefined ? options.bevelSegments : 3;
53285
53286     var bevelEnabled = options.bevelEnabled !== undefined ? options.bevelEnabled : true; // false
53287
53288     var curveSegments = options.curveSegments !== undefined ? options.curveSegments : 12;
53289
53290     var steps = options.steps !== undefined ? options.steps : 1;
53291
53292     var extrudePath = options.extrudePath;
53293     var extrudePts, extrudeByPath = false;
53294
53295     var material = options.material;
53296     var extrudeMaterial = options.extrudeMaterial;
53297
53298     // Use default WorldUVGenerator if no UV generators are specified.
53299     var uvgen = options.UVGenerator !== undefined ? options.UVGenerator : THREE.ExtrudeGeometry.WorldUVGenerator;
53300
53301     var shapebb = this.shapebb;
53302     //shapebb = shape.getBoundingBox();
53303
53304
53305
53306     var splineTube, binormal, normal, position2;
53307     if ( extrudePath ) {
53308
53309         extrudePts = extrudePath.getSpacedPoints( steps );
53310
53311         extrudeByPath = true;
53312         bevelEnabled = false; // bevels not supported for path extrusion
53313
53314         // SETUP TNB variables
53315
53316         // Reuse TNB from TubeGeomtry for now.
53317         // TODO1 - have a .isClosed in spline?
53318
53319         splineTube = options.frames !== undefined ? options.frames : new THREE.TubeGeometry.FrenetFrames(extrudePath, steps, false);
53320
53321         // console.log(splineTube, 'splineTube', splineTube.normals.length, 'steps', steps, 'extrudePts', extrudePts.length);
53322
53323         binormal = new THREE.Vector3();
53324         normal = new THREE.Vector3();
53325         position2 = new THREE.Vector3();
53326
53327     }
53328
53329     // Safeguards if bevels are not enabled
53330
53331     if ( ! bevelEnabled ) {
53332
53333         bevelSegments = 0;
53334         bevelThickness = 0;
53335         bevelSize = 0;
53336
53337     }
53338
53339     // Variables initalization
53340
53341     var ahole, h, hl; // looping of holes
53342     var scope = this;
53343     var bevelPoints = [];
53344
53345     var shapesOffset = this.vertices.length;
53346
53347     var shapePoints = shape.extractPoints();
53348
53349     var vertices = shapePoints.shape;
53350     var holes = shapePoints.holes;
53351
53352     var reverse = !THREE.Shape.Utils.isClockWise( vertices ) ;
53353
53354     if ( reverse ) {
53355
53356         vertices = vertices.reverse();
53357
53358         // Maybe we should also check if holes are in the opposite direction, just to be safe ...
53359
53360         for ( h = 0, hl = holes.length; h < hl; h ++ ) {
53361
53362             ahole = holes[ h ];
53363
53364             if ( THREE.Shape.Utils.isClockWise( ahole ) ) {
53365
53366                 holes[ h ] = ahole.reverse();
53367
53368             }
53369
53370         }
53371
53372         reverse = false; // If vertices are in order now, we shouldn't need to worry about them again (hopefully)!
53373
53374     }
53375
53376
53377     var faces = THREE.Shape.Utils.triangulateShape ( vertices, holes );
53378
53379     /* Vertices */
53380
53381     var contour = vertices; // vertices has all points but contour has only points of circumference
53382
53383     for ( h = 0, hl = holes.length;  h < hl; h ++ ) {
53384
53385         ahole = holes[ h ];
53386
53387         vertices = vertices.concat( ahole );
53388
53389     }
53390
53391
53392     function scalePt2 ( pt, vec, size ) {
53393
53394         if ( !vec ) console.log( "die" );
53395
53396         return vec.clone().multiplyScalar( size ).addSelf( pt );
53397
53398     }
53399
53400     var b, bs, t, z,
53401         vert, vlen = vertices.length,
53402         face, flen = faces.length,
53403         cont, clen = contour.length;
53404
53405
53406     // Find directions for point movement
53407
53408     var RAD_TO_DEGREES = 180 / Math.PI;
53409
53410
53411     function getBevelVec( pt_i, pt_j, pt_k ) {
53412
53413         // Algorithm 2
53414
53415         return getBevelVec2( pt_i, pt_j, pt_k );
53416
53417     }
53418
53419     function getBevelVec1( pt_i, pt_j, pt_k ) {
53420
53421         var anglea = Math.atan2( pt_j.y - pt_i.y, pt_j.x - pt_i.x );
53422         var angleb = Math.atan2( pt_k.y - pt_i.y, pt_k.x - pt_i.x );
53423
53424         if ( anglea > angleb ) {
53425
53426             angleb += Math.PI * 2;
53427
53428         }
53429
53430         var anglec = ( anglea + angleb ) / 2;
53431
53432
53433         //console.log('angle1', anglea * RAD_TO_DEGREES,'angle2', angleb * RAD_TO_DEGREES, 'anglec', anglec *RAD_TO_DEGREES);
53434
53435         var x = - Math.cos( anglec );
53436         var y = - Math.sin( anglec );
53437
53438         var vec = new THREE.Vector2( x, y ); //.normalize();
53439
53440         return vec;
53441
53442     }
53443
53444     function getBevelVec2( pt_i, pt_j, pt_k ) {
53445
53446         var a = THREE.ExtrudeGeometry.__v1,
53447             b = THREE.ExtrudeGeometry.__v2,
53448             v_hat = THREE.ExtrudeGeometry.__v3,
53449             w_hat = THREE.ExtrudeGeometry.__v4,
53450             p = THREE.ExtrudeGeometry.__v5,
53451             q = THREE.ExtrudeGeometry.__v6,
53452             v, w,
53453             v_dot_w_hat, q_sub_p_dot_w_hat,
53454             s, intersection;
53455
53456         // good reading for line-line intersection
53457         // http://sputsoft.com/blog/2010/03/line-line-intersection.html
53458
53459         // define a as vector j->i
53460         // define b as vectot k->i
53461
53462         a.set( pt_i.x - pt_j.x, pt_i.y - pt_j.y );
53463         b.set( pt_i.x - pt_k.x, pt_i.y - pt_k.y );
53464
53465         // get unit vectors
53466
53467         v = a.normalize();
53468         w = b.normalize();
53469
53470         // normals from pt i
53471
53472         v_hat.set( -v.y, v.x );
53473         w_hat.set( w.y, -w.x );
53474
53475         // pts from i
53476
53477         p.copy( pt_i ).addSelf( v_hat );
53478         q.copy( pt_i ).addSelf( w_hat );
53479
53480         if ( p.equals( q ) ) {
53481
53482             //console.log("Warning: lines are straight");
53483             return w_hat.clone();
53484
53485         }
53486
53487         // Points from j, k. helps prevents points cross overover most of the time
53488
53489         p.copy( pt_j ).addSelf( v_hat );
53490         q.copy( pt_k ).addSelf( w_hat );
53491
53492         v_dot_w_hat = v.dot( w_hat );
53493         q_sub_p_dot_w_hat = q.subSelf( p ).dot( w_hat );
53494
53495         // We should not reach these conditions
53496
53497         if ( v_dot_w_hat === 0 ) {
53498
53499             console.log( "Either infinite or no solutions!" );
53500
53501             if ( q_sub_p_dot_w_hat === 0 ) {
53502
53503                 console.log( "Its finite solutions." );
53504
53505             } else {
53506
53507                 console.log( "Too bad, no solutions." );
53508
53509             }
53510
53511         }
53512
53513         s = q_sub_p_dot_w_hat / v_dot_w_hat;
53514
53515         if ( s < 0 ) {
53516
53517             // in case of emergecy, revert to algorithm 1.
53518
53519             return getBevelVec1( pt_i, pt_j, pt_k );
53520
53521         }
53522
53523         intersection = v.multiplyScalar( s ).addSelf( p );
53524
53525         return intersection.subSelf( pt_i ).clone(); // Don't normalize!, otherwise sharp corners become ugly
53526
53527     }
53528
53529     var contourMovements = [];
53530
53531     for ( var i = 0, il = contour.length, j = il - 1, k = i + 1; i < il; i ++, j ++, k ++ ) {
53532
53533         if ( j === il ) j = 0;
53534         if ( k === il ) k = 0;
53535
53536         //  (j)---(i)---(k)
53537         // console.log('i,j,k', i, j , k)
53538
53539         var pt_i = contour[ i ];
53540         var pt_j = contour[ j ];
53541         var pt_k = contour[ k ];
53542
53543         contourMovements[ i ]= getBevelVec( contour[ i ], contour[ j ], contour[ k ] );
53544
53545     }
53546
53547     var holesMovements = [], oneHoleMovements, verticesMovements = contourMovements.concat();
53548
53549     for ( h = 0, hl = holes.length; h < hl; h ++ ) {
53550
53551         ahole = holes[ h ];
53552
53553         oneHoleMovements = [];
53554
53555         for ( i = 0, il = ahole.length, j = il - 1, k = i + 1; i < il; i ++, j ++, k ++ ) {
53556
53557             if ( j === il ) j = 0;
53558             if ( k === il ) k = 0;
53559
53560             //  (j)---(i)---(k)
53561             oneHoleMovements[ i ]= getBevelVec( ahole[ i ], ahole[ j ], ahole[ k ] );
53562
53563         }
53564
53565         holesMovements.push( oneHoleMovements );
53566         verticesMovements = verticesMovements.concat( oneHoleMovements );
53567
53568     }
53569
53570
53571     // Loop bevelSegments, 1 for the front, 1 for the back
53572
53573     for ( b = 0; b < bevelSegments; b ++ ) {
53574     //for ( b = bevelSegments; b > 0; b -- ) {
53575
53576         t = b / bevelSegments;
53577         z = bevelThickness * ( 1 - t );
53578
53579         //z = bevelThickness * t;
53580         bs = bevelSize * ( Math.sin ( t * Math.PI/2 ) ) ; // curved
53581         //bs = bevelSize * t ; // linear
53582
53583         // contract shape
53584
53585         for ( i = 0, il = contour.length; i < il; i ++ ) {
53586
53587             vert = scalePt2( contour[ i ], contourMovements[ i ], bs );
53588             //vert = scalePt( contour[ i ], contourCentroid, bs, false );
53589             v( vert.x, vert.y,  - z );
53590
53591         }
53592
53593         // expand holes
53594
53595         for ( h = 0, hl = holes.length; h < hl; h++ ) {
53596
53597             ahole = holes[ h ];
53598             oneHoleMovements = holesMovements[ h ];
53599
53600             for ( i = 0, il = ahole.length; i < il; i++ ) {
53601
53602                 vert = scalePt2( ahole[ i ], oneHoleMovements[ i ], bs );
53603                 //vert = scalePt( ahole[ i ], holesCentroids[ h ], bs, true );
53604
53605                 v( vert.x, vert.y,  -z );
53606
53607             }
53608
53609         }
53610
53611     }
53612
53613     bs = bevelSize;
53614
53615     // Back facing vertices
53616
53617     for ( i = 0; i < vlen; i ++ ) {
53618
53619         vert = bevelEnabled ? scalePt2( vertices[ i ], verticesMovements[ i ], bs ) : vertices[ i ];
53620
53621         if ( !extrudeByPath ) {
53622
53623             v( vert.x, vert.y, 0 );
53624
53625         } else {
53626
53627             // v( vert.x, vert.y + extrudePts[ 0 ].y, extrudePts[ 0 ].x );
53628
53629             normal.copy( splineTube.normals[0] ).multiplyScalar(vert.x);
53630             binormal.copy( splineTube.binormals[0] ).multiplyScalar(vert.y);
53631
53632             position2.copy( extrudePts[0] ).addSelf(normal).addSelf(binormal);
53633
53634             v( position2.x, position2.y, position2.z );
53635
53636         }
53637
53638     }
53639
53640     // Add stepped vertices...
53641     // Including front facing vertices
53642
53643     var s;
53644
53645     for ( s = 1; s <= steps; s ++ ) {
53646
53647         for ( i = 0; i < vlen; i ++ ) {
53648
53649             vert = bevelEnabled ? scalePt2( vertices[ i ], verticesMovements[ i ], bs ) : vertices[ i ];
53650
53651             if ( !extrudeByPath ) {
53652
53653                 v( vert.x, vert.y, amount / steps * s );
53654
53655             } else {
53656
53657                 // v( vert.x, vert.y + extrudePts[ s - 1 ].y, extrudePts[ s - 1 ].x );
53658
53659                 normal.copy( splineTube.normals[s] ).multiplyScalar( vert.x );
53660                 binormal.copy( splineTube.binormals[s] ).multiplyScalar( vert.y );
53661
53662                 position2.copy( extrudePts[s] ).addSelf( normal ).addSelf( binormal );
53663
53664                 v( position2.x, position2.y, position2.z );
53665
53666             }
53667
53668         }
53669
53670     }
53671
53672
53673     // Add bevel segments planes
53674
53675     //for ( b = 1; b <= bevelSegments; b ++ ) {
53676     for ( b = bevelSegments - 1; b >= 0; b -- ) {
53677
53678         t = b / bevelSegments;
53679         z = bevelThickness * ( 1 - t );
53680         //bs = bevelSize * ( 1-Math.sin ( ( 1 - t ) * Math.PI/2 ) );
53681         bs = bevelSize * Math.sin ( t * Math.PI/2 ) ;
53682
53683         // contract shape
53684
53685         for ( i = 0, il = contour.length; i < il; i ++ ) {
53686
53687             vert = scalePt2( contour[ i ], contourMovements[ i ], bs );
53688             v( vert.x, vert.y,  amount + z );
53689
53690         }
53691
53692         // expand holes
53693
53694         for ( h = 0, hl = holes.length; h < hl; h ++ ) {
53695
53696             ahole = holes[ h ];
53697             oneHoleMovements = holesMovements[ h ];
53698
53699             for ( i = 0, il = ahole.length; i < il; i ++ ) {
53700
53701                 vert = scalePt2( ahole[ i ], oneHoleMovements[ i ], bs );
53702
53703                 if ( !extrudeByPath ) {
53704
53705                     v( vert.x, vert.y,  amount + z );
53706
53707                 } else {
53708
53709                     v( vert.x, vert.y + extrudePts[ steps - 1 ].y, extrudePts[ steps - 1 ].x + z );
53710
53711                 }
53712
53713             }
53714
53715         }
53716
53717     }
53718
53719     /* Faces */
53720
53721     // Top and bottom faces
53722
53723     buildLidFaces();
53724
53725     // Sides faces
53726
53727     buildSideFaces();
53728
53729
53730     /////  Internal functions
53731
53732     function buildLidFaces() {
53733
53734         if ( bevelEnabled ) {
53735
53736             var layer = 0 ; // steps + 1
53737             var offset = vlen * layer;
53738
53739             // Bottom faces
53740
53741             for ( i = 0; i < flen; i ++ ) {
53742
53743                 face = faces[ i ];
53744                 f3( face[ 2 ]+ offset, face[ 1 ]+ offset, face[ 0 ] + offset, true );
53745
53746             }
53747
53748             layer = steps + bevelSegments * 2;
53749             offset = vlen * layer;
53750
53751             // Top faces
53752
53753             for ( i = 0; i < flen; i ++ ) {
53754
53755                 face = faces[ i ];
53756                 f3( face[ 0 ] + offset, face[ 1 ] + offset, face[ 2 ] + offset, false );
53757
53758             }
53759
53760         } else {
53761
53762             // Bottom faces
53763
53764             for ( i = 0; i < flen; i++ ) {
53765
53766                 face = faces[ i ];
53767                 f3( face[ 2 ], face[ 1 ], face[ 0 ], true );
53768
53769             }
53770
53771             // Top faces
53772
53773             for ( i = 0; i < flen; i ++ ) {
53774
53775                 face = faces[ i ];
53776                 f3( face[ 0 ] + vlen * steps, face[ 1 ] + vlen * steps, face[ 2 ] + vlen * steps, false );
53777
53778             }
53779         }
53780
53781     }
53782
53783     // Create faces for the z-sides of the shape
53784
53785     function buildSideFaces() {
53786
53787         var layeroffset = 0;
53788         sidewalls( contour, layeroffset );
53789         layeroffset += contour.length;
53790
53791         for ( h = 0, hl = holes.length;  h < hl; h ++ ) {
53792
53793             ahole = holes[ h ];
53794             sidewalls( ahole, layeroffset );
53795
53796             //, true
53797             layeroffset += ahole.length;
53798
53799         }
53800
53801     }
53802
53803     function sidewalls( contour, layeroffset ) {
53804
53805         var j, k;
53806         i = contour.length;
53807
53808         while ( --i >= 0 ) {
53809
53810             j = i;
53811             k = i - 1;
53812             if ( k < 0 ) k = contour.length - 1;
53813
53814             //console.log('b', i,j, i-1, k,vertices.length);
53815
53816             var s = 0, sl = steps  + bevelSegments * 2;
53817
53818             for ( s = 0; s < sl; s ++ ) {
53819
53820                 var slen1 = vlen * s;
53821                 var slen2 = vlen * ( s + 1 );
53822
53823                 var a = layeroffset + j + slen1,
53824                     b = layeroffset + k + slen1,
53825                     c = layeroffset + k + slen2,
53826                     d = layeroffset + j + slen2;
53827
53828                 f4( a, b, c, d, contour, s, sl, j, k );
53829
53830             }
53831         }
53832
53833     }
53834
53835
53836     function v( x, y, z ) {
53837
53838         scope.vertices.push( new THREE.Vector3( x, y, z ) );
53839
53840     }
53841
53842     function f3( a, b, c, isBottom ) {
53843
53844         a += shapesOffset;
53845         b += shapesOffset;
53846         c += shapesOffset;
53847
53848         // normal, color, material
53849         scope.faces.push( new THREE.Face3( a, b, c, null, null, material ) );
53850
53851         var uvs = isBottom ? uvgen.generateBottomUV( scope, shape, options, a, b, c ) : uvgen.generateTopUV( scope, shape, options, a, b, c );
53852
53853          scope.faceVertexUvs[ 0 ].push( uvs );
53854
53855     }
53856
53857     function f4( a, b, c, d, wallContour, stepIndex, stepsLength, contourIndex1, contourIndex2 ) {
53858
53859         a += shapesOffset;
53860         b += shapesOffset;
53861         c += shapesOffset;
53862         d += shapesOffset;
53863
53864          scope.faces.push( new THREE.Face4( a, b, c, d, null, null, extrudeMaterial ) );
53865
53866          var uvs = uvgen.generateSideWallUV( scope, shape, wallContour, options, a, b, c, d,
53867                                              stepIndex, stepsLength, contourIndex1, contourIndex2 );
53868          scope.faceVertexUvs[ 0 ].push( uvs );
53869
53870     }
53871
53872 };
53873
53874 THREE.ExtrudeGeometry.WorldUVGenerator = {
53875
53876     generateTopUV: function( geometry, extrudedShape, extrudeOptions, indexA, indexB, indexC ) {
53877         var ax = geometry.vertices[ indexA ].x,
53878             ay = geometry.vertices[ indexA ].y,
53879
53880             bx = geometry.vertices[ indexB ].x,
53881             by = geometry.vertices[ indexB ].y,
53882
53883             cx = geometry.vertices[ indexC ].x,
53884             cy = geometry.vertices[ indexC ].y;
53885
53886         return [
53887             new THREE.UV( ax, ay ),
53888             new THREE.UV( bx, by ),
53889             new THREE.UV( cx, cy )
53890         ];
53891
53892     },
53893
53894     generateBottomUV: function( geometry, extrudedShape, extrudeOptions, indexA, indexB, indexC ) {
53895
53896         return this.generateTopUV( geometry, extrudedShape, extrudeOptions, indexA, indexB, indexC );
53897
53898     },
53899
53900     generateSideWallUV: function( geometry, extrudedShape, wallContour, extrudeOptions,
53901                                   indexA, indexB, indexC, indexD, stepIndex, stepsLength,
53902                                   contourIndex1, contourIndex2 ) {
53903
53904         var ax = geometry.vertices[ indexA ].x,
53905             ay = geometry.vertices[ indexA ].y,
53906             az = geometry.vertices[ indexA ].z,
53907
53908             bx = geometry.vertices[ indexB ].x,
53909             by = geometry.vertices[ indexB ].y,
53910             bz = geometry.vertices[ indexB ].z,
53911
53912             cx = geometry.vertices[ indexC ].x,
53913             cy = geometry.vertices[ indexC ].y,
53914             cz = geometry.vertices[ indexC ].z,
53915
53916             dx = geometry.vertices[ indexD ].x,
53917             dy = geometry.vertices[ indexD ].y,
53918             dz = geometry.vertices[ indexD ].z;
53919
53920         if ( Math.abs( ay - by ) < 0.01 ) {
53921             return [
53922                 new THREE.UV( ax, 1 - az ),
53923                 new THREE.UV( bx, 1 - bz ),
53924                 new THREE.UV( cx, 1 - cz ),
53925                 new THREE.UV( dx, 1 - dz )
53926             ];
53927         } else {
53928             return [
53929                 new THREE.UV( ay, 1 - az ),
53930                 new THREE.UV( by, 1 - bz ),
53931                 new THREE.UV( cy, 1 - cz ),
53932                 new THREE.UV( dy, 1 - dz )
53933             ];
53934         }
53935     }
53936 };
53937
53938 THREE.ExtrudeGeometry.__v1 = new THREE.Vector2();
53939 THREE.ExtrudeGeometry.__v2 = new THREE.Vector2();
53940 THREE.ExtrudeGeometry.__v3 = new THREE.Vector2();
53941 THREE.ExtrudeGeometry.__v4 = new THREE.Vector2();
53942 THREE.ExtrudeGeometry.__v5 = new THREE.Vector2();
53943 THREE.ExtrudeGeometry.__v6 = new THREE.Vector2();
53944 /**
53945  * @author jonobr1 / http://jonobr1.com
53946  *
53947  * Creates a one-sided polygonal geometry from a path shape. Similar to
53948  * ExtrudeGeometry.
53949  *
53950  * parameters = {
53951  *
53952  *    curveSegments: <int>, // number of points on the curves. NOT USED AT THE MOMENT.
53953  *
53954  *    material: <int> // material index for front and back faces
53955  *    uvGenerator: <Object> // object that provides UV generator functions
53956  *
53957  * }
53958  **/
53959
53960 THREE.ShapeGeometry = function ( shapes, options ) {
53961
53962     THREE.Geometry.call( this );
53963
53964     if ( shapes instanceof Array === false ) shapes = [ shapes ];
53965
53966     this.shapebb = shapes[ shapes.length - 1 ].getBoundingBox();
53967
53968     this.addShapeList( shapes, options );
53969
53970     this.computeCentroids();
53971     this.computeFaceNormals();
53972
53973 };
53974
53975 THREE.ShapeGeometry.prototype = Object.create( THREE.Geometry.prototype );
53976
53977 /**
53978  * Add an array of shapes to THREE.ShapeGeometry.
53979  */
53980 THREE.ShapeGeometry.prototype.addShapeList = function ( shapes, options ) {
53981
53982     for ( var i = 0, l = shapes.length; i < l; i++ ) {
53983
53984         this.addShape( shapes[ i ], options );
53985
53986     }
53987
53988     return this;
53989
53990 };
53991
53992 /**
53993  * Adds a shape to THREE.ShapeGeometry, based on THREE.ExtrudeGeometry.
53994  */
53995 THREE.ShapeGeometry.prototype.addShape = function ( shape, options ) {
53996
53997     if ( options === undefined ) options = {};
53998
53999     var material = options.material;
54000     var uvgen = options.UVGenerator === undefined ? THREE.ExtrudeGeometry.WorldUVGenerator : options.UVGenerator;
54001
54002     var shapebb = this.shapebb;
54003
54004     //
54005
54006     var i, l, hole, s;
54007
54008     var shapesOffset = this.vertices.length;
54009     var shapePoints = shape.extractPoints();
54010
54011     var vertices = shapePoints.shape;
54012     var holes = shapePoints.holes;
54013
54014     var reverse = !THREE.Shape.Utils.isClockWise( vertices );
54015
54016     if ( reverse ) {
54017
54018         vertices = vertices.reverse();
54019
54020         // Maybe we should also check if holes are in the opposite direction, just to be safe...
54021
54022         for ( i = 0, l = holes.length; i < l; i++ ) {
54023
54024             hole = holes[ i ];
54025
54026             if ( THREE.Shape.Utils.isClockWise( hole ) ) {
54027
54028                 holes[ i ] = hole.reverse();
54029
54030             }
54031
54032         }
54033
54034         reverse = false;
54035
54036     }
54037
54038     var faces = THREE.Shape.Utils.triangulateShape( vertices, holes );
54039
54040     // Vertices
54041
54042     var contour = vertices;
54043
54044     for ( i = 0, l = holes.length; i < l; i++ ) {
54045
54046         hole = holes[ i ];
54047         vertices = vertices.concat( hole );
54048
54049     }
54050
54051     //
54052
54053     var vert, vlen = vertices.length;
54054     var face, flen = faces.length;
54055     var cont, clen = contour.length;
54056
54057     for ( i = 0; i < vlen; i++ ) {
54058
54059         vert = vertices[ i ];
54060
54061         this.vertices.push( new THREE.Vector3( vert.x, vert.y, 0 ) );
54062
54063     }
54064
54065     for ( i = 0; i < flen; i++ ) {
54066
54067         face = faces[ i ];
54068
54069         var a = face[ 2 ] + shapesOffset;
54070         var b = face[ 1 ] + shapesOffset;
54071         var c = face[ 0 ] + shapesOffset;
54072
54073         this.faces.push( new THREE.Face3( a, b, c, null, null, material ) );
54074         this.faceVertexUvs[ 0 ].push( uvgen.generateBottomUV( this, shape, options, a, b, c ) );
54075
54076     }
54077
54078 };
54079 /**
54080  * @author astrodud / http://astrodud.isgreat.org/
54081  * @author zz85 / https://github.com/zz85
54082  */
54083
54084 THREE.LatheGeometry = function ( points, steps, angle ) {
54085
54086     THREE.Geometry.call( this );
54087
54088     var _steps = steps || 12;
54089     var _angle = angle || 2 * Math.PI;
54090
54091     var _newV = [];
54092     var _matrix = new THREE.Matrix4().makeRotationZ( _angle / _steps );
54093
54094     for ( var j = 0; j < points.length; j ++ ) {
54095
54096         _newV[ j ] = points[ j ].clone();
54097         this.vertices.push( _newV[ j ] );
54098
54099     }
54100
54101     var i, il = _steps + 1;
54102
54103     for ( i = 0; i < il; i ++ ) {
54104
54105         for ( var j = 0; j < _newV.length; j ++ ) {
54106
54107             _newV[ j ] = _matrix.multiplyVector3( _newV[ j ].clone() );
54108             this.vertices.push( _newV[ j ] );
54109
54110         }
54111
54112     }
54113
54114     for ( i = 0; i < _steps; i ++ ) {
54115
54116         for ( var k = 0, kl = points.length; k < kl - 1; k ++ ) {
54117
54118             var a = i * kl + k;
54119             var b = ( ( i + 1 ) % il ) * kl + k;
54120             var c = ( ( i + 1 ) % il ) * kl + ( k + 1 ) % kl;
54121             var d = i * kl + ( k + 1 ) % kl;
54122
54123             this.faces.push( new THREE.Face4( a, b, c, d ) );
54124
54125             this.faceVertexUvs[ 0 ].push( [
54126
54127                 new THREE.UV( 1 - i / _steps, k / kl ),
54128                 new THREE.UV( 1 - ( i + 1 ) / _steps, k / kl ),
54129                 new THREE.UV( 1 - ( i + 1 ) / _steps, ( k + 1 ) / kl ),
54130                 new THREE.UV( 1 - i / _steps, ( k + 1 ) / kl )
54131
54132             ] );
54133
54134         }
54135
54136     }
54137
54138     this.computeCentroids();
54139     this.computeFaceNormals();
54140     this.computeVertexNormals();
54141
54142 };
54143
54144 THREE.LatheGeometry.prototype = Object.create( THREE.Geometry.prototype );
54145 /**
54146  * @author mrdoob / http://mrdoob.com/
54147  * based on http://papervision3d.googlecode.com/svn/trunk/as3/trunk/src/org/papervision3d/objects/primitives/Plane.as
54148  */
54149
54150 THREE.PlaneGeometry = function ( width, height, segmentsWidth, segmentsheight ) {
54151
54152     THREE.Geometry.call( this );
54153
54154     var ix, iz,
54155     width_half = width / 2,
54156     height_half = height / 2,
54157     gridX = segmentsWidth || 1,
54158     gridZ = segmentsheight || 1,
54159     gridX1 = gridX + 1,
54160     gridZ1 = gridZ + 1,
54161     segment_width = width / gridX,
54162     segment_height = height / gridZ,
54163     normal = new THREE.Vector3( 0, 0, 1 );
54164
54165     for ( iz = 0; iz < gridZ1; iz ++ ) {
54166
54167         for ( ix = 0; ix < gridX1; ix ++ ) {
54168
54169             var x = ix * segment_width - width_half;
54170             var y = iz * segment_height - height_half;
54171
54172             this.vertices.push( new THREE.Vector3( x, - y, 0 ) );
54173
54174         }
54175
54176     }
54177
54178     for ( iz = 0; iz < gridZ; iz ++ ) {
54179
54180         for ( ix = 0; ix < gridX; ix ++ ) {
54181
54182             var a = ix + gridX1 * iz;
54183             var b = ix + gridX1 * ( iz + 1 );
54184             var c = ( ix + 1 ) + gridX1 * ( iz + 1 );
54185             var d = ( ix + 1 ) + gridX1 * iz;
54186
54187             var face = new THREE.Face4( a, b, c, d );
54188             face.normal.copy( normal );
54189             face.vertexNormals.push( normal.clone(), normal.clone(), normal.clone(), normal.clone() );
54190
54191             this.faces.push( face );
54192             this.faceVertexUvs[ 0 ].push( [
54193                 new THREE.UV( ix / gridX, 1 - iz / gridZ ),
54194                 new THREE.UV( ix / gridX, 1 - ( iz + 1 ) / gridZ ),
54195                 new THREE.UV( ( ix + 1 ) / gridX, 1 - ( iz + 1 ) / gridZ ),
54196                 new THREE.UV( ( ix + 1 ) / gridX, 1 - iz / gridZ )
54197             ] );
54198
54199         }
54200
54201     }
54202
54203     this.computeCentroids();
54204
54205 };
54206
54207 THREE.PlaneGeometry.prototype = Object.create( THREE.Geometry.prototype );
54208 /**
54209  * @author mrdoob / http://mrdoob.com/
54210  */
54211
54212 THREE.SphereGeometry = function ( radius, segmentsWidth, segmentsHeight, phiStart, phiLength, thetaStart, thetaLength ) {
54213
54214     THREE.Geometry.call( this );
54215
54216     radius = radius || 50;
54217
54218     phiStart = phiStart !== undefined ? phiStart : 0;
54219     phiLength = phiLength !== undefined ? phiLength : Math.PI * 2;
54220
54221     thetaStart = thetaStart !== undefined ? thetaStart : 0;
54222     thetaLength = thetaLength !== undefined ? thetaLength : Math.PI;
54223
54224     var segmentsX = Math.max( 3, Math.floor( segmentsWidth ) || 8 );
54225     var segmentsY = Math.max( 2, Math.floor( segmentsHeight ) || 6 );
54226
54227     var x, y, vertices = [], uvs = [];
54228
54229     for ( y = 0; y <= segmentsY; y ++ ) {
54230
54231         var verticesRow = [];
54232         var uvsRow = [];
54233
54234         for ( x = 0; x <= segmentsX; x ++ ) {
54235
54236             var u = x / segmentsX;
54237             var v = y / segmentsY;
54238
54239             var vertex = new THREE.Vector3();
54240             vertex.x = - radius * Math.cos( phiStart + u * phiLength ) * Math.sin( thetaStart + v * thetaLength );
54241             vertex.y = radius * Math.cos( thetaStart + v * thetaLength );
54242             vertex.z = radius * Math.sin( phiStart + u * phiLength ) * Math.sin( thetaStart + v * thetaLength );
54243
54244             this.vertices.push( vertex );
54245
54246             verticesRow.push( this.vertices.length - 1 );
54247             uvsRow.push( new THREE.UV( u, 1 - v ) );
54248
54249         }
54250
54251         vertices.push( verticesRow );
54252         uvs.push( uvsRow );
54253
54254     }
54255
54256     for ( y = 0; y < segmentsY; y ++ ) {
54257
54258         for ( x = 0; x < segmentsX; x ++ ) {
54259
54260             var v1 = vertices[ y ][ x + 1 ];
54261             var v2 = vertices[ y ][ x ];
54262             var v3 = vertices[ y + 1 ][ x ];
54263             var v4 = vertices[ y + 1 ][ x + 1 ];
54264
54265             var n1 = this.vertices[ v1 ].clone().normalize();
54266             var n2 = this.vertices[ v2 ].clone().normalize();
54267             var n3 = this.vertices[ v3 ].clone().normalize();
54268             var n4 = this.vertices[ v4 ].clone().normalize();
54269
54270             var uv1 = uvs[ y ][ x + 1 ].clone();
54271             var uv2 = uvs[ y ][ x ].clone();
54272             var uv3 = uvs[ y + 1 ][ x ].clone();
54273             var uv4 = uvs[ y + 1 ][ x + 1 ].clone();
54274
54275             if ( Math.abs( this.vertices[ v1 ].y ) == radius ) {
54276
54277                 this.faces.push( new THREE.Face3( v1, v3, v4, [ n1, n3, n4 ] ) );
54278                 this.faceVertexUvs[ 0 ].push( [ uv1, uv3, uv4 ] );
54279
54280             } else if ( Math.abs( this.vertices[ v3 ].y ) ==  radius ) {
54281
54282                 this.faces.push( new THREE.Face3( v1, v2, v3, [ n1, n2, n3 ] ) );
54283                 this.faceVertexUvs[ 0 ].push( [ uv1, uv2, uv3 ] );
54284
54285             } else {
54286
54287                 this.faces.push( new THREE.Face4( v1, v2, v3, v4, [ n1, n2, n3, n4 ] ) );
54288                 this.faceVertexUvs[ 0 ].push( [ uv1, uv2, uv3, uv4 ] );
54289
54290             }
54291
54292         }
54293
54294     }
54295
54296     this.computeCentroids();
54297     this.computeFaceNormals();
54298
54299     this.boundingSphere = { radius: radius };
54300
54301 };
54302
54303 THREE.SphereGeometry.prototype = Object.create( THREE.Geometry.prototype );
54304 /**
54305  * @author zz85 / http://www.lab4games.net/zz85/blog
54306  * @author alteredq / http://alteredqualia.com/
54307  *
54308  * For creating 3D text geometry in three.js
54309  *
54310  * Text = 3D Text
54311  *
54312  * parameters = {
54313  *  size:             <float>,     // size of the text
54314  *  height:         <float>,     // thickness to extrude text
54315  *  curveSegments:     <int>,        // number of points on the curves
54316  *
54317  *  font:             <string>,        // font name
54318  *  weight:         <string>,        // font weight (normal, bold)
54319  *  style:             <string>,        // font style  (normal, italics)
54320  *
54321  *  bevelEnabled:    <bool>,            // turn on bevel
54322  *  bevelThickness: <float>,         // how deep into text bevel goes
54323  *  bevelSize:        <float>,         // how far from text outline is bevel
54324  *  }
54325  *
54326  */
54327
54328 /*    Usage Examples
54329
54330     // TextGeometry wrapper
54331
54332     var text3d = new TextGeometry( text, options );
54333
54334     // Complete manner
54335
54336     var textShapes = THREE.FontUtils.generateShapes( text, options );
54337     var text3d = new ExtrudeGeometry( textShapes, options );
54338
54339 */
54340
54341
54342 THREE.TextGeometry = function ( text, parameters ) {
54343
54344     var textShapes = THREE.FontUtils.generateShapes( text, parameters );
54345
54346     // translate parameters to ExtrudeGeometry API
54347
54348     parameters.amount = parameters.height !== undefined ? parameters.height : 50;
54349
54350     // defaults
54351
54352     if ( parameters.bevelThickness === undefined ) parameters.bevelThickness = 10;
54353     if ( parameters.bevelSize === undefined ) parameters.bevelSize = 8;
54354     if ( parameters.bevelEnabled === undefined ) parameters.bevelEnabled = false;
54355
54356     THREE.ExtrudeGeometry.call( this, textShapes, parameters );
54357
54358 };
54359
54360 THREE.TextGeometry.prototype = Object.create( THREE.ExtrudeGeometry.prototype );
54361 /**
54362  * @author oosmoxiecode
54363  * @author mrdoob / http://mrdoob.com/
54364  * based on http://code.google.com/p/away3d/source/browse/trunk/fp10/Away3DLite/src/away3dlite/primitives/Torus.as?r=2888
54365  */
54366
54367 THREE.TorusGeometry = function ( radius, tube, segmentsR, segmentsT, arc ) {
54368
54369     THREE.Geometry.call( this );
54370
54371     var scope = this;
54372
54373     this.radius = radius || 100;
54374     this.tube = tube || 40;
54375     this.segmentsR = segmentsR || 8;
54376     this.segmentsT = segmentsT || 6;
54377     this.arc = arc || Math.PI * 2;
54378
54379     var center = new THREE.Vector3(), uvs = [], normals = [];
54380
54381     for ( var j = 0; j <= this.segmentsR; j ++ ) {
54382
54383         for ( var i = 0; i <= this.segmentsT; i ++ ) {
54384
54385             var u = i / this.segmentsT * this.arc;
54386             var v = j / this.segmentsR * Math.PI * 2;
54387
54388             center.x = this.radius * Math.cos( u );
54389             center.y = this.radius * Math.sin( u );
54390
54391             var vertex = new THREE.Vector3();
54392             vertex.x = ( this.radius + this.tube * Math.cos( v ) ) * Math.cos( u );
54393             vertex.y = ( this.radius + this.tube * Math.cos( v ) ) * Math.sin( u );
54394             vertex.z = this.tube * Math.sin( v );
54395
54396             this.vertices.push( vertex );
54397
54398             uvs.push( new THREE.UV( i / this.segmentsT, j / this.segmentsR ) );
54399             normals.push( vertex.clone().subSelf( center ).normalize() );
54400
54401         }
54402     }
54403
54404
54405     for ( var j = 1; j <= this.segmentsR; j ++ ) {
54406
54407         for ( var i = 1; i <= this.segmentsT; i ++ ) {
54408
54409             var a = ( this.segmentsT + 1 ) * j + i - 1;
54410             var b = ( this.segmentsT + 1 ) * ( j - 1 ) + i - 1;
54411             var c = ( this.segmentsT + 1 ) * ( j - 1 ) + i;
54412             var d = ( this.segmentsT + 1 ) * j + i;
54413
54414             var face = new THREE.Face4( a, b, c, d, [ normals[ a ], normals[ b ], normals[ c ], normals[ d ] ] );
54415             face.normal.addSelf( normals[ a ] );
54416             face.normal.addSelf( normals[ b ] );
54417             face.normal.addSelf( normals[ c ] );
54418             face.normal.addSelf( normals[ d ] );
54419             face.normal.normalize();
54420
54421             this.faces.push( face );
54422
54423             this.faceVertexUvs[ 0 ].push( [ uvs[ a ].clone(), uvs[ b ].clone(), uvs[ c ].clone(), uvs[ d ].clone() ] );
54424         }
54425
54426     }
54427
54428     this.computeCentroids();
54429
54430 };
54431
54432 THREE.TorusGeometry.prototype = Object.create( THREE.Geometry.prototype );
54433 /**
54434  * @author oosmoxiecode
54435  * based on http://code.google.com/p/away3d/source/browse/trunk/fp10/Away3D/src/away3d/primitives/TorusKnot.as?spec=svn2473&r=2473
54436  */
54437
54438 THREE.TorusKnotGeometry = function ( radius, tube, segmentsR, segmentsT, p, q, heightScale ) {
54439
54440     THREE.Geometry.call( this );
54441
54442     var scope = this;
54443
54444     this.radius = radius || 200;
54445     this.tube = tube || 40;
54446     this.segmentsR = segmentsR || 64;
54447     this.segmentsT = segmentsT || 8;
54448     this.p = p || 2;
54449     this.q = q || 3;
54450     this.heightScale = heightScale || 1;
54451     this.grid = new Array(this.segmentsR);
54452
54453     var tang = new THREE.Vector3();
54454     var n = new THREE.Vector3();
54455     var bitan = new THREE.Vector3();
54456
54457     for ( var i = 0; i < this.segmentsR; ++ i ) {
54458
54459         this.grid[ i ] = new Array( this.segmentsT );
54460
54461         for ( var j = 0; j < this.segmentsT; ++ j ) {
54462
54463             var u = i / this.segmentsR * 2 * this.p * Math.PI;
54464             var v = j / this.segmentsT * 2 * Math.PI;
54465             var p1 = getPos( u, v, this.q, this.p, this.radius, this.heightScale );
54466             var p2 = getPos( u + 0.01, v, this.q, this.p, this.radius, this.heightScale );
54467             var cx, cy;
54468
54469             tang.sub( p2, p1 );
54470             n.add( p2, p1 );
54471
54472             bitan.cross( tang, n );
54473             n.cross( bitan, tang );
54474             bitan.normalize();
54475             n.normalize();
54476
54477             cx = - this.tube * Math.cos( v ); // TODO: Hack: Negating it so it faces outside.
54478             cy = this.tube * Math.sin( v );
54479
54480             p1.x += cx * n.x + cy * bitan.x;
54481             p1.y += cx * n.y + cy * bitan.y;
54482             p1.z += cx * n.z + cy * bitan.z;
54483
54484             this.grid[ i ][ j ] = vert( p1.x, p1.y, p1.z );
54485
54486         }
54487
54488     }
54489
54490     for ( var i = 0; i < this.segmentsR; ++ i ) {
54491
54492         for ( var j = 0; j < this.segmentsT; ++ j ) {
54493
54494             var ip = ( i + 1 ) % this.segmentsR;
54495             var jp = ( j + 1 ) % this.segmentsT;
54496
54497             var a = this.grid[ i ][ j ];
54498             var b = this.grid[ ip ][ j ];
54499             var c = this.grid[ ip ][ jp ];
54500             var d = this.grid[ i ][ jp ];
54501
54502             var uva = new THREE.UV( i / this.segmentsR, j / this.segmentsT );
54503             var uvb = new THREE.UV( ( i + 1 ) / this.segmentsR, j / this.segmentsT );
54504             var uvc = new THREE.UV( ( i + 1 ) / this.segmentsR, ( j + 1 ) / this.segmentsT );
54505             var uvd = new THREE.UV( i / this.segmentsR, ( j + 1 ) / this.segmentsT );
54506
54507             this.faces.push( new THREE.Face4( a, b, c, d ) );
54508             this.faceVertexUvs[ 0 ].push( [ uva,uvb,uvc, uvd ] );
54509
54510         }
54511     }
54512
54513     this.computeCentroids();
54514     this.computeFaceNormals();
54515     this.computeVertexNormals();
54516
54517     function vert( x, y, z ) {
54518
54519         return scope.vertices.push( new THREE.Vector3( x, y, z ) ) - 1;
54520
54521     }
54522
54523     function getPos( u, v, in_q, in_p, radius, heightScale ) {
54524
54525         var cu = Math.cos( u );
54526         var cv = Math.cos( v );
54527         var su = Math.sin( u );
54528         var quOverP = in_q / in_p * u;
54529         var cs = Math.cos( quOverP );
54530
54531         var tx = radius * ( 2 + cs ) * 0.5 * cu;
54532         var ty = radius * ( 2 + cs ) * su * 0.5;
54533         var tz = heightScale * radius * Math.sin( quOverP ) * 0.5;
54534
54535         return new THREE.Vector3( tx, ty, tz );
54536
54537     }
54538
54539 };
54540
54541 THREE.TorusKnotGeometry.prototype = Object.create( THREE.Geometry.prototype );
54542 /**
54543  * @author WestLangley / https://github.com/WestLangley
54544  * @author zz85 / https://github.com/zz85
54545  * @author miningold / https://github.com/miningold
54546  *
54547  * Modified from the TorusKnotGeometry by @oosmoxiecode
54548  *
54549  * Creates a tube which extrudes along a 3d spline
54550  *
54551  * Uses parallel transport frames as described in
54552  * http://www.cs.indiana.edu/pub/techreports/TR425.pdf
54553  */
54554
54555 THREE.TubeGeometry = function( path, segments, radius, segmentsRadius, closed, debug ) {
54556
54557     THREE.Geometry.call( this );
54558
54559     this.path = path;
54560     this.segments = segments || 64;
54561     this.radius = radius || 1;
54562     this.segmentsRadius = segmentsRadius || 8;
54563     this.closed = closed || false;
54564     if ( debug ) this.debug = new THREE.Object3D();
54565
54566     this.grid = [];
54567
54568     var scope = this,
54569
54570         tangent,
54571         normal,
54572         binormal,
54573
54574         numpoints = this.segments + 1,
54575
54576         x, y, z,
54577         tx, ty, tz,
54578         u, v,
54579
54580         cx, cy,
54581         pos, pos2 = new THREE.Vector3(),
54582         i, j,
54583         ip, jp,
54584         a, b, c, d,
54585         uva, uvb, uvc, uvd;
54586
54587     var frames = new THREE.TubeGeometry.FrenetFrames(path, segments, closed),
54588         tangents = frames.tangents,
54589         normals = frames.normals,
54590         binormals = frames.binormals;
54591
54592     // proxy internals
54593     this.tangents = tangents;
54594     this.normals = normals;
54595     this.binormals = binormals;
54596
54597
54598     function vert( x, y, z ) {
54599
54600         return scope.vertices.push( new THREE.Vector3( x, y, z ) ) - 1;
54601
54602     }
54603
54604
54605
54606
54607     // consruct the grid
54608
54609     for ( i = 0; i < numpoints; i++ ) {
54610
54611         this.grid[ i ] = [];
54612
54613         u = i / ( numpoints - 1 );
54614
54615         pos = path.getPointAt( u );
54616
54617         tangent = tangents[ i ];
54618         normal = normals[ i ];
54619         binormal = binormals[ i ];
54620
54621         if ( this.debug ) {
54622
54623             this.debug.add(new THREE.ArrowHelper(tangent, pos, radius, 0x0000ff));
54624             this.debug.add(new THREE.ArrowHelper(normal, pos, radius, 0xff0000));
54625             this.debug.add(new THREE.ArrowHelper(binormal, pos, radius, 0x00ff00));
54626
54627         }
54628
54629         for ( j = 0; j < this.segmentsRadius; j++ ) {
54630
54631             v = j / this.segmentsRadius * 2 * Math.PI;
54632
54633             cx = -this.radius * Math.cos( v ); // TODO: Hack: Negating it so it faces outside.
54634             cy = this.radius * Math.sin( v );
54635
54636             pos2.copy( pos );
54637             pos2.x += cx * normal.x + cy * binormal.x;
54638             pos2.y += cx * normal.y + cy * binormal.y;
54639             pos2.z += cx * normal.z + cy * binormal.z;
54640
54641             this.grid[ i ][ j ] = vert( pos2.x, pos2.y, pos2.z );
54642
54643         }
54644     }
54645
54646
54647     // construct the mesh
54648
54649     for ( i = 0; i < this.segments; i++ ) {
54650
54651         for ( j = 0; j < this.segmentsRadius; j++ ) {
54652
54653             ip = ( closed ) ? (i + 1) % this.segments : i + 1;
54654             jp = (j + 1) % this.segmentsRadius;
54655
54656             a = this.grid[ i ][ j ];        // *** NOT NECESSARILY PLANAR ! ***
54657             b = this.grid[ ip ][ j ];
54658             c = this.grid[ ip ][ jp ];
54659             d = this.grid[ i ][ jp ];
54660
54661             uva = new THREE.UV( i / this.segments, j / this.segmentsRadius );
54662             uvb = new THREE.UV( ( i + 1 ) / this.segments, j / this.segmentsRadius );
54663             uvc = new THREE.UV( ( i + 1 ) / this.segments, ( j + 1 ) / this.segmentsRadius );
54664             uvd = new THREE.UV( i / this.segments, ( j + 1 ) / this.segmentsRadius );
54665
54666             this.faces.push( new THREE.Face4( a, b, c, d ) );
54667             this.faceVertexUvs[ 0 ].push( [ uva, uvb, uvc, uvd ] );
54668
54669         }
54670     }
54671
54672     this.computeCentroids();
54673     this.computeFaceNormals();
54674     this.computeVertexNormals();
54675
54676 };
54677
54678 THREE.TubeGeometry.prototype = Object.create( THREE.Geometry.prototype );
54679
54680
54681 // For computing of Frenet frames, exposing the tangents, normals and binormals the spline
54682 THREE.TubeGeometry.FrenetFrames = function(path, segments, closed) {
54683
54684     var
54685         tangent = new THREE.Vector3(),
54686         normal = new THREE.Vector3(),
54687         binormal = new THREE.Vector3(),
54688
54689         tangents = [],
54690         normals = [],
54691         binormals = [],
54692
54693         vec = new THREE.Vector3(),
54694         mat = new THREE.Matrix4(),
54695
54696         numpoints = segments + 1,
54697         theta,
54698         epsilon = 0.0001,
54699         smallest,
54700
54701         tx, ty, tz,
54702         i, u, v;
54703
54704
54705     // expose internals
54706     this.tangents = tangents;
54707     this.normals = normals;
54708     this.binormals = binormals;
54709
54710     // compute the tangent vectors for each segment on the path
54711
54712     for ( i = 0; i < numpoints; i++ ) {
54713
54714         u = i / ( numpoints - 1 );
54715
54716         tangents[ i ] = path.getTangentAt( u );
54717         tangents[ i ].normalize();
54718
54719     }
54720
54721     initialNormal3();
54722
54723     function initialNormal1(lastBinormal) {
54724         // fixed start binormal. Has dangers of 0 vectors
54725         normals[ 0 ] = new THREE.Vector3();
54726         binormals[ 0 ] = new THREE.Vector3();
54727         if (lastBinormal===undefined) lastBinormal = new THREE.Vector3( 0, 0, 1 );
54728         normals[ 0 ].cross( lastBinormal, tangents[ 0 ] ).normalize();
54729         binormals[ 0 ].cross( tangents[ 0 ], normals[ 0 ] ).normalize();
54730     }
54731
54732     function initialNormal2() {
54733
54734         // This uses the Frenet-Serret formula for deriving binormal
54735         var t2 = path.getTangentAt( epsilon );
54736
54737         normals[ 0 ] = new THREE.Vector3().sub( t2, tangents[ 0 ] ).normalize();
54738         binormals[ 0 ] = new THREE.Vector3().cross( tangents[ 0 ], normals[ 0 ] );
54739
54740         normals[ 0 ].cross( binormals[ 0 ], tangents[ 0 ] ).normalize(); // last binormal x tangent
54741         binormals[ 0 ].cross( tangents[ 0 ], normals[ 0 ] ).normalize();
54742
54743     }
54744
54745     function initialNormal3() {
54746         // select an initial normal vector perpenicular to the first tangent vector,
54747         // and in the direction of the smallest tangent xyz component
54748
54749         normals[ 0 ] = new THREE.Vector3();
54750         binormals[ 0 ] = new THREE.Vector3();
54751         smallest = Number.MAX_VALUE;
54752         tx = Math.abs( tangents[ 0 ].x );
54753         ty = Math.abs( tangents[ 0 ].y );
54754         tz = Math.abs( tangents[ 0 ].z );
54755
54756         if ( tx <= smallest ) {
54757             smallest = tx;
54758             normal.set( 1, 0, 0 );
54759         }
54760
54761         if ( ty <= smallest ) {
54762             smallest = ty;
54763             normal.set( 0, 1, 0 );
54764         }
54765
54766         if ( tz <= smallest ) {
54767             normal.set( 0, 0, 1 );
54768         }
54769
54770         vec.cross( tangents[ 0 ], normal ).normalize();
54771
54772         normals[ 0 ].cross( tangents[ 0 ], vec );
54773         binormals[ 0 ].cross( tangents[ 0 ], normals[ 0 ] );
54774     }
54775
54776
54777     // compute the slowly-varying normal and binormal vectors for each segment on the path
54778
54779     for ( i = 1; i < numpoints; i++ ) {
54780
54781         normals[ i ] = normals[ i-1 ].clone();
54782
54783         binormals[ i ] = binormals[ i-1 ].clone();
54784
54785         vec.cross( tangents[ i-1 ], tangents[ i ] );
54786
54787         if ( vec.length() > epsilon ) {
54788
54789             vec.normalize();
54790
54791             theta = Math.acos( tangents[ i-1 ].dot( tangents[ i ] ) );
54792
54793             mat.makeRotationAxis( vec, theta ).multiplyVector3( normals[ i ] );
54794
54795         }
54796
54797         binormals[ i ].cross( tangents[ i ], normals[ i ] );
54798
54799     }
54800
54801
54802     // if the curve is closed, postprocess the vectors so the first and last normal vectors are the same
54803
54804     if ( closed ) {
54805
54806         theta = Math.acos( normals[ 0 ].dot( normals[ numpoints-1 ] ) );
54807         theta /= ( numpoints - 1 );
54808
54809         if ( tangents[ 0 ].dot( vec.cross( normals[ 0 ], normals[ numpoints-1 ] ) ) > 0 ) {
54810
54811             theta = -theta;
54812
54813         }
54814
54815         for ( i = 1; i < numpoints; i++ ) {
54816
54817             // twist a little...
54818             mat.makeRotationAxis( tangents[ i ], theta * i ).multiplyVector3( normals[ i ] );
54819             binormals[ i ].cross( tangents[ i ], normals[ i ] );
54820
54821         }
54822
54823     }
54824 };
54825 /**
54826  * @author clockworkgeek / https://github.com/clockworkgeek
54827  * @author timothypratley / https://github.com/timothypratley
54828  */
54829
54830 THREE.PolyhedronGeometry = function ( vertices, faces, radius, detail ) {
54831
54832     THREE.Geometry.call( this );
54833
54834     radius = radius || 1;
54835     detail = detail || 0;
54836
54837     var that = this;
54838
54839     for ( var i = 0, l = vertices.length; i < l; i ++ ) {
54840
54841         prepare( new THREE.Vector3( vertices[ i ][ 0 ], vertices[ i ][ 1 ], vertices[ i ][ 2 ] ) );
54842
54843     }
54844
54845     var midpoints = [], p = this.vertices;
54846
54847     for ( var i = 0, l = faces.length; i < l; i ++ ) {
54848
54849         make( p[ faces[ i ][ 0 ] ], p[ faces[ i ][ 1 ] ], p[ faces[ i ][ 2 ] ], detail );
54850
54851     }
54852
54853     this.mergeVertices();
54854
54855     // Apply radius
54856
54857     for ( var i = 0, l = this.vertices.length; i < l; i ++ ) {
54858
54859         this.vertices[ i ].multiplyScalar( radius );
54860
54861     }
54862
54863
54864     // Project vector onto sphere's surface
54865
54866     function prepare( vector ) {
54867
54868         var vertex = vector.normalize().clone();
54869         vertex.index = that.vertices.push( vertex ) - 1;
54870
54871         // Texture coords are equivalent to map coords, calculate angle and convert to fraction of a circle.
54872
54873         var u = azimuth( vector ) / 2 / Math.PI + 0.5;
54874         var v = inclination( vector ) / Math.PI + 0.5;
54875         vertex.uv = new THREE.UV( u, 1 - v );
54876
54877         return vertex;
54878
54879     }
54880
54881
54882     // Approximate a curved face with recursively sub-divided triangles.
54883
54884     function make( v1, v2, v3, detail ) {
54885
54886         if ( detail < 1 ) {
54887
54888             var face = new THREE.Face3( v1.index, v2.index, v3.index, [ v1.clone(), v2.clone(), v3.clone() ] );
54889             face.centroid.addSelf( v1 ).addSelf( v2 ).addSelf( v3 ).divideScalar( 3 );
54890             face.normal = face.centroid.clone().normalize();
54891             that.faces.push( face );
54892
54893             var azi = azimuth( face.centroid );
54894             that.faceVertexUvs[ 0 ].push( [
54895                 correctUV( v1.uv, v1, azi ),
54896                 correctUV( v2.uv, v2, azi ),
54897                 correctUV( v3.uv, v3, azi )
54898             ] );
54899
54900         } else {
54901
54902             detail -= 1;
54903
54904             // split triangle into 4 smaller triangles
54905
54906             make( v1, midpoint( v1, v2 ), midpoint( v1, v3 ), detail ); // top quadrant
54907             make( midpoint( v1, v2 ), v2, midpoint( v2, v3 ), detail ); // left quadrant
54908             make( midpoint( v1, v3 ), midpoint( v2, v3 ), v3, detail ); // right quadrant
54909             make( midpoint( v1, v2 ), midpoint( v2, v3 ), midpoint( v1, v3 ), detail ); // center quadrant
54910
54911         }
54912
54913     }
54914
54915     function midpoint( v1, v2 ) {
54916
54917         if ( !midpoints[ v1.index ] ) midpoints[ v1.index ] = [];
54918         if ( !midpoints[ v2.index ] ) midpoints[ v2.index ] = [];
54919
54920         var mid = midpoints[ v1.index ][ v2.index ];
54921
54922         if ( mid === undefined ) {
54923
54924             // generate mean point and project to surface with prepare()
54925
54926             midpoints[ v1.index ][ v2.index ] = midpoints[ v2.index ][ v1.index ] = mid = prepare(
54927                 new THREE.Vector3().add( v1, v2 ).divideScalar( 2 )
54928             );
54929         }
54930
54931         return mid;
54932
54933     }
54934
54935
54936     // Angle around the Y axis, counter-clockwise when looking from above.
54937
54938     function azimuth( vector ) {
54939
54940         return Math.atan2( vector.z, -vector.x );
54941
54942     }
54943
54944
54945     // Angle above the XZ plane.
54946
54947     function inclination( vector ) {
54948
54949         return Math.atan2( -vector.y, Math.sqrt( ( vector.x * vector.x ) + ( vector.z * vector.z ) ) );
54950
54951     }
54952
54953
54954     // Texture fixing helper. Spheres have some odd behaviours.
54955
54956     function correctUV( uv, vector, azimuth ) {
54957
54958         if ( ( azimuth < 0 ) && ( uv.u === 1 ) ) uv = new THREE.UV( uv.u - 1, uv.v );
54959         if ( ( vector.x === 0 ) && ( vector.z === 0 ) ) uv = new THREE.UV( azimuth / 2 / Math.PI + 0.5, uv.v );
54960         return uv;
54961
54962     }
54963
54964     this.computeCentroids();
54965
54966     this.boundingSphere = { radius: radius };
54967
54968 };
54969
54970 THREE.PolyhedronGeometry.prototype = Object.create( THREE.Geometry.prototype );
54971 /**
54972  * @author timothypratley / https://github.com/timothypratley
54973  */
54974
54975 THREE.IcosahedronGeometry = function ( radius, detail ) {
54976
54977     var t = ( 1 + Math.sqrt( 5 ) ) / 2;
54978
54979     var vertices = [
54980         [ -1,  t,  0 ], [  1, t, 0 ], [ -1, -t,  0 ], [  1, -t,  0 ],
54981         [  0, -1,  t ], [  0, 1, t ], [  0, -1, -t ], [  0,  1, -t ],
54982         [  t,  0, -1 ], [  t, 0, 1 ], [ -t,  0, -1 ], [ -t,  0,  1 ]
54983     ];
54984
54985     var faces = [
54986         [ 0, 11,  5 ], [ 0,  5,  1 ], [  0,  1,  7 ], [  0,  7, 10 ], [  0, 10, 11 ],
54987         [ 1,  5,  9 ], [ 5, 11,  4 ], [ 11, 10,  2 ], [ 10,  7,  6 ], [  7,  1,  8 ],
54988         [ 3,  9,  4 ], [ 3,  4,  2 ], [  3,  2,  6 ], [  3,  6,  8 ], [  3,  8,  9 ],
54989         [ 4,  9,  5 ], [ 2,  4, 11 ], [  6,  2, 10 ], [  8,  6,  7 ], [  9,  8,  1 ]
54990     ];
54991
54992     THREE.PolyhedronGeometry.call( this, vertices, faces, radius, detail );
54993
54994 };
54995
54996 THREE.IcosahedronGeometry.prototype = Object.create( THREE.Geometry.prototype );
54997 /**
54998  * @author timothypratley / https://github.com/timothypratley
54999  */
55000
55001 THREE.OctahedronGeometry = function ( radius, detail ) {
55002
55003     var vertices = [
55004         [ 1, 0, 0 ], [ -1, 0, 0 ], [ 0, 1, 0 ], [ 0, -1, 0 ], [ 0, 0, 1 ], [ 0, 0, -1 ]
55005     ];
55006
55007     var faces = [
55008         [ 0, 2, 4 ], [ 0, 4, 3 ], [ 0, 3, 5 ], [ 0, 5, 2 ], [ 1, 2, 5 ], [ 1, 5, 3 ], [ 1, 3, 4 ], [ 1, 4, 2 ]
55009     ];
55010
55011     THREE.PolyhedronGeometry.call( this, vertices, faces, radius, detail );
55012 };
55013
55014 THREE.OctahedronGeometry.prototype = Object.create( THREE.Geometry.prototype );
55015 /**
55016  * @author timothypratley / https://github.com/timothypratley
55017  */
55018
55019 THREE.TetrahedronGeometry = function ( radius, detail ) {
55020
55021     var vertices = [
55022         [ 1,  1,  1 ], [ -1, -1, 1 ], [ -1, 1, -1 ], [ 1, -1, -1 ]
55023     ];
55024
55025     var faces = [
55026         [ 2, 1, 0 ], [ 0, 3, 2 ], [ 1, 3, 0 ], [ 2, 3, 1 ]
55027     ];
55028
55029     THREE.PolyhedronGeometry.call( this, vertices, faces, radius, detail );
55030
55031 };
55032
55033 THREE.TetrahedronGeometry.prototype = Object.create( THREE.Geometry.prototype );
55034 /**
55035  * @author zz85 / https://github.com/zz85
55036  * Parametric Surfaces Geometry
55037  * based on the brilliant article by @prideout http://prideout.net/blog/?p=44
55038  *
55039  * new THREE.ParametricGeometry( parametricFunction, uSegments, ySegements, useTris );
55040  *
55041  */
55042
55043 THREE.ParametricGeometry = function ( func, slices, stacks, useTris ) {
55044
55045     THREE.Geometry.call( this );
55046
55047     var verts = this.vertices;
55048     var faces = this.faces;
55049     var uvs = this.faceVertexUvs[ 0 ];
55050
55051     useTris = (useTris === undefined) ? false : useTris;
55052
55053     var i, il, j, p;
55054     var u, v;
55055
55056     var stackCount = stacks + 1;
55057     var sliceCount = slices + 1;
55058
55059     for ( i = 0; i <= stacks; i ++ ) {
55060
55061         v = i / stacks;
55062
55063         for ( j = 0; j <= slices; j ++ ) {
55064
55065             u = j / slices;
55066
55067             p = func( u, v );
55068             verts.push( p );
55069
55070         }
55071     }
55072
55073     var a, b, c, d;
55074     var uva, uvb, uvc, uvd;
55075
55076     for ( i = 0; i < stacks; i ++ ) {
55077
55078         for ( j = 0; j < slices; j ++ ) {
55079
55080             a = i * sliceCount + j;
55081             b = i * sliceCount + j + 1;
55082             c = (i + 1) * sliceCount + j;
55083             d = (i + 1) * sliceCount + j + 1;
55084
55085             uva = new THREE.UV( j / slices, i / stacks );
55086             uvb = new THREE.UV( ( j + 1 ) / slices, i / stacks );
55087             uvc = new THREE.UV( j / slices, ( i + 1 ) / stacks );
55088             uvd = new THREE.UV( ( j + 1 ) / slices, ( i + 1 ) / stacks );
55089
55090             if ( useTris ) {
55091
55092                 faces.push( new THREE.Face3( a, b, c ) );
55093                 faces.push( new THREE.Face3( b, d, c ) );
55094
55095                 uvs.push( [ uva, uvb, uvc ] );
55096                 uvs.push( [ uvb, uvd, uvc ] );
55097
55098             } else {
55099
55100                 faces.push( new THREE.Face4( a, b, d, c ) );
55101                 uvs.push( [ uva, uvb, uvd, uvc ] );
55102
55103             }
55104
55105         }
55106
55107     }
55108
55109     // console.log(this);
55110
55111     // magic bullet
55112     // var diff = this.mergeVertices();
55113     // console.log('removed ', diff, ' vertices by merging');
55114
55115     this.computeCentroids();
55116     this.computeFaceNormals();
55117     this.computeVertexNormals();
55118
55119 };
55120
55121 THREE.ParametricGeometry.prototype = Object.create( THREE.Geometry.prototype );
55122 /**
55123  * @author qiao / https://github.com/qiao
55124  * @fileoverview This is a convex hull generator using the incremental method.
55125  * The complexity is O(n^2) where n is the number of vertices.
55126  * O(nlogn) algorithms do exist, but they are much more complicated.
55127  *
55128  * Benchmark:
55129  *
55130  *  Platform: CPU: P7350 @2.00GHz Engine: V8
55131  *
55132  *  Num Vertices    Time(ms)
55133  *
55134  *     10           1
55135  *     20           3
55136  *     30           19
55137  *     40           48
55138  *     50           107
55139  */
55140
55141 THREE.ConvexGeometry = function( vertices ) {
55142
55143     THREE.Geometry.call( this );
55144
55145     var faces = [ [ 0, 1, 2 ], [ 0, 2, 1 ] ];
55146
55147     for ( var i = 3; i < vertices.length; i++ ) {
55148
55149         addPoint( i );
55150
55151     }
55152
55153
55154     function addPoint( vertexId ) {
55155
55156         var vertex = vertices[ vertexId ].clone();
55157
55158         var mag = vertex.length();
55159         vertex.x += mag * randomOffset();
55160         vertex.y += mag * randomOffset();
55161         vertex.z += mag * randomOffset();
55162
55163         var hole = [];
55164
55165         for ( var f = 0; f < faces.length; ) {
55166
55167             var face = faces[ f ];
55168
55169             // for each face, if the vertex can see it,
55170             // then we try to add the face's edges into the hole.
55171             if ( visible( face, vertex ) ) {
55172
55173                 for ( var e = 0; e < 3; e++ ) {
55174
55175                     var edge = [ face[ e ], face[ ( e + 1 ) % 3 ] ];
55176                     var boundary = true;
55177
55178                     // remove duplicated edges.
55179                     for ( var h = 0; h < hole.length; h++ ) {
55180
55181                         if ( equalEdge( hole[ h ], edge ) ) {
55182
55183                             hole[ h ] = hole[ hole.length - 1 ];
55184                             hole.pop();
55185                             boundary = false;
55186                             break;
55187
55188                         }
55189
55190                     }
55191
55192                     if ( boundary ) {
55193
55194                         hole.push( edge );
55195
55196                     }
55197
55198                 }
55199
55200                 // remove faces[ f ]
55201                 faces[ f ] = faces[ faces.length - 1 ];
55202                 faces.pop();
55203
55204             } else { // not visible
55205
55206                 f++;
55207
55208             }
55209         }
55210
55211         // construct the new faces formed by the edges of the hole and the vertex
55212         for ( var h = 0; h < hole.length; h++ ) {
55213
55214             faces.push( [
55215                 hole[ h ][ 0 ],
55216                 hole[ h ][ 1 ],
55217                 vertexId
55218             ] );
55219
55220         }
55221     }
55222
55223     /**
55224      * Whether the face is visible from the vertex
55225      */
55226     function visible( face, vertex ) {
55227
55228         var va = vertices[ face[ 0 ] ];
55229         var vb = vertices[ face[ 1 ] ];
55230         var vc = vertices[ face[ 2 ] ];
55231
55232         var n = normal( va, vb, vc );
55233
55234         // distance from face to origin
55235         var dist = n.dot( va );
55236
55237         return n.dot( vertex ) >= dist;
55238
55239     }
55240
55241     /**
55242      * Face normal
55243      */
55244     function normal( va, vb, vc ) {
55245
55246         var cb = new THREE.Vector3();
55247         var ab = new THREE.Vector3();
55248
55249         cb.sub( vc, vb );
55250         ab.sub( va, vb );
55251         cb.crossSelf( ab );
55252
55253         if ( !cb.isZero() ) {
55254
55255             cb.normalize();
55256
55257         }
55258
55259         return cb;
55260
55261     }
55262
55263     /**
55264      * Detect whether two edges are equal.
55265      * Note that when constructing the convex hull, two same edges can only
55266      * be of the negative direction.
55267      */
55268     function equalEdge( ea, eb ) {
55269
55270         return ea[ 0 ] === eb[ 1 ] && ea[ 1 ] === eb[ 0 ];
55271
55272     }
55273
55274     /**
55275      * Create a random offset between -1e-6 and 1e-6.
55276      */
55277     function randomOffset() {
55278
55279         return ( Math.random() - 0.5 ) * 2 * 1e-6;
55280
55281     }
55282
55283
55284     /**
55285      * XXX: Not sure if this is the correct approach. Need someone to review.
55286      */
55287     function vertexUv( vertex ) {
55288
55289         var mag = vertex.length();
55290         return new THREE.UV( vertex.x / mag, vertex.y / mag );
55291
55292     }
55293
55294     // Push vertices into `this.vertices`, skipping those inside the hull
55295     var id = 0;
55296     var newId = new Array( vertices.length ); // map from old vertex id to new id
55297
55298     for ( var i = 0; i < faces.length; i++ ) {
55299
55300          var face = faces[ i ];
55301
55302          for ( var j = 0; j < 3; j++ ) {
55303
55304                 if ( newId[ face[ j ] ] === undefined ) {
55305
55306                         newId[ face[ j ] ] = id++;
55307                         this.vertices.push( vertices[ face[ j ] ] );
55308
55309                 }
55310
55311                 face[ j ] = newId[ face[ j ] ];
55312
55313          }
55314
55315     }
55316
55317     // Convert faces into instances of THREE.Face3
55318     for ( var i = 0; i < faces.length; i++ ) {
55319
55320         this.faces.push( new THREE.Face3(
55321                 faces[ i ][ 0 ],
55322                 faces[ i ][ 1 ],
55323                 faces[ i ][ 2 ]
55324         ) );
55325
55326     }
55327
55328     // Compute UVs
55329     for ( var i = 0; i < this.faces.length; i++ ) {
55330
55331         var face = this.faces[ i ];
55332
55333         this.faceVertexUvs[ 0 ].push( [
55334             vertexUv( this.vertices[ face.a ] ),
55335             vertexUv( this.vertices[ face.b ] ),
55336             vertexUv( this.vertices[ face.c ])
55337         ] );
55338
55339     }
55340
55341
55342     this.computeCentroids();
55343     this.computeFaceNormals();
55344     this.computeVertexNormals();
55345
55346 };
55347
55348 THREE.ConvexGeometry.prototype = Object.create( THREE.Geometry.prototype );
55349 /**
55350  * @author sroucheray / http://sroucheray.org/
55351  * @author mrdoob / http://mrdoob.com/
55352  */
55353
55354 THREE.AxisHelper = function () {
55355
55356     THREE.Object3D.call( this );
55357
55358     var lineGeometry = new THREE.Geometry();
55359     lineGeometry.vertices.push( new THREE.Vector3() );
55360     lineGeometry.vertices.push( new THREE.Vector3( 0, 100, 0 ) );
55361
55362     var coneGeometry = new THREE.CylinderGeometry( 0, 5, 25, 5, 1 );
55363
55364     var line, cone;
55365
55366     // x
55367
55368     line = new THREE.Line( lineGeometry, new THREE.LineBasicMaterial( { color : 0xff0000 } ) );
55369     line.rotation.z = - Math.PI / 2;
55370     this.add( line );
55371
55372     cone = new THREE.Mesh( coneGeometry, new THREE.MeshBasicMaterial( { color : 0xff0000 } ) );
55373     cone.position.x = 100;
55374     cone.rotation.z = - Math.PI / 2;
55375     this.add( cone );
55376
55377     // y
55378
55379     line = new THREE.Line( lineGeometry, new THREE.LineBasicMaterial( { color : 0x00ff00 } ) );
55380     this.add( line );
55381
55382     cone = new THREE.Mesh( coneGeometry, new THREE.MeshBasicMaterial( { color : 0x00ff00 } ) );
55383     cone.position.y = 100;
55384     this.add( cone );
55385
55386     // z
55387
55388     line = new THREE.Line( lineGeometry, new THREE.LineBasicMaterial( { color : 0x0000ff } ) );
55389     line.rotation.x = Math.PI / 2;
55390     this.add( line );
55391
55392     cone = new THREE.Mesh( coneGeometry, new THREE.MeshBasicMaterial( { color : 0x0000ff } ) );
55393     cone.position.z = 100;
55394     cone.rotation.x = Math.PI / 2;
55395     this.add( cone );
55396
55397 };
55398
55399 THREE.AxisHelper.prototype = Object.create( THREE.Object3D.prototype );
55400 /**
55401  * @author WestLangley / http://github.com/WestLangley
55402  * @author zz85 / https://github.com/zz85
55403  *
55404  * Creates an arrow for visualizing directions
55405  *
55406  * Parameters:
55407  *  dir - Vector3
55408  *  origin - Vector3
55409  *  length - Number
55410  *  hex - color in hex value
55411  */
55412
55413 THREE.ArrowHelper = function ( dir, origin, length, hex ) {
55414
55415     THREE.Object3D.call( this );
55416
55417     if ( hex === undefined ) hex = 0xffff00;
55418     if ( length === undefined ) length = 20;
55419
55420     var lineGeometry = new THREE.Geometry();
55421     lineGeometry.vertices.push( new THREE.Vector3( 0, 0, 0 ) );
55422     lineGeometry.vertices.push( new THREE.Vector3( 0, 1, 0 ) );
55423
55424     this.line = new THREE.Line( lineGeometry, new THREE.LineBasicMaterial( { color: hex } ) );
55425     this.add( this.line );
55426
55427     var coneGeometry = new THREE.CylinderGeometry( 0, 0.05, 0.25, 5, 1 );
55428
55429     this.cone = new THREE.Mesh( coneGeometry, new THREE.MeshBasicMaterial( { color: hex } ) );
55430     this.cone.position.set( 0, 1, 0 );
55431     this.add( this.cone );
55432
55433     if ( origin instanceof THREE.Vector3 ) this.position = origin;
55434
55435     this.setDirection( dir );
55436     this.setLength( length );
55437
55438 };
55439
55440 THREE.ArrowHelper.prototype = Object.create( THREE.Object3D.prototype );
55441
55442 THREE.ArrowHelper.prototype.setDirection = function ( dir ) {
55443
55444     var axis = new THREE.Vector3( 0, 1, 0 ).crossSelf( dir );
55445
55446     var radians = Math.acos( new THREE.Vector3( 0, 1, 0 ).dot( dir.clone().normalize() ) );
55447
55448     this.matrix = new THREE.Matrix4().makeRotationAxis( axis.normalize(), radians );
55449
55450     this.rotation.setEulerFromRotationMatrix( this.matrix, this.eulerOrder );
55451
55452 };
55453
55454 THREE.ArrowHelper.prototype.setLength = function ( length ) {
55455
55456     this.scale.set( length, length, length );
55457
55458 };
55459
55460 THREE.ArrowHelper.prototype.setColor = function ( hex ) {
55461
55462     this.line.material.color.setHex( hex );
55463     this.cone.material.color.setHex( hex );
55464
55465 };
55466 /**
55467  * @author alteredq / http://alteredqualia.com/
55468  *
55469  *    - shows frustum, line of sight and up of the camera
55470  *    - suitable for fast updates
55471  *     - based on frustum visualization in lightgl.js shadowmap example
55472  *        http://evanw.github.com/lightgl.js/tests/shadowmap.html
55473  */
55474
55475 THREE.CameraHelper = function ( camera ) {
55476
55477     THREE.Line.call( this );
55478
55479     var scope = this;
55480
55481     this.geometry = new THREE.Geometry();
55482     this.material = new THREE.LineBasicMaterial( { color: 0xffffff, vertexColors: THREE.FaceColors } );
55483     this.type = THREE.LinePieces;
55484
55485     this.matrixWorld = camera.matrixWorld;
55486     this.matrixAutoUpdate = false;
55487
55488     this.pointMap = {};
55489
55490     // colors
55491
55492     var hexFrustum = 0xffaa00;
55493     var hexCone = 0xff0000;
55494     var hexUp = 0x00aaff;
55495     var hexTarget = 0xffffff;
55496     var hexCross = 0x333333;
55497
55498     // near
55499
55500     addLine( "n1", "n2", hexFrustum );
55501     addLine( "n2", "n4", hexFrustum );
55502     addLine( "n4", "n3", hexFrustum );
55503     addLine( "n3", "n1", hexFrustum );
55504
55505     // far
55506
55507     addLine( "f1", "f2", hexFrustum );
55508     addLine( "f2", "f4", hexFrustum );
55509     addLine( "f4", "f3", hexFrustum );
55510     addLine( "f3", "f1", hexFrustum );
55511
55512     // sides
55513
55514     addLine( "n1", "f1", hexFrustum );
55515     addLine( "n2", "f2", hexFrustum );
55516     addLine( "n3", "f3", hexFrustum );
55517     addLine( "n4", "f4", hexFrustum );
55518
55519     // cone
55520
55521     addLine( "p", "n1", hexCone );
55522     addLine( "p", "n2", hexCone );
55523     addLine( "p", "n3", hexCone );
55524     addLine( "p", "n4", hexCone );
55525
55526     // up
55527
55528     addLine( "u1", "u2", hexUp );
55529     addLine( "u2", "u3", hexUp );
55530     addLine( "u3", "u1", hexUp );
55531
55532     // target
55533
55534     addLine( "c", "t", hexTarget );
55535     addLine( "p", "c", hexCross );
55536
55537     // cross
55538
55539     addLine( "cn1", "cn2", hexCross );
55540     addLine( "cn3", "cn4", hexCross );
55541
55542     addLine( "cf1", "cf2", hexCross );
55543     addLine( "cf3", "cf4", hexCross );
55544
55545     this.camera = camera;
55546
55547     function addLine( a, b, hex ) {
55548
55549         addPoint( a, hex );
55550         addPoint( b, hex );
55551
55552     }
55553
55554     function addPoint( id, hex ) {
55555
55556         scope.geometry.vertices.push( new THREE.Vector3() );
55557         scope.geometry.colors.push( new THREE.Color( hex ) );
55558
55559         if ( scope.pointMap[ id ] === undefined ) scope.pointMap[ id ] = [];
55560
55561         scope.pointMap[ id ].push( scope.geometry.vertices.length - 1 );
55562
55563     }
55564
55565     this.update( camera );
55566
55567 };
55568
55569 THREE.CameraHelper.prototype = Object.create( THREE.Line.prototype );
55570
55571 THREE.CameraHelper.prototype.update = function () {
55572
55573     var scope = this;
55574
55575     var w = 1, h = 1;
55576
55577     // we need just camera projection matrix
55578     // world matrix must be identity
55579
55580     THREE.CameraHelper.__c.projectionMatrix.copy( this.camera.projectionMatrix );
55581
55582     // center / target
55583
55584     setPoint( "c", 0, 0, -1 );
55585     setPoint( "t", 0, 0,  1 );
55586
55587     // near
55588
55589     setPoint( "n1", -w, -h, -1 );
55590     setPoint( "n2",  w, -h, -1 );
55591     setPoint( "n3", -w,  h, -1 );
55592     setPoint( "n4",  w,  h, -1 );
55593
55594     // far
55595
55596     setPoint( "f1", -w, -h, 1 );
55597     setPoint( "f2",  w, -h, 1 );
55598     setPoint( "f3", -w,  h, 1 );
55599     setPoint( "f4",  w,  h, 1 );
55600
55601     // up
55602
55603     setPoint( "u1",  w * 0.7, h * 1.1, -1 );
55604     setPoint( "u2", -w * 0.7, h * 1.1, -1 );
55605     setPoint( "u3",        0, h * 2,   -1 );
55606
55607     // cross
55608
55609     setPoint( "cf1", -w,  0, 1 );
55610     setPoint( "cf2",  w,  0, 1 );
55611     setPoint( "cf3",  0, -h, 1 );
55612     setPoint( "cf4",  0,  h, 1 );
55613
55614     setPoint( "cn1", -w,  0, -1 );
55615     setPoint( "cn2",  w,  0, -1 );
55616     setPoint( "cn3",  0, -h, -1 );
55617     setPoint( "cn4",  0,  h, -1 );
55618
55619     function setPoint( point, x, y, z ) {
55620
55621         THREE.CameraHelper.__v.set( x, y, z );
55622         THREE.CameraHelper.__projector.unprojectVector( THREE.CameraHelper.__v, THREE.CameraHelper.__c );
55623
55624         var points = scope.pointMap[ point ];
55625
55626         if ( points !== undefined ) {
55627
55628             for ( var i = 0, il = points.length; i < il; i ++ ) {
55629
55630                 scope.geometry.vertices[ points[ i ] ].copy( THREE.CameraHelper.__v );
55631
55632             }
55633
55634         }
55635
55636     }
55637
55638     this.geometry.verticesNeedUpdate = true;
55639
55640 };
55641
55642 THREE.CameraHelper.__projector = new THREE.Projector();
55643 THREE.CameraHelper.__v = new THREE.Vector3();
55644 THREE.CameraHelper.__c = new THREE.Camera();
55645
55646 /*
55647  *    @author zz85 / http://twitter.com/blurspline / http://www.lab4games.net/zz85/blog
55648  *
55649  *    Subdivision Geometry Modifier
55650  *        using Catmull-Clark Subdivision Surfaces
55651  *        for creating smooth geometry meshes
55652  *
55653  *    Note: a modifier modifies vertices and faces of geometry,
55654  *        so use THREE.GeometryUtils.clone() if orignal geoemtry needs to be retained
55655  *
55656  *    Readings:
55657  *        http://en.wikipedia.org/wiki/Catmull%E2%80%93Clark_subdivision_surface
55658  *        http://www.rorydriscoll.com/2008/08/01/catmull-clark-subdivision-the-basics/
55659  *        http://xrt.wikidot.com/blog:31
55660  *        "Subdivision Surfaces in Character Animation"
55661  *
55662  *    Supports:
55663  *        Closed and Open geometries.
55664  *
55665  *    TODO:
55666  *        crease vertex and "semi-sharp" features
55667  *        selective subdivision
55668  */
55669
55670 THREE.SubdivisionModifier = function( subdivisions ) {
55671
55672     this.subdivisions = (subdivisions === undefined ) ? 1 : subdivisions;
55673
55674     // Settings
55675     this.useOldVertexColors = false;
55676     this.supportUVs = true;
55677     this.debug = false;
55678
55679 };
55680
55681 // Applies the "modify" pattern
55682 THREE.SubdivisionModifier.prototype.modify = function ( geometry ) {
55683
55684     var repeats = this.subdivisions;
55685
55686     while ( repeats-- > 0 ) {
55687         this.smooth( geometry );
55688     }
55689
55690 };
55691
55692 // Performs an iteration of Catmull-Clark Subdivision
55693 THREE.SubdivisionModifier.prototype.smooth = function ( oldGeometry ) {
55694
55695     //debug( 'running smooth' );
55696
55697     // New set of vertices, faces and uvs
55698     var newVertices = [], newFaces = [], newUVs = [];
55699
55700     function v( x, y, z ) {
55701         newVertices.push( new THREE.Vector3( x, y, z ) );
55702     }
55703
55704     var scope = this;
55705
55706     function debug() {
55707         if (scope.debug) console.log.apply(console, arguments);
55708     }
55709
55710     function warn() {
55711         if (console)
55712         console.log.apply(console, arguments);
55713     }
55714
55715     function f4( a, b, c, d, oldFace, orders, facei ) {
55716
55717         // TODO move vertex selection over here!
55718
55719         var newFace = new THREE.Face4( a, b, c, d, null, oldFace.color, oldFace.materialIndex );
55720
55721         if (scope.useOldVertexColors) {
55722
55723             newFace.vertexColors = [];
55724
55725             var color, tmpColor, order;
55726             for (var i=0;i<4;i++) {
55727                 order = orders[i];
55728
55729                 color = new THREE.Color(),
55730                 color.setRGB(0,0,0);
55731
55732                 for (var j=0, jl=0; j<order.length;j++) {
55733                     tmpColor = oldFace.vertexColors[order[j]-1];
55734                     color.r += tmpColor.r;
55735                     color.g += tmpColor.g;
55736                     color.b += tmpColor.b;
55737                 }
55738
55739                 color.r /= order.length;
55740                 color.g /= order.length;
55741                 color.b /= order.length;
55742
55743                 newFace.vertexColors[i] = color;
55744
55745             }
55746
55747         }
55748
55749         newFaces.push( newFace );
55750
55751         if (scope.supportUVs) {
55752
55753             var aUv = [
55754                 getUV(a, ''),
55755                 getUV(b, facei),
55756                 getUV(c, facei),
55757                 getUV(d, facei)
55758             ];
55759
55760             if (!aUv[0]) debug('a :( ', a+':'+facei);
55761             else if (!aUv[1]) debug('b :( ', b+':'+facei);
55762             else if (!aUv[2]) debug('c :( ', c+':'+facei);
55763             else if (!aUv[3]) debug('d :( ', d+':'+facei);
55764             else
55765                 newUVs.push( aUv );
55766
55767         }
55768     }
55769
55770     function edge_hash( a, b ) {
55771
55772         return Math.min( a, b ) + "_" + Math.max( a, b );
55773
55774     }
55775
55776     function computeEdgeFaces( geometry ) {
55777
55778         var i, il, v1, v2, j, k,
55779             face, faceIndices, faceIndex,
55780             edge,
55781             hash,
55782             edgeFaceMap = {};
55783
55784         function mapEdgeHash( hash, i ) {
55785
55786             if ( edgeFaceMap[ hash ] === undefined ) {
55787
55788                 edgeFaceMap[ hash ] = [];
55789
55790             }
55791
55792             edgeFaceMap[ hash ].push( i );
55793         }
55794
55795
55796         // construct vertex -> face map
55797
55798         for( i = 0, il = geometry.faces.length; i < il; i ++ ) {
55799
55800             face = geometry.faces[ i ];
55801
55802             if ( face instanceof THREE.Face3 ) {
55803
55804                 hash = edge_hash( face.a, face.b );
55805                 mapEdgeHash( hash, i );
55806
55807                 hash = edge_hash( face.b, face.c );
55808                 mapEdgeHash( hash, i );
55809
55810                 hash = edge_hash( face.c, face.a );
55811                 mapEdgeHash( hash, i );
55812
55813             } else if ( face instanceof THREE.Face4 ) {
55814
55815                 hash = edge_hash( face.a, face.b );
55816                 mapEdgeHash( hash, i );
55817
55818                 hash = edge_hash( face.b, face.c );
55819                 mapEdgeHash( hash, i );
55820
55821                 hash = edge_hash( face.c, face.d );
55822                 mapEdgeHash( hash, i );
55823
55824                 hash = edge_hash( face.d, face.a );
55825                 mapEdgeHash( hash, i );
55826
55827             }
55828
55829         }
55830
55831         // extract faces
55832
55833         // var edges = [];
55834         //
55835         // var numOfEdges = 0;
55836         // for (i in edgeFaceMap) {
55837         //     numOfEdges++;
55838         //
55839         //     edge = edgeFaceMap[i];
55840         //     edges.push(edge);
55841         //
55842         // }
55843
55844         //debug('edgeFaceMap', edgeFaceMap, 'geometry.edges',geometry.edges, 'numOfEdges', numOfEdges);
55845
55846         return edgeFaceMap;
55847
55848     }
55849
55850     var originalPoints = oldGeometry.vertices;
55851     var originalFaces = oldGeometry.faces;
55852
55853     var newPoints = originalPoints.concat(); // Vertices
55854
55855     var facePoints = [], edgePoints = {};
55856
55857     var sharpEdges = {}, sharpVertices = [], sharpFaces = [];
55858
55859     var uvForVertices = {}; // Stored in {vertex}:{old face} format
55860
55861     var originalVerticesLength = originalPoints.length;
55862
55863     function getUV(vertexNo, oldFaceNo) {
55864         var j,jl;
55865
55866         var key = vertexNo+':'+oldFaceNo;
55867         var theUV = uvForVertices[key];
55868
55869         if (!theUV) {
55870             if (vertexNo>=originalVerticesLength && vertexNo < (originalVerticesLength + originalFaces.length)) {
55871                 debug('face pt');
55872             } else {
55873                 debug('edge pt');
55874             }
55875
55876             warn('warning, UV not found for', key);
55877
55878             return null;
55879         }
55880
55881         return theUV;
55882
55883         // Original faces -> Vertex Nos.
55884         // new Facepoint -> Vertex Nos.
55885         // edge Points
55886
55887     }
55888
55889     function addUV(vertexNo, oldFaceNo, value) {
55890
55891         var key = vertexNo+':'+oldFaceNo;
55892         if (!(key in uvForVertices)) {
55893             uvForVertices[key] = value;
55894         } else {
55895             warn('dup vertexNo', vertexNo, 'oldFaceNo', oldFaceNo, 'value', value, 'key', key, uvForVertices[key]);
55896         }
55897     }
55898
55899     // Step 1
55900     //    For each face, add a face point
55901     //    Set each face point to be the centroid of all original points for the respective face.
55902     // debug(oldGeometry);
55903     var i, il, j, jl, face;
55904
55905     // For Uvs
55906     var uvs = oldGeometry.faceVertexUvs[0];
55907     var abcd = 'abcd', vertice;
55908
55909     debug('originalFaces, uvs, originalVerticesLength', originalFaces.length, uvs.length, originalVerticesLength);
55910     if (scope.supportUVs)
55911     for (i=0, il = uvs.length; i<il; i++ ) {
55912         for (j=0,jl=uvs[i].length;j<jl;j++) {
55913             vertice = originalFaces[i][abcd.charAt(j)];
55914
55915             addUV(vertice, i, uvs[i][j]);
55916
55917         }
55918     }
55919
55920     if (uvs.length == 0) scope.supportUVs = false;
55921
55922     // Additional UVs check, if we index original
55923     var uvCount = 0;
55924     for (var u in uvForVertices) {
55925         uvCount++;
55926     }
55927     if (!uvCount) {
55928         scope.supportUVs = false;
55929         debug('no uvs');
55930     }
55931
55932     debug('-- Original Faces + Vertices UVs completed', uvForVertices, 'vs', uvs.length);
55933
55934     var avgUv ;
55935     for (i=0, il = originalFaces.length; i<il ;i++) {
55936         face = originalFaces[ i ];
55937         facePoints.push( face.centroid );
55938         newPoints.push( face.centroid );
55939
55940
55941         if (!scope.supportUVs) continue;
55942
55943         // Prepare subdivided uv
55944
55945         avgUv = new THREE.UV();
55946
55947         if ( face instanceof THREE.Face3 ) {
55948             avgUv.u = getUV( face.a, i ).u + getUV( face.b, i ).u + getUV( face.c, i ).u;
55949             avgUv.v = getUV( face.a, i ).v + getUV( face.b, i ).v + getUV( face.c, i ).v;
55950             avgUv.u /= 3;
55951             avgUv.v /= 3;
55952
55953         } else if ( face instanceof THREE.Face4 ) {
55954             avgUv.u = getUV( face.a, i ).u + getUV( face.b, i ).u + getUV( face.c, i ).u + getUV( face.d, i ).u;
55955             avgUv.v = getUV( face.a, i ).v + getUV( face.b, i ).v + getUV( face.c, i ).v + getUV( face.d, i ).v;
55956             avgUv.u /= 4;
55957             avgUv.v /= 4;
55958         }
55959
55960         addUV(originalVerticesLength + i, '', avgUv);
55961
55962     }
55963
55964     debug('-- added UVs for new Faces', uvForVertices);
55965
55966     // Step 2
55967     //    For each edge, add an edge point.
55968     //    Set each edge point to be the average of the two neighbouring face points and its two original endpoints.
55969
55970     var edgeFaceMap = computeEdgeFaces ( oldGeometry ); // Edge Hash -> Faces Index
55971     var edge, faceIndexA, faceIndexB, avg;
55972
55973     // debug('edgeFaceMap', edgeFaceMap);
55974
55975     var edgeCount = 0;
55976
55977     var edgeVertex, edgeVertexA, edgeVertexB;
55978
55979     ////
55980
55981     var vertexEdgeMap = {}; // Gives edges connecting from each vertex
55982     var vertexFaceMap = {}; // Gives faces connecting from each vertex
55983
55984     function addVertexEdgeMap(vertex, edge) {
55985         if (vertexEdgeMap[vertex]===undefined) {
55986             vertexEdgeMap[vertex] = [];
55987         }
55988
55989         vertexEdgeMap[vertex].push(edge);
55990     }
55991
55992     function addVertexFaceMap(vertex, face, edge) {
55993         if (vertexFaceMap[vertex]===undefined) {
55994             vertexFaceMap[vertex] = {};
55995         }
55996
55997         vertexFaceMap[vertex][face] = edge;
55998         // vertexFaceMap[vertex][face] = null;
55999     }
56000
56001     // Prepares vertexEdgeMap and vertexFaceMap
56002     for (i in edgeFaceMap) { // This is for every edge
56003         edge = edgeFaceMap[i];
56004
56005         edgeVertex = i.split('_');
56006         edgeVertexA = edgeVertex[0];
56007         edgeVertexB = edgeVertex[1];
56008
56009         // Maps an edgeVertex to connecting edges
56010         addVertexEdgeMap(edgeVertexA, [edgeVertexA, edgeVertexB] );
56011         addVertexEdgeMap(edgeVertexB, [edgeVertexA, edgeVertexB] );
56012
56013
56014         for (j=0,jl=edge.length;j<jl;j++) {
56015             face = edge[j];
56016
56017             addVertexFaceMap(edgeVertexA, face, i);
56018             addVertexFaceMap(edgeVertexB, face, i);
56019         }
56020
56021         if (edge.length < 2) {
56022             // edge is "sharp";
56023             sharpEdges[i] = true;
56024             sharpVertices[edgeVertexA] = true;
56025             sharpVertices[edgeVertexB] = true;
56026
56027         }
56028
56029     }
56030
56031     debug('vertexEdgeMap',vertexEdgeMap, 'vertexFaceMap', vertexFaceMap);
56032
56033
56034     for (i in edgeFaceMap) {
56035         edge = edgeFaceMap[i];
56036
56037         faceIndexA = edge[0]; // face index a
56038         faceIndexB = edge[1]; // face index b
56039
56040         edgeVertex = i.split('_');
56041         edgeVertexA = edgeVertex[0];
56042         edgeVertexB = edgeVertex[1];
56043
56044
56045         avg = new THREE.Vector3();
56046
56047         //debug(i, faceIndexB,facePoints[faceIndexB]);
56048
56049         if (sharpEdges[i]) {
56050             //debug('warning, ', i, 'edge has only 1 connecting face', edge);
56051
56052             // For a sharp edge, average the edge end points.
56053             avg.addSelf(originalPoints[edgeVertexA]);
56054             avg.addSelf(originalPoints[edgeVertexB]);
56055
56056             avg.multiplyScalar(0.5);
56057
56058             sharpVertices[newPoints.length] = true;
56059
56060         } else {
56061
56062             avg.addSelf(facePoints[faceIndexA]);
56063             avg.addSelf(facePoints[faceIndexB]);
56064
56065             avg.addSelf(originalPoints[edgeVertexA]);
56066             avg.addSelf(originalPoints[edgeVertexB]);
56067
56068             avg.multiplyScalar(0.25);
56069
56070         }
56071
56072         edgePoints[i] = originalVerticesLength + originalFaces.length + edgeCount;
56073
56074         newPoints.push( avg );
56075
56076         edgeCount ++;
56077
56078         if (!scope.supportUVs) {
56079             continue;
56080         }
56081
56082         // debug('faceIndexAB', faceIndexA, faceIndexB, sharpEdges[i]);
56083
56084         // Prepare subdivided uv
56085
56086         avgUv = new THREE.UV();
56087
56088         avgUv.u = getUV(edgeVertexA, faceIndexA).u + getUV(edgeVertexB, faceIndexA).u;
56089         avgUv.v = getUV(edgeVertexA, faceIndexA).v + getUV(edgeVertexB, faceIndexA).v;
56090         avgUv.u /= 2;
56091         avgUv.v /= 2;
56092
56093         addUV(edgePoints[i], faceIndexA, avgUv);
56094
56095         if (!sharpEdges[i]) {
56096         avgUv = new THREE.UV();
56097
56098         avgUv.u = getUV(edgeVertexA, faceIndexB).u + getUV(edgeVertexB, faceIndexB).u;
56099         avgUv.v = getUV(edgeVertexA, faceIndexB).v + getUV(edgeVertexB, faceIndexB).v;
56100         avgUv.u /= 2;
56101         avgUv.v /= 2;
56102
56103         addUV(edgePoints[i], faceIndexB, avgUv);
56104         }
56105
56106     }
56107
56108     debug('-- Step 2 done');
56109
56110     // Step 3
56111     //    For each face point, add an edge for every edge of the face,
56112     //    connecting the face point to each edge point for the face.
56113
56114
56115     var facePt, currentVerticeIndex;
56116
56117     var hashAB, hashBC, hashCD, hashDA, hashCA;
56118
56119     var abc123 = ['123', '12', '2', '23'];
56120     var bca123 = ['123', '23', '3', '31'];
56121     var cab123 = ['123', '31', '1', '12'];
56122     var abc1234 = ['1234', '12', '2', '23'];
56123     var bcd1234 = ['1234', '23', '3', '34'];
56124     var cda1234 = ['1234', '34', '4', '41'];
56125     var dab1234 = ['1234', '41', '1', '12'];
56126
56127
56128     for (i=0, il = facePoints.length; i<il ;i++) { // for every face
56129         facePt = facePoints[i];
56130         face = originalFaces[i];
56131         currentVerticeIndex = originalVerticesLength+ i;
56132
56133         if ( face instanceof THREE.Face3 ) {
56134
56135             // create 3 face4s
56136
56137             hashAB = edge_hash( face.a, face.b );
56138             hashBC = edge_hash( face.b, face.c );
56139             hashCA = edge_hash( face.c, face.a );
56140
56141             f4( currentVerticeIndex, edgePoints[hashAB], face.b, edgePoints[hashBC], face, abc123, i );
56142             f4( currentVerticeIndex, edgePoints[hashBC], face.c, edgePoints[hashCA], face, bca123, i );
56143             f4( currentVerticeIndex, edgePoints[hashCA], face.a, edgePoints[hashAB], face, cab123, i );
56144
56145         } else if ( face instanceof THREE.Face4 ) {
56146             // create 4 face4s
56147
56148             hashAB = edge_hash( face.a, face.b );
56149             hashBC = edge_hash( face.b, face.c );
56150             hashCD = edge_hash( face.c, face.d );
56151             hashDA = edge_hash( face.d, face.a );
56152
56153             f4( currentVerticeIndex, edgePoints[hashAB], face.b, edgePoints[hashBC], face, abc1234, i );
56154             f4( currentVerticeIndex, edgePoints[hashBC], face.c, edgePoints[hashCD], face, bcd1234, i );
56155             f4( currentVerticeIndex, edgePoints[hashCD], face.d, edgePoints[hashDA], face, cda1234, i );
56156             f4( currentVerticeIndex, edgePoints[hashDA], face.a, edgePoints[hashAB], face, dab1234, i );
56157
56158
56159         } else {
56160             debug('face should be a face!', face);
56161         }
56162     }
56163
56164     newVertices = newPoints;
56165
56166     // debug('original ', oldGeometry.vertices.length, oldGeometry.faces.length );
56167     // debug('new points', newPoints.length, 'faces', newFaces.length );
56168
56169     // Step 4
56170
56171     //    For each original point P,
56172     //        take the average F of all n face points for faces touching P,
56173     //        and take the average R of all n edge midpoints for edges touching P,
56174     //        where each edge midpoint is the average of its two endpoint vertices.
56175     //    Move each original point to the point
56176
56177
56178     var F = new THREE.Vector3();
56179     var R = new THREE.Vector3();
56180
56181     var n;
56182     for (i=0, il = originalPoints.length; i<il; i++) {
56183         // (F + 2R + (n-3)P) / n
56184
56185         if (vertexEdgeMap[i]===undefined) continue;
56186
56187         F.set(0,0,0);
56188         R.set(0,0,0);
56189         var newPos =  new THREE.Vector3(0,0,0);
56190
56191         var f =0;
56192         for (j in vertexFaceMap[i]) {
56193             F.addSelf(facePoints[j]);
56194             f++;
56195         }
56196
56197         var sharpEdgeCount = 0;
56198
56199         n = vertexEdgeMap[i].length;
56200
56201         for (j=0;j<n;j++) {
56202             if (
56203                 sharpEdges[
56204                     edge_hash(vertexEdgeMap[i][j][0],vertexEdgeMap[i][j][1])
56205                 ]) {
56206                     sharpEdgeCount++;
56207                 }
56208         }
56209
56210         if ( sharpEdgeCount==2 ) {
56211             continue;
56212             // Do not move vertex if there's 2 connecting sharp edges.
56213         }
56214
56215         /*
56216         if (sharpEdgeCount>2) {
56217             // TODO
56218         }
56219         */
56220
56221         F.divideScalar(f);
56222
56223
56224
56225         for (j=0; j<n;j++) {
56226             edge = vertexEdgeMap[i][j];
56227             var midPt = originalPoints[edge[0]].clone().addSelf(originalPoints[edge[1]]).divideScalar(2);
56228             R.addSelf(midPt);
56229             // R.addSelf(originalPoints[edge[0]]);
56230             // R.addSelf(originalPoints[edge[1]]);
56231         }
56232
56233         R.divideScalar(n);
56234
56235         newPos.addSelf(originalPoints[i]);
56236         newPos.multiplyScalar(n - 3);
56237
56238         newPos.addSelf(F);
56239         newPos.addSelf(R.multiplyScalar(2));
56240         newPos.divideScalar(n);
56241
56242         newVertices[i] = newPos;
56243
56244
56245     }
56246
56247     var newGeometry = oldGeometry; // Let's pretend the old geometry is now new :P
56248
56249     newGeometry.vertices = newVertices;
56250     newGeometry.faces = newFaces;
56251     newGeometry.faceVertexUvs[ 0 ] = newUVs;
56252
56253     delete newGeometry.__tmpVertices; // makes __tmpVertices undefined :P
56254
56255     newGeometry.computeCentroids();
56256     newGeometry.computeFaceNormals();
56257     newGeometry.computeVertexNormals();
56258
56259 };
56260 /**
56261  * @author alteredq / http://alteredqualia.com/
56262  */
56263
56264 THREE.ImmediateRenderObject = function ( ) {
56265
56266     THREE.Object3D.call( this );
56267
56268     this.render = function ( renderCallback ) { };
56269
56270 };
56271
56272 THREE.ImmediateRenderObject.prototype = Object.create( THREE.Object3D.prototype );
56273 /**
56274  * @author mikael emtinger / http://gomo.se/
56275  * @author alteredq / http://alteredqualia.com/
56276  */
56277
56278 THREE.LensFlare = function ( texture, size, distance, blending, color ) {
56279
56280     THREE.Object3D.call( this );
56281
56282     this.lensFlares = [];
56283
56284     this.positionScreen = new THREE.Vector3();
56285     this.customUpdateCallback = undefined;
56286
56287     if( texture !== undefined ) {
56288
56289         this.add( texture, size, distance, blending, color );
56290
56291     }
56292
56293 };
56294
56295 THREE.LensFlare.prototype = Object.create( THREE.Object3D.prototype );
56296
56297
56298 /*
56299  * Add: adds another flare
56300  */
56301
56302 THREE.LensFlare.prototype.add = function ( texture, size, distance, blending, color, opacity ) {
56303
56304     if( size === undefined ) size = -1;
56305     if( distance === undefined ) distance = 0;
56306     if( opacity === undefined ) opacity = 1;
56307     if( color === undefined ) color = new THREE.Color( 0xffffff );
56308     if( blending === undefined ) blending = THREE.NormalBlending;
56309
56310     distance = Math.min( distance, Math.max( 0, distance ) );
56311
56312     this.lensFlares.push( { texture: texture,             // THREE.Texture
56313                             size: size,                 // size in pixels (-1 = use texture.width)
56314                             distance: distance,         // distance (0-1) from light source (0=at light source)
56315                             x: 0, y: 0, z: 0,            // screen position (-1 => 1) z = 0 is ontop z = 1 is back
56316                             scale: 1,                     // scale
56317                             rotation: 1,                 // rotation
56318                             opacity: opacity,            // opacity
56319                             color: color,                // color
56320                             blending: blending } );        // blending
56321
56322 };
56323
56324
56325 /*
56326  * Update lens flares update positions on all flares based on the screen position
56327  * Set myLensFlare.customUpdateCallback to alter the flares in your project specific way.
56328  */
56329
56330 THREE.LensFlare.prototype.updateLensFlares = function () {
56331
56332     var f, fl = this.lensFlares.length;
56333     var flare;
56334     var vecX = -this.positionScreen.x * 2;
56335     var vecY = -this.positionScreen.y * 2;
56336
56337     for( f = 0; f < fl; f ++ ) {
56338
56339         flare = this.lensFlares[ f ];
56340
56341         flare.x = this.positionScreen.x + vecX * flare.distance;
56342         flare.y = this.positionScreen.y + vecY * flare.distance;
56343
56344         flare.wantedRotation = flare.x * Math.PI * 0.25;
56345         flare.rotation += ( flare.wantedRotation - flare.rotation ) * 0.25;
56346
56347     }
56348
56349 };
56350
56351
56352
56353
56354
56355
56356
56357
56358
56359
56360
56361
56362 /**
56363  * @author alteredq / http://alteredqualia.com/
56364  */
56365
56366 THREE.MorphBlendMesh = function( geometry, material ) {
56367
56368     THREE.Mesh.call( this, geometry, material );
56369
56370     this.animationsMap = {};
56371     this.animationsList = [];
56372
56373     // prepare default animation
56374     // (all frames played together in 1 second)
56375
56376     var numFrames = this.geometry.morphTargets.length;
56377
56378     var name = "__default";
56379
56380     var startFrame = 0;
56381     var endFrame = numFrames - 1;
56382
56383     var fps = numFrames / 1;
56384
56385     this.createAnimation( name, startFrame, endFrame, fps );
56386     this.setAnimationWeight( name, 1 );
56387
56388 };
56389
56390 THREE.MorphBlendMesh.prototype = Object.create( THREE.Mesh.prototype );
56391
56392 THREE.MorphBlendMesh.prototype.createAnimation = function ( name, start, end, fps ) {
56393
56394     var animation = {
56395
56396         startFrame: start,
56397         endFrame: end,
56398
56399         length: end - start + 1,
56400
56401         fps: fps,
56402         duration: ( end - start ) / fps,
56403
56404         lastFrame: 0,
56405         currentFrame: 0,
56406
56407         active: false,
56408
56409         time: 0,
56410         direction: 1,
56411         weight: 1,
56412
56413         directionBackwards: false,
56414         mirroredLoop: false
56415
56416     };
56417
56418     this.animationsMap[ name ] = animation;
56419     this.animationsList.push( animation );
56420
56421 };
56422
56423 THREE.MorphBlendMesh.prototype.autoCreateAnimations = function ( fps ) {
56424
56425     var pattern = /([a-z]+)(\d+)/;
56426
56427     var firstAnimation, frameRanges = {};
56428
56429     var geometry = this.geometry;
56430
56431     for ( var i = 0, il = geometry.morphTargets.length; i < il; i ++ ) {
56432
56433         var morph = geometry.morphTargets[ i ];
56434         var chunks = morph.name.match( pattern );
56435
56436         if ( chunks && chunks.length > 1 ) {
56437
56438             var name = chunks[ 1 ];
56439             var num = chunks[ 2 ];
56440
56441             if ( ! frameRanges[ name ] ) frameRanges[ name ] = { start: Infinity, end: -Infinity };
56442
56443             var range = frameRanges[ name ];
56444
56445             if ( i < range.start ) range.start = i;
56446             if ( i > range.end ) range.end = i;
56447
56448             if ( ! firstAnimation ) firstAnimation = name;
56449
56450         }
56451
56452     }
56453
56454     for ( var name in frameRanges ) {
56455
56456         var range = frameRanges[ name ];
56457         this.createAnimation( name, range.start, range.end, fps );
56458
56459     }
56460
56461     this.firstAnimation = firstAnimation;
56462
56463 };
56464
56465 THREE.MorphBlendMesh.prototype.setAnimationDirectionForward = function ( name ) {
56466
56467     var animation = this.animationsMap[ name ];
56468
56469     if ( animation ) {
56470
56471         animation.direction = 1;
56472         animation.directionBackwards = false;
56473
56474     }
56475
56476 };
56477
56478 THREE.MorphBlendMesh.prototype.setAnimationDirectionBackward = function ( name ) {
56479
56480     var animation = this.animationsMap[ name ];
56481
56482     if ( animation ) {
56483
56484         animation.direction = -1;
56485         animation.directionBackwards = true;
56486
56487     }
56488
56489 };
56490
56491 THREE.MorphBlendMesh.prototype.setAnimationFPS = function ( name, fps ) {
56492
56493     var animation = this.animationsMap[ name ];
56494
56495     if ( animation ) {
56496
56497         animation.fps = fps;
56498         animation.duration = ( animation.end - animation.start ) / animation.fps;
56499
56500     }
56501
56502 };
56503
56504 THREE.MorphBlendMesh.prototype.setAnimationDuration = function ( name, duration ) {
56505
56506     var animation = this.animationsMap[ name ];
56507
56508     if ( animation ) {
56509
56510         animation.duration = duration;
56511         animation.fps = ( animation.end - animation.start ) / animation.duration;
56512
56513     }
56514
56515 };
56516
56517 THREE.MorphBlendMesh.prototype.setAnimationWeight = function ( name, weight ) {
56518
56519     var animation = this.animationsMap[ name ];
56520
56521     if ( animation ) {
56522
56523         animation.weight = weight;
56524
56525     }
56526
56527 };
56528
56529 THREE.MorphBlendMesh.prototype.setAnimationTime = function ( name, time ) {
56530
56531     var animation = this.animationsMap[ name ];
56532
56533     if ( animation ) {
56534
56535         animation.time = time;
56536
56537     }
56538
56539 };
56540
56541 THREE.MorphBlendMesh.prototype.getAnimationTime = function ( name ) {
56542
56543     var time = 0;
56544
56545     var animation = this.animationsMap[ name ];
56546
56547     if ( animation ) {
56548
56549         time = animation.time;
56550
56551     }
56552
56553     return time;
56554
56555 };
56556
56557 THREE.MorphBlendMesh.prototype.getAnimationDuration = function ( name ) {
56558
56559     var duration = -1;
56560
56561     var animation = this.animationsMap[ name ];
56562
56563     if ( animation ) {
56564
56565         duration = animation.duration;
56566
56567     }
56568
56569     return duration;
56570
56571 };
56572
56573 THREE.MorphBlendMesh.prototype.playAnimation = function ( name ) {
56574
56575     var animation = this.animationsMap[ name ];
56576
56577     if ( animation ) {
56578
56579         animation.time = 0;
56580         animation.active = true;
56581
56582     } else {
56583
56584         console.warn( "animation[" + name + "] undefined" );
56585
56586     }
56587
56588 };
56589
56590 THREE.MorphBlendMesh.prototype.stopAnimation = function ( name ) {
56591
56592     var animation = this.animationsMap[ name ];
56593
56594     if ( animation ) {
56595
56596         animation.active = false;
56597
56598     }
56599
56600 };
56601
56602 THREE.MorphBlendMesh.prototype.update = function ( delta ) {
56603
56604     for ( var i = 0, il = this.animationsList.length; i < il; i ++ ) {
56605
56606         var animation = this.animationsList[ i ];
56607
56608         if ( ! animation.active ) continue;
56609
56610         var frameTime = animation.duration / animation.length;
56611
56612         animation.time += animation.direction * delta;
56613
56614         if ( animation.mirroredLoop ) {
56615
56616             if ( animation.time > animation.duration || animation.time < 0 ) {
56617
56618                 animation.direction *= -1;
56619
56620                 if ( animation.time > animation.duration ) {
56621
56622                     animation.time = animation.duration;
56623                     animation.directionBackwards = true;
56624
56625                 }
56626
56627                 if ( animation.time < 0 ) {
56628
56629                     animation.time = 0;
56630                     animation.directionBackwards = false;
56631
56632                 }
56633
56634             }
56635
56636         } else {
56637
56638             animation.time = animation.time % animation.duration;
56639
56640             if ( animation.time < 0 ) animation.time += animation.duration;
56641
56642         }
56643
56644         var keyframe = animation.startFrame + THREE.Math.clamp( Math.floor( animation.time / frameTime ), 0, animation.length - 1 );
56645         var weight = animation.weight;
56646
56647         if ( keyframe !== animation.currentFrame ) {
56648
56649             this.morphTargetInfluences[ animation.lastFrame ] = 0;
56650             this.morphTargetInfluences[ animation.currentFrame ] = 1 * weight;
56651
56652             this.morphTargetInfluences[ keyframe ] = 0;
56653
56654             animation.lastFrame = animation.currentFrame;
56655             animation.currentFrame = keyframe;
56656
56657         }
56658
56659         var mix = ( animation.time % frameTime ) / frameTime;
56660
56661         if ( animation.directionBackwards ) mix = 1 - mix;
56662
56663         this.morphTargetInfluences[ animation.currentFrame ] = mix * weight;
56664         this.morphTargetInfluences[ animation.lastFrame ] = ( 1 - mix ) * weight;
56665
56666     }
56667
56668 };
56669 /**
56670  * @author mikael emtinger / http://gomo.se/
56671  * @author alteredq / http://alteredqualia.com/
56672  */
56673
56674 THREE.LensFlarePlugin = function ( ) {
56675
56676     var _gl, _renderer, _lensFlare = {};
56677
56678     this.init = function ( renderer ) {
56679
56680         _gl = renderer.context;
56681         _renderer = renderer;
56682
56683         _lensFlare.vertices = new Float32Array( 8 + 8 );
56684         _lensFlare.faces = new Uint16Array( 6 );
56685
56686         var i = 0;
56687         _lensFlare.vertices[ i++ ] = -1; _lensFlare.vertices[ i++ ] = -1;    // vertex
56688         _lensFlare.vertices[ i++ ] = 0;  _lensFlare.vertices[ i++ ] = 0;    // uv... etc.
56689
56690         _lensFlare.vertices[ i++ ] = 1;  _lensFlare.vertices[ i++ ] = -1;
56691         _lensFlare.vertices[ i++ ] = 1;  _lensFlare.vertices[ i++ ] = 0;
56692
56693         _lensFlare.vertices[ i++ ] = 1;  _lensFlare.vertices[ i++ ] = 1;
56694         _lensFlare.vertices[ i++ ] = 1;  _lensFlare.vertices[ i++ ] = 1;
56695
56696         _lensFlare.vertices[ i++ ] = -1; _lensFlare.vertices[ i++ ] = 1;
56697         _lensFlare.vertices[ i++ ] = 0;  _lensFlare.vertices[ i++ ] = 1;
56698
56699         i = 0;
56700         _lensFlare.faces[ i++ ] = 0; _lensFlare.faces[ i++ ] = 1; _lensFlare.faces[ i++ ] = 2;
56701         _lensFlare.faces[ i++ ] = 0; _lensFlare.faces[ i++ ] = 2; _lensFlare.faces[ i++ ] = 3;
56702
56703         // buffers
56704
56705         _lensFlare.vertexBuffer     = _gl.createBuffer();
56706         _lensFlare.elementBuffer    = _gl.createBuffer();
56707
56708         _gl.bindBuffer( _gl.ARRAY_BUFFER, _lensFlare.vertexBuffer );
56709         _gl.bufferData( _gl.ARRAY_BUFFER, _lensFlare.vertices, _gl.STATIC_DRAW );
56710
56711         _gl.bindBuffer( _gl.ELEMENT_ARRAY_BUFFER, _lensFlare.elementBuffer );
56712         _gl.bufferData( _gl.ELEMENT_ARRAY_BUFFER, _lensFlare.faces, _gl.STATIC_DRAW );
56713
56714         // textures
56715
56716         _lensFlare.tempTexture      = _gl.createTexture();
56717         _lensFlare.occlusionTexture = _gl.createTexture();
56718
56719         _gl.bindTexture( _gl.TEXTURE_2D, _lensFlare.tempTexture );
56720         _gl.texImage2D( _gl.TEXTURE_2D, 0, _gl.RGB, 16, 16, 0, _gl.RGB, _gl.UNSIGNED_BYTE, null );
56721         _gl.texParameteri( _gl.TEXTURE_2D, _gl.TEXTURE_WRAP_S, _gl.CLAMP_TO_EDGE );
56722         _gl.texParameteri( _gl.TEXTURE_2D, _gl.TEXTURE_WRAP_T, _gl.CLAMP_TO_EDGE );
56723         _gl.texParameteri( _gl.TEXTURE_2D, _gl.TEXTURE_MAG_FILTER, _gl.NEAREST );
56724         _gl.texParameteri( _gl.TEXTURE_2D, _gl.TEXTURE_MIN_FILTER, _gl.NEAREST );
56725
56726         _gl.bindTexture( _gl.TEXTURE_2D, _lensFlare.occlusionTexture );
56727         _gl.texImage2D( _gl.TEXTURE_2D, 0, _gl.RGBA, 16, 16, 0, _gl.RGBA, _gl.UNSIGNED_BYTE, null );
56728         _gl.texParameteri( _gl.TEXTURE_2D, _gl.TEXTURE_WRAP_S, _gl.CLAMP_TO_EDGE );
56729         _gl.texParameteri( _gl.TEXTURE_2D, _gl.TEXTURE_WRAP_T, _gl.CLAMP_TO_EDGE );
56730         _gl.texParameteri( _gl.TEXTURE_2D, _gl.TEXTURE_MAG_FILTER, _gl.NEAREST );
56731         _gl.texParameteri( _gl.TEXTURE_2D, _gl.TEXTURE_MIN_FILTER, _gl.NEAREST );
56732
56733         if ( _gl.getParameter( _gl.MAX_VERTEX_TEXTURE_IMAGE_UNITS ) <= 0 ) {
56734
56735             _lensFlare.hasVertexTexture = false;
56736             _lensFlare.program = createProgram( THREE.ShaderFlares[ "lensFlare" ] );
56737
56738         } else {
56739
56740             _lensFlare.hasVertexTexture = true;
56741             _lensFlare.program = createProgram( THREE.ShaderFlares[ "lensFlareVertexTexture" ] );
56742
56743         }
56744
56745         _lensFlare.attributes = {};
56746         _lensFlare.uniforms = {};
56747
56748         _lensFlare.attributes.vertex       = _gl.getAttribLocation ( _lensFlare.program, "position" );
56749         _lensFlare.attributes.uv           = _gl.getAttribLocation ( _lensFlare.program, "uv" );
56750
56751         _lensFlare.uniforms.renderType     = _gl.getUniformLocation( _lensFlare.program, "renderType" );
56752         _lensFlare.uniforms.map            = _gl.getUniformLocation( _lensFlare.program, "map" );
56753         _lensFlare.uniforms.occlusionMap   = _gl.getUniformLocation( _lensFlare.program, "occlusionMap" );
56754         _lensFlare.uniforms.opacity        = _gl.getUniformLocation( _lensFlare.program, "opacity" );
56755         _lensFlare.uniforms.color          = _gl.getUniformLocation( _lensFlare.program, "color" );
56756         _lensFlare.uniforms.scale          = _gl.getUniformLocation( _lensFlare.program, "scale" );
56757         _lensFlare.uniforms.rotation       = _gl.getUniformLocation( _lensFlare.program, "rotation" );
56758         _lensFlare.uniforms.screenPosition = _gl.getUniformLocation( _lensFlare.program, "screenPosition" );
56759
56760         _lensFlare.attributesEnabled = false;
56761
56762     };
56763
56764
56765     /*
56766      * Render lens flares
56767      * Method: renders 16x16 0xff00ff-colored points scattered over the light source area,
56768      *         reads these back and calculates occlusion.
56769      *         Then _lensFlare.update_lensFlares() is called to re-position and
56770      *         update transparency of flares. Then they are rendered.
56771      *
56772      */
56773
56774     this.render = function ( scene, camera, viewportWidth, viewportHeight ) {
56775
56776         var flares = scene.__webglFlares,
56777             nFlares = flares.length;
56778
56779         if ( ! nFlares ) return;
56780
56781         var tempPosition = new THREE.Vector3();
56782
56783         var invAspect = viewportHeight / viewportWidth,
56784             halfViewportWidth = viewportWidth * 0.5,
56785             halfViewportHeight = viewportHeight * 0.5;
56786
56787         var size = 16 / viewportHeight,
56788             scale = new THREE.Vector2( size * invAspect, size );
56789
56790         var screenPosition = new THREE.Vector3( 1, 1, 0 ),
56791             screenPositionPixels = new THREE.Vector2( 1, 1 );
56792
56793         var uniforms = _lensFlare.uniforms,
56794             attributes = _lensFlare.attributes;
56795
56796         // set _lensFlare program and reset blending
56797
56798         _gl.useProgram( _lensFlare.program );
56799
56800         if ( ! _lensFlare.attributesEnabled ) {
56801
56802             _gl.enableVertexAttribArray( _lensFlare.attributes.vertex );
56803             _gl.enableVertexAttribArray( _lensFlare.attributes.uv );
56804
56805             _lensFlare.attributesEnabled = true;
56806
56807         }
56808
56809         // loop through all lens flares to update their occlusion and positions
56810         // setup gl and common used attribs/unforms
56811
56812         _gl.uniform1i( uniforms.occlusionMap, 0 );
56813         _gl.uniform1i( uniforms.map, 1 );
56814
56815         _gl.bindBuffer( _gl.ARRAY_BUFFER, _lensFlare.vertexBuffer );
56816         _gl.vertexAttribPointer( attributes.vertex, 2, _gl.FLOAT, false, 2 * 8, 0 );
56817         _gl.vertexAttribPointer( attributes.uv, 2, _gl.FLOAT, false, 2 * 8, 8 );
56818
56819         _gl.bindBuffer( _gl.ELEMENT_ARRAY_BUFFER, _lensFlare.elementBuffer );
56820
56821         _gl.disable( _gl.CULL_FACE );
56822         _gl.depthMask( false );
56823
56824         var i, j, jl, flare, sprite;
56825
56826         for ( i = 0; i < nFlares; i ++ ) {
56827
56828             size = 16 / viewportHeight;
56829             scale.set( size * invAspect, size );
56830
56831             // calc object screen position
56832
56833             flare = flares[ i ];
56834
56835             tempPosition.set( flare.matrixWorld.elements[12], flare.matrixWorld.elements[13], flare.matrixWorld.elements[14] );
56836
56837             camera.matrixWorldInverse.multiplyVector3( tempPosition );
56838             camera.projectionMatrix.multiplyVector3( tempPosition );
56839
56840             // setup arrays for gl programs
56841
56842             screenPosition.copy( tempPosition )
56843
56844             screenPositionPixels.x = screenPosition.x * halfViewportWidth + halfViewportWidth;
56845             screenPositionPixels.y = screenPosition.y * halfViewportHeight + halfViewportHeight;
56846
56847             // screen cull
56848
56849             if ( _lensFlare.hasVertexTexture || (
56850                 screenPositionPixels.x > 0 &&
56851                 screenPositionPixels.x < viewportWidth &&
56852                 screenPositionPixels.y > 0 &&
56853                 screenPositionPixels.y < viewportHeight ) ) {
56854
56855                 // save current RGB to temp texture
56856
56857                 _gl.activeTexture( _gl.TEXTURE1 );
56858                 _gl.bindTexture( _gl.TEXTURE_2D, _lensFlare.tempTexture );
56859                 _gl.copyTexImage2D( _gl.TEXTURE_2D, 0, _gl.RGB, screenPositionPixels.x - 8, screenPositionPixels.y - 8, 16, 16, 0 );
56860
56861
56862                 // render pink quad
56863
56864                 _gl.uniform1i( uniforms.renderType, 0 );
56865                 _gl.uniform2f( uniforms.scale, scale.x, scale.y );
56866                 _gl.uniform3f( uniforms.screenPosition, screenPosition.x, screenPosition.y, screenPosition.z );
56867
56868                 _gl.disable( _gl.BLEND );
56869                 _gl.enable( _gl.DEPTH_TEST );
56870
56871                 _gl.drawElements( _gl.TRIANGLES, 6, _gl.UNSIGNED_SHORT, 0 );
56872
56873
56874                 // copy result to occlusionMap
56875
56876                 _gl.activeTexture( _gl.TEXTURE0 );
56877                 _gl.bindTexture( _gl.TEXTURE_2D, _lensFlare.occlusionTexture );
56878                 _gl.copyTexImage2D( _gl.TEXTURE_2D, 0, _gl.RGBA, screenPositionPixels.x - 8, screenPositionPixels.y - 8, 16, 16, 0 );
56879
56880
56881                 // restore graphics
56882
56883                 _gl.uniform1i( uniforms.renderType, 1 );
56884                 _gl.disable( _gl.DEPTH_TEST );
56885
56886                 _gl.activeTexture( _gl.TEXTURE1 );
56887                 _gl.bindTexture( _gl.TEXTURE_2D, _lensFlare.tempTexture );
56888                 _gl.drawElements( _gl.TRIANGLES, 6, _gl.UNSIGNED_SHORT, 0 );
56889
56890
56891                 // update object positions
56892
56893                 flare.positionScreen.copy( screenPosition )
56894
56895                 if ( flare.customUpdateCallback ) {
56896
56897                     flare.customUpdateCallback( flare );
56898
56899                 } else {
56900
56901                     flare.updateLensFlares();
56902
56903                 }
56904
56905                 // render flares
56906
56907                 _gl.uniform1i( uniforms.renderType, 2 );
56908                 _gl.enable( _gl.BLEND );
56909
56910                 for ( j = 0, jl = flare.lensFlares.length; j < jl; j ++ ) {
56911
56912                     sprite = flare.lensFlares[ j ];
56913
56914                     if ( sprite.opacity > 0.001 && sprite.scale > 0.001 ) {
56915
56916                         screenPosition.x = sprite.x;
56917                         screenPosition.y = sprite.y;
56918                         screenPosition.z = sprite.z;
56919
56920                         size = sprite.size * sprite.scale / viewportHeight;
56921
56922                         scale.x = size * invAspect;
56923                         scale.y = size;
56924
56925                         _gl.uniform3f( uniforms.screenPosition, screenPosition.x, screenPosition.y, screenPosition.z );
56926                         _gl.uniform2f( uniforms.scale, scale.x, scale.y );
56927                         _gl.uniform1f( uniforms.rotation, sprite.rotation );
56928
56929                         _gl.uniform1f( uniforms.opacity, sprite.opacity );
56930                         _gl.uniform3f( uniforms.color, sprite.color.r, sprite.color.g, sprite.color.b );
56931
56932                         _renderer.setBlending( sprite.blending, sprite.blendEquation, sprite.blendSrc, sprite.blendDst );
56933                         _renderer.setTexture( sprite.texture, 1 );
56934
56935                         _gl.drawElements( _gl.TRIANGLES, 6, _gl.UNSIGNED_SHORT, 0 );
56936
56937                     }
56938
56939                 }
56940
56941             }
56942
56943         }
56944
56945         // restore gl
56946
56947         _gl.enable( _gl.CULL_FACE );
56948         _gl.enable( _gl.DEPTH_TEST );
56949         _gl.depthMask( true );
56950
56951     };
56952
56953     function createProgram ( shader ) {
56954
56955         var program = _gl.createProgram();
56956
56957         var fragmentShader = _gl.createShader( _gl.FRAGMENT_SHADER );
56958         var vertexShader = _gl.createShader( _gl.VERTEX_SHADER );
56959
56960         _gl.shaderSource( fragmentShader, shader.fragmentShader );
56961         _gl.shaderSource( vertexShader, shader.vertexShader );
56962
56963         _gl.compileShader( fragmentShader );
56964         _gl.compileShader( vertexShader );
56965
56966         _gl.attachShader( program, fragmentShader );
56967         _gl.attachShader( program, vertexShader );
56968
56969         _gl.linkProgram( program );
56970
56971         return program;
56972
56973     };
56974
56975 };/**
56976  * @author alteredq / http://alteredqualia.com/
56977  */
56978
56979 THREE.ShadowMapPlugin = function ( ) {
56980
56981     var _gl,
56982     _renderer,
56983     _depthMaterial, _depthMaterialMorph, _depthMaterialSkin, _depthMaterialMorphSkin,
56984
56985     _frustum = new THREE.Frustum(),
56986     _projScreenMatrix = new THREE.Matrix4(),
56987
56988     _min = new THREE.Vector3(),
56989     _max = new THREE.Vector3();
56990
56991     this.init = function ( renderer ) {
56992
56993         _gl = renderer.context;
56994         _renderer = renderer;
56995
56996         var depthShader = THREE.ShaderLib[ "depthRGBA" ];
56997         var depthUniforms = THREE.UniformsUtils.clone( depthShader.uniforms );
56998
56999         _depthMaterial = new THREE.ShaderMaterial( { fragmentShader: depthShader.fragmentShader, vertexShader: depthShader.vertexShader, uniforms: depthUniforms } );
57000         _depthMaterialMorph = new THREE.ShaderMaterial( { fragmentShader: depthShader.fragmentShader, vertexShader: depthShader.vertexShader, uniforms: depthUniforms, morphTargets: true } );
57001         _depthMaterialSkin = new THREE.ShaderMaterial( { fragmentShader: depthShader.fragmentShader, vertexShader: depthShader.vertexShader, uniforms: depthUniforms, skinning: true } );
57002         _depthMaterialMorphSkin = new THREE.ShaderMaterial( { fragmentShader: depthShader.fragmentShader, vertexShader: depthShader.vertexShader, uniforms: depthUniforms, morphTargets: true, skinning: true } );
57003
57004         _depthMaterial._shadowPass = true;
57005         _depthMaterialMorph._shadowPass = true;
57006         _depthMaterialSkin._shadowPass = true;
57007         _depthMaterialMorphSkin._shadowPass = true;
57008
57009     };
57010
57011     this.render = function ( scene, camera ) {
57012
57013         if ( ! ( _renderer.shadowMapEnabled && _renderer.shadowMapAutoUpdate ) ) return;
57014
57015         this.update( scene, camera );
57016
57017     };
57018
57019     this.update = function ( scene, camera ) {
57020
57021         var i, il, j, jl, n,
57022
57023         shadowMap, shadowMatrix, shadowCamera,
57024         program, buffer, material,
57025         webglObject, object, light,
57026         renderList,
57027
57028         lights = [],
57029         k = 0,
57030
57031         fog = null;
57032
57033         // set GL state for depth map
57034
57035         _gl.clearColor( 1, 1, 1, 1 );
57036         _gl.disable( _gl.BLEND );
57037
57038         _gl.enable( _gl.CULL_FACE );
57039         _gl.frontFace( _gl.CCW );
57040
57041         if ( _renderer.shadowMapCullFrontFaces ) {
57042
57043             _gl.cullFace( _gl.FRONT );
57044
57045         } else {
57046
57047             _gl.cullFace( _gl.BACK );
57048
57049         }
57050
57051         _renderer.setDepthTest( true );
57052
57053         // preprocess lights
57054         //     - skip lights that are not casting shadows
57055         //    - create virtual lights for cascaded shadow maps
57056
57057         for ( i = 0, il = scene.__lights.length; i < il; i ++ ) {
57058
57059             light = scene.__lights[ i ];
57060
57061             if ( ! light.castShadow ) continue;
57062
57063             if ( ( light instanceof THREE.DirectionalLight ) && light.shadowCascade ) {
57064
57065                 for ( n = 0; n < light.shadowCascadeCount; n ++ ) {
57066
57067                     var virtualLight;
57068
57069                     if ( ! light.shadowCascadeArray[ n ] ) {
57070
57071                         virtualLight = createVirtualLight( light, n );
57072                         virtualLight.originalCamera = camera;
57073
57074                         var gyro = new THREE.Gyroscope();
57075                         gyro.position = light.shadowCascadeOffset;
57076
57077                         gyro.add( virtualLight );
57078                         gyro.add( virtualLight.target );
57079
57080                         camera.add( gyro );
57081
57082                         light.shadowCascadeArray[ n ] = virtualLight;
57083
57084                         console.log( "Created virtualLight", virtualLight );
57085
57086                     } else {
57087
57088                         virtualLight = light.shadowCascadeArray[ n ];
57089
57090                     }
57091
57092                     updateVirtualLight( light, n );
57093
57094                     lights[ k ] = virtualLight;
57095                     k ++;
57096
57097                 }
57098
57099             } else {
57100
57101                 lights[ k ] = light;
57102                 k ++;
57103
57104             }
57105
57106         }
57107
57108         // render depth map
57109
57110         for ( i = 0, il = lights.length; i < il; i ++ ) {
57111
57112             light = lights[ i ];
57113
57114             if ( ! light.shadowMap ) {
57115
57116                 var pars = { minFilter: THREE.LinearFilter, magFilter: THREE.LinearFilter, format: THREE.RGBAFormat };
57117
57118                 light.shadowMap = new THREE.WebGLRenderTarget( light.shadowMapWidth, light.shadowMapHeight, pars );
57119                 light.shadowMapSize = new THREE.Vector2( light.shadowMapWidth, light.shadowMapHeight );
57120
57121                 light.shadowMatrix = new THREE.Matrix4();
57122
57123             }
57124
57125             if ( ! light.shadowCamera ) {
57126
57127                 if ( light instanceof THREE.SpotLight ) {
57128
57129                     light.shadowCamera = new THREE.PerspectiveCamera( light.shadowCameraFov, light.shadowMapWidth / light.shadowMapHeight, light.shadowCameraNear, light.shadowCameraFar );
57130
57131                 } else if ( light instanceof THREE.DirectionalLight ) {
57132
57133                     light.shadowCamera = new THREE.OrthographicCamera( light.shadowCameraLeft, light.shadowCameraRight, light.shadowCameraTop, light.shadowCameraBottom, light.shadowCameraNear, light.shadowCameraFar );
57134
57135                 } else {
57136
57137                     console.error( "Unsupported light type for shadow" );
57138                     continue;
57139
57140                 }
57141
57142                 scene.add( light.shadowCamera );
57143
57144                 if ( _renderer.autoUpdateScene ) scene.updateMatrixWorld();
57145
57146             }
57147
57148             if ( light.shadowCameraVisible && ! light.cameraHelper ) {
57149
57150                 light.cameraHelper = new THREE.CameraHelper( light.shadowCamera );
57151                 light.shadowCamera.add( light.cameraHelper );
57152
57153             }
57154
57155             if ( light.isVirtual && virtualLight.originalCamera == camera ) {
57156
57157                 updateShadowCamera( camera, light );
57158
57159             }
57160
57161             shadowMap = light.shadowMap;
57162             shadowMatrix = light.shadowMatrix;
57163             shadowCamera = light.shadowCamera;
57164
57165             shadowCamera.position.copy( light.matrixWorld.getPosition() );
57166             shadowCamera.lookAt( light.target.matrixWorld.getPosition() );
57167             shadowCamera.updateMatrixWorld();
57168
57169             shadowCamera.matrixWorldInverse.getInverse( shadowCamera.matrixWorld );
57170
57171             if ( light.cameraHelper ) light.cameraHelper.visible = light.shadowCameraVisible;
57172             if ( light.shadowCameraVisible ) light.cameraHelper.update();
57173
57174             // compute shadow matrix
57175
57176             shadowMatrix.set( 0.5, 0.0, 0.0, 0.5,
57177                               0.0, 0.5, 0.0, 0.5,
57178                               0.0, 0.0, 0.5, 0.5,
57179                               0.0, 0.0, 0.0, 1.0 );
57180
57181             shadowMatrix.multiplySelf( shadowCamera.projectionMatrix );
57182             shadowMatrix.multiplySelf( shadowCamera.matrixWorldInverse );
57183
57184             // update camera matrices and frustum
57185
57186             if ( ! shadowCamera._viewMatrixArray ) shadowCamera._viewMatrixArray = new Float32Array( 16 );
57187             if ( ! shadowCamera._projectionMatrixArray ) shadowCamera._projectionMatrixArray = new Float32Array( 16 );
57188
57189             shadowCamera.matrixWorldInverse.flattenToArray( shadowCamera._viewMatrixArray );
57190             shadowCamera.projectionMatrix.flattenToArray( shadowCamera._projectionMatrixArray );
57191
57192             _projScreenMatrix.multiply( shadowCamera.projectionMatrix, shadowCamera.matrixWorldInverse );
57193             _frustum.setFromMatrix( _projScreenMatrix );
57194
57195             // render shadow map
57196
57197             _renderer.setRenderTarget( shadowMap );
57198             _renderer.clear();
57199
57200             // set object matrices & frustum culling
57201
57202             renderList = scene.__webglObjects;
57203
57204             for ( j = 0, jl = renderList.length; j < jl; j ++ ) {
57205
57206                 webglObject = renderList[ j ];
57207                 object = webglObject.object;
57208
57209                 webglObject.render = false;
57210
57211                 if ( object.visible && object.castShadow ) {
57212
57213                     if ( ! ( object instanceof THREE.Mesh ) || ! ( object.frustumCulled ) || _frustum.contains( object ) ) {
57214
57215                         object._modelViewMatrix.multiply( shadowCamera.matrixWorldInverse, object.matrixWorld );
57216
57217                         webglObject.render = true;
57218
57219                     }
57220
57221                 }
57222
57223             }
57224
57225             // render regular objects
57226
57227             for ( j = 0, jl = renderList.length; j < jl; j ++ ) {
57228
57229                 webglObject = renderList[ j ];
57230
57231                 if ( webglObject.render ) {
57232
57233                     object = webglObject.object;
57234                     buffer = webglObject.buffer;
57235
57236                     // culling is overriden globally for all objects
57237                     // while rendering depth map
57238
57239                     if ( object.customDepthMaterial ) {
57240
57241                         material = object.customDepthMaterial;
57242
57243                     } else if ( object instanceof THREE.SkinnedMesh ) {
57244
57245                         material = object.geometry.morphTargets.length ? _depthMaterialMorphSkin : _depthMaterialSkin;
57246
57247                     } else if ( object.geometry.morphTargets.length ) {
57248
57249                         material = _depthMaterialMorph;
57250
57251                     } else {
57252
57253                         material = _depthMaterial;
57254
57255                     }
57256
57257                     if ( buffer instanceof THREE.BufferGeometry ) {
57258
57259                         _renderer.renderBufferDirect( shadowCamera, scene.__lights, fog, material, buffer, object );
57260
57261                     } else {
57262
57263                         _renderer.renderBuffer( shadowCamera, scene.__lights, fog, material, buffer, object );
57264
57265                     }
57266
57267                 }
57268
57269             }
57270
57271             // set matrices and render immediate objects
57272
57273             renderList = scene.__webglObjectsImmediate;
57274
57275             for ( j = 0, jl = renderList.length; j < jl; j ++ ) {
57276
57277                 webglObject = renderList[ j ];
57278                 object = webglObject.object;
57279
57280                 if ( object.visible && object.castShadow ) {
57281
57282                     object._modelViewMatrix.multiply( shadowCamera.matrixWorldInverse, object.matrixWorld );
57283
57284                     _renderer.renderImmediateObject( shadowCamera, scene.__lights, fog, _depthMaterial, object );
57285
57286                 }
57287
57288             }
57289
57290         }
57291
57292         // restore GL state
57293
57294         var clearColor = _renderer.getClearColor(),
57295         clearAlpha = _renderer.getClearAlpha();
57296
57297         _gl.clearColor( clearColor.r, clearColor.g, clearColor.b, clearAlpha );
57298         _gl.enable( _gl.BLEND );
57299
57300         if ( _renderer.shadowMapCullFrontFaces ) {
57301
57302             _gl.cullFace( _gl.BACK );
57303
57304         }
57305
57306     };
57307
57308     function createVirtualLight( light, cascade ) {
57309
57310         var virtualLight = new THREE.DirectionalLight();
57311
57312         virtualLight.isVirtual = true;
57313
57314         virtualLight.onlyShadow = true;
57315         virtualLight.castShadow = true;
57316
57317         virtualLight.shadowCameraNear = light.shadowCameraNear;
57318         virtualLight.shadowCameraFar = light.shadowCameraFar;
57319
57320         virtualLight.shadowCameraLeft = light.shadowCameraLeft;
57321         virtualLight.shadowCameraRight = light.shadowCameraRight;
57322         virtualLight.shadowCameraBottom = light.shadowCameraBottom;
57323         virtualLight.shadowCameraTop = light.shadowCameraTop;
57324
57325         virtualLight.shadowCameraVisible = light.shadowCameraVisible;
57326
57327         virtualLight.shadowDarkness = light.shadowDarkness;
57328
57329         virtualLight.shadowBias = light.shadowCascadeBias[ cascade ];
57330         virtualLight.shadowMapWidth = light.shadowCascadeWidth[ cascade ];
57331         virtualLight.shadowMapHeight = light.shadowCascadeHeight[ cascade ];
57332
57333         virtualLight.pointsWorld = [];
57334         virtualLight.pointsFrustum = [];
57335
57336         var pointsWorld = virtualLight.pointsWorld,
57337             pointsFrustum = virtualLight.pointsFrustum;
57338
57339         for ( var i = 0; i < 8; i ++ ) {
57340
57341             pointsWorld[ i ] = new THREE.Vector3();
57342             pointsFrustum[ i ] = new THREE.Vector3();
57343
57344         }
57345
57346         var nearZ = light.shadowCascadeNearZ[ cascade ];
57347         var farZ = light.shadowCascadeFarZ[ cascade ];
57348
57349         pointsFrustum[ 0 ].set( -1, -1, nearZ );
57350         pointsFrustum[ 1 ].set(  1, -1, nearZ );
57351         pointsFrustum[ 2 ].set( -1,  1, nearZ );
57352         pointsFrustum[ 3 ].set(  1,  1, nearZ );
57353
57354         pointsFrustum[ 4 ].set( -1, -1, farZ );
57355         pointsFrustum[ 5 ].set(  1, -1, farZ );
57356         pointsFrustum[ 6 ].set( -1,  1, farZ );
57357         pointsFrustum[ 7 ].set(  1,  1, farZ );
57358
57359         return virtualLight;
57360
57361     }
57362
57363     // Synchronize virtual light with the original light
57364
57365     function updateVirtualLight( light, cascade ) {
57366
57367         var virtualLight = light.shadowCascadeArray[ cascade ];
57368
57369         virtualLight.position.copy( light.position );
57370         virtualLight.target.position.copy( light.target.position );
57371         virtualLight.lookAt( virtualLight.target );
57372
57373         virtualLight.shadowCameraVisible = light.shadowCameraVisible;
57374         virtualLight.shadowDarkness = light.shadowDarkness;
57375
57376         virtualLight.shadowBias = light.shadowCascadeBias[ cascade ];
57377
57378         var nearZ = light.shadowCascadeNearZ[ cascade ];
57379         var farZ = light.shadowCascadeFarZ[ cascade ];
57380
57381         var pointsFrustum = virtualLight.pointsFrustum;
57382
57383         pointsFrustum[ 0 ].z = nearZ;
57384         pointsFrustum[ 1 ].z = nearZ;
57385         pointsFrustum[ 2 ].z = nearZ;
57386         pointsFrustum[ 3 ].z = nearZ;
57387
57388         pointsFrustum[ 4 ].z = farZ;
57389         pointsFrustum[ 5 ].z = farZ;
57390         pointsFrustum[ 6 ].z = farZ;
57391         pointsFrustum[ 7 ].z = farZ;
57392
57393     }
57394
57395     // Fit shadow camera's ortho frustum to camera frustum
57396
57397     function updateShadowCamera( camera, light ) {
57398
57399         var shadowCamera = light.shadowCamera,
57400             pointsFrustum = light.pointsFrustum,
57401             pointsWorld = light.pointsWorld;
57402
57403         _min.set( Infinity, Infinity, Infinity );
57404         _max.set( -Infinity, -Infinity, -Infinity );
57405
57406         for ( var i = 0; i < 8; i ++ ) {
57407
57408             var p = pointsWorld[ i ];
57409
57410             p.copy( pointsFrustum[ i ] );
57411             THREE.ShadowMapPlugin.__projector.unprojectVector( p, camera );
57412
57413             shadowCamera.matrixWorldInverse.multiplyVector3( p );
57414
57415             if ( p.x < _min.x ) _min.x = p.x;
57416             if ( p.x > _max.x ) _max.x = p.x;
57417
57418             if ( p.y < _min.y ) _min.y = p.y;
57419             if ( p.y > _max.y ) _max.y = p.y;
57420
57421             if ( p.z < _min.z ) _min.z = p.z;
57422             if ( p.z > _max.z ) _max.z = p.z;
57423
57424         }
57425
57426         shadowCamera.left = _min.x;
57427         shadowCamera.right = _max.x;
57428         shadowCamera.top = _max.y;
57429         shadowCamera.bottom = _min.y;
57430
57431         // can't really fit near/far
57432         //shadowCamera.near = _min.z;
57433         //shadowCamera.far = _max.z;
57434
57435         shadowCamera.updateProjectionMatrix();
57436
57437     }
57438
57439 };
57440
57441 THREE.ShadowMapPlugin.__projector = new THREE.Projector();
57442 /**
57443  * @author mikael emtinger / http://gomo.se/
57444  * @author alteredq / http://alteredqualia.com/
57445  */
57446
57447 THREE.SpritePlugin = function ( ) {
57448
57449     var _gl, _renderer, _sprite = {};
57450
57451     this.init = function ( renderer ) {
57452
57453         _gl = renderer.context;
57454         _renderer = renderer;
57455
57456         _sprite.vertices = new Float32Array( 8 + 8 );
57457         _sprite.faces    = new Uint16Array( 6 );
57458
57459         var i = 0;
57460
57461         _sprite.vertices[ i++ ] = -1; _sprite.vertices[ i++ ] = -1;    // vertex 0
57462         _sprite.vertices[ i++ ] = 0;  _sprite.vertices[ i++ ] = 0;    // uv 0
57463
57464         _sprite.vertices[ i++ ] = 1;  _sprite.vertices[ i++ ] = -1;    // vertex 1
57465         _sprite.vertices[ i++ ] = 1;  _sprite.vertices[ i++ ] = 0;    // uv 1
57466
57467         _sprite.vertices[ i++ ] = 1;  _sprite.vertices[ i++ ] = 1;    // vertex 2
57468         _sprite.vertices[ i++ ] = 1;  _sprite.vertices[ i++ ] = 1;    // uv 2
57469
57470         _sprite.vertices[ i++ ] = -1; _sprite.vertices[ i++ ] = 1;    // vertex 3
57471         _sprite.vertices[ i++ ] = 0;  _sprite.vertices[ i++ ] = 1;    // uv 3
57472
57473         i = 0;
57474
57475         _sprite.faces[ i++ ] = 0; _sprite.faces[ i++ ] = 1; _sprite.faces[ i++ ] = 2;
57476         _sprite.faces[ i++ ] = 0; _sprite.faces[ i++ ] = 2; _sprite.faces[ i++ ] = 3;
57477
57478         _sprite.vertexBuffer  = _gl.createBuffer();
57479         _sprite.elementBuffer = _gl.createBuffer();
57480
57481         _gl.bindBuffer( _gl.ARRAY_BUFFER, _sprite.vertexBuffer );
57482         _gl.bufferData( _gl.ARRAY_BUFFER, _sprite.vertices, _gl.STATIC_DRAW );
57483
57484         _gl.bindBuffer( _gl.ELEMENT_ARRAY_BUFFER, _sprite.elementBuffer );
57485         _gl.bufferData( _gl.ELEMENT_ARRAY_BUFFER, _sprite.faces, _gl.STATIC_DRAW );
57486
57487         _sprite.program = createProgram( THREE.ShaderSprite[ "sprite" ] );
57488
57489         _sprite.attributes = {};
57490         _sprite.uniforms = {};
57491
57492         _sprite.attributes.position           = _gl.getAttribLocation ( _sprite.program, "position" );
57493         _sprite.attributes.uv                 = _gl.getAttribLocation ( _sprite.program, "uv" );
57494
57495         _sprite.uniforms.uvOffset             = _gl.getUniformLocation( _sprite.program, "uvOffset" );
57496         _sprite.uniforms.uvScale              = _gl.getUniformLocation( _sprite.program, "uvScale" );
57497
57498         _sprite.uniforms.rotation             = _gl.getUniformLocation( _sprite.program, "rotation" );
57499         _sprite.uniforms.scale                = _gl.getUniformLocation( _sprite.program, "scale" );
57500         _sprite.uniforms.alignment            = _gl.getUniformLocation( _sprite.program, "alignment" );
57501
57502         _sprite.uniforms.color                = _gl.getUniformLocation( _sprite.program, "color" );
57503         _sprite.uniforms.map                  = _gl.getUniformLocation( _sprite.program, "map" );
57504         _sprite.uniforms.opacity              = _gl.getUniformLocation( _sprite.program, "opacity" );
57505
57506         _sprite.uniforms.useScreenCoordinates = _gl.getUniformLocation( _sprite.program, "useScreenCoordinates" );
57507         _sprite.uniforms.affectedByDistance   = _gl.getUniformLocation( _sprite.program, "affectedByDistance" );
57508         _sprite.uniforms.screenPosition          = _gl.getUniformLocation( _sprite.program, "screenPosition" );
57509         _sprite.uniforms.modelViewMatrix      = _gl.getUniformLocation( _sprite.program, "modelViewMatrix" );
57510         _sprite.uniforms.projectionMatrix     = _gl.getUniformLocation( _sprite.program, "projectionMatrix" );
57511
57512         _sprite.attributesEnabled = false;
57513
57514     };
57515
57516     this.render = function ( scene, camera, viewportWidth, viewportHeight ) {
57517
57518         var sprites = scene.__webglSprites,
57519             nSprites = sprites.length;
57520
57521         if ( ! nSprites ) return;
57522
57523         var attributes = _sprite.attributes,
57524             uniforms = _sprite.uniforms;
57525
57526         var invAspect = viewportHeight / viewportWidth;
57527
57528         var halfViewportWidth = viewportWidth * 0.5,
57529             halfViewportHeight = viewportHeight * 0.5;
57530
57531         var mergeWith3D = true;
57532
57533         // setup gl
57534
57535         _gl.useProgram( _sprite.program );
57536
57537         if ( ! _sprite.attributesEnabled ) {
57538
57539             _gl.enableVertexAttribArray( attributes.position );
57540             _gl.enableVertexAttribArray( attributes.uv );
57541
57542             _sprite.attributesEnabled = true;
57543
57544         }
57545
57546         _gl.disable( _gl.CULL_FACE );
57547         _gl.enable( _gl.BLEND );
57548         _gl.depthMask( true );
57549
57550         _gl.bindBuffer( _gl.ARRAY_BUFFER, _sprite.vertexBuffer );
57551         _gl.vertexAttribPointer( attributes.position, 2, _gl.FLOAT, false, 2 * 8, 0 );
57552         _gl.vertexAttribPointer( attributes.uv, 2, _gl.FLOAT, false, 2 * 8, 8 );
57553
57554         _gl.bindBuffer( _gl.ELEMENT_ARRAY_BUFFER, _sprite.elementBuffer );
57555
57556         _gl.uniformMatrix4fv( uniforms.projectionMatrix, false, camera._projectionMatrixArray );
57557
57558         _gl.activeTexture( _gl.TEXTURE0 );
57559         _gl.uniform1i( uniforms.map, 0 );
57560
57561         // update positions and sort
57562
57563         var i, sprite, screenPosition, size, scale = [];
57564
57565         for( i = 0; i < nSprites; i ++ ) {
57566
57567             sprite = sprites[ i ];
57568
57569             if ( ! sprite.visible || sprite.opacity === 0 ) continue;
57570
57571             if( ! sprite.useScreenCoordinates ) {
57572
57573                 sprite._modelViewMatrix.multiply( camera.matrixWorldInverse, sprite.matrixWorld );
57574                 sprite.z = - sprite._modelViewMatrix.elements[14];
57575
57576             } else {
57577
57578                 sprite.z = - sprite.position.z;
57579
57580             }
57581
57582         }
57583
57584         sprites.sort( painterSort );
57585
57586         // render all sprites
57587
57588         for( i = 0; i < nSprites; i ++ ) {
57589
57590             sprite = sprites[ i ];
57591
57592             if ( ! sprite.visible || sprite.opacity === 0 ) continue;
57593
57594             if ( sprite.map && sprite.map.image && sprite.map.image.width ) {
57595
57596                 if ( sprite.useScreenCoordinates ) {
57597
57598                     _gl.uniform1i( uniforms.useScreenCoordinates, 1 );
57599                     _gl.uniform3f( uniforms.screenPosition, ( sprite.position.x - halfViewportWidth  ) / halfViewportWidth,
57600                                                             ( halfViewportHeight - sprite.position.y ) / halfViewportHeight,
57601                                                               Math.max( 0, Math.min( 1, sprite.position.z ) ) );
57602
57603                 } else {
57604
57605                     _gl.uniform1i( uniforms.useScreenCoordinates, 0 );
57606                     _gl.uniform1i( uniforms.affectedByDistance, sprite.affectedByDistance ? 1 : 0 );
57607                     _gl.uniformMatrix4fv( uniforms.modelViewMatrix, false, sprite._modelViewMatrix.elements );
57608
57609                 }
57610
57611                 size = sprite.map.image.width / ( sprite.scaleByViewport ? viewportHeight : 1 );
57612
57613                 scale[ 0 ] = size * invAspect * sprite.scale.x;
57614                 scale[ 1 ] = size * sprite.scale.y;
57615
57616                 _gl.uniform2f( uniforms.uvScale, sprite.uvScale.x, sprite.uvScale.y );
57617                 _gl.uniform2f( uniforms.uvOffset, sprite.uvOffset.x, sprite.uvOffset.y );
57618                 _gl.uniform2f( uniforms.alignment, sprite.alignment.x, sprite.alignment.y );
57619
57620                 _gl.uniform1f( uniforms.opacity, sprite.opacity );
57621                 _gl.uniform3f( uniforms.color, sprite.color.r, sprite.color.g, sprite.color.b );
57622
57623                 _gl.uniform1f( uniforms.rotation, sprite.rotation );
57624                 _gl.uniform2fv( uniforms.scale, scale );
57625
57626                 if ( sprite.mergeWith3D && !mergeWith3D ) {
57627
57628                     _gl.enable( _gl.DEPTH_TEST );
57629                     mergeWith3D = true;
57630
57631                 } else if ( ! sprite.mergeWith3D && mergeWith3D ) {
57632
57633                     _gl.disable( _gl.DEPTH_TEST );
57634                     mergeWith3D = false;
57635
57636                 }
57637
57638                 _renderer.setBlending( sprite.blending, sprite.blendEquation, sprite.blendSrc, sprite.blendDst );
57639                 _renderer.setTexture( sprite.map, 0 );
57640
57641                 _gl.drawElements( _gl.TRIANGLES, 6, _gl.UNSIGNED_SHORT, 0 );
57642
57643             }
57644
57645         }
57646
57647         // restore gl
57648
57649         _gl.enable( _gl.CULL_FACE );
57650         _gl.enable( _gl.DEPTH_TEST );
57651         _gl.depthMask( true );
57652
57653     };
57654
57655     function createProgram ( shader ) {
57656
57657         var program = _gl.createProgram();
57658
57659         var fragmentShader = _gl.createShader( _gl.FRAGMENT_SHADER );
57660         var vertexShader = _gl.createShader( _gl.VERTEX_SHADER );
57661
57662         _gl.shaderSource( fragmentShader, shader.fragmentShader );
57663         _gl.shaderSource( vertexShader, shader.vertexShader );
57664
57665         _gl.compileShader( fragmentShader );
57666         _gl.compileShader( vertexShader );
57667
57668         _gl.attachShader( program, fragmentShader );
57669         _gl.attachShader( program, vertexShader );
57670
57671         _gl.linkProgram( program );
57672
57673         return program;
57674
57675     };
57676
57677     function painterSort ( a, b ) {
57678
57679         return b.z - a.z;
57680
57681     };
57682
57683 };/**
57684  * @author alteredq / http://alteredqualia.com/
57685  */
57686
57687 THREE.DepthPassPlugin = function ( ) {
57688
57689     this.enabled = false;
57690     this.renderTarget = null;
57691
57692     var _gl,
57693     _renderer,
57694     _depthMaterial, _depthMaterialMorph,
57695
57696     _frustum = new THREE.Frustum(),
57697     _projScreenMatrix = new THREE.Matrix4();
57698
57699     this.init = function ( renderer ) {
57700
57701         _gl = renderer.context;
57702         _renderer = renderer;
57703
57704         var depthShader = THREE.ShaderLib[ "depthRGBA" ];
57705         var depthUniforms = THREE.UniformsUtils.clone( depthShader.uniforms );
57706
57707         _depthMaterial = new THREE.ShaderMaterial( { fragmentShader: depthShader.fragmentShader, vertexShader: depthShader.vertexShader, uniforms: depthUniforms } );
57708         _depthMaterialMorph = new THREE.ShaderMaterial( { fragmentShader: depthShader.fragmentShader, vertexShader: depthShader.vertexShader, uniforms: depthUniforms, morphTargets: true } );
57709
57710         _depthMaterial._shadowPass = true;
57711         _depthMaterialMorph._shadowPass = true;
57712
57713     };
57714
57715     this.render = function ( scene, camera ) {
57716
57717         if ( ! this.enabled ) return;
57718
57719         this.update( scene, camera );
57720
57721     };
57722
57723     this.update = function ( scene, camera ) {
57724
57725         var i, il, j, jl, n,
57726
57727         program, buffer, material,
57728         webglObject, object, light,
57729         renderList,
57730
57731         fog = null;
57732
57733         // set GL state for depth map
57734
57735         _gl.clearColor( 1, 1, 1, 1 );
57736         _gl.disable( _gl.BLEND );
57737
57738         _renderer.setDepthTest( true );
57739
57740         // update scene
57741
57742         if ( _renderer.autoUpdateScene ) scene.updateMatrixWorld();
57743
57744         // update camera matrices and frustum
57745
57746         if ( ! camera._viewMatrixArray ) camera._viewMatrixArray = new Float32Array( 16 );
57747         if ( ! camera._projectionMatrixArray ) camera._projectionMatrixArray = new Float32Array( 16 );
57748
57749         camera.matrixWorldInverse.getInverse( camera.matrixWorld );
57750
57751         camera.matrixWorldInverse.flattenToArray( camera._viewMatrixArray );
57752         camera.projectionMatrix.flattenToArray( camera._projectionMatrixArray );
57753
57754         _projScreenMatrix.multiply( camera.projectionMatrix, camera.matrixWorldInverse );
57755         _frustum.setFromMatrix( _projScreenMatrix );
57756
57757         // render depth map
57758
57759         _renderer.setRenderTarget( this.renderTarget );
57760         _renderer.clear();
57761
57762         // set object matrices & frustum culling
57763
57764         renderList = scene.__webglObjects;
57765
57766         for ( j = 0, jl = renderList.length; j < jl; j ++ ) {
57767
57768             webglObject = renderList[ j ];
57769             object = webglObject.object;
57770
57771             webglObject.render = false;
57772
57773             if ( object.visible ) {
57774
57775                 if ( ! ( object instanceof THREE.Mesh ) || ! ( object.frustumCulled ) || _frustum.contains( object ) ) {
57776
57777                     //object.matrixWorld.flattenToArray( object._modelMatrixArray );
57778                     object._modelViewMatrix.multiply( camera.matrixWorldInverse, object.matrixWorld);
57779
57780                     webglObject.render = true;
57781
57782                 }
57783
57784             }
57785
57786         }
57787
57788         // render regular objects
57789
57790         for ( j = 0, jl = renderList.length; j < jl; j ++ ) {
57791
57792             webglObject = renderList[ j ];
57793
57794             if ( webglObject.render ) {
57795
57796                 object = webglObject.object;
57797                 buffer = webglObject.buffer;
57798
57799                 if ( object.material ) _renderer.setMaterialFaces( object.material );
57800
57801                 if ( object.customDepthMaterial ) {
57802
57803                     material = object.customDepthMaterial;
57804
57805                 } else if ( object.geometry.morphTargets.length ) {
57806
57807                     material = _depthMaterialMorph;
57808
57809                 } else {
57810
57811                     material = _depthMaterial;
57812
57813                 }
57814
57815                 if ( buffer instanceof THREE.BufferGeometry ) {
57816
57817                     _renderer.renderBufferDirect( camera, scene.__lights, fog, material, buffer, object );
57818
57819                 } else {
57820
57821                     _renderer.renderBuffer( camera, scene.__lights, fog, material, buffer, object );
57822
57823                 }
57824
57825             }
57826
57827         }
57828
57829         // set matrices and render immediate objects
57830
57831         renderList = scene.__webglObjectsImmediate;
57832
57833         for ( j = 0, jl = renderList.length; j < jl; j ++ ) {
57834
57835             webglObject = renderList[ j ];
57836             object = webglObject.object;
57837
57838             if ( object.visible && object.castShadow ) {
57839
57840                 /*
57841                 if ( object.matrixAutoUpdate ) {
57842
57843                     object.matrixWorld.flattenToArray( object._modelMatrixArray );
57844
57845                 }
57846                 */
57847
57848                 object._modelViewMatrix.multiply( camera.matrixWorldInverse, object.matrixWorld);
57849
57850                 _renderer.renderImmediateObject( camera, scene.__lights, fog, _depthMaterial, object );
57851
57852             }
57853
57854         }
57855
57856         // restore GL state
57857
57858         var clearColor = _renderer.getClearColor(),
57859         clearAlpha = _renderer.getClearAlpha();
57860
57861         _gl.clearColor( clearColor.r, clearColor.g, clearColor.b, clearAlpha );
57862         _gl.enable( _gl.BLEND );
57863
57864     };
57865
57866 };
57867
57868 /**
57869  * @author mikael emtinger / http://gomo.se/
57870  *
57871  */
57872
57873 THREE.ShaderFlares = {
57874
57875     'lensFlareVertexTexture': {
57876
57877         vertexShader: [
57878
57879             "uniform vec3 screenPosition;",
57880             "uniform vec2 scale;",
57881             "uniform float rotation;",
57882             "uniform int renderType;",
57883
57884             "uniform sampler2D occlusionMap;",
57885
57886             "attribute vec2 position;",
57887             "attribute vec2 uv;",
57888
57889             "varying vec2 vUV;",
57890             "varying float vVisibility;",
57891
57892             "void main() {",
57893
57894                 "vUV = uv;",
57895
57896                 "vec2 pos = position;",
57897
57898                 "if( renderType == 2 ) {",
57899
57900                     "vec4 visibility = texture2D( occlusionMap, vec2( 0.1, 0.1 ) ) +",
57901                                       "texture2D( occlusionMap, vec2( 0.5, 0.1 ) ) +",
57902                                       "texture2D( occlusionMap, vec2( 0.9, 0.1 ) ) +",
57903                                       "texture2D( occlusionMap, vec2( 0.9, 0.5 ) ) +",
57904                                       "texture2D( occlusionMap, vec2( 0.9, 0.9 ) ) +",
57905                                       "texture2D( occlusionMap, vec2( 0.5, 0.9 ) ) +",
57906                                       "texture2D( occlusionMap, vec2( 0.1, 0.9 ) ) +",
57907                                       "texture2D( occlusionMap, vec2( 0.1, 0.5 ) ) +",
57908                                       "texture2D( occlusionMap, vec2( 0.5, 0.5 ) );",
57909
57910                     "vVisibility = (       visibility.r / 9.0 ) *",
57911                                   "( 1.0 - visibility.g / 9.0 ) *",
57912                                   "(       visibility.b / 9.0 ) *",
57913                                   "( 1.0 - visibility.a / 9.0 );",
57914
57915                     "pos.x = cos( rotation ) * position.x - sin( rotation ) * position.y;",
57916                     "pos.y = sin( rotation ) * position.x + cos( rotation ) * position.y;",
57917
57918                 "}",
57919
57920                 "gl_Position = vec4( ( pos * scale + screenPosition.xy ).xy, screenPosition.z, 1.0 );",
57921
57922             "}"
57923
57924         ].join( "\n" ),
57925
57926         fragmentShader: [
57927
57928             "precision mediump float;",
57929
57930             "uniform sampler2D map;",
57931             "uniform float opacity;",
57932             "uniform int renderType;",
57933             "uniform vec3 color;",
57934
57935             "varying vec2 vUV;",
57936             "varying float vVisibility;",
57937
57938             "void main() {",
57939
57940                 // pink square
57941
57942                 "if( renderType == 0 ) {",
57943
57944                     "gl_FragColor = vec4( 1.0, 0.0, 1.0, 0.0 );",
57945
57946                 // restore
57947
57948                 "} else if( renderType == 1 ) {",
57949
57950                     "gl_FragColor = texture2D( map, vUV );",
57951
57952                 // flare
57953
57954                 "} else {",
57955
57956                     "vec4 texture = texture2D( map, vUV );",
57957                     "texture.a *= opacity * vVisibility;",
57958                     "gl_FragColor = texture;",
57959                     "gl_FragColor.rgb *= color;",
57960
57961                 "}",
57962
57963             "}"
57964         ].join( "\n" )
57965
57966     },
57967
57968
57969     'lensFlare': {
57970
57971         vertexShader: [
57972
57973             "uniform vec3 screenPosition;",
57974             "uniform vec2 scale;",
57975             "uniform float rotation;",
57976             "uniform int renderType;",
57977
57978             "attribute vec2 position;",
57979             "attribute vec2 uv;",
57980
57981             "varying vec2 vUV;",
57982
57983             "void main() {",
57984
57985                 "vUV = uv;",
57986
57987                 "vec2 pos = position;",
57988
57989                 "if( renderType == 2 ) {",
57990
57991                     "pos.x = cos( rotation ) * position.x - sin( rotation ) * position.y;",
57992                     "pos.y = sin( rotation ) * position.x + cos( rotation ) * position.y;",
57993
57994                 "}",
57995
57996                 "gl_Position = vec4( ( pos * scale + screenPosition.xy ).xy, screenPosition.z, 1.0 );",
57997
57998             "}"
57999
58000         ].join( "\n" ),
58001
58002         fragmentShader: [
58003
58004             "precision mediump float;",
58005
58006             "uniform sampler2D map;",
58007             "uniform sampler2D occlusionMap;",
58008             "uniform float opacity;",
58009             "uniform int renderType;",
58010             "uniform vec3 color;",
58011
58012             "varying vec2 vUV;",
58013
58014             "void main() {",
58015
58016                 // pink square
58017
58018                 "if( renderType == 0 ) {",
58019
58020                     "gl_FragColor = vec4( texture2D( map, vUV ).rgb, 0.0 );",
58021
58022                 // restore
58023
58024                 "} else if( renderType == 1 ) {",
58025
58026                     "gl_FragColor = texture2D( map, vUV );",
58027
58028                 // flare
58029
58030                 "} else {",
58031
58032                     "float visibility = texture2D( occlusionMap, vec2( 0.5, 0.1 ) ).a +",
58033                                        "texture2D( occlusionMap, vec2( 0.9, 0.5 ) ).a +",
58034                                        "texture2D( occlusionMap, vec2( 0.5, 0.9 ) ).a +",
58035                                        "texture2D( occlusionMap, vec2( 0.1, 0.5 ) ).a;",
58036
58037                     "visibility = ( 1.0 - visibility / 4.0 );",
58038
58039                     "vec4 texture = texture2D( map, vUV );",
58040                     "texture.a *= opacity * visibility;",
58041                     "gl_FragColor = texture;",
58042                     "gl_FragColor.rgb *= color;",
58043
58044                 "}",
58045
58046             "}"
58047
58048         ].join( "\n" )
58049
58050     }
58051
58052 };
58053 /**
58054  * @author mikael emtinger / http://gomo.se/
58055  *
58056  */
58057
58058 THREE.ShaderSprite = {
58059
58060     'sprite': {
58061
58062         vertexShader: [
58063
58064             "uniform int useScreenCoordinates;",
58065             "uniform int affectedByDistance;",
58066             "uniform vec3 screenPosition;",
58067             "uniform mat4 modelViewMatrix;",
58068             "uniform mat4 projectionMatrix;",
58069             "uniform float rotation;",
58070             "uniform vec2 scale;",
58071             "uniform vec2 alignment;",
58072             "uniform vec2 uvOffset;",
58073             "uniform vec2 uvScale;",
58074
58075             "attribute vec2 position;",
58076             "attribute vec2 uv;",
58077
58078             "varying vec2 vUV;",
58079
58080             "void main() {",
58081
58082                 "vUV = uvOffset + uv * uvScale;",
58083
58084                 "vec2 alignedPosition = position + alignment;",
58085
58086                 "vec2 rotatedPosition;",
58087                 "rotatedPosition.x = ( cos( rotation ) * alignedPosition.x - sin( rotation ) * alignedPosition.y ) * scale.x;",
58088                 "rotatedPosition.y = ( sin( rotation ) * alignedPosition.x + cos( rotation ) * alignedPosition.y ) * scale.y;",
58089
58090                 "vec4 finalPosition;",
58091
58092                 "if( useScreenCoordinates != 0 ) {",
58093
58094                     "finalPosition = vec4( screenPosition.xy + rotatedPosition, screenPosition.z, 1.0 );",
58095
58096                 "} else {",
58097
58098                     "finalPosition = projectionMatrix * modelViewMatrix * vec4( 0.0, 0.0, 0.0, 1.0 );",
58099                     "finalPosition.xy += rotatedPosition * ( affectedByDistance == 1 ? 1.0 : finalPosition.z );",
58100
58101                 "}",
58102
58103                 "gl_Position = finalPosition;",
58104
58105             "}"
58106
58107         ].join( "\n" ),
58108
58109         fragmentShader: [
58110
58111             "precision mediump float;",
58112
58113             "uniform vec3 color;",
58114             "uniform sampler2D map;",
58115             "uniform float opacity;",
58116
58117             "varying vec2 vUV;",
58118
58119             "void main() {",
58120
58121                 "vec4 texture = texture2D( map, vUV );",
58122                 "gl_FragColor = vec4( color * texture.xyz, texture.a * opacity );",
58123
58124             "}"
58125
58126         ].join( "\n" )
58127
58128     }
58129
58130 };
58131 /**
58132  * @author alteredq / http://alteredqualia.com/
58133  *
58134  */
58135
58136
58137 THREE.ShaderSkin = {
58138
58139     /* ------------------------------------------------------------------------------------------
58140     //    Simple skin shader
58141     //        - per-pixel Blinn-Phong diffuse term mixed with half-Lambert wrap-around term (per color component)
58142     //        - physically based specular term (Kelemen/Szirmay-Kalos specular reflectance)
58143     //
58144     //        - diffuse map
58145     //        - bump map
58146     //        - specular map
58147     //        - point, directional and hemisphere lights (use with "lights: true" material option)
58148     //        - fog (use with "fog: true" material option)
58149     //        - shadow maps
58150     //
58151     // ------------------------------------------------------------------------------------------ */
58152
58153     'skinSimple' : {
58154
58155         uniforms: THREE.UniformsUtils.merge( [
58156
58157             THREE.UniformsLib[ "fog" ],
58158             THREE.UniformsLib[ "lights" ],
58159             THREE.UniformsLib[ "shadowmap" ],
58160
58161             {
58162
58163             "enableBump"    : { type: "i", value: 0 },
58164             "enableSpecular": { type: "i", value: 0 },
58165
58166             "tDiffuse"    : { type: "t", value: null },
58167             "tBeckmann"    : { type: "t", value: null },
58168
58169             "uDiffuseColor":  { type: "c", value: new THREE.Color( 0xeeeeee ) },
58170             "uSpecularColor": { type: "c", value: new THREE.Color( 0x111111 ) },
58171             "uAmbientColor":  { type: "c", value: new THREE.Color( 0x050505 ) },
58172             "uOpacity":       { type: "f", value: 1 },
58173
58174             "uRoughness":               { type: "f", value: 0.15 },
58175             "uSpecularBrightness":     { type: "f", value: 0.75 },
58176
58177             "bumpMap"    : { type: "t", value: null },
58178             "bumpScale" : { type: "f", value: 1 },
58179
58180             "specularMap" : { type: "t", value: null },
58181
58182             "offsetRepeat" : { type: "v4", value: new THREE.Vector4( 0, 0, 1, 1 ) },
58183
58184             "uWrapRGB":    { type: "v3", value: new THREE.Vector3( 0.75, 0.375, 0.1875 ) }
58185
58186             }
58187
58188         ] ),
58189
58190         fragmentShader: [
58191
58192             "#define USE_BUMPMAP",
58193             "#extension GL_OES_standard_derivatives : enable",
58194
58195             "uniform bool enableBump;",
58196             "uniform bool enableSpecular;",
58197
58198             "uniform vec3 uAmbientColor;",
58199             "uniform vec3 uDiffuseColor;",
58200             "uniform vec3 uSpecularColor;",
58201             "uniform float uOpacity;",
58202
58203             "uniform float uRoughness;",
58204             "uniform float uSpecularBrightness;",
58205
58206             "uniform vec3 uWrapRGB;",
58207
58208             "uniform sampler2D tDiffuse;",
58209             "uniform sampler2D tBeckmann;",
58210
58211             "uniform sampler2D specularMap;",
58212
58213             "varying vec3 vNormal;",
58214             "varying vec2 vUv;",
58215
58216             "uniform vec3 ambientLightColor;",
58217
58218             "#if MAX_DIR_LIGHTS > 0",
58219
58220                 "uniform vec3 directionalLightColor[ MAX_DIR_LIGHTS ];",
58221                 "uniform vec3 directionalLightDirection[ MAX_DIR_LIGHTS ];",
58222
58223             "#endif",
58224
58225             "#if MAX_HEMI_LIGHTS > 0",
58226
58227                 "uniform vec3 hemisphereLightSkyColor[ MAX_HEMI_LIGHTS ];",
58228                 "uniform vec3 hemisphereLightGroundColor[ MAX_HEMI_LIGHTS ];",
58229                 "uniform vec3 hemisphereLightPosition[ MAX_HEMI_LIGHTS ];",
58230
58231             "#endif",
58232
58233             "#if MAX_POINT_LIGHTS > 0",
58234
58235                 "uniform vec3 pointLightColor[ MAX_POINT_LIGHTS ];",
58236                 "uniform vec3 pointLightPosition[ MAX_POINT_LIGHTS ];",
58237                 "uniform float pointLightDistance[ MAX_POINT_LIGHTS ];",
58238
58239             "#endif",
58240
58241             "varying vec3 vViewPosition;",
58242
58243             THREE.ShaderChunk[ "shadowmap_pars_fragment" ],
58244             THREE.ShaderChunk[ "fog_pars_fragment" ],
58245             THREE.ShaderChunk[ "bumpmap_pars_fragment" ],
58246
58247             // Fresnel term
58248
58249             "float fresnelReflectance( vec3 H, vec3 V, float F0 ) {",
58250
58251                 "float base = 1.0 - dot( V, H );",
58252                 "float exponential = pow( base, 5.0 );",
58253
58254                 "return exponential + F0 * ( 1.0 - exponential );",
58255
58256             "}",
58257
58258             // Kelemen/Szirmay-Kalos specular BRDF
58259
58260             "float KS_Skin_Specular( vec3 N,",         // Bumped surface normal
58261                                     "vec3 L,",         // Points to light
58262                                     "vec3 V,",         // Points to eye
58263                                     "float m,",      // Roughness
58264                                     "float rho_s",     // Specular brightness
58265                                     ") {",
58266
58267                 "float result = 0.0;",
58268                 "float ndotl = dot( N, L );",
58269
58270                 "if( ndotl > 0.0 ) {",
58271
58272                     "vec3 h = L + V;", // Unnormalized half-way vector
58273                     "vec3 H = normalize( h );",
58274
58275                     "float ndoth = dot( N, H );",
58276
58277                     "float PH = pow( 2.0 * texture2D( tBeckmann, vec2( ndoth, m ) ).x, 10.0 );",
58278
58279                     "float F = fresnelReflectance( H, V, 0.028 );",
58280                     "float frSpec = max( PH * F / dot( h, h ), 0.0 );",
58281
58282                     "result = ndotl * rho_s * frSpec;", // BRDF * dot(N,L) * rho_s
58283
58284                 "}",
58285
58286                 "return result;",
58287
58288             "}",
58289
58290             "void main() {",
58291
58292                 "gl_FragColor = vec4( vec3( 1.0 ), uOpacity );",
58293
58294                 "vec4 colDiffuse = texture2D( tDiffuse, vUv );",
58295                 "colDiffuse.rgb *= colDiffuse.rgb;",
58296
58297                 "gl_FragColor = gl_FragColor * colDiffuse;",
58298
58299                 "vec3 normal = normalize( vNormal );",
58300                 "vec3 viewPosition = normalize( vViewPosition );",
58301
58302                 "float specularStrength;",
58303
58304                 "if ( enableSpecular ) {",
58305
58306                     "vec4 texelSpecular = texture2D( specularMap, vUv );",
58307                     "specularStrength = texelSpecular.r;",
58308
58309                 "} else {",
58310
58311                     "specularStrength = 1.0;",
58312
58313                 "}",
58314
58315                 "#ifdef USE_BUMPMAP",
58316
58317                     "if ( enableBump ) normal = perturbNormalArb( -vViewPosition, normal, dHdxy_fwd() );",
58318
58319                 "#endif",
58320
58321                 // point lights
58322
58323                 "vec3 specularTotal = vec3( 0.0 );",
58324
58325                 "#if MAX_POINT_LIGHTS > 0",
58326
58327                     "vec3 pointTotal = vec3( 0.0 );",
58328
58329                     "for ( int i = 0; i < MAX_POINT_LIGHTS; i ++ ) {",
58330
58331                         "vec4 lPosition = viewMatrix * vec4( pointLightPosition[ i ], 1.0 );",
58332
58333                         "vec3 lVector = lPosition.xyz + vViewPosition.xyz;",
58334
58335                         "float lDistance = 1.0;",
58336
58337                         "if ( pointLightDistance[ i ] > 0.0 )",
58338                             "lDistance = 1.0 - min( ( length( lVector ) / pointLightDistance[ i ] ), 1.0 );",
58339
58340                         "lVector = normalize( lVector );",
58341
58342                         "float pointDiffuseWeightFull = max( dot( normal, lVector ), 0.0 );",
58343                         "float pointDiffuseWeightHalf = max( 0.5 * dot( normal, lVector ) + 0.5, 0.0 );",
58344                         "vec3 pointDiffuseWeight = mix( vec3 ( pointDiffuseWeightFull ), vec3( pointDiffuseWeightHalf ), uWrapRGB );",
58345
58346                         "float pointSpecularWeight = KS_Skin_Specular( normal, lVector, viewPosition, uRoughness, uSpecularBrightness );",
58347
58348                         "pointTotal    += lDistance * uDiffuseColor * pointLightColor[ i ] * pointDiffuseWeight;",
58349                         "specularTotal += lDistance * uSpecularColor * pointLightColor[ i ] * pointSpecularWeight * specularStrength;",
58350
58351                     "}",
58352
58353                 "#endif",
58354
58355                 // directional lights
58356
58357                 "#if MAX_DIR_LIGHTS > 0",
58358
58359                     "vec3 dirTotal = vec3( 0.0 );",
58360
58361                     "for( int i = 0; i < MAX_DIR_LIGHTS; i++ ) {",
58362
58363                         "vec4 lDirection = viewMatrix * vec4( directionalLightDirection[ i ], 0.0 );",
58364
58365                         "vec3 dirVector = normalize( lDirection.xyz );",
58366
58367                         "float dirDiffuseWeightFull = max( dot( normal, dirVector ), 0.0 );",
58368                         "float dirDiffuseWeightHalf = max( 0.5 * dot( normal, dirVector ) + 0.5, 0.0 );",
58369                         "vec3 dirDiffuseWeight = mix( vec3 ( dirDiffuseWeightFull ), vec3( dirDiffuseWeightHalf ), uWrapRGB );",
58370
58371                         "float dirSpecularWeight =  KS_Skin_Specular( normal, dirVector, viewPosition, uRoughness, uSpecularBrightness );",
58372
58373                         "dirTotal        += uDiffuseColor * directionalLightColor[ i ] * dirDiffuseWeight;",
58374                         "specularTotal += uSpecularColor * directionalLightColor[ i ] * dirSpecularWeight * specularStrength;",
58375
58376                     "}",
58377
58378                 "#endif",
58379
58380                 // hemisphere lights
58381
58382                 "#if MAX_HEMI_LIGHTS > 0",
58383
58384                     "vec3 hemiTotal = vec3( 0.0 );",
58385
58386                     "for ( int i = 0; i < MAX_HEMI_LIGHTS; i ++ ) {",
58387
58388                         "vec4 lPosition = viewMatrix * vec4( hemisphereLightPosition[ i ], 1.0 );",
58389                         "vec3 lVector = normalize( lPosition.xyz + vViewPosition.xyz );",
58390
58391                         "float dotProduct = dot( normal, lVector );",
58392                         "float hemiDiffuseWeight = 0.5 * dotProduct + 0.5;",
58393
58394                         "hemiTotal += uDiffuseColor * mix( hemisphereLightGroundColor[ i ], hemisphereLightSkyColor[ i ], hemiDiffuseWeight );",
58395
58396                         // specular (sky light)
58397
58398                         "float hemiSpecularWeight = 0.0;",
58399                         "hemiSpecularWeight += KS_Skin_Specular( normal, lVector, viewPosition, uRoughness, uSpecularBrightness );",
58400
58401                         // specular (ground light)
58402
58403                         "vec3 lVectorGround = normalize( -lPosition.xyz + vViewPosition.xyz );",
58404                         "hemiSpecularWeight += KS_Skin_Specular( normal, lVectorGround, viewPosition, uRoughness, uSpecularBrightness );",
58405
58406                         "specularTotal += uSpecularColor * mix( hemisphereLightGroundColor[ i ], hemisphereLightSkyColor[ i ], hemiDiffuseWeight ) * hemiSpecularWeight * specularStrength;",
58407
58408                     "}",
58409
58410                 "#endif",
58411
58412                 // all lights contribution summation
58413
58414                 "vec3 totalLight = vec3( 0.0 );",
58415
58416                 "#if MAX_DIR_LIGHTS > 0",
58417                     "totalLight += dirTotal;",
58418                 "#endif",
58419
58420                 "#if MAX_POINT_LIGHTS > 0",
58421                     "totalLight += pointTotal;",
58422                 "#endif",
58423
58424                 "#if MAX_HEMI_LIGHTS > 0",
58425                     "totalLight += hemiTotal;",
58426                 "#endif",
58427
58428                 "gl_FragColor.xyz = gl_FragColor.xyz * ( totalLight + ambientLightColor * uAmbientColor ) + specularTotal;",
58429
58430                 THREE.ShaderChunk[ "shadowmap_fragment" ],
58431                 THREE.ShaderChunk[ "linear_to_gamma_fragment" ],
58432                 THREE.ShaderChunk[ "fog_fragment" ],
58433
58434             "}"
58435
58436         ].join("\n"),
58437
58438         vertexShader: [
58439
58440             "uniform vec4 offsetRepeat;",
58441
58442             "varying vec3 vNormal;",
58443             "varying vec2 vUv;",
58444
58445             "varying vec3 vViewPosition;",
58446
58447             THREE.ShaderChunk[ "shadowmap_pars_vertex" ],
58448
58449             "void main() {",
58450
58451                 "vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );",
58452                 "vec4 mPosition = modelMatrix * vec4( position, 1.0 );",
58453
58454                 "vViewPosition = -mvPosition.xyz;",
58455
58456                 "vNormal = normalMatrix * normal;",
58457
58458                 "vUv = uv * offsetRepeat.zw + offsetRepeat.xy;",
58459
58460                 "gl_Position = projectionMatrix * mvPosition;",
58461
58462                 THREE.ShaderChunk[ "shadowmap_vertex" ],
58463
58464             "}"
58465
58466         ].join( "\n" )
58467
58468     },
58469
58470     /* ------------------------------------------------------------------------------------------
58471     //    Skin shader
58472     //        - Blinn-Phong diffuse term (using normal + diffuse maps)
58473     //        - subsurface scattering approximation by four blur layers
58474     //        - physically based specular term (Kelemen/Szirmay-Kalos specular reflectance)
58475     //
58476     //        - point and directional lights (use with "lights: true" material option)
58477     //
58478     //        - based on Nvidia Advanced Skin Rendering GDC 2007 presentation
58479     //          and GPU Gems 3 Chapter 14. Advanced Techniques for Realistic Real-Time Skin Rendering
58480     //
58481     //            http://developer.download.nvidia.com/presentations/2007/gdc/Advanced_Skin.pdf
58482     //            http://http.developer.nvidia.com/GPUGems3/gpugems3_ch14.html
58483     // ------------------------------------------------------------------------------------------ */
58484
58485     'skin' : {
58486
58487         uniforms: THREE.UniformsUtils.merge( [
58488
58489             THREE.UniformsLib[ "fog" ],
58490             THREE.UniformsLib[ "lights" ],
58491
58492             {
58493
58494             "passID": { type: "i", value: 0 },
58495
58496             "tDiffuse"    : { type: "t", value: null },
58497             "tNormal"    : { type: "t", value: null },
58498
58499             "tBlur1"    : { type: "t", value: null },
58500             "tBlur2"    : { type: "t", value: null },
58501             "tBlur3"    : { type: "t", value: null },
58502             "tBlur4"    : { type: "t", value: null },
58503
58504             "tBeckmann"    : { type: "t", value: null },
58505
58506             "uNormalScale": { type: "f", value: 1.0 },
58507
58508             "uDiffuseColor":  { type: "c", value: new THREE.Color( 0xeeeeee ) },
58509             "uSpecularColor": { type: "c", value: new THREE.Color( 0x111111 ) },
58510             "uAmbientColor":  { type: "c", value: new THREE.Color( 0x050505 ) },
58511             "uOpacity":       { type: "f", value: 1 },
58512
58513             "uRoughness":               { type: "f", value: 0.15 },
58514             "uSpecularBrightness":     { type: "f", value: 0.75 }
58515
58516             }
58517
58518         ] ),
58519
58520         fragmentShader: [
58521
58522             "uniform vec3 uAmbientColor;",
58523             "uniform vec3 uDiffuseColor;",
58524             "uniform vec3 uSpecularColor;",
58525             "uniform float uOpacity;",
58526
58527             "uniform float uRoughness;",
58528             "uniform float uSpecularBrightness;",
58529
58530             "uniform int passID;",
58531
58532             "uniform sampler2D tDiffuse;",
58533             "uniform sampler2D tNormal;",
58534
58535             "uniform sampler2D tBlur1;",
58536             "uniform sampler2D tBlur2;",
58537             "uniform sampler2D tBlur3;",
58538             "uniform sampler2D tBlur4;",
58539
58540             "uniform sampler2D tBeckmann;",
58541
58542             "uniform float uNormalScale;",
58543
58544             "varying vec3 vTangent;",
58545             "varying vec3 vBinormal;",
58546             "varying vec3 vNormal;",
58547             "varying vec2 vUv;",
58548
58549             "uniform vec3 ambientLightColor;",
58550
58551             "#if MAX_DIR_LIGHTS > 0",
58552                 "uniform vec3 directionalLightColor[ MAX_DIR_LIGHTS ];",
58553                 "uniform vec3 directionalLightDirection[ MAX_DIR_LIGHTS ];",
58554             "#endif",
58555
58556             "#if MAX_POINT_LIGHTS > 0",
58557                 "uniform vec3 pointLightColor[ MAX_POINT_LIGHTS ];",
58558                 "varying vec4 vPointLight[ MAX_POINT_LIGHTS ];",
58559             "#endif",
58560
58561             "varying vec3 vViewPosition;",
58562
58563             THREE.ShaderChunk[ "fog_pars_fragment" ],
58564
58565             "float fresnelReflectance( vec3 H, vec3 V, float F0 ) {",
58566
58567                 "float base = 1.0 - dot( V, H );",
58568                 "float exponential = pow( base, 5.0 );",
58569
58570                 "return exponential + F0 * ( 1.0 - exponential );",
58571
58572             "}",
58573
58574             // Kelemen/Szirmay-Kalos specular BRDF
58575
58576             "float KS_Skin_Specular( vec3 N,",         // Bumped surface normal
58577                                     "vec3 L,",         // Points to light
58578                                     "vec3 V,",         // Points to eye
58579                                     "float m,",      // Roughness
58580                                     "float rho_s",     // Specular brightness
58581                                     ") {",
58582
58583                 "float result = 0.0;",
58584                 "float ndotl = dot( N, L );",
58585
58586                 "if( ndotl > 0.0 ) {",
58587
58588                     "vec3 h = L + V;", // Unnormalized half-way vector
58589                     "vec3 H = normalize( h );",
58590
58591                     "float ndoth = dot( N, H );",
58592
58593                     "float PH = pow( 2.0 * texture2D( tBeckmann, vec2( ndoth, m ) ).x, 10.0 );",
58594                     "float F = fresnelReflectance( H, V, 0.028 );",
58595                     "float frSpec = max( PH * F / dot( h, h ), 0.0 );",
58596
58597                     "result = ndotl * rho_s * frSpec;", // BRDF * dot(N,L) * rho_s
58598
58599                 "}",
58600
58601                 "return result;",
58602
58603             "}",
58604
58605             "void main() {",
58606
58607                 "gl_FragColor = vec4( 1.0 );",
58608
58609                 "vec4 mColor = vec4( uDiffuseColor, uOpacity );",
58610                 "vec4 mSpecular = vec4( uSpecularColor, uOpacity );",
58611
58612                 "vec3 normalTex = texture2D( tNormal, vUv ).xyz * 2.0 - 1.0;",
58613                 "normalTex.xy *= uNormalScale;",
58614                 "normalTex = normalize( normalTex );",
58615
58616                 "vec4 colDiffuse = texture2D( tDiffuse, vUv );",
58617                 "colDiffuse *= colDiffuse;",
58618
58619                 "gl_FragColor = gl_FragColor * colDiffuse;",
58620
58621                 "mat3 tsb = mat3( vTangent, vBinormal, vNormal );",
58622                 "vec3 finalNormal = tsb * normalTex;",
58623
58624                 "vec3 normal = normalize( finalNormal );",
58625                 "vec3 viewPosition = normalize( vViewPosition );",
58626
58627                 // point lights
58628
58629                 "vec3 specularTotal = vec3( 0.0 );",
58630
58631                 "#if MAX_POINT_LIGHTS > 0",
58632
58633                     "vec4 pointTotal = vec4( vec3( 0.0 ), 1.0 );",
58634
58635                     "for ( int i = 0; i < MAX_POINT_LIGHTS; i ++ ) {",
58636
58637                         "vec3 pointVector = normalize( vPointLight[ i ].xyz );",
58638                         "float pointDistance = vPointLight[ i ].w;",
58639
58640                         "float pointDiffuseWeight = max( dot( normal, pointVector ), 0.0 );",
58641
58642                         "pointTotal  += pointDistance * vec4( pointLightColor[ i ], 1.0 ) * ( mColor * pointDiffuseWeight );",
58643
58644                         "if ( passID == 1 )",
58645                             "specularTotal += pointDistance * mSpecular.xyz * pointLightColor[ i ] * KS_Skin_Specular( normal, pointVector, viewPosition, uRoughness, uSpecularBrightness );",
58646
58647                     "}",
58648
58649                 "#endif",
58650
58651                 // directional lights
58652
58653                 "#if MAX_DIR_LIGHTS > 0",
58654
58655                     "vec4 dirTotal = vec4( vec3( 0.0 ), 1.0 );",
58656
58657                     "for( int i = 0; i < MAX_DIR_LIGHTS; i++ ) {",
58658
58659                         "vec4 lDirection = viewMatrix * vec4( directionalLightDirection[ i ], 0.0 );",
58660
58661                         "vec3 dirVector = normalize( lDirection.xyz );",
58662
58663                         "float dirDiffuseWeight = max( dot( normal, dirVector ), 0.0 );",
58664
58665                         "dirTotal  += vec4( directionalLightColor[ i ], 1.0 ) * ( mColor * dirDiffuseWeight );",
58666
58667                         "if ( passID == 1 )",
58668                             "specularTotal += mSpecular.xyz * directionalLightColor[ i ] * KS_Skin_Specular( normal, dirVector, viewPosition, uRoughness, uSpecularBrightness );",
58669
58670                     "}",
58671
58672                 "#endif",
58673
58674                 // all lights contribution summation
58675
58676                 "vec4 totalLight = vec4( vec3( 0.0 ), uOpacity );",
58677
58678                 "#if MAX_DIR_LIGHTS > 0",
58679                     "totalLight += dirTotal;",
58680                 "#endif",
58681
58682                 "#if MAX_POINT_LIGHTS > 0",
58683                     "totalLight += pointTotal;",
58684                 "#endif",
58685
58686                 "gl_FragColor = gl_FragColor * totalLight;",
58687
58688                 "if ( passID == 0 ) {",
58689
58690                     "gl_FragColor = vec4( sqrt( gl_FragColor.xyz ), gl_FragColor.w );",
58691
58692                 "} else if ( passID == 1 ) {",
58693
58694                     //"#define VERSION1",
58695
58696                     "#ifdef VERSION1",
58697
58698                         "vec3 nonblurColor = sqrt( gl_FragColor.xyz );",
58699
58700                     "#else",
58701
58702                         "vec3 nonblurColor = gl_FragColor.xyz;",
58703
58704                     "#endif",
58705
58706                     "vec3 blur1Color = texture2D( tBlur1, vUv ).xyz;",
58707                     "vec3 blur2Color = texture2D( tBlur2, vUv ).xyz;",
58708                     "vec3 blur3Color = texture2D( tBlur3, vUv ).xyz;",
58709                     "vec3 blur4Color = texture2D( tBlur4, vUv ).xyz;",
58710
58711
58712                     //"gl_FragColor = vec4( blur1Color, gl_FragColor.w );",
58713
58714                     //"gl_FragColor = vec4( vec3( 0.22, 0.5, 0.7 ) * nonblurColor + vec3( 0.2, 0.5, 0.3 ) * blur1Color + vec3( 0.58, 0.0, 0.0 ) * blur2Color, gl_FragColor.w );",
58715
58716                     //"gl_FragColor = vec4( vec3( 0.25, 0.6, 0.8 ) * nonblurColor + vec3( 0.15, 0.25, 0.2 ) * blur1Color + vec3( 0.15, 0.15, 0.0 ) * blur2Color + vec3( 0.45, 0.0, 0.0 ) * blur3Color, gl_FragColor.w );",
58717
58718
58719                     "gl_FragColor = vec4( vec3( 0.22,  0.437, 0.635 ) * nonblurColor + ",
58720                                          "vec3( 0.101, 0.355, 0.365 ) * blur1Color + ",
58721                                          "vec3( 0.119, 0.208, 0.0 )   * blur2Color + ",
58722                                          "vec3( 0.114, 0.0,   0.0 )   * blur3Color + ",
58723                                          "vec3( 0.444, 0.0,   0.0 )   * blur4Color",
58724                                          ", gl_FragColor.w );",
58725
58726                     "gl_FragColor.xyz *= pow( colDiffuse.xyz, vec3( 0.5 ) );",
58727
58728                     "gl_FragColor.xyz += ambientLightColor * uAmbientColor * colDiffuse.xyz + specularTotal;",
58729
58730                     "#ifndef VERSION1",
58731
58732                         "gl_FragColor.xyz = sqrt( gl_FragColor.xyz );",
58733
58734                     "#endif",
58735
58736                 "}",
58737
58738                 THREE.ShaderChunk[ "fog_fragment" ],
58739
58740             "}"
58741
58742         ].join("\n"),
58743
58744         vertexShader: [
58745
58746             "attribute vec4 tangent;",
58747
58748             "#ifdef VERTEX_TEXTURES",
58749
58750                 "uniform sampler2D tDisplacement;",
58751                 "uniform float uDisplacementScale;",
58752                 "uniform float uDisplacementBias;",
58753
58754             "#endif",
58755
58756             "varying vec3 vTangent;",
58757             "varying vec3 vBinormal;",
58758             "varying vec3 vNormal;",
58759             "varying vec2 vUv;",
58760
58761             "#if MAX_POINT_LIGHTS > 0",
58762
58763                 "uniform vec3 pointLightPosition[ MAX_POINT_LIGHTS ];",
58764                 "uniform float pointLightDistance[ MAX_POINT_LIGHTS ];",
58765
58766                 "varying vec4 vPointLight[ MAX_POINT_LIGHTS ];",
58767
58768             "#endif",
58769
58770             "varying vec3 vViewPosition;",
58771
58772             "void main() {",
58773
58774                 "vec4 mPosition = modelMatrix * vec4( position, 1.0 );",
58775
58776                 "vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );",
58777
58778                 "vViewPosition = -mvPosition.xyz;",
58779
58780                 "vNormal = normalize( normalMatrix * normal );",
58781
58782                 // tangent and binormal vectors
58783
58784                 "vTangent = normalize( normalMatrix * tangent.xyz );",
58785
58786                 "vBinormal = cross( vNormal, vTangent ) * tangent.w;",
58787                 "vBinormal = normalize( vBinormal );",
58788
58789                 "vUv = uv;",
58790
58791                 // point lights
58792
58793                 "#if MAX_POINT_LIGHTS > 0",
58794
58795                     "for( int i = 0; i < MAX_POINT_LIGHTS; i++ ) {",
58796
58797                         "vec4 lPosition = viewMatrix * vec4( pointLightPosition[ i ], 1.0 );",
58798
58799                         "vec3 lVector = lPosition.xyz - mvPosition.xyz;",
58800
58801                         "float lDistance = 1.0;",
58802
58803                         "if ( pointLightDistance[ i ] > 0.0 )",
58804                             "lDistance = 1.0 - min( ( length( lVector ) / pointLightDistance[ i ] ), 1.0 );",
58805
58806                         "lVector = normalize( lVector );",
58807
58808                         "vPointLight[ i ] = vec4( lVector, lDistance );",
58809
58810                     "}",
58811
58812                 "#endif",
58813
58814                 // displacement mapping
58815
58816                 "#ifdef VERTEX_TEXTURES",
58817
58818                     "vec3 dv = texture2D( tDisplacement, uv ).xyz;",
58819                     "float df = uDisplacementScale * dv.x + uDisplacementBias;",
58820                     "vec4 displacedPosition = vec4( vNormal.xyz * df, 0.0 ) + mvPosition;",
58821                     "gl_Position = projectionMatrix * displacedPosition;",
58822
58823                 "#else",
58824
58825                     "gl_Position = projectionMatrix * mvPosition;",
58826
58827                 "#endif",
58828
58829             "}"
58830
58831         ].join("\n"),
58832
58833         vertexShaderUV: [
58834
58835             "attribute vec4 tangent;",
58836
58837             "#ifdef VERTEX_TEXTURES",
58838
58839                 "uniform sampler2D tDisplacement;",
58840                 "uniform float uDisplacementScale;",
58841                 "uniform float uDisplacementBias;",
58842
58843             "#endif",
58844
58845             "varying vec3 vTangent;",
58846             "varying vec3 vBinormal;",
58847             "varying vec3 vNormal;",
58848             "varying vec2 vUv;",
58849
58850             "#if MAX_POINT_LIGHTS > 0",
58851
58852                 "uniform vec3 pointLightPosition[ MAX_POINT_LIGHTS ];",
58853                 "uniform float pointLightDistance[ MAX_POINT_LIGHTS ];",
58854
58855                 "varying vec4 vPointLight[ MAX_POINT_LIGHTS ];",
58856
58857             "#endif",
58858
58859             "varying vec3 vViewPosition;",
58860
58861             "void main() {",
58862
58863                 "vec4 mPosition = modelMatrix * vec4( position, 1.0 );",
58864
58865                 "vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );",
58866
58867                 "vViewPosition = -mvPosition.xyz;",
58868
58869                 "vNormal = normalize( normalMatrix * normal );",
58870
58871                 // tangent and binormal vectors
58872
58873                 "vTangent = normalize( normalMatrix * tangent.xyz );",
58874
58875                 "vBinormal = cross( vNormal, vTangent ) * tangent.w;",
58876                 "vBinormal = normalize( vBinormal );",
58877
58878                 "vUv = uv;",
58879
58880                 // point lights
58881
58882                 "#if MAX_POINT_LIGHTS > 0",
58883
58884                     "for( int i = 0; i < MAX_POINT_LIGHTS; i++ ) {",
58885
58886                         "vec4 lPosition = viewMatrix * vec4( pointLightPosition[ i ], 1.0 );",
58887
58888                         "vec3 lVector = lPosition.xyz - mvPosition.xyz;",
58889
58890                         "float lDistance = 1.0;",
58891
58892                         "if ( pointLightDistance[ i ] > 0.0 )",
58893                             "lDistance = 1.0 - min( ( length( lVector ) / pointLightDistance[ i ] ), 1.0 );",
58894
58895                         "lVector = normalize( lVector );",
58896
58897                         "vPointLight[ i ] = vec4( lVector, lDistance );",
58898
58899                     "}",
58900
58901                 "#endif",
58902
58903                 "gl_Position = vec4( uv.x * 2.0 - 1.0, uv.y * 2.0 - 1.0, 0.0, 1.0 );",
58904
58905             "}"
58906
58907         ].join("\n")
58908
58909     },
58910
58911     /* ------------------------------------------------------------------------------------------
58912     // Beckmann distribution function
58913     //    - to be used in specular term of skin shader
58914     //    - render a screen-aligned quad to precompute a 512 x 512 texture
58915     //
58916     //        - from http://developer.nvidia.com/node/171
58917      ------------------------------------------------------------------------------------------ */
58918
58919     "beckmann" : {
58920
58921         uniforms: {},
58922
58923         vertexShader: [
58924
58925             "varying vec2 vUv;",
58926
58927             "void main() {",
58928
58929                 "vUv = uv;",
58930                 "gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );",
58931
58932             "}"
58933
58934         ].join("\n"),
58935
58936         fragmentShader: [
58937
58938             "varying vec2 vUv;",
58939
58940             "float PHBeckmann( float ndoth, float m ) {",
58941
58942                 "float alpha = acos( ndoth );",
58943                 "float ta = tan( alpha );",
58944
58945                 "float val = 1.0 / ( m * m * pow( ndoth, 4.0 ) ) * exp( -( ta * ta ) / ( m * m ) );",
58946                 "return val;",
58947
58948             "}",
58949
58950             "float KSTextureCompute( vec2 tex ) {",
58951
58952                 // Scale the value to fit within [0,1]  invert upon lookup.
58953
58954                 "return 0.5 * pow( PHBeckmann( tex.x, tex.y ), 0.1 );",
58955
58956             "}",
58957
58958             "void main() {",
58959
58960                 "float x = KSTextureCompute( vUv );",
58961
58962                 "gl_FragColor = vec4( x, x, x, 1.0 );",
58963
58964             "}"
58965
58966         ].join("\n")
58967
58968     }
58969
58970 };
58971 //////////////////////////////////////////////////////////////////////////////
58972 //                                                                          //
58973 // Wii Opera SDK - Drawing Class v2.6.16 2008-12-14                         //
58974 // (c) 2007-2008 Daniel Gump. All Rights Reserved.                          //
58975 // http://wiioperasdk.com, http://hullbreachonline.com                      //
58976 // hullbreach@hullbreachonline.com                                          //
58977 //                                                                          //
58978 //  Wii is a trademark of Nintendo Co., Ltd.                                //
58979 //  Opera is a trademark of Opera, ASA.                                     //
58980 //  This software package is not associated with either company             //
58981 //  but was created to support users of both.  Its alternative name         //
58982 //  when supporting other products is the HULLBREACH SDK.                   //
58983 //                                                                          //
58984 //  Redistribution and use in source and binary forms, with or without      //
58985 //  modification, are permitted provided that the following conditions      //
58986 //  are met:                                                                //
58987 //    * Redistributions of source code must retain the above copyright      //
58988 //      notice, this list of conditions and the following disclaimer.       //
58989 //    * Redistributions in binary form must reproduce the above copyright   //
58990 //      notice, this list of conditions and the following disclaimer in     //
58991 //      the documentation and/or other materials provided with the          //
58992 //      distribution.                                                       //
58993 //    * Neither the names HULLBREACH ONLINE nor WII OPERA SDK nor the names //
58994 //      of its contributors may be used to endorse or promote products      //
58995 //      derived from this software without specific prior written           //
58996 //      permission.                                                         //
58997 //    * If the explicit purpose of the software is not to support the       //
58998 //      Nintendo Wii or the Opera Web browser, then the names of such must  //
58999 //      not be used in any derived product. The name shall be the           //
59000 //      HULLBREACH SDK with a reference link to http://hullbreachonline.    //
59001 //                                                                          //
59002 //  THIS SOFTWARE IS PROVIDED BY Daniel Gump ''AS IS'' AND ANY EXPRESS OR   //
59003 //  IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED          //
59004 //  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE  //
59005 //  DISCLAIMED. IN NO EVENT SHALL Daniel Gump BE LIABLE FOR ANY DIRECT,     //
59006 //  INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES      //
59007 //  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR      //
59008 //  SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)      //
59009 //  HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,     //
59010 //  STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING   //
59011 //  IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE      //
59012 //  POSSIBILITY OF SUCH DAMAGE.                                             //
59013 //////////////////////////////////////////////////////////////////////////////
59014
59015 function Drawing(){
59016         this.WIREFRAME = 1; this.FILL = 2;
59017         ZOOM = 1;
59018         CANVAS = null;
59019         TEXTURES = null;
59020 }
59021 Drawing.prototype.initialize = function(canvas){
59022         CANVAS = canvas.getContext("2d");
59023         CANVAS.lineJoin = "round";
59024         CANVAS.lineWidth = 1;
59025 }
59026 Drawing.prototype.loadTextures = function(textures){ TEXTURES = textures; }
59027 Drawing.prototype.setFillColor = function(r,g,b){ CANVAS.fillStyle = "rgb("+(r>255?255:(r<0?0:r|0))+", "+(g>255?255:(g<0?0:g|0))+", "+(b>255?255:(b<0?0:b|0))+")"; }
59028 Drawing.prototype.setFillColorA = function(r,g,b,a){ CANVAS.fillStyle = "rgba("+(r>255?255:(r<0?0:r|0))+", "+(g>255?255:(g<0?0:g|0))+", "+(b>255?255:(b<0?0:b|0))+", "+(a>255?1:(a<0?0:a/255))+")"; }
59029 Drawing.prototype.setLineColor = function(r,g,b){ CANVAS.strokeStyle = "rgb("+(r>255?255:(r<0?0:r|0))+", "+(g>255?255:(g<0?0:g|0))+", "+(b>255?255:(b<0?0:b|0))+")"; }
59030 Drawing.prototype.setLineColorA = function(r,g,b,a){ CANVAS.strokeStyle = "rgba("+(r>255?255:(r<0?0:r|0))+", "+(g>255?255:(g<0?0:g|0))+", "+(b>255?255:(b<0?0:b|0))+", "+(a>255?1:(a<0?0:a/255))+")"; }
59031 Drawing.prototype.clipCircle = function(centerx,centery,radius){ CANVAS.beginPath(); CANVAS.arc(centerx,centery,radius,0,6.28318531,false); CANVAS.clip(); }
59032 Drawing.prototype.clipRectangle = function(x1,y1,x2,y2){ CANVAS.beginPath(); CANVAS.strokeRect(x1,y1,x2-x1,y2-y1); CANVAS.clip(); }
59033 Drawing.prototype.drawCircle = function(centerx,centery,radius,style){
59034         CANVAS.beginPath();
59035         CANVAS.arc(centerx, centery, radius, 0, Math.PI*2, false);
59036         if(style & this.FILL) CANVAS.fill();
59037         if(style & this.WIREFRAME) CANVAS.stroke();
59038 }
59039 Drawing.prototype.drawImage = function(x1,y1,x2,y2,img,angle){
59040         if(img.complete){
59041                 x1|=0;
59042                 y1|=0;
59043                 x2|=0;
59044                 y2|=0;
59045                 if(x2<x1) x2=x1+1;
59046                 if(y2<y1) y2=y1+1;
59047                 var centerx = (x1+x2)>>1;
59048                 var centery = (y1+y2)>>1;
59049
59050                 CANVAS.save();
59051                 CANVAS.translate(centerx, centery);
59052                 if(angle) CANVAS.rotate(angle*0.01745329);
59053                 CANVAS.drawImage(img, x1-centerx, y1-centery, x2-x1, y2-y1);
59054                 CANVAS.restore();
59055         }
59056 }
59057 Drawing.prototype.drawLine = function(x1, y1, x2, y2){ CANVAS.beginPath(); CANVAS.moveTo(x1|0, y1|0); CANVAS.lineTo(x2|0, y2|0); CANVAS.stroke(); }
59058 Drawing.prototype.drawRectangle = function(x1, y1, x2, y2, style, angle){
59059         x1|=0;
59060         y1|=0;
59061         x2|=0;
59062         y2|=0;
59063         
59064         if(!angle){
59065                 if(style & this.FILL) CANVAS.fillRect(x1, y1, x2-x1, y2-y1);
59066                 if(style & this.WIREFRAME) CANVAS.strokeRect(x1, y1, x2-x1, y2-y1);
59067         }else{
59068                 var centerx = (x1+x2)>>1; var centery = (y1+y2)>>1;
59069
59070                 CANVAS.save();
59071                 CANVAS.translate(centerx, centery);
59072                 CANVAS.rotate(angle*DEGTORAD);
59073                 if(style & this.FILL) CANVAS.fillRect(x1-centerx, y1-centery, x2-x1, y2-y1);
59074                 if(style & this.WIREFRAME) CANVAS.strokeRect(x1-centerx, y1-centery, x2-x1, y2-y1);
59075                 CANVAS.restore();
59076         }
59077 }
59078 Drawing.prototype.drawScene = function(array,style){
59079         var piOver2 = 1.570796326794897;
59080         var piOver4 = 0.785398163397448;
59081         var sqrt2half = 1.414213562373095;
59082
59083         for(tri=array.length;--tri>=0;){
59084                 var x1 = array[tri][0];
59085                 var y1 = array[tri][1];
59086                 var x2 = array[tri][2];
59087                 var y2 = array[tri][3];
59088                 var x3 = array[tri][4];
59089                 var y3 = array[tri][5];
59090                 shade=array[tri][10];
59091
59092                 if(TEXTURES && array[tri][9]>=0){
59093                         CANVAS.save();
59094
59095                         var u = (x2-x3)*(x2-x3)+(y2-y3)*(y2-y3);
59096                         var v = (x1-x3)*(x1-x3)+(y1-y3)*(y1-y3);
59097                         var w = (x2-x1)*(x2-x1)+(y2-y1)*(y2-y1);
59098
59099                         var canvasRot = 0.5*Math.acos((w+v-u)/(2*Math.sqrt(w*v)));
59100                         var scale = Math.cos(canvasRot)*sqrt2half;
59101
59102                         CANVAS.translate(x1,y1);
59103                         CANVAS.rotate(Math.atan2(y2-y1,x2-x1)-piOver2+canvasRot);
59104                         CANVAS.scale(Math.tan(canvasRot),1);
59105                         CANVAS.rotate(piOver4);
59106                         CANVAS.scale(Math.sqrt(w)*scale,Math.sqrt(v)*scale);
59107                         //CANVAS.transform(x2-x1,y2-y1,x3-x1,y3-y1, x1,y1);
59108                         CANVAS.drawImage((canvasimg = TEXTURES[array[tri][9]]), 0,0, canvasimg.width,canvasimg.height, 0,0, 1,1);
59109                         CANVAS.restore();
59110
59111                         if(shade!=0){
59112                                 CANVAS.beginPath();
59113                                 CANVAS.moveTo(x1,y1);
59114                                 CANVAS.lineTo(x2,y2);
59115                                 CANVAS.lineTo(x3,y3);
59116                                 CANVAS.lineTo(x1,y1);
59117                                 if(shade>0){
59118                                         if(shade>1) shade=1;
59119                                         CANVAS.fillStyle = "rgba(255,255,255,"+(shade)+")";
59120                                         CANVAS.strokeStyle = "rgba(255,255,255,"+(shade*.5)+")";
59121                                 }else if(shade<0){
59122                                         if(shade<-1) shade=-1;
59123                                         CANVAS.fillStyle = "rgba(0,0,0,"+(-shade)+")";
59124                                         CANVAS.strokeStyle = "rgba(0,0,0,"+(-shade*.5)+")";
59125                                 }
59126                                 if(style & this.FILL) CANVAS.fill();
59127                                 if(style & this.WIREFRAME) CANVAS.stroke();
59128                         }
59129                 }else{
59130                         var red = array[tri][6];
59131                         var green = array[tri][7];
59132                         var blue = array[tri][8];
59133                         if(shade!=0){
59134                                 red=(red*=++shade)>255?255:(red<0?0:red);
59135                                 green=(green*=shade)>255?255:(green<0?0:green);
59136                                 blue=(blue*=shade)>255?255:(blue<0?0:blue);
59137                         }
59138                         var color = "rgb("+(red|0)+","+(green|0)+","+(blue|0)+")";
59139                         CANVAS.beginPath();
59140                         CANVAS.moveTo(x1,y1);
59141                         CANVAS.lineTo(x2,y2);
59142                         CANVAS.lineTo(x3,y3);
59143                         CANVAS.lineTo(x1,y1);
59144                         if(style & this.FILL){ CANVAS.fillStyle = color; CANVAS.fill(); }
59145                         if(style & this.WIREFRAME){ CANVAS.strokeStyle = color; CANVAS.stroke(); }
59146                 }
59147         }
59148 }
59149
59150 Drawing.prototype.drawFloor = function(x1,x2,y1,x3,x4,y2,img){
59151         if((x2|=0)==(x1|=0)) x2++;
59152         if((y2|=0)==(y1|=0)) y2++;
59153         if((x4|=0)==(x3|=0)) x4++;
59154         var absdy=(dy = y2-y1)<0?-dy:dy;
59155
59156         var sourceD = img.width-1, sourceY = (img.height-1)*(dx2 = x4-x3)/dy;
59157         var destX = (x3-x1)/dy;
59158         var tempY = 0;
59159         var destW2 = (dx1 = x2-x1);
59160
59161         var absscale = (fullscale = 1.5*(dy>>31?-1:1)+dy/img.height)>>31?-(fullscale-1):(fullscale+1);
59162         var destwfullscale = fullscale*(dx2-dx1+1)/dy;
59163
59164         while(tempY<0?-tempY:tempY<=absdy){
59165                 CANVAS.drawImage(img, 0, sourceY*tempY/destW2, sourceD, 1, x1+destX*tempY, tempY+y1, destW2, absscale);
59166                 tempY+=fullscale;
59167                 destW2+=destwfullscale;
59168         }       
59169 }
59170 Drawing.prototype.drawWall = function(x1,y1,y2,x2,y3,y4,img){
59171         if(x2==x1) x2++;
59172         if(y2==y1) y2++;
59173         if(y4==y3) y4++;
59174         var dx = x2-x1, dy1 = y2-y1, dy2 = y4-y3;
59175         var absdx=dx<0?-dx:dx;
59176
59177         var sourceH = img.height-1, sourceX = (img.width-1)*dy2/dx;
59178         var destY = (y3-y1)/dx;
59179         var tempX = 0;
59180
59181         var fullscale = 1.5*(dx<0?-1:1)+dx/img.width;
59182         var absscale = fullscale<0?(-fullscale-1):(fullscale+1);
59183         var desthfullscale = fullscale*(dy2-dy1+1)/dx;
59184
59185         while(tempX<0?-tempX:tempX<=absdx){
59186                 CANVAS.drawImage(img, sourceX*tempX/dy1, 0, 1, sourceH, tempX+x1, y1+destY*tempX, absscale, dy1);
59187                 tempX+=fullscale;
59188                 dy1+=desthfullscale;
59189         }       
59190 }
59191 Drawing.prototype.zoom = function(zoom,width,height){
59192         ZOOM = zoom;
59193         CANVAS.translate(width>>1, height>>1);
59194         CANVAS.scale(ZOOM, ZOOM);
59195         CANVAS.translate(-width>>1, -height>>1);
59196 }
59197 Drawing.prototype.unZoom = function(width,height){
59198         CANVAS.translate(width>>1, height>>1);
59199         CANVAS.scale(1/ZOOM, 1/ZOOM);
59200         CANVAS.translate(-width>>1, -height>>1);
59201         ZOOM = 1;
59202 }
59203 Drawing.prototype.clear = function(x1, y1, x2, y2){ CANVAS.clearRect(x1, y1, x2-x1, y2-y1); }
59204
59205 Draw = new Drawing();var jWorkflow=function(){return{order:function(h,j){var i=[],f,d=null,g=function(){var a=false;return{take:function(){a=true},pass:function(b){var c;a=false;if(f.length){c=f.shift();b=c.func.apply(c.context,[b,g]);a||g.pass(b)}else d.func&&d.func.apply(d.context,[])}}}(),e={andThen:function(a,b){if(typeof a!=="function")throw"expected function but was "+typeof a;i.push({func:a,context:b});return e},chill:function(a){return e.andThen(function(b,c){c.take();setTimeout(function(){c.pass(b)},a)})},start:function(a,
59206 b){d={func:a,context:b};f=i.slice();g.pass()}};return h?e.andThen(h,j):e}}}();if(typeof module==="object"&&typeof require==="function")module.exports=jWorkflow;
59207 /*
59208   OpenLayers.js -- OpenLayers Map Viewer Library
59209
59210   Copyright 2005-2010 OpenLayers Contributors, released under the Clear BSD
59211   license. Full license text below taken from http://svn.openlayers.org/trunk/openlayers/license.txt
59212
59213         Copyright 2005-2011 OpenLayers Contributors. All rights reserved. See
59214         authors.txt for full list.
59215          
59216         Redistribution and use in source and binary forms, with or without modification,
59217         are permitted provided that the following conditions are met:
59218          
59219         1. Redistributions of source code must retain the above copyright notice, this
59220         list of conditions and the following disclaimer.
59221          
59222         2. Redistributions in binary form must reproduce the above copyright notice,
59223         this list of conditions and the following disclaimer in the documentation and/or
59224         other materials provided with the distribution.
59225          
59226         THIS SOFTWARE IS PROVIDED BY OPENLAYERS CONTRIBUTORS ``AS IS'' AND ANY EXPRESS
59227         OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
59228         MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
59229         SHALL COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
59230         INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
59231         LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
59232         PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
59233         LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
59234         OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
59235         ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
59236          
59237         The views and conclusions contained in the software and documentation are those
59238         of the authors and should not be interpreted as representing official policies,
59239         either expressed or implied, of OpenLayers Contributors.
59240
59241   Includes compressed code under the following licenses:
59242
59243   (For uncompressed versions of the code used please see the
59244   OpenLayers SVN repository: <http://openlayers.org/>)
59245
59246 */
59247
59248 /**  
59249 *  
59250 *  Contains portions of Rico <http://openrico.org/>
59251
59252 *  Copyright 2005 Sabre Airline Solutions  
59253 *  
59254 *  Licensed under the Apache License, Version 2.0 (the "License"); you
59255 *  may not use this file except in compliance with the License. You
59256 *  may obtain a copy of the License at
59257 *  
59258 *         http://www.apache.org/licenses/LICENSE-2.0  
59259 *  
59260 *  Unless required by applicable law or agreed to in writing, software
59261 *  distributed under the License is distributed on an "AS IS" BASIS,
59262 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
59263 *  implied. See the License for the specific language governing
59264 *  permissions and limitations under the License. 
59265 *
59266 **/
59267
59268 /**
59269  * Contains XMLHttpRequest.js <http://code.google.com/p/xmlhttprequest/>
59270  * Copyright 2007 Sergey Ilinsky (http://www.ilinsky.com)
59271  *
59272  * Licensed under the Apache License, Version 2.0 (the "License");
59273  * you may not use this file except in compliance with the License.
59274  * You may obtain a copy of the License at
59275  * http://www.apache.org/licenses/LICENSE-2.0
59276  */
59277
59278 /**
59279  * Contains portions of Gears <http://code.google.com/apis/gears/>
59280  *
59281  * Copyright 2007, Google Inc.
59282  *
59283  * Redistribution and use in source and binary forms, with or without
59284  * modification, are permitted provided that the following conditions are met:
59285  *
59286  *  1. Redistributions of source code must retain the above copyright notice,
59287  *     this list of conditions and the following disclaimer.
59288  *  2. Redistributions in binary form must reproduce the above copyright notice,
59289  *     this list of conditions and the following disclaimer in the documentation
59290  *     and/or other materials provided with the distribution.
59291  *  3. Neither the name of Google Inc. nor the names of its contributors may be
59292  *     used to endorse or promote products derived from this software without
59293  *     specific prior written permission.
59294  *
59295  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
59296  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
59297  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
59298  * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
59299  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
59300  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
59301  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
59302  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
59303  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
59304  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
59305  *
59306  * Sets up google.gears.*, which is *the only* supported way to access Gears.
59307  *
59308  * Circumvent this file at your own risk!
59309  *
59310  * In the future, Gears may automatically define google.gears.* without this
59311  * file. Gears may use these objects to transparently fix bugs and compatibility
59312  * issues. Applications that use the code below will continue to work seamlessly
59313  * when that happens.
59314  */
59315 var OpenLayers={singleFile:true};(function(){var singleFile=(typeof OpenLayers=="object"&&OpenLayers.singleFile);var scriptLocation;window.OpenLayers={_scriptName:(!singleFile)?"lib/OpenLayers.js":"OpenLayers.js",_getScriptLocation:function(){if(scriptLocation!=undefined){return scriptLocation;}
59316 scriptLocation="";var isOL=new RegExp("(^|(.*?\\/))("+OpenLayers._scriptName+")(\\?|$)");var scripts=document.getElementsByTagName('script');for(var i=0,len=scripts.length;i<len;i++){var src=scripts[i].getAttribute('src');if(src){var match=src.match(isOL);if(match){scriptLocation=match[1];break;}}}
59317 return scriptLocation;}};if(!singleFile){var jsfiles=new Array("OpenLayers/Util.js","OpenLayers/BaseTypes.js","OpenLayers/BaseTypes/Class.js","OpenLayers/BaseTypes/Bounds.js","OpenLayers/BaseTypes/Element.js","OpenLayers/BaseTypes/LonLat.js","OpenLayers/BaseTypes/Pixel.js","OpenLayers/BaseTypes/Size.js","OpenLayers/Console.js","OpenLayers/Tween.js","Rico/Corner.js","Rico/Color.js","OpenLayers/Ajax.js","OpenLayers/Events.js","OpenLayers/Request.js","OpenLayers/Request/XMLHttpRequest.js","OpenLayers/Projection.js","OpenLayers/Map.js","OpenLayers/Layer.js","OpenLayers/Icon.js","OpenLayers/Marker.js","OpenLayers/Marker/Box.js","OpenLayers/Popup.js","OpenLayers/Tile.js","OpenLayers/Tile/Image.js","OpenLayers/Tile/Image/IFrame.js","OpenLayers/Tile/WFS.js","OpenLayers/Layer/Image.js","OpenLayers/Layer/SphericalMercator.js","OpenLayers/Layer/EventPane.js","OpenLayers/Layer/FixedZoomLevels.js","OpenLayers/Layer/Google.js","OpenLayers/Layer/Google/v3.js","OpenLayers/Layer/VirtualEarth.js","OpenLayers/Layer/Yahoo.js","OpenLayers/Layer/HTTPRequest.js","OpenLayers/Layer/Grid.js","OpenLayers/Layer/MapGuide.js","OpenLayers/Layer/MapServer.js","OpenLayers/Layer/MapServer/Untiled.js","OpenLayers/Layer/KaMap.js","OpenLayers/Layer/KaMapCache.js","OpenLayers/Layer/MultiMap.js","OpenLayers/Layer/Markers.js","OpenLayers/Layer/Text.js","OpenLayers/Layer/WorldWind.js","OpenLayers/Layer/ArcGIS93Rest.js","OpenLayers/Layer/WMS.js","OpenLayers/Layer/WMS/Untiled.js","OpenLayers/Layer/WMS/Post.js","OpenLayers/Layer/WMTS.js","OpenLayers/Layer/ArcIMS.js","OpenLayers/Layer/GeoRSS.js","OpenLayers/Layer/Boxes.js","OpenLayers/Layer/XYZ.js","OpenLayers/Layer/TMS.js","OpenLayers/Layer/TileCache.js","OpenLayers/Layer/Zoomify.js","OpenLayers/Popup/Anchored.js","OpenLayers/Popup/AnchoredBubble.js","OpenLayers/Popup/Framed.js","OpenLayers/Popup/FramedCloud.js","OpenLayers/Feature.js","OpenLayers/Feature/Vector.js","OpenLayers/Feature/WFS.js","OpenLayers/Handler.js","OpenLayers/Handler/Click.js","OpenLayers/Handler/Hover.js","OpenLayers/Handler/Point.js","OpenLayers/Handler/Path.js","OpenLayers/Handler/Polygon.js","OpenLayers/Handler/Feature.js","OpenLayers/Handler/Drag.js","OpenLayers/Handler/RegularPolygon.js","OpenLayers/Handler/Box.js","OpenLayers/Handler/MouseWheel.js","OpenLayers/Handler/Keyboard.js","OpenLayers/Control.js","OpenLayers/Control/Attribution.js","OpenLayers/Control/Button.js","OpenLayers/Control/ZoomBox.js","OpenLayers/Control/ZoomToMaxExtent.js","OpenLayers/Control/DragPan.js","OpenLayers/Control/Navigation.js","OpenLayers/Control/MouseDefaults.js","OpenLayers/Control/MousePosition.js","OpenLayers/Control/OverviewMap.js","OpenLayers/Control/KeyboardDefaults.js","OpenLayers/Control/PanZoom.js","OpenLayers/Control/PanZoomBar.js","OpenLayers/Control/ArgParser.js","OpenLayers/Control/Permalink.js","OpenLayers/Control/Scale.js","OpenLayers/Control/ScaleLine.js","OpenLayers/Control/Snapping.js","OpenLayers/Control/Split.js","OpenLayers/Control/LayerSwitcher.js","OpenLayers/Control/DrawFeature.js","OpenLayers/Control/DragFeature.js","OpenLayers/Control/ModifyFeature.js","OpenLayers/Control/Panel.js","OpenLayers/Control/SelectFeature.js","OpenLayers/Control/NavigationHistory.js","OpenLayers/Control/Measure.js","OpenLayers/Control/WMSGetFeatureInfo.js","OpenLayers/Control/WMTSGetFeatureInfo.js","OpenLayers/Control/Graticule.js","OpenLayers/Control/TransformFeature.js","OpenLayers/Control/SLDSelect.js","OpenLayers/Geometry.js","OpenLayers/Geometry/Rectangle.js","OpenLayers/Geometry/Collection.js","OpenLayers/Geometry/Point.js","OpenLayers/Geometry/MultiPoint.js","OpenLayers/Geometry/Curve.js","OpenLayers/Geometry/LineString.js","OpenLayers/Geometry/LinearRing.js","OpenLayers/Geometry/Polygon.js","OpenLayers/Geometry/MultiLineString.js","OpenLayers/Geometry/MultiPolygon.js","OpenLayers/Geometry/Surface.js","OpenLayers/Renderer.js","OpenLayers/Renderer/Elements.js","OpenLayers/Renderer/SVG.js","OpenLayers/Renderer/Canvas.js","OpenLayers/Renderer/VML.js","OpenLayers/Layer/Vector.js","OpenLayers/Layer/Vector/RootContainer.js","OpenLayers/Strategy.js","OpenLayers/Strategy/Filter.js","OpenLayers/Strategy/Fixed.js","OpenLayers/Strategy/Cluster.js","OpenLayers/Strategy/Paging.js","OpenLayers/Strategy/BBOX.js","OpenLayers/Strategy/Save.js","OpenLayers/Strategy/Refresh.js","OpenLayers/Filter.js","OpenLayers/Filter/FeatureId.js","OpenLayers/Filter/Logical.js","OpenLayers/Filter/Comparison.js","OpenLayers/Filter/Spatial.js","OpenLayers/Protocol.js","OpenLayers/Protocol/HTTP.js","OpenLayers/Protocol/SQL.js","OpenLayers/Protocol/SQL/Gears.js","OpenLayers/Protocol/WFS.js","OpenLayers/Protocol/WFS/v1.js","OpenLayers/Protocol/WFS/v1_0_0.js","OpenLayers/Protocol/WFS/v1_1_0.js","OpenLayers/Protocol/SOS.js","OpenLayers/Protocol/SOS/v1_0_0.js","OpenLayers/Layer/PointTrack.js","OpenLayers/Layer/GML.js","OpenLayers/Style.js","OpenLayers/Style2.js","OpenLayers/StyleMap.js","OpenLayers/Rule.js","OpenLayers/Format.js","OpenLayers/Format/XML.js","OpenLayers/Format/Context.js","OpenLayers/Format/ArcXML.js","OpenLayers/Format/ArcXML/Features.js","OpenLayers/Format/GML.js","OpenLayers/Format/GML/Base.js","OpenLayers/Format/GML/v2.js","OpenLayers/Format/GML/v3.js","OpenLayers/Format/Atom.js","OpenLayers/Format/KML.js","OpenLayers/Format/GeoRSS.js","OpenLayers/Format/WFS.js","OpenLayers/Format/WFSCapabilities.js","OpenLayers/Format/WFSCapabilities/v1.js","OpenLayers/Format/WFSCapabilities/v1_0_0.js","OpenLayers/Format/WFSCapabilities/v1_1_0.js","OpenLayers/Format/WFSDescribeFeatureType.js","OpenLayers/Format/WMSDescribeLayer.js","OpenLayers/Format/WMSDescribeLayer/v1_1.js","OpenLayers/Format/WKT.js","OpenLayers/Format/OSM.js","OpenLayers/Format/GPX.js","OpenLayers/Format/Filter.js","OpenLayers/Format/Filter/v1.js","OpenLayers/Format/Filter/v1_0_0.js","OpenLayers/Format/Filter/v1_1_0.js","OpenLayers/Format/SLD.js","OpenLayers/Format/SLD/v1.js","OpenLayers/Format/SLD/v1_0_0.js","OpenLayers/Format/OWSCommon/v1.js","OpenLayers/Format/OWSCommon/v1_0_0.js","OpenLayers/Format/OWSCommon/v1_1_0.js","OpenLayers/Format/CSWGetDomain.js","OpenLayers/Format/CSWGetDomain/v2_0_2.js","OpenLayers/Format/CSWGetRecords.js","OpenLayers/Format/CSWGetRecords/v2_0_2.js","OpenLayers/Format/WFST.js","OpenLayers/Format/WFST/v1.js","OpenLayers/Format/WFST/v1_0_0.js","OpenLayers/Format/WFST/v1_1_0.js","OpenLayers/Format/Text.js","OpenLayers/Format/JSON.js","OpenLayers/Format/GeoJSON.js","OpenLayers/Format/WMC.js","OpenLayers/Format/WMC/v1.js","OpenLayers/Format/WMC/v1_0_0.js","OpenLayers/Format/WMC/v1_1_0.js","OpenLayers/Format/WMSCapabilities.js","OpenLayers/Format/WMSCapabilities/v1.js","OpenLayers/Format/WMSCapabilities/v1_1.js","OpenLayers/Format/WMSCapabilities/v1_1_0.js","OpenLayers/Format/WMSCapabilities/v1_1_1.js","OpenLayers/Format/WMSCapabilities/v1_3.js","OpenLayers/Format/WMSCapabilities/v1_3_0.js","OpenLayers/Format/WMSGetFeatureInfo.js","OpenLayers/Format/SOSCapabilities.js","OpenLayers/Format/SOSCapabilities/v1_0_0.js","OpenLayers/Format/SOSGetObservation.js","OpenLayers/Format/SOSGetFeatureOfInterest.js","OpenLayers/Format/OWSContext.js","OpenLayers/Format/OWSContext/v0_3_1.js","OpenLayers/Format/WMTSCapabilities.js","OpenLayers/Format/WMTSCapabilities/v1_0_0.js","OpenLayers/Layer/WFS.js","OpenLayers/Control/GetFeature.js","OpenLayers/Control/MouseToolbar.js","OpenLayers/Control/NavToolbar.js","OpenLayers/Control/PanPanel.js","OpenLayers/Control/Pan.js","OpenLayers/Control/ZoomIn.js","OpenLayers/Control/ZoomOut.js","OpenLayers/Control/ZoomPanel.js","OpenLayers/Control/EditingToolbar.js","OpenLayers/Symbolizer.js","OpenLayers/Symbolizer/Point.js","OpenLayers/Symbolizer/Line.js","OpenLayers/Symbolizer/Polygon.js","OpenLayers/Symbolizer/Text.js","OpenLayers/Symbolizer/Raster.js","OpenLayers/Lang.js","OpenLayers/Lang/en.js");var agent=navigator.userAgent;var docWrite=(agent.match("MSIE")||agent.match("Safari"));if(docWrite){var allScriptTags=new Array(jsfiles.length);}
59318 var host=OpenLayers._getScriptLocation()+"lib/";for(var i=0,len=jsfiles.length;i<len;i++){if(docWrite){allScriptTags[i]="<script src='"+host+jsfiles[i]+"'></script>";}else{var s=document.createElement("script");s.src=host+jsfiles[i];var h=document.getElementsByTagName("head").length?document.getElementsByTagName("head")[0]:document.body;h.appendChild(s);}}
59319 if(docWrite){document.write(allScriptTags.join(""));}}})();OpenLayers.VERSION_NUMBER="OpenLayers 2.10 -- $Revision: 10721 $";OpenLayers.String={startsWith:function(str,sub){return(str.indexOf(sub)==0);},contains:function(str,sub){return(str.indexOf(sub)!=-1);},trim:function(str){return str.replace(/^\s\s*/,'').replace(/\s\s*$/,'');},camelize:function(str){var oStringList=str.split('-');var camelizedString=oStringList[0];for(var i=1,len=oStringList.length;i<len;i++){var s=oStringList[i];camelizedString+=s.charAt(0).toUpperCase()+s.substring(1);}
59320 return camelizedString;},format:function(template,context,args){if(!context){context=window;}
59321 var replacer=function(str,match){var replacement;var subs=match.split(/\.+/);for(var i=0;i<subs.length;i++){if(i==0){replacement=context;}
59322 replacement=replacement[subs[i]];}
59323 if(typeof replacement=="function"){replacement=args?replacement.apply(null,args):replacement();}
59324 if(typeof replacement=='undefined'){return'undefined';}else{return replacement;}};return template.replace(OpenLayers.String.tokenRegEx,replacer);},tokenRegEx:/\$\{([\w.]+?)\}/g,numberRegEx:/^([+-]?)(?=\d|\.\d)\d*(\.\d*)?([Ee]([+-]?\d+))?$/,isNumeric:function(value){return OpenLayers.String.numberRegEx.test(value);},numericIf:function(value){return OpenLayers.String.isNumeric(value)?parseFloat(value):value;}};if(!String.prototype.startsWith){String.prototype.startsWith=function(sStart){OpenLayers.Console.warn(OpenLayers.i18n("methodDeprecated",{'newMethod':'OpenLayers.String.startsWith'}));return OpenLayers.String.startsWith(this,sStart);};}
59325 if(!String.prototype.contains){String.prototype.contains=function(str){OpenLayers.Console.warn(OpenLayers.i18n("methodDeprecated",{'newMethod':'OpenLayers.String.contains'}));return OpenLayers.String.contains(this,str);};}
59326 if(!String.prototype.trim){String.prototype.trim=function(){OpenLayers.Console.warn(OpenLayers.i18n("methodDeprecated",{'newMethod':'OpenLayers.String.trim'}));return OpenLayers.String.trim(this);};}
59327 if(!String.prototype.camelize){String.prototype.camelize=function(){OpenLayers.Console.warn(OpenLayers.i18n("methodDeprecated",{'newMethod':'OpenLayers.String.camelize'}));return OpenLayers.String.camelize(this);};}
59328 OpenLayers.Number={decimalSeparator:".",thousandsSeparator:",",limitSigDigs:function(num,sig){var fig=0;if(sig>0){fig=parseFloat(num.toPrecision(sig));}
59329 return fig;},format:function(num,dec,tsep,dsep){dec=(typeof dec!="undefined")?dec:0;tsep=(typeof tsep!="undefined")?tsep:OpenLayers.Number.thousandsSeparator;dsep=(typeof dsep!="undefined")?dsep:OpenLayers.Number.decimalSeparator;if(dec!=null){num=parseFloat(num.toFixed(dec));}
59330 var parts=num.toString().split(".");if(parts.length==1&&dec==null){dec=0;}
59331 var integer=parts[0];if(tsep){var thousands=/(-?[0-9]+)([0-9]{3})/;while(thousands.test(integer)){integer=integer.replace(thousands,"$1"+tsep+"$2");}}
59332 var str;if(dec==0){str=integer;}else{var rem=parts.length>1?parts[1]:"0";if(dec!=null){rem=rem+new Array(dec-rem.length+1).join("0");}
59333 str=integer+dsep+rem;}
59334 return str;}};if(!Number.prototype.limitSigDigs){Number.prototype.limitSigDigs=function(sig){OpenLayers.Console.warn(OpenLayers.i18n("methodDeprecated",{'newMethod':'OpenLayers.Number.limitSigDigs'}));return OpenLayers.Number.limitSigDigs(this,sig);};}
59335 OpenLayers.Function={bind:function(func,object){var args=Array.prototype.slice.apply(arguments,[2]);return function(){var newArgs=args.concat(Array.prototype.slice.apply(arguments,[0]));return func.apply(object,newArgs);};},bindAsEventListener:function(func,object){return function(event){return func.call(object,event||window.event);};},False:function(){return false;},True:function(){return true;}};if(!Function.prototype.bind){Function.prototype.bind=function(){OpenLayers.Console.warn(OpenLayers.i18n("methodDeprecated",{'newMethod':'OpenLayers.Function.bind'}));Array.prototype.unshift.apply(arguments,[this]);return OpenLayers.Function.bind.apply(null,arguments);};}
59336 if(!Function.prototype.bindAsEventListener){Function.prototype.bindAsEventListener=function(object){OpenLayers.Console.warn(OpenLayers.i18n("methodDeprecated",{'newMethod':'OpenLayers.Function.bindAsEventListener'}));return OpenLayers.Function.bindAsEventListener(this,object);};}
59337 OpenLayers.Array={filter:function(array,callback,caller){var selected=[];if(Array.prototype.filter){selected=array.filter(callback,caller);}else{var len=array.length;if(typeof callback!="function"){throw new TypeError();}
59338 for(var i=0;i<len;i++){if(i in array){var val=array[i];if(callback.call(caller,val,i,array)){selected.push(val);}}}}
59339 return selected;}};OpenLayers.Date={toISOString:(function(){if("toISOString"in Date.prototype){return function(date){return date.toISOString();}}else{function pad(num,len){var str=num+"";while(str.length<len){str="0"+str;}
59340 return str;}
59341 return function(date){var str;if(isNaN(date.getTime())){str="Invalid Date";}else{str=date.getUTCFullYear()+"-"+
59342 pad(date.getUTCMonth()+1,2)+"-"+
59343 pad(date.getUTCDate(),2)+"T"+
59344 pad(date.getUTCHours(),2)+":"+
59345 pad(date.getUTCMinutes(),2)+":"+
59346 pad(date.getUTCSeconds(),2)+"."+
59347 pad(date.getUTCMilliseconds(),3)+"Z";}
59348 return str;}}})(),parse:function(str){var date;var elapsed=Date.parse(str);if(!isNaN(elapsed)){date=new Date(elapsed);}else{var match=str.match(/^(?:(\d{4})(?:-(\d{2})(?:-(\d{2}))?)?)?(?:T(\d{1,2}):(\d{2}):(\d{2}(?:\.\d+)?)(Z|(?:[+-]\d{1,2}(?::(\d{2}))?)))?$/);var date;if(match&&(match[1]||match[7])){var year=parseInt(match[1],10)||0;var month=(parseInt(match[2],10)-1)||0;var day=parseInt(match[3],10)||1;date=new Date(Date.UTC(year,month,day));var type=match[7];if(type){var hours=parseInt(match[4],10);var minutes=parseInt(match[5],10);var secFrac=parseFloat(match[6]);var seconds=secFrac|0;var milliseconds=Math.round(1000*(secFrac-seconds));date.setUTCHours(hours,minutes,seconds,milliseconds);if(type!=="Z"){var hoursOffset=parseInt(type,10);var minutesOffset=parseInt(match[8])||0;var offset=-1000*(60*(hoursOffset*60)+minutesOffset*60);date=new Date(date.getTime()+offset);}}}else{date=new Date("invalid");}}
59349 return date;}};OpenLayers.Class=function(){var Class=function(){if(arguments&&arguments[0]!=OpenLayers.Class.isPrototype){this.initialize.apply(this,arguments);}};var extended={};var parent,initialize,Type;for(var i=0,len=arguments.length;i<len;++i){Type=arguments[i];if(typeof Type=="function"){if(i==0&&len>1){initialize=Type.prototype.initialize;Type.prototype.initialize=function(){};extended=new Type();if(initialize===undefined){delete Type.prototype.initialize;}else{Type.prototype.initialize=initialize;}}
59350 parent=Type.prototype;}else{parent=Type;}
59351 OpenLayers.Util.extend(extended,parent);}
59352 Class.prototype=extended;return Class;};OpenLayers.Class.isPrototype=function(){};OpenLayers.Class.create=function(){return function(){if(arguments&&arguments[0]!=OpenLayers.Class.isPrototype){this.initialize.apply(this,arguments);}};};OpenLayers.Class.inherit=function(){var superClass=arguments[0];var proto=new superClass(OpenLayers.Class.isPrototype);for(var i=1,len=arguments.length;i<len;i++){if(typeof arguments[i]=="function"){var mixin=arguments[i];arguments[i]=new mixin(OpenLayers.Class.isPrototype);}
59353 OpenLayers.Util.extend(proto,arguments[i]);}
59354 return proto;};OpenLayers.Util={};OpenLayers.Util.getElement=function(){var elements=[];for(var i=0,len=arguments.length;i<len;i++){var element=arguments[i];if(typeof element=='string'){element=document.getElementById(element);}
59355 if(arguments.length==1){return element;}
59356 elements.push(element);}
59357 return elements;};OpenLayers.Util.isElement=function(o){return!!(o&&o.nodeType===1);};if(typeof window.$==="undefined"){window.$=OpenLayers.Util.getElement;}
59358 OpenLayers.Util.extend=function(destination,source){destination=destination||{};if(source){for(var property in source){var value=source[property];if(value!==undefined){destination[property]=value;}}
59359 var sourceIsEvt=typeof window.Event=="function"&&source instanceof window.Event;if(!sourceIsEvt&&source.hasOwnProperty&&source.hasOwnProperty('toString')){destination.toString=source.toString;}}
59360 return destination;};OpenLayers.Util.removeItem=function(array,item){for(var i=array.length-1;i>=0;i--){if(array[i]==item){array.splice(i,1);}}
59361 return array;};OpenLayers.Util.clearArray=function(array){OpenLayers.Console.warn(OpenLayers.i18n("methodDeprecated",{'newMethod':'array = []'}));array.length=0;};OpenLayers.Util.indexOf=function(array,obj){if(typeof array.indexOf=="function"){return array.indexOf(obj);}else{for(var i=0,len=array.length;i<len;i++){if(array[i]==obj){return i;}}
59362 return-1;}};OpenLayers.Util.modifyDOMElement=function(element,id,px,sz,position,border,overflow,opacity){if(id){element.id=id;}
59363 if(px){element.style.left=px.x+"px";element.style.top=px.y+"px";}
59364 if(sz){element.style.width=sz.w+"px";element.style.height=sz.h+"px";}
59365 if(position){element.style.position=position;}
59366 if(border){element.style.border=border;}
59367 if(overflow){element.style.overflow=overflow;}
59368 if(parseFloat(opacity)>=0.0&&parseFloat(opacity)<1.0){element.style.filter='alpha(opacity='+(opacity*100)+')';element.style.opacity=opacity;}else if(parseFloat(opacity)==1.0){element.style.filter='';element.style.opacity='';}};OpenLayers.Util.createDiv=function(id,px,sz,imgURL,position,border,overflow,opacity){var dom=document.createElement('div');if(imgURL){dom.style.backgroundImage='url('+imgURL+')';}
59369 if(!id){id=OpenLayers.Util.createUniqueID("OpenLayersDiv");}
59370 if(!position){position="absolute";}
59371 OpenLayers.Util.modifyDOMElement(dom,id,px,sz,position,border,overflow,opacity);return dom;};OpenLayers.Util.createImage=function(id,px,sz,imgURL,position,border,opacity,delayDisplay){var image=document.createElement("img");if(!id){id=OpenLayers.Util.createUniqueID("OpenLayersDiv");}
59372 if(!position){position="relative";}
59373 OpenLayers.Util.modifyDOMElement(image,id,px,sz,position,border,null,opacity);if(delayDisplay){image.style.display="none";OpenLayers.Event.observe(image,"load",OpenLayers.Function.bind(OpenLayers.Util.onImageLoad,image));OpenLayers.Event.observe(image,"error",OpenLayers.Function.bind(OpenLayers.Util.onImageLoadError,image));}
59374 image.style.alt=id;image.galleryImg="no";if(imgURL){image.src=imgURL;}
59375 return image;};OpenLayers.Util.setOpacity=function(element,opacity){OpenLayers.Util.modifyDOMElement(element,null,null,null,null,null,null,opacity);};OpenLayers.Util.onImageLoad=function(){if(!this.viewRequestID||(this.map&&this.viewRequestID==this.map.viewRequestID)){this.style.display="";}
59376 OpenLayers.Element.removeClass(this,"olImageLoadError");};OpenLayers.IMAGE_RELOAD_ATTEMPTS=0;OpenLayers.Util.onImageLoadError=function(){this._attempts=(this._attempts)?(this._attempts+1):1;if(this._attempts<=OpenLayers.IMAGE_RELOAD_ATTEMPTS){var urls=this.urls;if(urls&&urls instanceof Array&&urls.length>1){var src=this.src.toString();var current_url,k;for(k=0;current_url=urls[k];k++){if(src.indexOf(current_url)!=-1){break;}}
59377 var guess=Math.floor(urls.length*Math.random());var new_url=urls[guess];k=0;while(new_url==current_url&&k++<4){guess=Math.floor(urls.length*Math.random());new_url=urls[guess];}
59378 this.src=src.replace(current_url,new_url);}else{this.src=this.src;}}else{OpenLayers.Element.addClass(this,"olImageLoadError");}
59379 this.style.display="";};OpenLayers.Util.alphaHackNeeded=null;OpenLayers.Util.alphaHack=function(){if(OpenLayers.Util.alphaHackNeeded==null){var arVersion=navigator.appVersion.split("MSIE");var version=parseFloat(arVersion[1]);var filter=false;try{filter=!!(document.body.filters);}catch(e){}
59380 OpenLayers.Util.alphaHackNeeded=(filter&&(version>=5.5)&&(version<7));}
59381 return OpenLayers.Util.alphaHackNeeded;};OpenLayers.Util.modifyAlphaImageDiv=function(div,id,px,sz,imgURL,position,border,sizing,opacity){OpenLayers.Util.modifyDOMElement(div,id,px,sz,position,null,null,opacity);var img=div.childNodes[0];if(imgURL){img.src=imgURL;}
59382 OpenLayers.Util.modifyDOMElement(img,div.id+"_innerImage",null,sz,"relative",border);if(OpenLayers.Util.alphaHack()){if(div.style.display!="none"){div.style.display="inline-block";}
59383 if(sizing==null){sizing="scale";}
59384 div.style.filter="progid:DXImageTransform.Microsoft"+".AlphaImageLoader(src='"+img.src+"', "+"sizingMethod='"+sizing+"')";if(parseFloat(div.style.opacity)>=0.0&&parseFloat(div.style.opacity)<1.0){div.style.filter+=" alpha(opacity="+div.style.opacity*100+")";}
59385 img.style.filter="alpha(opacity=0)";}};OpenLayers.Util.createAlphaImageDiv=function(id,px,sz,imgURL,position,border,sizing,opacity,delayDisplay){var div=OpenLayers.Util.createDiv();var img=OpenLayers.Util.createImage(null,null,null,null,null,null,null,false);div.appendChild(img);if(delayDisplay){img.style.display="none";OpenLayers.Event.observe(img,"load",OpenLayers.Function.bind(OpenLayers.Util.onImageLoad,div));OpenLayers.Event.observe(img,"error",OpenLayers.Function.bind(OpenLayers.Util.onImageLoadError,div));}
59386 OpenLayers.Util.modifyAlphaImageDiv(div,id,px,sz,imgURL,position,border,sizing,opacity);return div;};OpenLayers.Util.upperCaseObject=function(object){var uObject={};for(var key in object){uObject[key.toUpperCase()]=object[key];}
59387 return uObject;};OpenLayers.Util.applyDefaults=function(to,from){to=to||{};var fromIsEvt=typeof window.Event=="function"&&from instanceof window.Event;for(var key in from){if(to[key]===undefined||(!fromIsEvt&&from.hasOwnProperty&&from.hasOwnProperty(key)&&!to.hasOwnProperty(key))){to[key]=from[key];}}
59388 if(!fromIsEvt&&from&&from.hasOwnProperty&&from.hasOwnProperty('toString')&&!to.hasOwnProperty('toString')){to.toString=from.toString;}
59389 return to;};OpenLayers.Util.getParameterString=function(params){var paramsArray=[];for(var key in params){var value=params[key];if((value!=null)&&(typeof value!='function')){var encodedValue;if(typeof value=='object'&&value.constructor==Array){var encodedItemArray=[];var item;for(var itemIndex=0,len=value.length;itemIndex<len;itemIndex++){item=value[itemIndex];encodedItemArray.push(encodeURIComponent((item===null||item===undefined)?"":item));}
59390 encodedValue=encodedItemArray.join(",");}
59391 else{encodedValue=encodeURIComponent(value);}
59392 paramsArray.push(encodeURIComponent(key)+"="+encodedValue);}}
59393 return paramsArray.join("&");};OpenLayers.Util.urlAppend=function(url,paramStr){var newUrl=url;if(paramStr){var parts=(url+" ").split(/[?&]/);newUrl+=(parts.pop()===" "?paramStr:parts.length?"&"+paramStr:"?"+paramStr);}
59394 return newUrl;};OpenLayers.ImgPath='';OpenLayers.Util.getImagesLocation=function(){return OpenLayers.ImgPath||(OpenLayers._getScriptLocation()+"img/");};OpenLayers.Util.Try=function(){var returnValue=null;for(var i=0,len=arguments.length;i<len;i++){var lambda=arguments[i];try{returnValue=lambda();break;}catch(e){}}
59395 return returnValue;};OpenLayers.Util.getNodes=function(p,tagName){var nodes=OpenLayers.Util.Try(function(){return OpenLayers.Util._getNodes(p.documentElement.childNodes,tagName);},function(){return OpenLayers.Util._getNodes(p.childNodes,tagName);});return nodes;};OpenLayers.Util._getNodes=function(nodes,tagName){var retArray=[];for(var i=0,len=nodes.length;i<len;i++){if(nodes[i].nodeName==tagName){retArray.push(nodes[i]);}}
59396 return retArray;};OpenLayers.Util.getTagText=function(parent,item,index){var result=OpenLayers.Util.getNodes(parent,item);if(result&&(result.length>0))
59397 {if(!index){index=0;}
59398 if(result[index].childNodes.length>1){return result.childNodes[1].nodeValue;}
59399 else if(result[index].childNodes.length==1){return result[index].firstChild.nodeValue;}}else{return"";}};OpenLayers.Util.getXmlNodeValue=function(node){var val=null;OpenLayers.Util.Try(function(){val=node.text;if(!val){val=node.textContent;}
59400 if(!val){val=node.firstChild.nodeValue;}},function(){val=node.textContent;});return val;};OpenLayers.Util.mouseLeft=function(evt,div){var target=(evt.relatedTarget)?evt.relatedTarget:evt.toElement;while(target!=div&&target!=null){target=target.parentNode;}
59401 return(target!=div);};OpenLayers.Util.DEFAULT_PRECISION=14;OpenLayers.Util.toFloat=function(number,precision){if(precision==null){precision=OpenLayers.Util.DEFAULT_PRECISION;}
59402 var number;if(precision==0){number=parseFloat(number);}else{number=parseFloat(parseFloat(number).toPrecision(precision));}
59403 return number;};OpenLayers.Util.rad=function(x){return x*Math.PI/180;};OpenLayers.Util.deg=function(x){return x*180/Math.PI;};OpenLayers.Util.VincentyConstants={a:6378137,b:6356752.3142,f:1/298.257223563};OpenLayers.Util.distVincenty=function(p1,p2){var ct=OpenLayers.Util.VincentyConstants;var a=ct.a,b=ct.b,f=ct.f;var L=OpenLayers.Util.rad(p2.lon-p1.lon);var U1=Math.atan((1-f)*Math.tan(OpenLayers.Util.rad(p1.lat)));var U2=Math.atan((1-f)*Math.tan(OpenLayers.Util.rad(p2.lat)));var sinU1=Math.sin(U1),cosU1=Math.cos(U1);var sinU2=Math.sin(U2),cosU2=Math.cos(U2);var lambda=L,lambdaP=2*Math.PI;var iterLimit=20;while(Math.abs(lambda-lambdaP)>1e-12&&--iterLimit>0){var sinLambda=Math.sin(lambda),cosLambda=Math.cos(lambda);var sinSigma=Math.sqrt((cosU2*sinLambda)*(cosU2*sinLambda)+
59404 (cosU1*sinU2-sinU1*cosU2*cosLambda)*(cosU1*sinU2-sinU1*cosU2*cosLambda));if(sinSigma==0){return 0;}
59405 var cosSigma=sinU1*sinU2+cosU1*cosU2*cosLambda;var sigma=Math.atan2(sinSigma,cosSigma);var alpha=Math.asin(cosU1*cosU2*sinLambda/sinSigma);var cosSqAlpha=Math.cos(alpha)*Math.cos(alpha);var cos2SigmaM=cosSigma-2*sinU1*sinU2/cosSqAlpha;var C=f/16*cosSqAlpha*(4+f*(4-3*cosSqAlpha));lambdaP=lambda;lambda=L+(1-C)*f*Math.sin(alpha)*(sigma+C*sinSigma*(cos2SigmaM+C*cosSigma*(-1+2*cos2SigmaM*cos2SigmaM)));}
59406 if(iterLimit==0){return NaN;}
59407 var uSq=cosSqAlpha*(a*a-b*b)/(b*b);var A=1+uSq/16384*(4096+uSq*(-768+uSq*(320-175*uSq)));var B=uSq/1024*(256+uSq*(-128+uSq*(74-47*uSq)));var deltaSigma=B*sinSigma*(cos2SigmaM+B/4*(cosSigma*(-1+2*cos2SigmaM*cos2SigmaM)-
59408 B/6*cos2SigmaM*(-3+4*sinSigma*sinSigma)*(-3+4*cos2SigmaM*cos2SigmaM)));var s=b*A*(sigma-deltaSigma);var d=s.toFixed(3)/1000;return d;};OpenLayers.Util.destinationVincenty=function(lonlat,brng,dist){var u=OpenLayers.Util;var ct=u.VincentyConstants;var a=ct.a,b=ct.b,f=ct.f;var lon1=lonlat.lon;var lat1=lonlat.lat;var s=dist;var alpha1=u.rad(brng);var sinAlpha1=Math.sin(alpha1);var cosAlpha1=Math.cos(alpha1);var tanU1=(1-f)*Math.tan(u.rad(lat1));var cosU1=1/Math.sqrt((1+tanU1*tanU1)),sinU1=tanU1*cosU1;var sigma1=Math.atan2(tanU1,cosAlpha1);var sinAlpha=cosU1*sinAlpha1;var cosSqAlpha=1-sinAlpha*sinAlpha;var uSq=cosSqAlpha*(a*a-b*b)/(b*b);var A=1+uSq/16384*(4096+uSq*(-768+uSq*(320-175*uSq)));var B=uSq/1024*(256+uSq*(-128+uSq*(74-47*uSq)));var sigma=s/(b*A),sigmaP=2*Math.PI;while(Math.abs(sigma-sigmaP)>1e-12){var cos2SigmaM=Math.cos(2*sigma1+sigma);var sinSigma=Math.sin(sigma);var cosSigma=Math.cos(sigma);var deltaSigma=B*sinSigma*(cos2SigmaM+B/4*(cosSigma*(-1+2*cos2SigmaM*cos2SigmaM)-
59409 B/6*cos2SigmaM*(-3+4*sinSigma*sinSigma)*(-3+4*cos2SigmaM*cos2SigmaM)));sigmaP=sigma;sigma=s/(b*A)+deltaSigma;}
59410 var tmp=sinU1*sinSigma-cosU1*cosSigma*cosAlpha1;var lat2=Math.atan2(sinU1*cosSigma+cosU1*sinSigma*cosAlpha1,(1-f)*Math.sqrt(sinAlpha*sinAlpha+tmp*tmp));var lambda=Math.atan2(sinSigma*sinAlpha1,cosU1*cosSigma-sinU1*sinSigma*cosAlpha1);var C=f/16*cosSqAlpha*(4+f*(4-3*cosSqAlpha));var L=lambda-(1-C)*f*sinAlpha*(sigma+C*sinSigma*(cos2SigmaM+C*cosSigma*(-1+2*cos2SigmaM*cos2SigmaM)));var revAz=Math.atan2(sinAlpha,-tmp);return new OpenLayers.LonLat(lon1+u.deg(L),u.deg(lat2));};OpenLayers.Util.getParameters=function(url){url=url||window.location.href;var paramsString="";if(OpenLayers.String.contains(url,'?')){var start=url.indexOf('?')+1;var end=OpenLayers.String.contains(url,"#")?url.indexOf('#'):url.length;paramsString=url.substring(start,end);}
59411 var parameters={};var pairs=paramsString.split(/[&;]/);for(var i=0,len=pairs.length;i<len;++i){var keyValue=pairs[i].split('=');if(keyValue[0]){var key=decodeURIComponent(keyValue[0]);var value=keyValue[1]||'';value=decodeURIComponent(value.replace(/\+/g," ")).split(",");if(value.length==1){value=value[0];}
59412 parameters[key]=value;}}
59413 return parameters;};OpenLayers.Util.getArgs=function(url){OpenLayers.Console.warn(OpenLayers.i18n("methodDeprecated",{'newMethod':'OpenLayers.Util.getParameters'}));return OpenLayers.Util.getParameters(url);};OpenLayers.Util.lastSeqID=0;OpenLayers.Util.createUniqueID=function(prefix){if(prefix==null){prefix="id_";}
59414 OpenLayers.Util.lastSeqID+=1;return prefix+OpenLayers.Util.lastSeqID;};OpenLayers.INCHES_PER_UNIT={'inches':1.0,'ft':12.0,'mi':63360.0,'m':39.3701,'km':39370.1,'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;OpenLayers.METERS_PER_INCH=0.02540005080010160020;OpenLayers.Util.extend(OpenLayers.INCHES_PER_UNIT,{"Inch":OpenLayers.INCHES_PER_UNIT.inches,"Meter":1.0/OpenLayers.METERS_PER_INCH,"Foot":0.30480060960121920243/OpenLayers.METERS_PER_INCH,"IFoot":0.30480000000000000000/OpenLayers.METERS_PER_INCH,"ClarkeFoot":0.3047972651151/OpenLayers.METERS_PER_INCH,"SearsFoot":0.30479947153867624624/OpenLayers.METERS_PER_INCH,"GoldCoastFoot":0.30479971018150881758/OpenLayers.METERS_PER_INCH,"IInch":0.02540000000000000000/OpenLayers.METERS_PER_INCH,"MicroInch":0.00002540000000000000/OpenLayers.METERS_PER_INCH,"Mil":0.00000002540000000000/OpenLayers.METERS_PER_INCH,"Centimeter":0.01000000000000000000/OpenLayers.METERS_PER_INCH,"Kilometer":1000.00000000000000000000/OpenLayers.METERS_PER_INCH,"Yard":0.91440182880365760731/OpenLayers.METERS_PER_INCH,"SearsYard":0.914398414616029/OpenLayers.METERS_PER_INCH,"IndianYard":0.91439853074444079983/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/OpenLayers.METERS_PER_INCH,"IndianFt75":0.3047995/OpenLayers.METERS_PER_INCH,"Mile":1609.34721869443738887477/OpenLayers.METERS_PER_INCH,"IYard":0.91440000000000000000/OpenLayers.METERS_PER_INCH,"IMile":1609.34400000000000000000/OpenLayers.METERS_PER_INCH,"NautM":1852.00000000000000000000/OpenLayers.METERS_PER_INCH,"Lat-66":110943.316488932731/OpenLayers.METERS_PER_INCH,"Lat-83":110946.25736872234125/OpenLayers.METERS_PER_INCH,"Decimeter":0.10000000000000000000/OpenLayers.METERS_PER_INCH,"Millimeter":0.00100000000000000000/OpenLayers.METERS_PER_INCH,"Dekameter":10.00000000000000000000/OpenLayers.METERS_PER_INCH,"Decameter":10.00000000000000000000/OpenLayers.METERS_PER_INCH,"Hectometer":100.00000000000000000000/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.20116782494375872/OpenLayers.METERS_PER_INCH,"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.00000000000000000000/OpenLayers.METERS_PER_INCH,"ModAmFt":0.304812252984505969011938/OpenLayers.METERS_PER_INCH,"Fathom":1.8288/OpenLayers.METERS_PER_INCH,"NautM-UK":1853.184/OpenLayers.METERS_PER_INCH,"50kilometers":50000.0/OpenLayers.METERS_PER_INCH,"150kilometers":150000.0/OpenLayers.METERS_PER_INCH});OpenLayers.Util.extend(OpenLayers.INCHES_PER_UNIT,{"mm":OpenLayers.INCHES_PER_UNIT["Meter"]/1000.0,"cm":OpenLayers.INCHES_PER_UNIT["Meter"]/100.0,"dm":OpenLayers.INCHES_PER_UNIT["Meter"]*100.0,"km":OpenLayers.INCHES_PER_UNIT["Meter"]*1000.0,"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"],"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(scale){var normScale=(scale>1.0)?(1.0/scale):scale;return normScale;};OpenLayers.Util.getResolutionFromScale=function(scale,units){var resolution;if(scale){if(units==null){units="degrees";}
59415 var normScale=OpenLayers.Util.normalizeScale(scale);resolution=1/(normScale*OpenLayers.INCHES_PER_UNIT[units]*OpenLayers.DOTS_PER_INCH);}
59416 return resolution;};OpenLayers.Util.getScaleFromResolution=function(resolution,units){if(units==null){units="degrees";}
59417 var scale=resolution*OpenLayers.INCHES_PER_UNIT[units]*OpenLayers.DOTS_PER_INCH;return scale;};OpenLayers.Util.safeStopPropagation=function(evt){OpenLayers.Event.stop(evt,true);};OpenLayers.Util.pagePosition=function(forElement){var valueT=0,valueL=0;var element=forElement;var child=forElement;while(element){if(element==document.body){if(OpenLayers.Element.getStyle(child,'position')=='absolute'){break;}}
59418 valueT+=element.offsetTop||0;valueL+=element.offsetLeft||0;child=element;try{element=element.offsetParent;}catch(e){OpenLayers.Console.error(OpenLayers.i18n("pagePositionFailed",{'elemId':element.id}));break;}}
59419 element=forElement;while(element){valueT-=element.scrollTop||0;valueL-=element.scrollLeft||0;element=element.parentNode;}
59420 return[valueL,valueT];};OpenLayers.Util.isEquivalentUrl=function(url1,url2,options){options=options||{};OpenLayers.Util.applyDefaults(options,{ignoreCase:true,ignorePort80:true,ignoreHash:true});var urlObj1=OpenLayers.Util.createUrlObject(url1,options);var urlObj2=OpenLayers.Util.createUrlObject(url2,options);for(var key in urlObj1){if(key!=="args"){if(urlObj1[key]!=urlObj2[key]){return false;}}}
59421 for(var key in urlObj1.args){if(urlObj1.args[key]!=urlObj2.args[key]){return false;}
59422 delete urlObj2.args[key];}
59423 for(var key in urlObj2.args){return false;}
59424 return true;};OpenLayers.Util.createUrlObject=function(url,options){options=options||{};if(!(/^\w+:\/\//).test(url)){var loc=window.location;var port=loc.port?":"+loc.port:"";var fullUrl=loc.protocol+"//"+loc.host.split(":").shift()+port;if(url.indexOf("/")===0){url=fullUrl+url;}else{var parts=loc.pathname.split("/");parts.pop();url=fullUrl+parts.join("/")+"/"+url;}}
59425 if(options.ignoreCase){url=url.toLowerCase();}
59426 var a=document.createElement('a');a.href=url;var urlObject={};urlObject.host=a.host.split(":").shift();urlObject.protocol=a.protocol;if(options.ignorePort80){urlObject.port=(a.port=="80"||a.port=="0")?"":a.port;}else{urlObject.port=(a.port==""||a.port=="0")?"80":a.port;}
59427 urlObject.hash=(options.ignoreHash||a.hash==="#")?"":a.hash;var queryString=a.search;if(!queryString){var qMark=url.indexOf("?");queryString=(qMark!=-1)?url.substr(qMark):"";}
59428 urlObject.args=OpenLayers.Util.getParameters(queryString);urlObject.pathname=(a.pathname.charAt(0)=="/")?a.pathname:"/"+a.pathname;return urlObject;};OpenLayers.Util.removeTail=function(url){var head=null;var qMark=url.indexOf("?");var hashMark=url.indexOf("#");if(qMark==-1){head=(hashMark!=-1)?url.substr(0,hashMark):url;}else{head=(hashMark!=-1)?url.substr(0,Math.min(qMark,hashMark)):url.substr(0,qMark);}
59429 return head;};OpenLayers.Util.getBrowserName=function(){var browserName="";var ua=navigator.userAgent.toLowerCase();if(ua.indexOf("opera")!=-1){browserName="opera";}else if(ua.indexOf("msie")!=-1){browserName="msie";}else if(ua.indexOf("safari")!=-1){browserName="safari";}else if(ua.indexOf("mozilla")!=-1){if(ua.indexOf("firefox")!=-1){browserName="firefox";}else{browserName="mozilla";}}
59430 return browserName;};OpenLayers.Util.getRenderedDimensions=function(contentHTML,size,options){var w,h;var container=document.createElement("div");container.style.visibility="hidden";var containerElement=(options&&options.containerElement)?options.containerElement:document.body;if(size){if(size.w){w=size.w;container.style.width=w+"px";}else if(size.h){h=size.h;container.style.height=h+"px";}}
59431 if(options&&options.displayClass){container.className=options.displayClass;}
59432 var content=document.createElement("div");content.innerHTML=contentHTML;content.style.overflow="visible";if(content.childNodes){for(var i=0,l=content.childNodes.length;i<l;i++){if(!content.childNodes[i].style)continue;content.childNodes[i].style.overflow="visible";}}
59433 container.appendChild(content);containerElement.appendChild(container);var parentHasPositionAbsolute=false;var parent=container.parentNode;while(parent&&parent.tagName.toLowerCase()!="body"){var parentPosition=OpenLayers.Element.getStyle(parent,"position");if(parentPosition=="absolute"){parentHasPositionAbsolute=true;break;}else if(parentPosition&&parentPosition!="static"){break;}
59434 parent=parent.parentNode;}
59435 if(!parentHasPositionAbsolute){container.style.position="absolute";}
59436 if(!w){w=parseInt(content.scrollWidth);container.style.width=w+"px";}
59437 if(!h){h=parseInt(content.scrollHeight);}
59438 container.removeChild(content);containerElement.removeChild(container);return new OpenLayers.Size(w,h);};OpenLayers.Util.getScrollbarWidth=function(){var scrollbarWidth=OpenLayers.Util._scrollbarWidth;if(scrollbarWidth==null){var scr=null;var inn=null;var wNoScroll=0;var wScroll=0;scr=document.createElement('div');scr.style.position='absolute';scr.style.top='-1000px';scr.style.left='-1000px';scr.style.width='100px';scr.style.height='50px';scr.style.overflow='hidden';inn=document.createElement('div');inn.style.width='100%';inn.style.height='200px';scr.appendChild(inn);document.body.appendChild(scr);wNoScroll=inn.offsetWidth;scr.style.overflow='scroll';wScroll=inn.offsetWidth;document.body.removeChild(document.body.lastChild);OpenLayers.Util._scrollbarWidth=(wNoScroll-wScroll);scrollbarWidth=OpenLayers.Util._scrollbarWidth;}
59439 return scrollbarWidth;};OpenLayers.Util.getFormattedLonLat=function(coordinate,axis,dmsOption){if(!dmsOption){dmsOption='dms';}
59440 var abscoordinate=Math.abs(coordinate)
59441 var coordinatedegrees=Math.floor(abscoordinate);var coordinateminutes=(abscoordinate-coordinatedegrees)/(1/60);var tempcoordinateminutes=coordinateminutes;coordinateminutes=Math.floor(coordinateminutes);var coordinateseconds=(tempcoordinateminutes-coordinateminutes)/(1/60);coordinateseconds=Math.round(coordinateseconds*10);coordinateseconds/=10;if(coordinatedegrees<10){coordinatedegrees="0"+coordinatedegrees;}
59442 var str=coordinatedegrees+"\u00B0";if(dmsOption.indexOf('dm')>=0){if(coordinateminutes<10){coordinateminutes="0"+coordinateminutes;}
59443 str+=coordinateminutes+"'";if(dmsOption.indexOf('dms')>=0){if(coordinateseconds<10){coordinateseconds="0"+coordinateseconds;}
59444 str+=coordinateseconds+'"';}}
59445 if(axis=="lon"){str+=coordinate<0?OpenLayers.i18n("W"):OpenLayers.i18n("E");}else{str+=coordinate<0?OpenLayers.i18n("S"):OpenLayers.i18n("N");}
59446 return str;};OpenLayers.Rico=new Object();OpenLayers.Rico.Corner={round:function(e,options){e=OpenLayers.Util.getElement(e);this._setOptions(options);var color=this.options.color;if(this.options.color=="fromElement"){color=this._background(e);}
59447 var bgColor=this.options.bgColor;if(this.options.bgColor=="fromParent"){bgColor=this._background(e.offsetParent);}
59448 this._roundCornersImpl(e,color,bgColor);},changeColor:function(theDiv,newColor){theDiv.style.backgroundColor=newColor;var spanElements=theDiv.parentNode.getElementsByTagName("span");for(var currIdx=0;currIdx<spanElements.length;currIdx++){spanElements[currIdx].style.backgroundColor=newColor;}},changeOpacity:function(theDiv,newOpacity){var mozillaOpacity=newOpacity;var ieOpacity='alpha(opacity='+newOpacity*100+')';theDiv.style.opacity=mozillaOpacity;theDiv.style.filter=ieOpacity;var spanElements=theDiv.parentNode.getElementsByTagName("span");for(var currIdx=0;currIdx<spanElements.length;currIdx++){spanElements[currIdx].style.opacity=mozillaOpacity;spanElements[currIdx].style.filter=ieOpacity;}},reRound:function(theDiv,options){var topRico=theDiv.parentNode.childNodes[0];var bottomRico=theDiv.parentNode.childNodes[2];theDiv.parentNode.removeChild(topRico);theDiv.parentNode.removeChild(bottomRico);this.round(theDiv.parentNode,options);},_roundCornersImpl:function(e,color,bgColor){if(this.options.border){this._renderBorder(e,bgColor);}
59449 if(this._isTopRounded()){this._roundTopCorners(e,color,bgColor);}
59450 if(this._isBottomRounded()){this._roundBottomCorners(e,color,bgColor);}},_renderBorder:function(el,bgColor){var borderValue="1px solid "+this._borderColor(bgColor);var borderL="border-left: "+borderValue;var borderR="border-right: "+borderValue;var style="style='"+borderL+";"+borderR+"'";el.innerHTML="<div "+style+">"+el.innerHTML+"</div>";},_roundTopCorners:function(el,color,bgColor){var corner=this._createCorner(bgColor);for(var i=0;i<this.options.numSlices;i++){corner.appendChild(this._createCornerSlice(color,bgColor,i,"top"));}
59451 el.style.paddingTop=0;el.insertBefore(corner,el.firstChild);},_roundBottomCorners:function(el,color,bgColor){var corner=this._createCorner(bgColor);for(var i=(this.options.numSlices-1);i>=0;i--){corner.appendChild(this._createCornerSlice(color,bgColor,i,"bottom"));}
59452 el.style.paddingBottom=0;el.appendChild(corner);},_createCorner:function(bgColor){var corner=document.createElement("div");corner.style.backgroundColor=(this._isTransparent()?"transparent":bgColor);return corner;},_createCornerSlice:function(color,bgColor,n,position){var slice=document.createElement("span");var inStyle=slice.style;inStyle.backgroundColor=color;inStyle.display="block";inStyle.height="1px";inStyle.overflow="hidden";inStyle.fontSize="1px";var borderColor=this._borderColor(color,bgColor);if(this.options.border&&n==0){inStyle.borderTopStyle="solid";inStyle.borderTopWidth="1px";inStyle.borderLeftWidth="0px";inStyle.borderRightWidth="0px";inStyle.borderBottomWidth="0px";inStyle.height="0px";inStyle.borderColor=borderColor;}
59453 else if(borderColor){inStyle.borderColor=borderColor;inStyle.borderStyle="solid";inStyle.borderWidth="0px 1px";}
59454 if(!this.options.compact&&(n==(this.options.numSlices-1))){inStyle.height="2px";}
59455 this._setMargin(slice,n,position);this._setBorder(slice,n,position);return slice;},_setOptions:function(options){this.options={corners:"all",color:"fromElement",bgColor:"fromParent",blend:true,border:false,compact:false};OpenLayers.Util.extend(this.options,options||{});this.options.numSlices=this.options.compact?2:4;if(this._isTransparent()){this.options.blend=false;}},_whichSideTop:function(){if(this._hasString(this.options.corners,"all","top")){return"";}
59456 if(this.options.corners.indexOf("tl")>=0&&this.options.corners.indexOf("tr")>=0){return"";}
59457 if(this.options.corners.indexOf("tl")>=0){return"left";}else if(this.options.corners.indexOf("tr")>=0){return"right";}
59458 return"";},_whichSideBottom:function(){if(this._hasString(this.options.corners,"all","bottom")){return"";}
59459 if(this.options.corners.indexOf("bl")>=0&&this.options.corners.indexOf("br")>=0){return"";}
59460 if(this.options.corners.indexOf("bl")>=0){return"left";}else if(this.options.corners.indexOf("br")>=0){return"right";}
59461 return"";},_borderColor:function(color,bgColor){if(color=="transparent"){return bgColor;}else if(this.options.border){return this.options.border;}else if(this.options.blend){return this._blend(bgColor,color);}else{return"";}},_setMargin:function(el,n,corners){var marginSize=this._marginSize(n);var whichSide=corners=="top"?this._whichSideTop():this._whichSideBottom();if(whichSide=="left"){el.style.marginLeft=marginSize+"px";el.style.marginRight="0px";}
59462 else if(whichSide=="right"){el.style.marginRight=marginSize+"px";el.style.marginLeft="0px";}
59463 else{el.style.marginLeft=marginSize+"px";el.style.marginRight=marginSize+"px";}},_setBorder:function(el,n,corners){var borderSize=this._borderSize(n);var whichSide=corners=="top"?this._whichSideTop():this._whichSideBottom();if(whichSide=="left"){el.style.borderLeftWidth=borderSize+"px";el.style.borderRightWidth="0px";}
59464 else if(whichSide=="right"){el.style.borderRightWidth=borderSize+"px";el.style.borderLeftWidth="0px";}
59465 else{el.style.borderLeftWidth=borderSize+"px";el.style.borderRightWidth=borderSize+"px";}
59466 if(this.options.border!=false){el.style.borderLeftWidth=borderSize+"px";el.style.borderRightWidth=borderSize+"px";}},_marginSize:function(n){if(this._isTransparent()){return 0;}
59467 var marginSizes=[5,3,2,1];var blendedMarginSizes=[3,2,1,0];var compactMarginSizes=[2,1];var smBlendedMarginSizes=[1,0];if(this.options.compact&&this.options.blend){return smBlendedMarginSizes[n];}else if(this.options.compact){return compactMarginSizes[n];}else if(this.options.blend){return blendedMarginSizes[n];}else{return marginSizes[n];}},_borderSize:function(n){var transparentBorderSizes=[5,3,2,1];var blendedBorderSizes=[2,1,1,1];var compactBorderSizes=[1,0];var actualBorderSizes=[0,2,0,0];if(this.options.compact&&(this.options.blend||this._isTransparent())){return 1;}else if(this.options.compact){return compactBorderSizes[n];}else if(this.options.blend){return blendedBorderSizes[n];}else if(this.options.border){return actualBorderSizes[n];}else if(this._isTransparent()){return transparentBorderSizes[n];}
59468 return 0;},_hasString:function(str){for(var i=1;i<arguments.length;i++)if(str.indexOf(arguments[i])>=0){return true;}return false;},_blend:function(c1,c2){var cc1=OpenLayers.Rico.Color.createFromHex(c1);cc1.blend(OpenLayers.Rico.Color.createFromHex(c2));return cc1;},_background:function(el){try{return OpenLayers.Rico.Color.createColorFromBackground(el).asHex();}catch(err){return"#ffffff";}},_isTransparent:function(){return this.options.color=="transparent";},_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(el){return el.childNodes.length==1&&el.childNodes[0].nodeType==3;}};(function(){if(window.google&&google.gears){return;}
59469 var factory=null;if(typeof GearsFactory!='undefined'){factory=new GearsFactory();}else{try{factory=new ActiveXObject('Gears.Factory');if(factory.getBuildInfo().indexOf('ie_mobile')!=-1){factory.privateSetGlobalObject(this);}}catch(e){if((typeof navigator.mimeTypes!='undefined')&&navigator.mimeTypes["application/x-googlegears"]){factory=document.createElement("object");factory.style.display="none";factory.width=0;factory.height=0;factory.type="application/x-googlegears";document.documentElement.appendChild(factory);}}}
59470 if(!factory){return;}
59471 if(!window.google){google={};}
59472 if(!google.gears){google.gears={factory:factory};}})();OpenLayers.Element={visible:function(element){return OpenLayers.Util.getElement(element).style.display!='none';},toggle:function(){for(var i=0,len=arguments.length;i<len;i++){var element=OpenLayers.Util.getElement(arguments[i]);var display=OpenLayers.Element.visible(element)?'hide':'show';OpenLayers.Element[display](element);}},hide:function(){for(var i=0,len=arguments.length;i<len;i++){var element=OpenLayers.Util.getElement(arguments[i]);if(element){element.style.display='none';}}},show:function(){for(var i=0,len=arguments.length;i<len;i++){var element=OpenLayers.Util.getElement(arguments[i]);if(element){element.style.display='';}}},remove:function(element){element=OpenLayers.Util.getElement(element);element.parentNode.removeChild(element);},getHeight:function(element){element=OpenLayers.Util.getElement(element);return element.offsetHeight;},getDimensions:function(element){element=OpenLayers.Util.getElement(element);if(OpenLayers.Element.getStyle(element,'display')!='none'){return{width:element.offsetWidth,height:element.offsetHeight};}
59473 var els=element.style;var originalVisibility=els.visibility;var originalPosition=els.position;var originalDisplay=els.display;els.visibility='hidden';els.position='absolute';els.display='';var originalWidth=element.clientWidth;var originalHeight=element.clientHeight;els.display=originalDisplay;els.position=originalPosition;els.visibility=originalVisibility;return{width:originalWidth,height:originalHeight};},hasClass:function(element,name){var names=element.className;return(!!names&&new RegExp("(^|\\s)"+name+"(\\s|$)").test(names));},addClass:function(element,name){if(!OpenLayers.Element.hasClass(element,name)){element.className+=(element.className?" ":"")+name;}
59474 return element;},removeClass:function(element,name){var names=element.className;if(names){element.className=OpenLayers.String.trim(names.replace(new RegExp("(^|\\s+)"+name+"(\\s+|$)")," "));}
59475 return element;},toggleClass:function(element,name){if(OpenLayers.Element.hasClass(element,name)){OpenLayers.Element.removeClass(element,name);}else{OpenLayers.Element.addClass(element,name);}
59476 return element;},getStyle:function(element,style){element=OpenLayers.Util.getElement(element);var value=null;if(element&&element.style){value=element.style[OpenLayers.String.camelize(style)];if(!value){if(document.defaultView&&document.defaultView.getComputedStyle){var css=document.defaultView.getComputedStyle(element,null);value=css?css.getPropertyValue(style):null;}else if(element.currentStyle){value=element.currentStyle[OpenLayers.String.camelize(style)];}}
59477 var positions=['left','top','right','bottom'];if(window.opera&&(OpenLayers.Util.indexOf(positions,style)!=-1)&&(OpenLayers.Element.getStyle(element,'position')=='static')){value='auto';}}
59478 return value=='auto'?null:value;}};OpenLayers.Size=OpenLayers.Class({w:0.0,h:0.0,initialize:function(w,h){this.w=parseFloat(w);this.h=parseFloat(h);},toString:function(){return("w="+this.w+",h="+this.h);},clone:function(){return new OpenLayers.Size(this.w,this.h);},equals:function(sz){var equals=false;if(sz!=null){equals=((this.w==sz.w&&this.h==sz.h)||(isNaN(this.w)&&isNaN(this.h)&&isNaN(sz.w)&&isNaN(sz.h)));}
59479 return equals;},CLASS_NAME:"OpenLayers.Size"});OpenLayers.Console={log:function(){},debug:function(){},info:function(){},warn:function(){},error:function(){},userError:function(error){alert(error);},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"};(function(){var scripts=document.getElementsByTagName("script");for(var i=0,len=scripts.length;i<len;++i){if(scripts[i].src.indexOf("firebug.js")!=-1){if(console){OpenLayers.Util.extend(OpenLayers.Console,console);break;}}}})();OpenLayers.Icon=OpenLayers.Class({url:null,size:null,offset:null,calculateOffset:null,imageDiv:null,px:null,initialize:function(url,size,offset,calculateOffset){this.url=url;this.size=(size)?size:new OpenLayers.Size(20,20);this.offset=offset?offset:new OpenLayers.Pixel(-(this.size.w/2),-(this.size.h/2));this.calculateOffset=calculateOffset;var id=OpenLayers.Util.createUniqueID("OL_Icon_");this.imageDiv=OpenLayers.Util.createAlphaImageDiv(id);},destroy:function(){this.erase();OpenLayers.Event.stopObservingElement(this.imageDiv.firstChild);this.imageDiv.innerHTML="";this.imageDiv=null;},clone:function(){return new OpenLayers.Icon(this.url,this.size,this.offset,this.calculateOffset);},setSize:function(size){if(size!=null){this.size=size;}
59480 this.draw();},setUrl:function(url){if(url!=null){this.url=url;}
59481 this.draw();},draw:function(px){OpenLayers.Util.modifyAlphaImageDiv(this.imageDiv,null,null,this.size,this.url,"absolute");this.moveTo(px);return this.imageDiv;},erase:function(){if(this.imageDiv!=null&&this.imageDiv.parentNode!=null){OpenLayers.Element.remove(this.imageDiv);}},setOpacity:function(opacity){OpenLayers.Util.modifyAlphaImageDiv(this.imageDiv,null,null,null,null,null,null,null,opacity);},moveTo:function(px){if(px!=null){this.px=px;}
59482 if(this.imageDiv!=null){if(this.px==null){this.display(false);}else{if(this.calculateOffset){this.offset=this.calculateOffset(this.size);}
59483 var offsetPx=this.px.offset(this.offset);OpenLayers.Util.modifyAlphaImageDiv(this.imageDiv,null,offsetPx);}}},display:function(display){this.imageDiv.style.display=(display)?"":"none";},isDrawn:function(){var isDrawn=(this.imageDiv&&this.imageDiv.parentNode&&(this.imageDiv.parentNode.nodeType!=11));return isDrawn;},CLASS_NAME:"OpenLayers.Icon"});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:false,minSize:null,maxSize:null,displayClass:"olPopup",contentDisplayClass:"olPopupContent",padding:0,disableFirefoxOverflowHack:false,fixPadding:function(){if(typeof this.padding=="number"){this.padding=new OpenLayers.Bounds(this.padding,this.padding,this.padding,this.padding);}},panMapIfOutOfView:false,keepInMap:false,closeOnMove:false,map:null,initialize:function(id,lonlat,contentSize,contentHTML,closeBox,closeBoxCallback){if(id==null){id=OpenLayers.Util.createUniqueID(this.CLASS_NAME+"_");}
59484 this.id=id;this.lonlat=lonlat;this.contentSize=(contentSize!=null)?contentSize:new OpenLayers.Size(OpenLayers.Popup.WIDTH,OpenLayers.Popup.HEIGHT);if(contentHTML!=null){this.contentHTML=contentHTML;}
59485 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;var groupDivId=this.id+"_GroupDiv";this.groupDiv=OpenLayers.Util.createDiv(groupDivId,null,null,null,"relative",null,"hidden");var id=this.div.id+"_contentDiv";this.contentDiv=OpenLayers.Util.createDiv(id,null,this.contentSize.clone(),null,"relative");this.contentDiv.className=this.contentDisplayClass;this.groupDiv.appendChild(this.contentDiv);this.div.appendChild(this.groupDiv);if(closeBox){this.addCloseBox(closeBoxCallback);}
59486 this.registerEvents();},destroy:function(){this.id=null;this.lonlat=null;this.size=null;this.contentHTML=null;this.backgroundColor=null;this.opacity=null;this.border=null;if(this.closeOnMove&&this.map){this.map.events.unregister("movestart",this,this.hide);}
59487 this.events.destroy();this.events=null;if(this.closeDiv){OpenLayers.Event.stopObservingElement(this.closeDiv);this.groupDiv.removeChild(this.closeDiv);}
59488 this.closeDiv=null;this.div.removeChild(this.groupDiv);this.groupDiv=null;if(this.map!=null){this.map.removePopup(this);}
59489 this.map=null;this.div=null;this.autoSize=null;this.minSize=null;this.maxSize=null;this.padding=null;this.panMapIfOutOfView=null;},draw:function(px){if(px==null){if((this.lonlat!=null)&&(this.map!=null)){px=this.map.getLayerPxFromLonLat(this.lonlat);}}
59490 if(this.closeOnMove){this.map.events.register("movestart",this,this.hide);}
59491 if(!this.disableFirefoxOverflowHack&&OpenLayers.Util.getBrowserName()=='firefox'){this.map.events.register("movestart",this,function(){var style=document.defaultView.getComputedStyle(this.contentDiv,null);var currentOverflow=style.getPropertyValue("overflow");if(currentOverflow!="hidden"){this.contentDiv._oldOverflow=currentOverflow;this.contentDiv.style.overflow="hidden";}});this.map.events.register("moveend",this,function(){var oldOverflow=this.contentDiv._oldOverflow;if(oldOverflow){this.contentDiv.style.overflow=oldOverflow;this.contentDiv._oldOverflow=null;}});}
59492 this.moveTo(px);if(!this.autoSize&&!this.size){this.setSize(this.contentSize);}
59493 this.setBackgroundColor();this.setOpacity();this.setBorder();this.setContentHTML();if(this.panMapIfOutOfView){this.panIntoView();}
59494 return this.div;},updatePosition:function(){if((this.lonlat)&&(this.map)){var px=this.map.getLayerPxFromLonLat(this.lonlat);if(px){this.moveTo(px);}}},moveTo:function(px){if((px!=null)&&(this.div!=null)){this.div.style.left=px.x+"px";this.div.style.top=px.y+"px";}},visible:function(){return OpenLayers.Element.visible(this.div);},toggle:function(){if(this.visible()){this.hide();}else{this.show();}},show:function(){OpenLayers.Element.show(this.div);if(this.panMapIfOutOfView){this.panIntoView();}},hide:function(){OpenLayers.Element.hide(this.div);},setSize:function(contentSize){this.size=contentSize.clone();var contentDivPadding=this.getContentDivPadding();var wPadding=contentDivPadding.left+contentDivPadding.right;var hPadding=contentDivPadding.top+contentDivPadding.bottom;this.fixPadding();wPadding+=this.padding.left+this.padding.right;hPadding+=this.padding.top+this.padding.bottom;if(this.closeDiv){var closeDivWidth=parseInt(this.closeDiv.style.width);wPadding+=closeDivWidth+contentDivPadding.right;}
59495 this.size.w+=wPadding;this.size.h+=hPadding;if(OpenLayers.Util.getBrowserName()=="msie"){this.contentSize.w+=contentDivPadding.left+contentDivPadding.right;this.contentSize.h+=contentDivPadding.bottom+contentDivPadding.top;}
59496 if(this.div!=null){this.div.style.width=this.size.w+"px";this.div.style.height=this.size.h+"px";}
59497 if(this.contentDiv!=null){this.contentDiv.style.width=contentSize.w+"px";this.contentDiv.style.height=contentSize.h+"px";}},updateSize:function(){var preparedHTML="<div class='"+this.contentDisplayClass+"'>"+
59498 this.contentDiv.innerHTML+"</div>";var containerElement=(this.map)?this.map.layerContainerDiv:document.body;var realSize=OpenLayers.Util.getRenderedDimensions(preparedHTML,null,{displayClass:this.displayClass,containerElement:containerElement});var safeSize=this.getSafeContentSize(realSize);var newSize=null;if(safeSize.equals(realSize)){newSize=realSize;}else{var fixedSize=new OpenLayers.Size();fixedSize.w=(safeSize.w<realSize.w)?safeSize.w:null;fixedSize.h=(safeSize.h<realSize.h)?safeSize.h:null;if(fixedSize.w&&fixedSize.h){newSize=safeSize;}else{var clippedSize=OpenLayers.Util.getRenderedDimensions(preparedHTML,fixedSize,{displayClass:this.contentDisplayClass,containerElement:containerElement});var currentOverflow=OpenLayers.Element.getStyle(this.contentDiv,"overflow");if((currentOverflow!="hidden")&&(clippedSize.equals(safeSize))){var scrollBar=OpenLayers.Util.getScrollbarWidth();if(fixedSize.w){clippedSize.h+=scrollBar;}else{clippedSize.w+=scrollBar;}}
59499 newSize=this.getSafeContentSize(clippedSize);}}
59500 this.setSize(newSize);},setBackgroundColor:function(color){if(color!=undefined){this.backgroundColor=color;}
59501 if(this.div!=null){this.div.style.backgroundColor=this.backgroundColor;}},setOpacity:function(opacity){if(opacity!=undefined){this.opacity=opacity;}
59502 if(this.div!=null){this.div.style.opacity=this.opacity;this.div.style.filter='alpha(opacity='+this.opacity*100+')';}},setBorder:function(border){if(border!=undefined){this.border=border;}
59503 if(this.div!=null){this.div.style.border=this.border;}},setContentHTML:function(contentHTML){if(contentHTML!=null){this.contentHTML=contentHTML;}
59504 if((this.contentDiv!=null)&&(this.contentHTML!=null)&&(this.contentHTML!=this.contentDiv.innerHTML)){this.contentDiv.innerHTML=this.contentHTML;if(this.autoSize){this.registerImageListeners();this.updateSize();}}},registerImageListeners:function(){var onImgLoad=function(){this.popup.updateSize();if(this.popup.visible()&&this.popup.panMapIfOutOfView){this.popup.panIntoView();}
59505 OpenLayers.Event.stopObserving(this.img,"load",this.img._onImageLoad);};var images=this.contentDiv.getElementsByTagName("img");for(var i=0,len=images.length;i<len;i++){var img=images[i];if(img.width==0||img.height==0){var context={'popup':this,'img':img};img._onImgLoad=OpenLayers.Function.bind(onImgLoad,context);OpenLayers.Event.observe(img,'load',img._onImgLoad);}}},getSafeContentSize:function(size){var safeContentSize=size.clone();var contentDivPadding=this.getContentDivPadding();var wPadding=contentDivPadding.left+contentDivPadding.right;var hPadding=contentDivPadding.top+contentDivPadding.bottom;this.fixPadding();wPadding+=this.padding.left+this.padding.right;hPadding+=this.padding.top+this.padding.bottom;if(this.closeDiv){var closeDivWidth=parseInt(this.closeDiv.style.width);wPadding+=closeDivWidth+contentDivPadding.right;}
59506 if(this.minSize){safeContentSize.w=Math.max(safeContentSize.w,(this.minSize.w-wPadding));safeContentSize.h=Math.max(safeContentSize.h,(this.minSize.h-hPadding));}
59507 if(this.maxSize){safeContentSize.w=Math.min(safeContentSize.w,(this.maxSize.w-wPadding));safeContentSize.h=Math.min(safeContentSize.h,(this.maxSize.h-hPadding));}
59508 if(this.map&&this.map.size){var extraX=0,extraY=0;if(this.keepInMap&&!this.panMapIfOutOfView){var px=this.map.getPixelFromLonLat(this.lonlat);switch(this.relativePosition){case"tr":extraX=px.x;extraY=this.map.size.h-px.y;break;case"tl":extraX=this.map.size.w-px.x;extraY=this.map.size.h-px.y;break;case"bl":extraX=this.map.size.w-px.x;extraY=px.y;break;case"br":extraX=px.x;extraY=px.y;break;default:extraX=px.x;extraY=this.map.size.h-px.y;break;}}
59509 var maxY=this.map.size.h-
59510 this.map.paddingForPopups.top-
59511 this.map.paddingForPopups.bottom-
59512 hPadding-extraY;var maxX=this.map.size.w-
59513 this.map.paddingForPopups.left-
59514 this.map.paddingForPopups.right-
59515 wPadding-extraX;safeContentSize.w=Math.min(safeContentSize.w,maxX);safeContentSize.h=Math.min(safeContentSize.h,maxY);}
59516 return safeContentSize;},getContentDivPadding:function(){var contentDivPadding=this._contentDivPadding;if(!contentDivPadding){if(this.div.parentNode==null){this.div.style.display="none";document.body.appendChild(this.div);}
59517 contentDivPadding=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,"padding-top"));this._contentDivPadding=contentDivPadding;if(this.div.parentNode==document.body){document.body.removeChild(this.div);this.div.style.display="";}}
59518 return contentDivPadding;},addCloseBox:function(callback){this.closeDiv=OpenLayers.Util.createDiv(this.id+"_close",null,new OpenLayers.Size(17,17));this.closeDiv.className="olPopupCloseBox";var contentDivPadding=this.getContentDivPadding();this.closeDiv.style.right=contentDivPadding.right+"px";this.closeDiv.style.top=contentDivPadding.top+"px";this.groupDiv.appendChild(this.closeDiv);var closePopup=callback||function(e){this.hide();OpenLayers.Event.stop(e);};OpenLayers.Event.observe(this.closeDiv,"click",OpenLayers.Function.bindAsEventListener(closePopup,this));},panIntoView:function(){var mapSize=this.map.getSize();var origTL=this.map.getViewPortPxFromLayerPx(new OpenLayers.Pixel(parseInt(this.div.style.left),parseInt(this.div.style.top)));var newTL=origTL.clone();if(origTL.x<this.map.paddingForPopups.left){newTL.x=this.map.paddingForPopups.left;}else
59519 if((origTL.x+this.size.w)>(mapSize.w-this.map.paddingForPopups.right)){newTL.x=mapSize.w-this.map.paddingForPopups.right-this.size.w;}
59520 if(origTL.y<this.map.paddingForPopups.top){newTL.y=this.map.paddingForPopups.top;}else
59521 if((origTL.y+this.size.h)>(mapSize.h-this.map.paddingForPopups.bottom)){newTL.y=mapSize.h-this.map.paddingForPopups.bottom-this.size.h;}
59522 var dx=origTL.x-newTL.x;var dy=origTL.y-newTL.y;this.map.pan(dx,dy);},registerEvents:function(){this.events=new OpenLayers.Events(this,this.div,null,true);this.events.on({"mousedown":this.onmousedown,"mousemove":this.onmousemove,"mouseup":this.onmouseup,"click":this.onclick,"mouseout":this.onmouseout,"dblclick":this.ondblclick,scope:this});},onmousedown:function(evt){this.mousedown=true;OpenLayers.Event.stop(evt,true);},onmousemove:function(evt){if(this.mousedown){OpenLayers.Event.stop(evt,true);}},onmouseup:function(evt){if(this.mousedown){this.mousedown=false;OpenLayers.Event.stop(evt,true);}},onclick:function(evt){OpenLayers.Event.stop(evt,true);},onmouseout:function(evt){this.mousedown=false;},ondblclick:function(evt){OpenLayers.Event.stop(evt,true);},CLASS_NAME:"OpenLayers.Popup"});OpenLayers.Popup.WIDTH=200;OpenLayers.Popup.HEIGHT=200;OpenLayers.Popup.COLOR="white";OpenLayers.Popup.OPACITY=1;OpenLayers.Popup.BORDER="0px";OpenLayers.Protocol=OpenLayers.Class({format:null,options:null,autoDestroy:true,defaultFilter:null,initialize:function(options){options=options||{};OpenLayers.Util.extend(this,options);this.options=options;},mergeWithDefaultFilter:function(filter){var merged;if(filter&&this.defaultFilter){merged=new OpenLayers.Filter.Logical({type:OpenLayers.Filter.Logical.AND,filters:[this.defaultFilter,filter]});}else{merged=filter||this.defaultFilter||undefined;}
59523 return merged;},destroy:function(){this.options=null;this.format=null;},read:function(options){options=options||{};options.filter=this.mergeWithDefaultFilter(options.filter);},create:function(){},update:function(){},"delete":function(){},commit:function(){},abort:function(response){},createCallback:function(method,response,options){return OpenLayers.Function.bind(function(){method.apply(this,[response,options]);},this);},CLASS_NAME:"OpenLayers.Protocol"});OpenLayers.Protocol.Response=OpenLayers.Class({code:null,requestType:null,last:true,features:null,reqFeatures:null,priv:null,initialize:function(options){OpenLayers.Util.extend(this,options);},success:function(){return this.code>0;},CLASS_NAME:"OpenLayers.Protocol.Response"});OpenLayers.Protocol.Response.SUCCESS=1;OpenLayers.Protocol.Response.FAILURE=0;OpenLayers.Renderer=OpenLayers.Class({container:null,root:null,extent:null,locked:false,size:null,resolution:null,map:null,initialize:function(containerID,options){this.container=OpenLayers.Util.getElement(containerID);},destroy:function(){this.container=null;this.extent=null;this.size=null;this.resolution=null;this.map=null;},supported:function(){return false;},setExtent:function(extent,resolutionChanged){this.extent=extent.clone();if(resolutionChanged){this.resolution=null;}},setSize:function(size){this.size=size.clone();this.resolution=null;},getResolution:function(){this.resolution=this.resolution||this.map.getResolution();return this.resolution;},drawFeature:function(feature,style){if(style==null){style=feature.style;}
59524 if(feature.geometry){var bounds=feature.geometry.getBounds();if(bounds){if(!bounds.intersectsBounds(this.extent)){style={display:"none"};}
59525 var rendered=this.drawGeometry(feature.geometry,style,feature.id);if(style.display!="none"&&style.label&&rendered!==false){var location=feature.geometry.getCentroid();if(style.labelXOffset||style.labelYOffset){xOffset=isNaN(style.labelXOffset)?0:style.labelXOffset;yOffset=isNaN(style.labelYOffset)?0:style.labelYOffset;var res=this.getResolution();location.move(xOffset*res,yOffset*res);}
59526 this.drawText(feature.id,style,location);}else{this.removeText(feature.id);}
59527 return rendered;}}},drawGeometry:function(geometry,style,featureId){},drawText:function(featureId,style,location){},removeText:function(featureId){},clear:function(){},getFeatureIdFromEvent:function(evt){},eraseFeatures:function(features){if(!(features instanceof Array)){features=[features];}
59528 for(var i=0,len=features.length;i<len;++i){var feature=features[i];this.eraseGeometry(feature.geometry,feature.id);this.removeText(feature.id);}},eraseGeometry:function(geometry,featureId){},moveRoot:function(renderer){},getRenderLayerId:function(){return this.container.id;},applyDefaultSymbolizer:function(symbolizer){var result=OpenLayers.Util.extend({},OpenLayers.Renderer.defaultSymbolizer);if(symbolizer.stroke===false){delete result.strokeWidth;delete result.strokeColor;}
59529 if(symbolizer.fill===false){delete result.fillColor;}
59530 OpenLayers.Util.extend(result,symbolizer);return result;},CLASS_NAME:"OpenLayers.Renderer"});OpenLayers.Renderer.defaultSymbolizer={fillColor:"#000000",strokeColor:"#000000",strokeWidth:2,fillOpacity:1,strokeOpacity:1,pointRadius:0};OpenLayers.Strategy=OpenLayers.Class({layer:null,options:null,active:null,autoActivate:true,autoDestroy:true,initialize:function(options){OpenLayers.Util.extend(this,options);this.options=options;this.active=false;},destroy:function(){this.deactivate();this.layer=null;this.options=null;},setLayer:function(layer){this.layer=layer;},activate:function(){if(!this.active){this.active=true;return true;}
59531 return false;},deactivate:function(){if(this.active){this.active=false;return true;}
59532 return false;},CLASS_NAME:"OpenLayers.Strategy"});OpenLayers.Symbolizer=OpenLayers.Class({zIndex:0,initialize:function(config){OpenLayers.Util.extend(this,config);},clone:function(){var Type=eval(this.CLASS_NAME);return new Type(OpenLayers.Util.extend({},this));},CLASS_NAME:"OpenLayers.Symbolizer"});OpenLayers.Rico.Color=OpenLayers.Class({initialize:function(red,green,blue){this.rgb={r:red,g:green,b:blue};},setRed:function(r){this.rgb.r=r;},setGreen:function(g){this.rgb.g=g;},setBlue:function(b){this.rgb.b=b;},setHue:function(h){var hsb=this.asHSB();hsb.h=h;this.rgb=OpenLayers.Rico.Color.HSBtoRGB(hsb.h,hsb.s,hsb.b);},setSaturation:function(s){var hsb=this.asHSB();hsb.s=s;this.rgb=OpenLayers.Rico.Color.HSBtoRGB(hsb.h,hsb.s,hsb.b);},setBrightness:function(b){var hsb=this.asHSB();hsb.b=b;this.rgb=OpenLayers.Rico.Color.HSBtoRGB(hsb.h,hsb.s,hsb.b);},darken:function(percent){var hsb=this.asHSB();this.rgb=OpenLayers.Rico.Color.HSBtoRGB(hsb.h,hsb.s,Math.max(hsb.b-percent,0));},brighten:function(percent){var hsb=this.asHSB();this.rgb=OpenLayers.Rico.Color.HSBtoRGB(hsb.h,hsb.s,Math.min(hsb.b+percent,1));},blend:function(other){this.rgb.r=Math.floor((this.rgb.r+other.rgb.r)/2);this.rgb.g=Math.floor((this.rgb.g+other.rgb.g)/2);this.rgb.b=Math.floor((this.rgb.b+other.rgb.b)/2);},isBright:function(){var hsb=this.asHSB();return this.asHSB().b>0.5;},isDark:function(){return!this.isBright();},asRGB:function(){return"rgb("+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();}});OpenLayers.Rico.Color.createFromHex=function(hexCode){if(hexCode.length==4){var shortHexCode=hexCode;var hexCode='#';for(var i=1;i<4;i++){hexCode+=(shortHexCode.charAt(i)+
59533 shortHexCode.charAt(i));}}
59534 if(hexCode.indexOf('#')==0){hexCode=hexCode.substring(1);}
59535 var red=hexCode.substring(0,2);var green=hexCode.substring(2,4);var blue=hexCode.substring(4,6);return new OpenLayers.Rico.Color(parseInt(red,16),parseInt(green,16),parseInt(blue,16));};OpenLayers.Rico.Color.createColorFromBackground=function(elem){var actualColor=RicoUtil.getElementsComputedStyle(OpenLayers.Util.getElement(elem),"backgroundColor","background-color");if(actualColor=="transparent"&&elem.parentNode){return OpenLayers.Rico.Color.createColorFromBackground(elem.parentNode);}
59536 if(actualColor==null){return new OpenLayers.Rico.Color(255,255,255);}
59537 if(actualColor.indexOf("rgb(")==0){var colors=actualColor.substring(4,actualColor.length-1);var colorArray=colors.split(",");return new OpenLayers.Rico.Color(parseInt(colorArray[0]),parseInt(colorArray[1]),parseInt(colorArray[2]));}
59538 else if(actualColor.indexOf("#")==0){return OpenLayers.Rico.Color.createFromHex(actualColor);}
59539 else{return new OpenLayers.Rico.Color(255,255,255);}};OpenLayers.Rico.Color.HSBtoRGB=function(hue,saturation,brightness){var red=0;var green=0;var blue=0;if(saturation==0){red=parseInt(brightness*255.0+0.5);green=red;blue=red;}
59540 else{var h=(hue-Math.floor(hue))*6.0;var f=h-Math.floor(h);var p=brightness*(1.0-saturation);var q=brightness*(1.0-saturation*f);var t=brightness*(1.0-(saturation*(1.0-f)));switch(parseInt(h)){case 0:red=(brightness*255.0+0.5);green=(t*255.0+0.5);blue=(p*255.0+0.5);break;case 1:red=(q*255.0+0.5);green=(brightness*255.0+0.5);blue=(p*255.0+0.5);break;case 2:red=(p*255.0+0.5);green=(brightness*255.0+0.5);blue=(t*255.0+0.5);break;case 3:red=(p*255.0+0.5);green=(q*255.0+0.5);blue=(brightness*255.0+0.5);break;case 4:red=(t*255.0+0.5);green=(p*255.0+0.5);blue=(brightness*255.0+0.5);break;case 5:red=(brightness*255.0+0.5);green=(p*255.0+0.5);blue=(q*255.0+0.5);break;}}
59541 return{r:parseInt(red),g:parseInt(green),b:parseInt(blue)};};OpenLayers.Rico.Color.RGBtoHSB=function(r,g,b){var hue;var saturation;var brightness;var cmax=(r>g)?r:g;if(b>cmax){cmax=b;}
59542 var cmin=(r<g)?r:g;if(b<cmin){cmin=b;}
59543 brightness=cmax/255.0;if(cmax!=0){saturation=(cmax-cmin)/cmax;}else{saturation=0;}
59544 if(saturation==0){hue=0;}else{var redc=(cmax-r)/(cmax-cmin);var greenc=(cmax-g)/(cmax-cmin);var bluec=(cmax-b)/(cmax-cmin);if(r==cmax){hue=bluec-greenc;}else if(g==cmax){hue=2.0+redc-bluec;}else{hue=4.0+greenc-redc;}
59545 hue=hue/6.0;if(hue<0){hue=hue+1.0;}}
59546 return{h:hue,s:saturation,b:brightness};};OpenLayers.Bounds=OpenLayers.Class({left:null,bottom:null,right:null,top:null,centerLonLat:null,initialize:function(left,bottom,right,top){if(left!=null){this.left=OpenLayers.Util.toFloat(left);}
59547 if(bottom!=null){this.bottom=OpenLayers.Util.toFloat(bottom);}
59548 if(right!=null){this.right=OpenLayers.Util.toFloat(right);}
59549 if(top!=null){this.top=OpenLayers.Util.toFloat(top);}},clone:function(){return new OpenLayers.Bounds(this.left,this.bottom,this.right,this.top);},equals:function(bounds){var equals=false;if(bounds!=null){equals=((this.left==bounds.left)&&(this.right==bounds.right)&&(this.top==bounds.top)&&(this.bottom==bounds.bottom));}
59550 return equals;},toString:function(){return("left-bottom=("+this.left+","+this.bottom+")"
59551 +" right-top=("+this.right+","+this.top+")");},toArray:function(reverseAxisOrder){if(reverseAxisOrder===true){return[this.bottom,this.left,this.top,this.right];}else{return[this.left,this.bottom,this.right,this.top];}},toBBOX:function(decimal,reverseAxisOrder){if(decimal==null){decimal=6;}
59552 var mult=Math.pow(10,decimal);var xmin=Math.round(this.left*mult)/mult;var ymin=Math.round(this.bottom*mult)/mult;var xmax=Math.round(this.right*mult)/mult;var ymax=Math.round(this.top*mult)/mult;if(reverseAxisOrder===true){return ymin+","+xmin+","+ymax+","+xmax;}else{return xmin+","+ymin+","+xmax+","+ymax;}},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());},getCenterPixel:function(){return new OpenLayers.Pixel((this.left+this.right)/2,(this.bottom+this.top)/2);},getCenterLonLat:function(){if(!this.centerLonLat){this.centerLonLat=new OpenLayers.LonLat((this.left+this.right)/2,(this.bottom+this.top)/2);}
59553 return this.centerLonLat;},scale:function(ratio,origin){if(origin==null){origin=this.getCenterLonLat();}
59554 var origx,origy;if(origin.CLASS_NAME=="OpenLayers.LonLat"){origx=origin.lon;origy=origin.lat;}else{origx=origin.x;origy=origin.y;}
59555 var left=(this.left-origx)*ratio+origx;var bottom=(this.bottom-origy)*ratio+origy;var right=(this.right-origx)*ratio+origx;var top=(this.top-origy)*ratio+origy;return new OpenLayers.Bounds(left,bottom,right,top);},add:function(x,y){if((x==null)||(y==null)){var msg=OpenLayers.i18n("boundsAddError");OpenLayers.Console.error(msg);return null;}
59556 return new OpenLayers.Bounds(this.left+x,this.bottom+y,this.right+x,this.top+y);},extend:function(object){var bounds=null;if(object){switch(object.CLASS_NAME){case"OpenLayers.LonLat":bounds=new OpenLayers.Bounds(object.lon,object.lat,object.lon,object.lat);break;case"OpenLayers.Geometry.Point":bounds=new OpenLayers.Bounds(object.x,object.y,object.x,object.y);break;case"OpenLayers.Bounds":bounds=object;break;}
59557 if(bounds){this.centerLonLat=null;if((this.left==null)||(bounds.left<this.left)){this.left=bounds.left;}
59558 if((this.bottom==null)||(bounds.bottom<this.bottom)){this.bottom=bounds.bottom;}
59559 if((this.right==null)||(bounds.right>this.right)){this.right=bounds.right;}
59560 if((this.top==null)||(bounds.top>this.top)){this.top=bounds.top;}}}},containsLonLat:function(ll,inclusive){return this.contains(ll.lon,ll.lat,inclusive);},containsPixel:function(px,inclusive){return this.contains(px.x,px.y,inclusive);},contains:function(x,y,inclusive){if(inclusive==null){inclusive=true;}
59561 if(x==null||y==null){return false;}
59562 x=OpenLayers.Util.toFloat(x);y=OpenLayers.Util.toFloat(y);var contains=false;if(inclusive){contains=((x>=this.left)&&(x<=this.right)&&(y>=this.bottom)&&(y<=this.top));}else{contains=((x>this.left)&&(x<this.right)&&(y>this.bottom)&&(y<this.top));}
59563 return contains;},intersectsBounds:function(bounds,inclusive){if(inclusive==null){inclusive=true;}
59564 var intersects=false;var mightTouch=(this.left==bounds.right||this.right==bounds.left||this.top==bounds.bottom||this.bottom==bounds.top);if(inclusive||!mightTouch){var inBottom=(((bounds.bottom>=this.bottom)&&(bounds.bottom<=this.top))||((this.bottom>=bounds.bottom)&&(this.bottom<=bounds.top)));var inTop=(((bounds.top>=this.bottom)&&(bounds.top<=this.top))||((this.top>bounds.bottom)&&(this.top<bounds.top)));var inLeft=(((bounds.left>=this.left)&&(bounds.left<=this.right))||((this.left>=bounds.left)&&(this.left<=bounds.right)));var inRight=(((bounds.right>=this.left)&&(bounds.right<=this.right))||((this.right>=bounds.left)&&(this.right<=bounds.right)));intersects=((inBottom||inTop)&&(inLeft||inRight));}
59565 return intersects;},containsBounds:function(bounds,partial,inclusive){if(partial==null){partial=false;}
59566 if(inclusive==null){inclusive=true;}
59567 var bottomLeft=this.contains(bounds.left,bounds.bottom,inclusive);var bottomRight=this.contains(bounds.right,bounds.bottom,inclusive);var topLeft=this.contains(bounds.left,bounds.top,inclusive);var topRight=this.contains(bounds.right,bounds.top,inclusive);return(partial)?(bottomLeft||bottomRight||topLeft||topRight):(bottomLeft&&bottomRight&&topLeft&&topRight);},determineQuadrant:function(lonlat){var quadrant="";var center=this.getCenterLonLat();quadrant+=(lonlat.lat<center.lat)?"b":"t";quadrant+=(lonlat.lon<center.lon)?"l":"r";return quadrant;},transform:function(source,dest){this.centerLonLat=null;var ll=OpenLayers.Projection.transform({'x':this.left,'y':this.bottom},source,dest);var lr=OpenLayers.Projection.transform({'x':this.right,'y':this.bottom},source,dest);var ul=OpenLayers.Projection.transform({'x':this.left,'y':this.top},source,dest);var ur=OpenLayers.Projection.transform({'x':this.right,'y':this.top},source,dest);this.left=Math.min(ll.x,ul.x);this.bottom=Math.min(ll.y,lr.y);this.right=Math.max(lr.x,ur.x);this.top=Math.max(ul.y,ur.y);return this;},wrapDateLine:function(maxExtent,options){options=options||{};var leftTolerance=options.leftTolerance||0;var rightTolerance=options.rightTolerance||0;var newBounds=this.clone();if(maxExtent){while(newBounds.left<maxExtent.left&&(newBounds.right-rightTolerance)<=maxExtent.left){newBounds=newBounds.add(maxExtent.getWidth(),0);}
59568 while((newBounds.left+leftTolerance)>=maxExtent.right&&newBounds.right>maxExtent.right){newBounds=newBounds.add(-maxExtent.getWidth(),0);}}
59569 return newBounds;},CLASS_NAME:"OpenLayers.Bounds"});OpenLayers.Bounds.fromString=function(str){var bounds=str.split(",");return OpenLayers.Bounds.fromArray(bounds);};OpenLayers.Bounds.fromArray=function(bbox){return new OpenLayers.Bounds(parseFloat(bbox[0]),parseFloat(bbox[1]),parseFloat(bbox[2]),parseFloat(bbox[3]));};OpenLayers.Bounds.fromSize=function(size){return new OpenLayers.Bounds(0,size.h,size.w,0);};OpenLayers.Bounds.oppositeQuadrant=function(quadrant){var opp="";opp+=(quadrant.charAt(0)=='t')?'b':'t';opp+=(quadrant.charAt(1)=='l')?'r':'l';return opp;};OpenLayers.LonLat=OpenLayers.Class({lon:0.0,lat:0.0,initialize:function(lon,lat){this.lon=OpenLayers.Util.toFloat(lon);this.lat=OpenLayers.Util.toFloat(lat);},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(lon,lat){if((lon==null)||(lat==null)){var msg=OpenLayers.i18n("lonlatAddError");OpenLayers.Console.error(msg);return null;}
59570 return new OpenLayers.LonLat(this.lon+OpenLayers.Util.toFloat(lon),this.lat+OpenLayers.Util.toFloat(lat));},equals:function(ll){var equals=false;if(ll!=null){equals=((this.lon==ll.lon&&this.lat==ll.lat)||(isNaN(this.lon)&&isNaN(this.lat)&&isNaN(ll.lon)&&isNaN(ll.lat)));}
59571 return equals;},transform:function(source,dest){var point=OpenLayers.Projection.transform({'x':this.lon,'y':this.lat},source,dest);this.lon=point.x;this.lat=point.y;return this;},wrapDateLine:function(maxExtent){var newLonLat=this.clone();if(maxExtent){while(newLonLat.lon<maxExtent.left){newLonLat.lon+=maxExtent.getWidth();}
59572 while(newLonLat.lon>maxExtent.right){newLonLat.lon-=maxExtent.getWidth();}}
59573 return newLonLat;},CLASS_NAME:"OpenLayers.LonLat"});OpenLayers.LonLat.fromString=function(str){var pair=str.split(",");return new OpenLayers.LonLat(pair[0],pair[1]);};OpenLayers.Pixel=OpenLayers.Class({x:0.0,y:0.0,initialize:function(x,y){this.x=parseFloat(x);this.y=parseFloat(y);},toString:function(){return("x="+this.x+",y="+this.y);},clone:function(){return new OpenLayers.Pixel(this.x,this.y);},equals:function(px){var equals=false;if(px!=null){equals=((this.x==px.x&&this.y==px.y)||(isNaN(this.x)&&isNaN(this.y)&&isNaN(px.x)&&isNaN(px.y)));}
59574 return equals;},add:function(x,y){if((x==null)||(y==null)){var msg=OpenLayers.i18n("pixelAddError");OpenLayers.Console.error(msg);return null;}
59575 return new OpenLayers.Pixel(this.x+x,this.y+y);},offset:function(px){var newPx=this.clone();if(px){newPx=this.add(px.x,px.y);}
59576 return newPx;},CLASS_NAME:"OpenLayers.Pixel"});OpenLayers.Control=OpenLayers.Class({id:null,map:null,div:null,type:null,allowSelection:false,displayClass:"",title:"",autoActivate:false,active:null,handler:null,eventListeners:null,events:null,EVENT_TYPES:["activate","deactivate"],initialize:function(options){this.displayClass=this.CLASS_NAME.replace("OpenLayers.","ol").replace(/\./g,"");OpenLayers.Util.extend(this,options);this.events=new OpenLayers.Events(this,null,this.EVENT_TYPES);if(this.eventListeners instanceof Object){this.events.on(this.eventListeners);}
59577 if(this.id==null){this.id=OpenLayers.Util.createUniqueID(this.CLASS_NAME+"_");}},destroy:function(){if(this.events){if(this.eventListeners){this.events.un(this.eventListeners);}
59578 this.events.destroy();this.events=null;}
59579 this.eventListeners=null;if(this.handler){this.handler.destroy();this.handler=null;}
59580 if(this.handlers){for(var key in this.handlers){if(this.handlers.hasOwnProperty(key)&&typeof this.handlers[key].destroy=="function"){this.handlers[key].destroy();}}
59581 this.handlers=null;}
59582 if(this.map){this.map.removeControl(this);this.map=null;}},setMap:function(map){this.map=map;if(this.handler){this.handler.setMap(map);}},draw:function(px){if(this.div==null){this.div=OpenLayers.Util.createDiv(this.id);this.div.className=this.displayClass;if(!this.allowSelection){this.div.className+=" olControlNoSelect";this.div.setAttribute("unselectable","on",0);this.div.onselectstart=OpenLayers.Function.False;}
59583 if(this.title!=""){this.div.title=this.title;}}
59584 if(px!=null){this.position=px.clone();}
59585 this.moveTo(this.position);return this.div;},moveTo:function(px){if((px!=null)&&(this.div!=null)){this.div.style.left=px.x+"px";this.div.style.top=px.y+"px";}},activate:function(){if(this.active){return false;}
59586 if(this.handler){this.handler.activate();}
59587 this.active=true;if(this.map){OpenLayers.Element.addClass(this.map.viewPortDiv,this.displayClass.replace(/ /g,"")+"Active");}
59588 this.events.triggerEvent("activate");return true;},deactivate:function(){if(this.active){if(this.handler){this.handler.deactivate();}
59589 this.active=false;if(this.map){OpenLayers.Element.removeClass(this.map.viewPortDiv,this.displayClass.replace(/ /g,"")+"Active");}
59590 this.events.triggerEvent("deactivate");return true;}
59591 return false;},CLASS_NAME:"OpenLayers.Control"});OpenLayers.Control.TYPE_BUTTON=1;OpenLayers.Control.TYPE_TOGGLE=2;OpenLayers.Control.TYPE_TOOL=3;OpenLayers.Lang={code:null,defaultCode:"en",getCode:function(){if(!OpenLayers.Lang.code){OpenLayers.Lang.setCode();}
59592 return OpenLayers.Lang.code;},setCode:function(code){var lang;if(!code){code=(OpenLayers.Util.getBrowserName()=="msie")?navigator.userLanguage:navigator.language;}
59593 var parts=code.split('-');parts[0]=parts[0].toLowerCase();if(typeof OpenLayers.Lang[parts[0]]=="object"){lang=parts[0];}
59594 if(parts[1]){var testLang=parts[0]+'-'+parts[1].toUpperCase();if(typeof OpenLayers.Lang[testLang]=="object"){lang=testLang;}}
59595 if(!lang){OpenLayers.Console.warn('Failed to find OpenLayers.Lang.'+parts.join("-")+' dictionary, falling back to default language');lang=OpenLayers.Lang.defaultCode;}
59596 OpenLayers.Lang.code=lang;},translate:function(key,context){var dictionary=OpenLayers.Lang[OpenLayers.Lang.getCode()];var message=dictionary[key];if(!message){message=key;}
59597 if(context){message=OpenLayers.String.format(message,context);}
59598 return message;}};OpenLayers.i18n=OpenLayers.Lang.translate;OpenLayers.Popup.Anchored=OpenLayers.Class(OpenLayers.Popup,{relativePosition:null,keepInMap:true,anchor:null,initialize:function(id,lonlat,contentSize,contentHTML,anchor,closeBox,closeBoxCallback){var newArguments=[id,lonlat,contentSize,contentHTML,closeBox,closeBoxCallback];OpenLayers.Popup.prototype.initialize.apply(this,newArguments);this.anchor=(anchor!=null)?anchor:{size:new OpenLayers.Size(0,0),offset:new OpenLayers.Pixel(0,0)};},destroy:function(){this.anchor=null;this.relativePosition=null;OpenLayers.Popup.prototype.destroy.apply(this,arguments);},show:function(){this.updatePosition();OpenLayers.Popup.prototype.show.apply(this,arguments);},moveTo:function(px){var oldRelativePosition=this.relativePosition;this.relativePosition=this.calculateRelativePosition(px);var newPx=this.calculateNewPx(px);var newArguments=new Array(newPx);OpenLayers.Popup.prototype.moveTo.apply(this,newArguments);if(this.relativePosition!=oldRelativePosition){this.updateRelativePosition();}},setSize:function(contentSize){OpenLayers.Popup.prototype.setSize.apply(this,arguments);if((this.lonlat)&&(this.map)){var px=this.map.getLayerPxFromLonLat(this.lonlat);this.moveTo(px);}},calculateRelativePosition:function(px){var lonlat=this.map.getLonLatFromLayerPx(px);var extent=this.map.getExtent();var quadrant=extent.determineQuadrant(lonlat);return OpenLayers.Bounds.oppositeQuadrant(quadrant);},updateRelativePosition:function(){},calculateNewPx:function(px){var newPx=px.offset(this.anchor.offset);var size=this.size||this.contentSize;var top=(this.relativePosition.charAt(0)=='t');newPx.y+=(top)?-(size.h+this.anchor.size.h):this.anchor.size.h;var left=(this.relativePosition.charAt(1)=='l');newPx.x+=(left)?-(size.w+this.anchor.size.w):this.anchor.size.w;return newPx;},CLASS_NAME:"OpenLayers.Popup.Anchored"});OpenLayers.Protocol.SOS=function(options){options=OpenLayers.Util.applyDefaults(options,OpenLayers.Protocol.SOS.DEFAULTS);var cls=OpenLayers.Protocol.SOS["v"+options.version.replace(/\./g,"_")];if(!cls){throw"Unsupported SOS version: "+options.version;}
59599 return new cls(options);};OpenLayers.Protocol.SOS.DEFAULTS={"version":"1.0.0"};OpenLayers.Protocol.SQL=OpenLayers.Class(OpenLayers.Protocol,{databaseName:'ol',tableName:"ol_vector_features",postReadFiltering:true,initialize:function(options){OpenLayers.Protocol.prototype.initialize.apply(this,[options]);},destroy:function(){OpenLayers.Protocol.prototype.destroy.apply(this);},supported:function(){return false;},evaluateFilter:function(feature,filter){return filter&&this.postReadFiltering?filter.evaluate(feature):true;},CLASS_NAME:"OpenLayers.Protocol.SQL"});OpenLayers.Protocol.WFS=function(options){options=OpenLayers.Util.applyDefaults(options,OpenLayers.Protocol.WFS.DEFAULTS);var cls=OpenLayers.Protocol.WFS["v"+options.version.replace(/\./g,"_")];if(!cls){throw"Unsupported WFS version: "+options.version;}
59600 return new cls(options);};OpenLayers.Protocol.WFS.fromWMSLayer=function(layer,options){var typeName,featurePrefix;var param=layer.params["LAYERS"];var parts=(param instanceof Array?param[0]:param).split(":");if(parts.length>1){featurePrefix=parts[0];}
59601 typeName=parts.pop();var protocolOptions={url:layer.url,featureType:typeName,featurePrefix:featurePrefix,srsName:layer.projection&&layer.projection.getCode()||layer.map&&layer.map.getProjectionObject().getCode(),version:"1.1.0"};return new OpenLayers.Protocol.WFS(OpenLayers.Util.applyDefaults(options,protocolOptions));};OpenLayers.Protocol.WFS.DEFAULTS={"version":"1.0.0"};OpenLayers.Renderer.Canvas=OpenLayers.Class(OpenLayers.Renderer,{canvas:null,features:null,initialize:function(containerID){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={};},eraseGeometry:function(geometry,featureId){this.eraseFeatures(this.features[featureId][0]);},supported:function(){var canvas=document.createElement("canvas");return!!canvas.getContext;},setExtent:function(extent){this.extent=extent.clone();this.resolution=null;this.redraw();},setSize:function(size){this.size=size.clone();this.root.style.width=size.w+"px";this.root.style.height=size.h+"px";this.root.width=size.w;this.root.height=size.h;this.resolution=null;},drawFeature:function(feature,style){style=style||feature.style;style=this.applyDefaultSymbolizer(style);this.features[feature.id]=[feature,style];this.redraw();},drawGeometry:function(geometry,style){var className=geometry.CLASS_NAME;if((className=="OpenLayers.Geometry.Collection")||(className=="OpenLayers.Geometry.MultiPoint")||(className=="OpenLayers.Geometry.MultiLineString")||(className=="OpenLayers.Geometry.MultiPolygon")){for(var i=0;i<geometry.components.length;i++){this.drawGeometry(geometry.components[i],style);}
59602 return;}
59603 switch(geometry.CLASS_NAME){case"OpenLayers.Geometry.Point":this.drawPoint(geometry,style);break;case"OpenLayers.Geometry.LineString":this.drawLineString(geometry,style);break;case"OpenLayers.Geometry.LinearRing":this.drawLinearRing(geometry,style);break;case"OpenLayers.Geometry.Polygon":this.drawPolygon(geometry,style);break;default:break;}},drawExternalGraphic:function(pt,style){var img=new Image();if(style.graphicTitle){img.title=style.graphicTitle;}
59604 var width=style.graphicWidth||style.graphicHeight;var height=style.graphicHeight||style.graphicWidth;width=width?width:style.pointRadius*2;height=height?height:style.pointRadius*2;var xOffset=(style.graphicXOffset!=undefined)?style.graphicXOffset:-(0.5*width);var yOffset=(style.graphicYOffset!=undefined)?style.graphicYOffset:-(0.5*height);var context={img:img,x:(pt[0]+xOffset),y:(pt[1]+yOffset),width:width,height:height,opacity:style.graphicOpacity||style.fillOpacity,canvas:this.canvas};img.onload=OpenLayers.Function.bind(function(){this.canvas.globalAlpha=this.opacity;this.canvas.drawImage(this.img,this.x,this.y,this.width,this.height);},context);img.src=style.externalGraphic;},setCanvasStyle:function(type,style){if(type=="fill"){this.canvas.globalAlpha=style['fillOpacity'];this.canvas.fillStyle=style['fillColor'];}else if(type=="stroke"){this.canvas.globalAlpha=style['strokeOpacity'];this.canvas.strokeStyle=style['strokeColor'];this.canvas.lineWidth=style['strokeWidth'];}else{this.canvas.globalAlpha=0;this.canvas.lineWidth=1;}},drawPoint:function(geometry,style){if(style.graphic!==false){var pt=this.getLocalXY(geometry);if(style.externalGraphic){this.drawExternalGraphic(pt,style);}else{if(style.fill!==false){this.setCanvasStyle("fill",style);this.canvas.beginPath();this.canvas.arc(pt[0],pt[1],style.pointRadius,0,Math.PI*2,true);this.canvas.fill();}
59605 if(style.stroke!==false){this.setCanvasStyle("stroke",style);this.canvas.beginPath();this.canvas.arc(pt[0],pt[1],style.pointRadius,0,Math.PI*2,true);this.canvas.stroke();this.setCanvasStyle("reset");}}}},drawLineString:function(geometry,style){if(style.stroke!==false){this.setCanvasStyle("stroke",style);this.canvas.beginPath();var start=this.getLocalXY(geometry.components[0]);this.canvas.moveTo(start[0],start[1]);for(var i=1;i<geometry.components.length;i++){var pt=this.getLocalXY(geometry.components[i]);this.canvas.lineTo(pt[0],pt[1]);}
59606 this.canvas.stroke();}
59607 this.setCanvasStyle("reset");},drawLinearRing:function(geometry,style){if(style.fill!==false){this.setCanvasStyle("fill",style);this.canvas.beginPath();var start=this.getLocalXY(geometry.components[0]);this.canvas.moveTo(start[0],start[1]);for(var i=1;i<geometry.components.length-1;i++){var pt=this.getLocalXY(geometry.components[i]);this.canvas.lineTo(pt[0],pt[1]);}
59608 this.canvas.fill();}
59609 if(style.stroke!==false){this.setCanvasStyle("stroke",style);this.canvas.beginPath();var start=this.getLocalXY(geometry.components[0]);this.canvas.moveTo(start[0],start[1]);for(var i=1;i<geometry.components.length;i++){var pt=this.getLocalXY(geometry.components[i]);this.canvas.lineTo(pt[0],pt[1]);}
59610 this.canvas.stroke();}
59611 this.setCanvasStyle("reset");},drawPolygon:function(geometry,style){this.drawLinearRing(geometry.components[0],style);for(var i=1;i<geometry.components.length;i++){this.drawLinearRing(geometry.components[i],{fillOpacity:0,strokeWidth:0,strokeOpacity:0,strokeColor:'#000000',fillColor:'#000000'});}},drawText:function(location,style){style=OpenLayers.Util.extend({fontColor:"#000000",labelAlign:"cm"},style);var pt=this.getLocalXY(location);this.setCanvasStyle("reset");this.canvas.fillStyle=style.fontColor;this.canvas.globalAlpha=style.fontOpacity||1.0;var fontStyle=style.fontWeight+" "+style.fontSize+" "+style.fontFamily;if(this.canvas.fillText){var labelAlign=OpenLayers.Renderer.Canvas.LABEL_ALIGN[style.labelAlign[0]]||"center";this.canvas.font=fontStyle;this.canvas.textAlign=labelAlign;this.canvas.fillText(style.label,pt[0],pt[1]);}else if(this.canvas.mozDrawText){this.canvas.mozTextStyle=fontStyle;var len=this.canvas.mozMeasureText(style.label);switch(style.labelAlign[0]){case"l":break;case"r":pt[0]-=len;break;case"c":default:pt[0]-=len/2;}
59612 this.canvas.translate(pt[0],pt[1]);this.canvas.mozDrawText(style.label);this.canvas.translate(-1*pt[0],-1*pt[1]);}
59613 this.setCanvasStyle("reset");},getLocalXY:function(point){var resolution=this.getResolution();var extent=this.extent;var x=(point.x/resolution+(-extent.left/resolution));var y=((extent.top/resolution)-point.y/resolution);return[x,y];},clear:function(){this.canvas.clearRect(0,0,this.root.width,this.root.height);this.features={};},getFeatureIdFromEvent:function(evt){var loc=this.map.getLonLatFromPixel(evt.xy);var resolution=this.getResolution();var bounds=new OpenLayers.Bounds(loc.lon-resolution*5,loc.lat-resolution*5,loc.lon+resolution*5,loc.lat+resolution*5);var geom=bounds.toGeometry();for(var feat in this.features){if(!this.features.hasOwnProperty(feat)){continue;}
59614 if(this.features[feat][0].geometry.intersects(geom)){return feat;}}
59615 return null;},eraseFeatures:function(features){if(!(features instanceof Array)){features=[features];}
59616 for(var i=0;i<features.length;++i){delete this.features[features[i].id];}
59617 this.redraw();},redraw:function(){if(!this.locked){this.canvas.clearRect(0,0,this.root.width,this.root.height);var labelMap=[];var feature,style;for(var id in this.features){if(!this.features.hasOwnProperty(id)){continue;}
59618 feature=this.features[id][0];style=this.features[id][1];if(!feature.geometry){continue;}
59619 this.drawGeometry(feature.geometry,style);if(style.label){labelMap.push([feature,style]);}}
59620 var item;for(var i=0,len=labelMap.length;i<len;++i){item=labelMap[i];this.drawText(item[0].geometry.getCentroid(),item[1]);}}},CLASS_NAME:"OpenLayers.Renderer.Canvas"});OpenLayers.Renderer.Canvas.LABEL_ALIGN={"l":"left","r":"right"};OpenLayers.ElementsIndexer=OpenLayers.Class({maxZIndex:null,order:null,indices:null,compare:null,initialize:function(yOrdering){this.compare=yOrdering?OpenLayers.ElementsIndexer.IndexingMethods.Z_ORDER_Y_ORDER:OpenLayers.ElementsIndexer.IndexingMethods.Z_ORDER_DRAWING_ORDER;this.order=[];this.indices={};this.maxZIndex=0;},insert:function(newNode){if(this.exists(newNode)){this.remove(newNode);}
59621 var nodeId=newNode.id;this.determineZIndex(newNode);var leftIndex=-1;var rightIndex=this.order.length;var middle;while(rightIndex-leftIndex>1){middle=parseInt((leftIndex+rightIndex)/2);var placement=this.compare(this,newNode,OpenLayers.Util.getElement(this.order[middle]));if(placement>0){leftIndex=middle;}else{rightIndex=middle;}}
59622 this.order.splice(rightIndex,0,nodeId);this.indices[nodeId]=this.getZIndex(newNode);return this.getNextElement(rightIndex);},remove:function(node){var nodeId=node.id;var arrayIndex=OpenLayers.Util.indexOf(this.order,nodeId);if(arrayIndex>=0){this.order.splice(arrayIndex,1);delete this.indices[nodeId];if(this.order.length>0){var lastId=this.order[this.order.length-1];this.maxZIndex=this.indices[lastId];}else{this.maxZIndex=0;}}},clear:function(){this.order=[];this.indices={};this.maxZIndex=0;},exists:function(node){return(this.indices[node.id]!=null);},getZIndex:function(node){return node._style.graphicZIndex;},determineZIndex:function(node){var zIndex=node._style.graphicZIndex;if(zIndex==null){zIndex=this.maxZIndex;node._style.graphicZIndex=zIndex;}else if(zIndex>this.maxZIndex){this.maxZIndex=zIndex;}},getNextElement:function(index){var nextIndex=index+1;if(nextIndex<this.order.length){var nextElement=OpenLayers.Util.getElement(this.order[nextIndex]);if(nextElement==undefined){nextElement=this.getNextElement(nextIndex);}
59623 return nextElement;}else{return null;}},CLASS_NAME:"OpenLayers.ElementsIndexer"});OpenLayers.ElementsIndexer.IndexingMethods={Z_ORDER:function(indexer,newNode,nextNode){var newZIndex=indexer.getZIndex(newNode);var returnVal=0;if(nextNode){var nextZIndex=indexer.getZIndex(nextNode);returnVal=newZIndex-nextZIndex;}
59624 return returnVal;},Z_ORDER_DRAWING_ORDER:function(indexer,newNode,nextNode){var returnVal=OpenLayers.ElementsIndexer.IndexingMethods.Z_ORDER(indexer,newNode,nextNode);if(nextNode&&returnVal==0){returnVal=1;}
59625 return returnVal;},Z_ORDER_Y_ORDER:function(indexer,newNode,nextNode){var returnVal=OpenLayers.ElementsIndexer.IndexingMethods.Z_ORDER(indexer,newNode,nextNode);if(nextNode&&returnVal===0){var result=nextNode._boundsBottom-newNode._boundsBottom;returnVal=(result===0)?1:result;}
59626 return returnVal;}};OpenLayers.Renderer.Elements=OpenLayers.Class(OpenLayers.Renderer,{rendererRoot:null,root:null,vectorRoot:null,textRoot:null,xmlns:null,indexer:null,BACKGROUND_ID_SUFFIX:"_background",LABEL_ID_SUFFIX:"_label",initialize:function(containerID,options){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);this.root.appendChild(this.textRoot);this.rendererRoot.appendChild(this.root);this.container.appendChild(this.rendererRoot);if(options&&(options.zIndexing||options.yOrdering)){this.indexer=new OpenLayers.ElementsIndexer(options.yOrdering);}},destroy:function(){this.clear();this.rendererRoot=null;this.root=null;this.xmlns=null;OpenLayers.Renderer.prototype.destroy.apply(this,arguments);},clear:function(){var child;var root=this.vectorRoot;if(root){while(child=root.firstChild){root.removeChild(child);}}
59627 root=this.textRoot;if(root){while(child=root.firstChild){root.removeChild(child);}}
59628 if(this.indexer){this.indexer.clear();}},getNodeType:function(geometry,style){},drawGeometry:function(geometry,style,featureId){var className=geometry.CLASS_NAME;var rendered=true;if((className=="OpenLayers.Geometry.Collection")||(className=="OpenLayers.Geometry.MultiPoint")||(className=="OpenLayers.Geometry.MultiLineString")||(className=="OpenLayers.Geometry.MultiPolygon")){for(var i=0,len=geometry.components.length;i<len;i++){rendered=this.drawGeometry(geometry.components[i],style,featureId)&&rendered;}
59629 return rendered;};rendered=false;if(style.display!="none"){if(style.backgroundGraphic){this.redrawBackgroundNode(geometry.id,geometry,style,featureId);}
59630 rendered=this.redrawNode(geometry.id,geometry,style,featureId);}
59631 if(rendered==false){var node=document.getElementById(geometry.id);if(node){if(node._style.backgroundGraphic){node.parentNode.removeChild(document.getElementById(geometry.id+this.BACKGROUND_ID_SUFFIX));}
59632 node.parentNode.removeChild(node);}}
59633 return rendered;},redrawNode:function(id,geometry,style,featureId){style=this.applyDefaultSymbolizer(style);var node=this.nodeFactory(id,this.getNodeType(geometry,style));node._featureId=featureId;node._boundsBottom=geometry.getBounds().bottom;node._geometryClass=geometry.CLASS_NAME;node._style=style;var drawResult=this.drawGeometryNode(node,geometry,style);if(drawResult===false){return false;}
59634 node=drawResult.node;if(this.indexer){var insert=this.indexer.insert(node);if(insert){this.vectorRoot.insertBefore(node,insert);}else{this.vectorRoot.appendChild(node);}}else{if(node.parentNode!==this.vectorRoot){this.vectorRoot.appendChild(node);}}
59635 this.postDraw(node);return drawResult.complete;},redrawBackgroundNode:function(id,geometry,style,featureId){var backgroundStyle=OpenLayers.Util.extend({},style);backgroundStyle.externalGraphic=backgroundStyle.backgroundGraphic;backgroundStyle.graphicXOffset=backgroundStyle.backgroundXOffset;backgroundStyle.graphicYOffset=backgroundStyle.backgroundYOffset;backgroundStyle.graphicZIndex=backgroundStyle.backgroundGraphicZIndex;backgroundStyle.graphicWidth=backgroundStyle.backgroundWidth||backgroundStyle.graphicWidth;backgroundStyle.graphicHeight=backgroundStyle.backgroundHeight||backgroundStyle.graphicHeight;backgroundStyle.backgroundGraphic=null;backgroundStyle.backgroundXOffset=null;backgroundStyle.backgroundYOffset=null;backgroundStyle.backgroundGraphicZIndex=null;return this.redrawNode(id+this.BACKGROUND_ID_SUFFIX,geometry,backgroundStyle,null);},drawGeometryNode:function(node,geometry,style){style=style||node._style;var options={'isFilled':style.fill===undefined?true:style.fill,'isStroked':style.stroke===undefined?!!style.strokeWidth:style.stroke};var drawn;switch(geometry.CLASS_NAME){case"OpenLayers.Geometry.Point":if(style.graphic===false){options.isFilled=false;options.isStroked=false;}
59636 drawn=this.drawPoint(node,geometry);break;case"OpenLayers.Geometry.LineString":options.isFilled=false;drawn=this.drawLineString(node,geometry);break;case"OpenLayers.Geometry.LinearRing":drawn=this.drawLinearRing(node,geometry);break;case"OpenLayers.Geometry.Polygon":drawn=this.drawPolygon(node,geometry);break;case"OpenLayers.Geometry.Surface":drawn=this.drawSurface(node,geometry);break;case"OpenLayers.Geometry.Rectangle":drawn=this.drawRectangle(node,geometry);break;default:break;}
59637 node._options=options;if(drawn!=false){return{node:this.setStyle(node,style,options,geometry),complete:drawn};}else{return false;}},postDraw:function(node){},drawPoint:function(node,geometry){},drawLineString:function(node,geometry){},drawLinearRing:function(node,geometry){},drawPolygon:function(node,geometry){},drawRectangle:function(node,geometry){},drawCircle:function(node,geometry){},drawSurface:function(node,geometry){},removeText:function(featureId){var label=document.getElementById(featureId+this.LABEL_ID_SUFFIX);if(label){this.textRoot.removeChild(label);}},getFeatureIdFromEvent:function(evt){var target=evt.target;var useElement=target&&target.correspondingUseElement;var node=useElement?useElement:(target||evt.srcElement);var featureId=node._featureId;return featureId;},eraseGeometry:function(geometry,featureId){if((geometry.CLASS_NAME=="OpenLayers.Geometry.MultiPoint")||(geometry.CLASS_NAME=="OpenLayers.Geometry.MultiLineString")||(geometry.CLASS_NAME=="OpenLayers.Geometry.MultiPolygon")||(geometry.CLASS_NAME=="OpenLayers.Geometry.Collection")){for(var i=0,len=geometry.components.length;i<len;i++){this.eraseGeometry(geometry.components[i],featureId);}}else{var element=OpenLayers.Util.getElement(geometry.id);if(element&&element.parentNode){if(element.geometry){element.geometry.destroy();element.geometry=null;}
59638 element.parentNode.removeChild(element);if(this.indexer){this.indexer.remove(element);}
59639 if(element._style.backgroundGraphic){var backgroundId=geometry.id+this.BACKGROUND_ID_SUFFIX;var bElem=OpenLayers.Util.getElement(backgroundId);if(bElem&&bElem.parentNode){bElem.parentNode.removeChild(bElem);}}}}},nodeFactory:function(id,type){var node=OpenLayers.Util.getElement(id);if(node){if(!this.nodeTypeCompare(node,type)){node.parentNode.removeChild(node);node=this.nodeFactory(id,type);}}else{node=this.createNode(type,id);}
59640 return node;},nodeTypeCompare:function(node,type){},createNode:function(type,id){},moveRoot:function(renderer){var root=this.root;if(renderer.root.parentNode==this.rendererRoot){root=renderer.root;}
59641 root.parentNode.removeChild(root);renderer.rendererRoot.appendChild(root);},getRenderLayerId:function(){return this.root.parentNode.parentNode.id;},isComplexSymbol:function(graphicName){return(graphicName!="circle")&&!!graphicName;},CLASS_NAME:"OpenLayers.Renderer.Elements"});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.Strategy.Cluster=OpenLayers.Class(OpenLayers.Strategy,{distance:20,threshold:null,features:null,clusters:null,clustering:false,resolution:null,initialize:function(options){OpenLayers.Strategy.prototype.initialize.apply(this,[options]);},activate:function(){var activated=OpenLayers.Strategy.prototype.activate.call(this);if(activated){this.layer.events.on({"beforefeaturesadded":this.cacheFeatures,"moveend":this.cluster,scope:this});}
59642 return activated;},deactivate:function(){var deactivated=OpenLayers.Strategy.prototype.deactivate.call(this);if(deactivated){this.clearCache();this.layer.events.un({"beforefeaturesadded":this.cacheFeatures,"moveend":this.cluster,scope:this});}
59643 return deactivated;},cacheFeatures:function(event){var propagate=true;if(!this.clustering){this.clearCache();this.features=event.features;this.cluster();propagate=false;}
59644 return propagate;},clearCache:function(){this.features=null;},cluster:function(event){if((!event||event.zoomChanged)&&this.features){var resolution=this.layer.map.getResolution();if(resolution!=this.resolution||!this.clustersExist()){this.resolution=resolution;var clusters=[];var feature,clustered,cluster;for(var i=0;i<this.features.length;++i){feature=this.features[i];if(feature.geometry){clustered=false;for(var j=clusters.length-1;j>=0;--j){cluster=clusters[j];if(this.shouldCluster(cluster,feature)){this.addToCluster(cluster,feature);clustered=true;break;}}
59645 if(!clustered){clusters.push(this.createCluster(this.features[i]));}}}
59646 this.layer.removeAllFeatures();if(clusters.length>0){if(this.threshold>1){var clone=clusters.slice();clusters=[];var candidate;for(var i=0,len=clone.length;i<len;++i){candidate=clone[i];if(candidate.attributes.count<this.threshold){Array.prototype.push.apply(clusters,candidate.cluster);}else{clusters.push(candidate);}}}
59647 this.clustering=true;this.layer.addFeatures(clusters);this.clustering=false;}
59648 this.clusters=clusters;}}},clustersExist:function(){var exist=false;if(this.clusters&&this.clusters.length>0&&this.clusters.length==this.layer.features.length){exist=true;for(var i=0;i<this.clusters.length;++i){if(this.clusters[i]!=this.layer.features[i]){exist=false;break;}}}
59649 return exist;},shouldCluster:function(cluster,feature){var cc=cluster.geometry.getBounds().getCenterLonLat();var fc=feature.geometry.getBounds().getCenterLonLat();var distance=(Math.sqrt(Math.pow((cc.lon-fc.lon),2)+Math.pow((cc.lat-fc.lat),2))/this.resolution);return(distance<=this.distance);},addToCluster:function(cluster,feature){cluster.cluster.push(feature);cluster.attributes.count+=1;},createCluster:function(feature){var center=feature.geometry.getBounds().getCenterLonLat();var cluster=new OpenLayers.Feature.Vector(new OpenLayers.Geometry.Point(center.lon,center.lat),{count:1});cluster.cluster=[feature];return cluster;},CLASS_NAME:"OpenLayers.Strategy.Cluster"});OpenLayers.Strategy.Fixed=OpenLayers.Class(OpenLayers.Strategy,{preload:false,initialize:function(options){OpenLayers.Strategy.prototype.initialize.apply(this,[options]);},destroy:function(){OpenLayers.Strategy.prototype.destroy.apply(this,arguments);},activate:function(){if(OpenLayers.Strategy.prototype.activate.apply(this,arguments)){this.layer.events.on({"refresh":this.load,scope:this});if(this.layer.visibility==true||this.preload){this.load();}else{this.layer.events.on({"visibilitychanged":this.load,scope:this});}
59650 return true;}
59651 return false;},deactivate:function(){var deactivated=OpenLayers.Strategy.prototype.deactivate.call(this);if(deactivated){this.layer.events.un({"refresh":this.load,"visibilitychanged":this.load,scope:this});}
59652 return deactivated;},load:function(options){this.layer.events.triggerEvent("loadstart");this.layer.protocol.read(OpenLayers.Util.applyDefaults({callback:this.merge,filter:this.layer.filter,scope:this},options));this.layer.events.un({"visibilitychanged":this.load,scope:this});},merge:function(resp){this.layer.destroyFeatures();var features=resp.features;if(features&&features.length>0){var remote=this.layer.projection;var local=this.layer.map.getProjectionObject();if(!local.equals(remote)){var geom;for(var i=0,len=features.length;i<len;++i){geom=features[i].geometry;if(geom){geom.transform(remote,local);}}}
59653 this.layer.addFeatures(features);}
59654 this.layer.events.triggerEvent("loadend");},CLASS_NAME:"OpenLayers.Strategy.Fixed"});OpenLayers.Strategy.Paging=OpenLayers.Class(OpenLayers.Strategy,{features:null,length:10,num:null,paging:false,initialize:function(options){OpenLayers.Strategy.prototype.initialize.apply(this,[options]);},activate:function(){var activated=OpenLayers.Strategy.prototype.activate.call(this);if(activated){this.layer.events.on({"beforefeaturesadded":this.cacheFeatures,scope:this});}
59655 return activated;},deactivate:function(){var deactivated=OpenLayers.Strategy.prototype.deactivate.call(this);if(deactivated){this.clearCache();this.layer.events.un({"beforefeaturesadded":this.cacheFeatures,scope:this});}
59656 return deactivated;},cacheFeatures:function(event){if(!this.paging){this.clearCache();this.features=event.features;this.pageNext(event);}},clearCache:function(){if(this.features){for(var i=0;i<this.features.length;++i){this.features[i].destroy();}}
59657 this.features=null;this.num=null;},pageCount:function(){var numFeatures=this.features?this.features.length:0;return Math.ceil(numFeatures/this.length);},pageNum:function(){return this.num;},pageLength:function(newLength){if(newLength&&newLength>0){this.length=newLength;}
59658 return this.length;},pageNext:function(event){var changed=false;if(this.features){if(this.num===null){this.num=-1;}
59659 var start=(this.num+1)*this.length;changed=this.page(start,event);}
59660 return changed;},pagePrevious:function(){var changed=false;if(this.features){if(this.num===null){this.num=this.pageCount();}
59661 var start=(this.num-1)*this.length;changed=this.page(start);}
59662 return changed;},page:function(start,event){var changed=false;if(this.features){if(start>=0&&start<this.features.length){var num=Math.floor(start/this.length);if(num!=this.num){this.paging=true;var features=this.features.slice(start,start+this.length);this.layer.removeFeatures(this.layer.features);this.num=num;if(event&&event.features){event.features=features;}else{this.layer.addFeatures(features);}
59663 this.paging=false;changed=true;}}}
59664 return changed;},CLASS_NAME:"OpenLayers.Strategy.Paging"});OpenLayers.Strategy.Refresh=OpenLayers.Class(OpenLayers.Strategy,{force:false,interval:0,timer:null,initialize:function(options){OpenLayers.Strategy.prototype.initialize.apply(this,[options]);},activate:function(){var activated=OpenLayers.Strategy.prototype.activate.call(this);if(activated){if(this.layer.visibility===true){this.start();}
59665 this.layer.events.on({"visibilitychanged":this.reset,scope:this});}
59666 return activated;},deactivate:function(){var deactivated=OpenLayers.Strategy.prototype.deactivate.call(this);if(deactivated){this.stop();}
59667 return deactivated;},reset:function(){if(this.layer.visibility===true){this.start();}else{this.stop();}},start:function(){if(this.interval&&typeof this.interval==="number"&&this.interval>0){this.timer=window.setInterval(OpenLayers.Function.bind(this.refresh,this),this.interval);}},refresh:function(){if(this.layer&&this.layer.refresh&&typeof this.layer.refresh=="function"){this.layer.refresh({force:this.force});}},stop:function(){if(this.timer!==null){window.clearInterval(this.timer);this.timer=null;}},CLASS_NAME:"OpenLayers.Strategy.Refresh"});OpenLayers.Strategy.Save=OpenLayers.Class(OpenLayers.Strategy,{EVENT_TYPES:["start","success","fail"],events:null,auto:false,timer:null,initialize:function(options){OpenLayers.Strategy.prototype.initialize.apply(this,[options]);this.events=new OpenLayers.Events(this,null,this.EVENT_TYPES);},activate:function(){var activated=OpenLayers.Strategy.prototype.activate.call(this);if(activated){if(this.auto){if(typeof this.auto==="number"){this.timer=window.setInterval(OpenLayers.Function.bind(this.save,this),this.auto*1000);}else{this.layer.events.on({"featureadded":this.triggerSave,"afterfeaturemodified":this.triggerSave,scope:this});}}}
59668 return activated;},deactivate:function(){var deactivated=OpenLayers.Strategy.prototype.deactivate.call(this);if(deactivated){if(this.auto){if(typeof this.auto==="number"){window.clearInterval(this.timer);}else{this.layer.events.un({"featureadded":this.triggerSave,"afterfeaturemodified":this.triggerSave,scope:this});}}}
59669 return deactivated;},triggerSave:function(event){var feature=event.feature;if(feature.state===OpenLayers.State.INSERT||feature.state===OpenLayers.State.UPDATE||feature.state===OpenLayers.State.DELETE){this.save([event.feature]);}},save:function(features){if(!features){features=this.layer.features;}
59670 this.events.triggerEvent("start",{features:features});var remote=this.layer.projection;var local=this.layer.map.getProjectionObject();if(!local.equals(remote)){var len=features.length;var clones=new Array(len);var orig,clone;for(var i=0;i<len;++i){orig=features[i];clone=orig.clone();clone.fid=orig.fid;clone.state=orig.state;if(orig.url){clone.url=orig.url;}
59671 clone._original=orig;clone.geometry.transform(local,remote);clones[i]=clone;}
59672 features=clones;}
59673 this.layer.protocol.commit(features,{callback:this.onCommit,scope:this});},onCommit:function(response){var evt={"response":response};if(response.success()){var features=response.reqFeatures;var state,feature;var destroys=[];var insertIds=response.insertIds||[];var j=0;for(var i=0,len=features.length;i<len;++i){feature=features[i];feature=feature._original||feature;state=feature.state;if(state){if(state==OpenLayers.State.DELETE){destroys.push(feature);}else if(state==OpenLayers.State.INSERT){feature.fid=insertIds[j];++j;}
59674 feature.state=null;}}
59675 if(destroys.length>0){this.layer.destroyFeatures(destroys);}
59676 this.events.triggerEvent("success",evt);}else{this.events.triggerEvent("fail",evt);}},CLASS_NAME:"OpenLayers.Strategy.Save"});OpenLayers.Symbolizer.Line=OpenLayers.Class(OpenLayers.Symbolizer,{strokeColor:null,strokeOpacity:null,strokeWidth:null,strokeLinecap:null,strokeDashstyle:null,initialize:function(config){OpenLayers.Symbolizer.prototype.initialize.apply(this,arguments);},CLASS_NAME:"OpenLayers.Symbolizer.Line"});OpenLayers.Symbolizer.Point=OpenLayers.Class(OpenLayers.Symbolizer,{strokeColor:null,strokeOpacity:null,strokeWidth:null,strokeLinecap:null,strokeDashstyle:null,fillColor:null,fillOpacity:null,pointRadius:null,externalGraphic:null,graphicWidth:null,graphicHeight:null,graphicOpacity:null,graphicXOffset:null,graphicYOffset:null,rotation:null,graphicName:null,initialize:function(config){OpenLayers.Symbolizer.prototype.initialize.apply(this,arguments);},CLASS_NAME:"OpenLayers.Symbolizer.Point"});OpenLayers.Symbolizer.Polygon=OpenLayers.Class(OpenLayers.Symbolizer,{strokeColor:null,strokeOpacity:null,strokeWidth:null,strokeLinecap:null,strokeDashstyle:null,fillColor:null,fillOpacity:null,initialize:function(config){OpenLayers.Symbolizer.prototype.initialize.apply(this,arguments);},CLASS_NAME:"OpenLayers.Symbolizer.Polygon"});OpenLayers.Symbolizer.Raster=OpenLayers.Class(OpenLayers.Symbolizer,{initialize:function(config){OpenLayers.Symbolizer.prototype.initialize.apply(this,arguments);},CLASS_NAME:"OpenLayers.Symbolizer.Raster"});OpenLayers.Symbolizer.Text=OpenLayers.Class(OpenLayers.Symbolizer,{label:null,fontFamily:null,fontSize:null,fontWeight:null,fontStyle:null,initialize:function(config){OpenLayers.Symbolizer.prototype.initialize.apply(this,arguments);},CLASS_NAME:"OpenLayers.Symbolizer.Text"});OpenLayers.Tween=OpenLayers.Class({INTERVAL:10,easing:null,begin:null,finish:null,duration:null,callbacks:null,time:null,interval:null,playing:false,initialize:function(easing){this.easing=(easing)?easing:OpenLayers.Easing.Expo.easeOut;},start:function(begin,finish,duration,options){this.playing=true;this.begin=begin;this.finish=finish;this.duration=duration;this.callbacks=options.callbacks;this.time=0;if(this.interval){window.clearInterval(this.interval);this.interval=null;}
59677 if(this.callbacks&&this.callbacks.start){this.callbacks.start.call(this,this.begin);}
59678 this.interval=window.setInterval(OpenLayers.Function.bind(this.play,this),this.INTERVAL);},stop:function(){if(!this.playing){return;}
59679 if(this.callbacks&&this.callbacks.done){this.callbacks.done.call(this,this.finish);}
59680 window.clearInterval(this.interval);this.interval=null;this.playing=false;},play:function(){var value={};for(var i in this.begin){var b=this.begin[i];var f=this.finish[i];if(b==null||f==null||isNaN(b)||isNaN(f)){OpenLayers.Console.error('invalid value for Tween');}
59681 var c=f-b;value[i]=this.easing.apply(this,[this.time,b,c,this.duration]);}
59682 this.time++;if(this.callbacks&&this.callbacks.eachStep){this.callbacks.eachStep.call(this,value);}
59683 if(this.time>this.duration){this.stop();}},CLASS_NAME:"OpenLayers.Tween"});OpenLayers.Easing={CLASS_NAME:"OpenLayers.Easing"};OpenLayers.Easing.Linear={easeIn:function(t,b,c,d){return c*t/d+b;},easeOut:function(t,b,c,d){return c*t/d+b;},easeInOut:function(t,b,c,d){return c*t/d+b;},CLASS_NAME:"OpenLayers.Easing.Linear"};OpenLayers.Easing.Expo={easeIn:function(t,b,c,d){return(t==0)?b:c*Math.pow(2,10*(t/d-1))+b;},easeOut:function(t,b,c,d){return(t==d)?b+c:c*(-Math.pow(2,-10*t/d)+1)+b;},easeInOut:function(t,b,c,d){if(t==0)return b;if(t==d)return b+c;if((t/=d/2)<1)return c/2*Math.pow(2,10*(t-1))+b;return c/2*(-Math.pow(2,-10*--t)+2)+b;},CLASS_NAME:"OpenLayers.Easing.Expo"};OpenLayers.Easing.Quad={easeIn:function(t,b,c,d){return c*(t/=d)*t+b;},easeOut:function(t,b,c,d){return-c*(t/=d)*(t-2)+b;},easeInOut:function(t,b,c,d){if((t/=d/2)<1)return c/2*t*t+b;return-c/2*((--t)*(t-2)-1)+b;},CLASS_NAME:"OpenLayers.Easing.Quad"};OpenLayers.Control.ArgParser=OpenLayers.Class(OpenLayers.Control,{center:null,zoom:null,layers:null,displayProjection:null,initialize:function(options){OpenLayers.Control.prototype.initialize.apply(this,arguments);},setMap:function(map){OpenLayers.Control.prototype.setMap.apply(this,arguments);for(var i=0,len=this.map.controls.length;i<len;i++){var control=this.map.controls[i];if((control!=this)&&(control.CLASS_NAME=="OpenLayers.Control.ArgParser")){if(control.displayProjection!=this.displayProjection){this.displayProjection=control.displayProjection;}
59684 break;}}
59685 if(i==this.map.controls.length){var args=OpenLayers.Util.getParameters();if(args.layers){this.layers=args.layers;this.map.events.register('addlayer',this,this.configureLayers);this.configureLayers();}
59686 if(args.lat&&args.lon){this.center=new OpenLayers.LonLat(parseFloat(args.lon),parseFloat(args.lat));if(args.zoom){this.zoom=parseInt(args.zoom);}
59687 this.map.events.register('changebaselayer',this,this.setCenter);this.setCenter();}}},setCenter:function(){if(this.map.baseLayer){this.map.events.unregister('changebaselayer',this,this.setCenter);if(this.displayProjection){this.center.transform(this.displayProjection,this.map.getProjectionObject());}
59688 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 i=0,len=this.layers.length;i<len;i++){var layer=this.map.layers[i];var c=this.layers.charAt(i);if(c=="B"){this.map.setBaseLayer(layer);}else if((c=="T")||(c=="F")){layer.setVisibility(c=="T");}}}},CLASS_NAME:"OpenLayers.Control.ArgParser"});OpenLayers.Control.Attribution=OpenLayers.Class(OpenLayers.Control,{separator:", ",initialize:function(options){OpenLayers.Control.prototype.initialize.apply(this,arguments);},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,'addlayer':this.updateAttribution,'removelayer':this.updateAttribution,scope:this});this.updateAttribution();return this.div;},updateAttribution:function(){var attributions=[];if(this.map&&this.map.layers){for(var i=0,len=this.map.layers.length;i<len;i++){var layer=this.map.layers[i];if(layer.attribution&&layer.getVisibility()){if(OpenLayers.Util.indexOf(attributions,layer.attribution)===-1){attributions.push(layer.attribution);}}}
59689 this.div.innerHTML=attributions.join(this.separator);}},CLASS_NAME:"OpenLayers.Control.Attribution"});OpenLayers.Control.Button=OpenLayers.Class(OpenLayers.Control,{type:OpenLayers.Control.TYPE_BUTTON,trigger:function(){},CLASS_NAME:"OpenLayers.Control.Button"});OpenLayers.Control.Graticule=OpenLayers.Class(OpenLayers.Control,{autoActivate:true,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:true,visible:true,numPoints:50,targetSize:200,layerName:null,labelled:true,labelFormat:'dm',lineSymbolizer:{strokeColor:"#333",strokeWidth:1,strokeOpacity:0.5},labelSymbolizer:{},gratLayer:null,initialize:function(options){options=options||{};options.layerName=options.layerName||OpenLayers.i18n("graticule");OpenLayers.Control.prototype.initialize.apply(this,[options]);this.labelSymbolizer.stroke=false;this.labelSymbolizer.fill=false;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);if(this.gratLayer){this.gratLayer.destroy();this.gratLayer=null;}},draw:function(){OpenLayers.Control.prototype.draw.apply(this,arguments);if(!this.gratLayer){var gratStyle=new OpenLayers.Style({},{rules:[new OpenLayers.Rule({'symbolizer':{"Point":this.labelSymbolizer,"Line":this.lineSymbolizer}})]});this.gratLayer=new OpenLayers.Layer.Vector(this.layerName,{styleMap:new OpenLayers.StyleMap({'default':gratStyle}),visibility:this.visible,displayInLayerSwitcher:this.displayInLayerSwitcher});}
59690 return this.div;},activate:function(){if(OpenLayers.Control.prototype.activate.apply(this,arguments)){this.map.addLayer(this.gratLayer);this.map.events.register('moveend',this,this.update);this.update();return true;}else{return false;}},deactivate:function(){if(OpenLayers.Control.prototype.deactivate.apply(this,arguments)){this.map.events.unregister('moveend',this,this.update);this.map.removeLayer(this.gratLayer);return true;}else{return false;}},update:function(){var mapBounds=this.map.getExtent();if(!mapBounds){return;}
59691 this.gratLayer.destroyFeatures();var llProj=new OpenLayers.Projection("EPSG:4326");var mapProj=this.map.getProjectionObject();var mapRes=this.map.getResolution();if(mapProj.proj&&mapProj.proj.projName=="longlat"){this.numPoints=1;}
59692 var mapCenter=this.map.getCenter();var mapCenterLL=new OpenLayers.Pixel(mapCenter.lon,mapCenter.lat);OpenLayers.Projection.transform(mapCenterLL,mapProj,llProj);var testSq=this.targetSize*mapRes;testSq*=testSq;var llInterval;for(var i=0;i<this.intervals.length;++i){llInterval=this.intervals[i];var delta=llInterval/2;var p1=mapCenterLL.offset(new OpenLayers.Pixel(-delta,-delta));var p2=mapCenterLL.offset(new OpenLayers.Pixel(delta,delta));OpenLayers.Projection.transform(p1,llProj,mapProj);OpenLayers.Projection.transform(p2,llProj,mapProj);var distSq=(p1.x-p2.x)*(p1.x-p2.x)+(p1.y-p2.y)*(p1.y-p2.y);if(distSq<=testSq){break;}}
59693 mapCenterLL.x=Math.floor(mapCenterLL.x/llInterval)*llInterval;mapCenterLL.y=Math.floor(mapCenterLL.y/llInterval)*llInterval;var iter=0;var centerLonPoints=[mapCenterLL.clone()];var newPoint=mapCenterLL.clone();var mapXY;do{newPoint=newPoint.offset(new OpenLayers.Pixel(0,llInterval));mapXY=OpenLayers.Projection.transform(newPoint.clone(),llProj,mapProj);centerLonPoints.unshift(newPoint);}while(mapBounds.containsPixel(mapXY)&&++iter<1000);newPoint=mapCenterLL.clone();do{newPoint=newPoint.offset(new OpenLayers.Pixel(0,-llInterval));mapXY=OpenLayers.Projection.transform(newPoint.clone(),llProj,mapProj);centerLonPoints.push(newPoint);}while(mapBounds.containsPixel(mapXY)&&++iter<1000);iter=0;var centerLatPoints=[mapCenterLL.clone()];newPoint=mapCenterLL.clone();do{newPoint=newPoint.offset(new OpenLayers.Pixel(-llInterval,0));mapXY=OpenLayers.Projection.transform(newPoint.clone(),llProj,mapProj);centerLatPoints.unshift(newPoint);}while(mapBounds.containsPixel(mapXY)&&++iter<1000);newPoint=mapCenterLL.clone();do{newPoint=newPoint.offset(new OpenLayers.Pixel(llInterval,0));mapXY=OpenLayers.Projection.transform(newPoint.clone(),llProj,mapProj);centerLatPoints.push(newPoint);}while(mapBounds.containsPixel(mapXY)&&++iter<1000);var lines=[];for(var i=0;i<centerLatPoints.length;++i){var lon=centerLatPoints[i].x;var pointList=[];var labelPoint=null;var latEnd=Math.min(centerLonPoints[0].y,90);var latStart=Math.max(centerLonPoints[centerLonPoints.length-1].y,-90);var latDelta=(latEnd-latStart)/this.numPoints;var lat=latStart;for(var j=0;j<=this.numPoints;++j){var gridPoint=new OpenLayers.Geometry.Point(lon,lat);gridPoint.transform(llProj,mapProj);pointList.push(gridPoint);lat+=latDelta;if(gridPoint.y>=mapBounds.bottom&&!labelPoint){labelPoint=gridPoint;}}
59694 if(this.labelled){var labelPos=new OpenLayers.Geometry.Point(labelPoint.x,mapBounds.bottom);var labelAttrs={value:lon,label:this.labelled?OpenLayers.Util.getFormattedLonLat(lon,"lon",this.labelFormat):"",labelAlign:"cb",xOffset:0,yOffset:2};this.gratLayer.addFeatures(new OpenLayers.Feature.Vector(labelPos,labelAttrs));}
59695 var geom=new OpenLayers.Geometry.LineString(pointList);lines.push(new OpenLayers.Feature.Vector(geom));}
59696 for(var j=0;j<centerLonPoints.length;++j){lat=centerLonPoints[j].y;if(lat<-90||lat>90){continue;}
59697 var pointList=[];var lonStart=centerLatPoints[0].x;var lonEnd=centerLatPoints[centerLatPoints.length-1].x;var lonDelta=(lonEnd-lonStart)/this.numPoints;var lon=lonStart;var labelPoint=null;for(var i=0;i<=this.numPoints;++i){var gridPoint=new OpenLayers.Geometry.Point(lon,lat);gridPoint.transform(llProj,mapProj);pointList.push(gridPoint);lon+=lonDelta;if(gridPoint.x<mapBounds.right){labelPoint=gridPoint;}}
59698 if(this.labelled){var labelPos=new OpenLayers.Geometry.Point(mapBounds.right,labelPoint.y);var labelAttrs={value:lat,label:this.labelled?OpenLayers.Util.getFormattedLonLat(lat,"lat",this.labelFormat):"",labelAlign:"rb",xOffset:-2,yOffset:2};this.gratLayer.addFeatures(new OpenLayers.Feature.Vector(labelPos,labelAttrs));}
59699 var geom=new OpenLayers.Geometry.LineString(pointList);lines.push(new OpenLayers.Feature.Vector(geom));}
59700 this.gratLayer.addFeatures(lines);},CLASS_NAME:"OpenLayers.Control.Graticule"});OpenLayers.Control.LayerSwitcher=OpenLayers.Class(OpenLayers.Control,{roundedCorner:true,roundedCornerColor:"darkblue",layerStates:null,layersDiv:null,baseLayersDiv:null,baseLayers:null,dataLbl:null,dataLayersDiv:null,dataLayers:null,minimizeDiv:null,maximizeDiv:null,ascending:true,initialize:function(options){OpenLayers.Control.prototype.initialize.apply(this,arguments);this.layerStates=[];},destroy:function(){OpenLayers.Event.stopObservingElement(this.div);OpenLayers.Event.stopObservingElement(this.minimizeDiv);OpenLayers.Event.stopObservingElement(this.maximizeDiv);this.clearLayersArray("base");this.clearLayersArray("data");this.map.events.un({"addlayer":this.redraw,"changelayer":this.redraw,"removelayer":this.redraw,"changebaselayer":this.redraw,scope:this});OpenLayers.Control.prototype.destroy.apply(this,arguments);},setMap:function(map){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});},draw:function(){OpenLayers.Control.prototype.draw.apply(this);this.loadContents();if(!this.outsideViewport){this.minimizeControl();}
59701 this.redraw();return this.div;},clearLayersArray:function(layersType){var layers=this[layersType+"Layers"];if(layers){for(var i=0,len=layers.length;i<len;i++){var layer=layers[i];OpenLayers.Event.stopObservingElement(layer.inputElem);OpenLayers.Event.stopObservingElement(layer.labelSpan);}}
59702 this[layersType+"LayersDiv"].innerHTML="";this[layersType+"Layers"]=[];},checkRedraw:function(){var redraw=false;if(!this.layerStates.length||(this.map.layers.length!=this.layerStates.length)){redraw=true;}else{for(var i=0,len=this.layerStates.length;i<len;i++){var layerState=this.layerStates[i];var layer=this.map.layers[i];if((layerState.name!=layer.name)||(layerState.inRange!=layer.inRange)||(layerState.id!=layer.id)||(layerState.visibility!=layer.visibility)){redraw=true;break;}}}
59703 return redraw;},redraw:function(){if(!this.checkRedraw()){return this.div;}
59704 this.clearLayersArray("base");this.clearLayersArray("data");var containsOverlays=false;var containsBaseLayers=false;var len=this.map.layers.length;this.layerStates=new Array(len);for(var i=0;i<len;i++){var layer=this.map.layers[i];this.layerStates[i]={'name':layer.name,'visibility':layer.visibility,'inRange':layer.inRange,'id':layer.id};}
59705 var layers=this.map.layers.slice();if(!this.ascending){layers.reverse();}
59706 for(var i=0,len=layers.length;i<len;i++){var layer=layers[i];var baseLayer=layer.isBaseLayer;if(layer.displayInLayerSwitcher){if(baseLayer){containsBaseLayers=true;}else{containsOverlays=true;}
59707 var checked=(baseLayer)?(layer==this.map.baseLayer):layer.getVisibility();var inputElem=document.createElement("input");inputElem.id=this.id+"_input_"+layer.name;inputElem.name=(baseLayer)?this.id+"_baseLayers":layer.name;inputElem.type=(baseLayer)?"radio":"checkbox";inputElem.value=layer.name;inputElem.checked=checked;inputElem.defaultChecked=checked;if(!baseLayer&&!layer.inRange){inputElem.disabled=true;}
59708 var context={'inputElem':inputElem,'layer':layer,'layerSwitcher':this};OpenLayers.Event.observe(inputElem,"mouseup",OpenLayers.Function.bindAsEventListener(this.onInputClick,context));var labelSpan=document.createElement("span");OpenLayers.Element.addClass(labelSpan,"labelSpan")
59709 if(!baseLayer&&!layer.inRange){labelSpan.style.color="gray";}
59710 labelSpan.innerHTML=layer.name;labelSpan.style.verticalAlign=(baseLayer)?"bottom":"baseline";OpenLayers.Event.observe(labelSpan,"click",OpenLayers.Function.bindAsEventListener(this.onInputClick,context));var br=document.createElement("br");var groupArray=(baseLayer)?this.baseLayers:this.dataLayers;groupArray.push({'layer':layer,'inputElem':inputElem,'labelSpan':labelSpan});var groupDiv=(baseLayer)?this.baseLayersDiv:this.dataLayersDiv;groupDiv.appendChild(inputElem);groupDiv.appendChild(labelSpan);groupDiv.appendChild(br);}}
59711 this.dataLbl.style.display=(containsOverlays)?"":"none";this.baseLbl.style.display=(containsBaseLayers)?"":"none";return this.div;},onInputClick:function(e){if(!this.inputElem.disabled){if(this.inputElem.type=="radio"){this.inputElem.checked=true;this.layer.map.setBaseLayer(this.layer);}else{this.inputElem.checked=!this.inputElem.checked;this.layerSwitcher.updateMap();}}
59712 OpenLayers.Event.stop(e);},onLayerClick:function(e){this.updateMap();},updateMap:function(){for(var i=0,len=this.baseLayers.length;i<len;i++){var layerEntry=this.baseLayers[i];if(layerEntry.inputElem.checked){this.map.setBaseLayer(layerEntry.layer,false);}}
59713 for(var i=0,len=this.dataLayers.length;i<len;i++){var layerEntry=this.dataLayers[i];layerEntry.layer.setVisibility(layerEntry.inputElem.checked);}},maximizeControl:function(e){this.div.style.width="";this.div.style.height="";this.showControls(false);if(e!=null){OpenLayers.Event.stop(e);}},minimizeControl:function(e){this.div.style.width="0px";this.div.style.height="0px";this.showControls(true);if(e!=null){OpenLayers.Event.stop(e);}},showControls:function(minimize){this.maximizeDiv.style.display=minimize?"":"none";this.minimizeDiv.style.display=minimize?"none":"";this.layersDiv.style.display=minimize?"none":"";},loadContents:function(){OpenLayers.Event.observe(this.div,"mouseup",OpenLayers.Function.bindAsEventListener(this.mouseUp,this));OpenLayers.Event.observe(this.div,"click",this.ignoreEvent);OpenLayers.Event.observe(this.div,"mousedown",OpenLayers.Function.bindAsEventListener(this.mouseDown,this));OpenLayers.Event.observe(this.div,"dblclick",this.ignoreEvent);this.layersDiv=document.createElement("div");this.layersDiv.id=this.id+"_layersDiv";OpenLayers.Element.addClass(this.layersDiv,"layersDiv");this.baseLbl=document.createElement("div");this.baseLbl.innerHTML=OpenLayers.i18n("baseLayer");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,"dataLayersDiv");if(this.ascending){this.layersDiv.appendChild(this.baseLbl);this.layersDiv.appendChild(this.baseLayersDiv);this.layersDiv.appendChild(this.dataLbl);this.layersDiv.appendChild(this.dataLayersDiv);}else{this.layersDiv.appendChild(this.dataLbl);this.layersDiv.appendChild(this.dataLayersDiv);this.layersDiv.appendChild(this.baseLbl);this.layersDiv.appendChild(this.baseLayersDiv);}
59714 this.div.appendChild(this.layersDiv);if(this.roundedCorner){OpenLayers.Rico.Corner.round(this.div,{corners:"tl bl",bgColor:"transparent",color:this.roundedCornerColor,blend:false});OpenLayers.Rico.Corner.changeOpacity(this.layersDiv,0.75);}
59715 var imgLocation=OpenLayers.Util.getImagesLocation();var sz=new OpenLayers.Size(18,18);var img=imgLocation+'layer-switcher-maximize.png';this.maximizeDiv=OpenLayers.Util.createAlphaImageDiv("OpenLayers_Control_MaximizeDiv",null,sz,img,"absolute");OpenLayers.Element.addClass(this.maximizeDiv,"maximizeDiv");this.maximizeDiv.style.display="none";OpenLayers.Event.observe(this.maximizeDiv,"click",OpenLayers.Function.bindAsEventListener(this.maximizeControl,this));this.div.appendChild(this.maximizeDiv);var img=imgLocation+'layer-switcher-minimize.png';var sz=new OpenLayers.Size(18,18);this.minimizeDiv=OpenLayers.Util.createAlphaImageDiv("OpenLayers_Control_MinimizeDiv",null,sz,img,"absolute");OpenLayers.Element.addClass(this.minimizeDiv,"minimizeDiv");this.minimizeDiv.style.display="none";OpenLayers.Event.observe(this.minimizeDiv,"click",OpenLayers.Function.bindAsEventListener(this.minimizeControl,this));this.div.appendChild(this.minimizeDiv);},ignoreEvent:function(evt){OpenLayers.Event.stop(evt);},mouseDown:function(evt){this.isMouseDown=true;this.ignoreEvent(evt);},mouseUp:function(evt){if(this.isMouseDown){this.isMouseDown=false;this.ignoreEvent(evt);}},CLASS_NAME:"OpenLayers.Control.LayerSwitcher"});OpenLayers.Control.MouseDefaults=OpenLayers.Class(OpenLayers.Control,{performedDrag:false,wheelObserver:null,initialize:function(){OpenLayers.Control.prototype.initialize.apply(this,arguments);},destroy:function(){if(this.handler){this.handler.destroy();}
59716 this.handler=null;this.map.events.un({"click":this.defaultClick,"dblclick":this.defaultDblClick,"mousedown":this.defaultMouseDown,"mouseup":this.defaultMouseUp,"mousemove":this.defaultMouseMove,"mouseout":this.defaultMouseOut,scope:this});OpenLayers.Event.stopObserving(window,"DOMMouseScroll",this.wheelObserver);OpenLayers.Event.stopObserving(window,"mousewheel",this.wheelObserver);OpenLayers.Event.stopObserving(document,"mousewheel",this.wheelObserver);this.wheelObserver=null;OpenLayers.Control.prototype.destroy.apply(this,arguments);},draw:function(){this.map.events.on({"click":this.defaultClick,"dblclick":this.defaultDblClick,"mousedown":this.defaultMouseDown,"mouseup":this.defaultMouseUp,"mousemove":this.defaultMouseMove,"mouseout":this.defaultMouseOut,scope:this});this.registerWheelEvents();},registerWheelEvents:function(){this.wheelObserver=OpenLayers.Function.bindAsEventListener(this.onWheelEvent,this);OpenLayers.Event.observe(window,"DOMMouseScroll",this.wheelObserver);OpenLayers.Event.observe(window,"mousewheel",this.wheelObserver);OpenLayers.Event.observe(document,"mousewheel",this.wheelObserver);},defaultClick:function(evt){if(!OpenLayers.Event.isLeftClick(evt)){return;}
59717 var notAfterDrag=!this.performedDrag;this.performedDrag=false;return notAfterDrag;},defaultDblClick:function(evt){var newCenter=this.map.getLonLatFromViewPortPx(evt.xy);this.map.setCenter(newCenter,this.map.zoom+1);OpenLayers.Event.stop(evt);return false;},defaultMouseDown:function(evt){if(!OpenLayers.Event.isLeftClick(evt)){return;}
59718 this.mouseDragStart=evt.xy.clone();this.performedDrag=false;if(evt.shiftKey){this.map.div.style.cursor="crosshair";this.zoomBox=OpenLayers.Util.createDiv('zoomBox',this.mouseDragStart,null,null,"absolute","2px solid red");this.zoomBox.style.backgroundColor="white";this.zoomBox.style.filter="alpha(opacity=50)";this.zoomBox.style.opacity="0.50";this.zoomBox.style.fontSize="1px";this.zoomBox.style.zIndex=this.map.Z_INDEX_BASE["Popup"]-1;this.map.viewPortDiv.appendChild(this.zoomBox);}
59719 document.onselectstart=OpenLayers.Function.False;OpenLayers.Event.stop(evt);},defaultMouseMove:function(evt){this.mousePosition=evt.xy.clone();if(this.mouseDragStart!=null){if(this.zoomBox){var deltaX=Math.abs(this.mouseDragStart.x-evt.xy.x);var deltaY=Math.abs(this.mouseDragStart.y-evt.xy.y);this.zoomBox.style.width=Math.max(1,deltaX)+"px";this.zoomBox.style.height=Math.max(1,deltaY)+"px";if(evt.xy.x<this.mouseDragStart.x){this.zoomBox.style.left=evt.xy.x+"px";}
59720 if(evt.xy.y<this.mouseDragStart.y){this.zoomBox.style.top=evt.xy.y+"px";}}else{var deltaX=this.mouseDragStart.x-evt.xy.x;var deltaY=this.mouseDragStart.y-evt.xy.y;var size=this.map.getSize();var newXY=new OpenLayers.Pixel(size.w/2+deltaX,size.h/2+deltaY);var newCenter=this.map.getLonLatFromViewPortPx(newXY);this.map.setCenter(newCenter,null,true);this.mouseDragStart=evt.xy.clone();this.map.div.style.cursor="move";}
59721 this.performedDrag=true;}},defaultMouseUp:function(evt){if(!OpenLayers.Event.isLeftClick(evt)){return;}
59722 if(this.zoomBox){this.zoomBoxEnd(evt);}else{if(this.performedDrag){this.map.setCenter(this.map.center);}}
59723 document.onselectstart=null;this.mouseDragStart=null;this.map.div.style.cursor="";},defaultMouseOut:function(evt){if(this.mouseDragStart!=null&&OpenLayers.Util.mouseLeft(evt,this.map.div)){if(this.zoomBox){this.removeZoomBox();}
59724 this.mouseDragStart=null;}},defaultWheelUp:function(evt){if(this.map.getZoom()<=this.map.getNumZoomLevels()){this.map.setCenter(this.map.getLonLatFromPixel(evt.xy),this.map.getZoom()+1);}},defaultWheelDown:function(evt){if(this.map.getZoom()>0){this.map.setCenter(this.map.getLonLatFromPixel(evt.xy),this.map.getZoom()-1);}},zoomBoxEnd:function(evt){if(this.mouseDragStart!=null){if(Math.abs(this.mouseDragStart.x-evt.xy.x)>5||Math.abs(this.mouseDragStart.y-evt.xy.y)>5){var start=this.map.getLonLatFromViewPortPx(this.mouseDragStart);var end=this.map.getLonLatFromViewPortPx(evt.xy);var top=Math.max(start.lat,end.lat);var bottom=Math.min(start.lat,end.lat);var left=Math.min(start.lon,end.lon);var right=Math.max(start.lon,end.lon);var bounds=new OpenLayers.Bounds(left,bottom,right,top);this.map.zoomToExtent(bounds);}else{var end=this.map.getLonLatFromViewPortPx(evt.xy);this.map.setCenter(new OpenLayers.LonLat((end.lon),(end.lat)),this.map.getZoom()+1);}
59725 this.removeZoomBox();}},removeZoomBox:function(){this.map.viewPortDiv.removeChild(this.zoomBox);this.zoomBox=null;},onWheelEvent:function(e){var inMap=false;var elem=OpenLayers.Event.element(e);while(elem!=null){if(this.map&&elem==this.map.div){inMap=true;break;}
59726 elem=elem.parentNode;}
59727 if(inMap){var delta=0;if(!e){e=window.event;}
59728 if(e.wheelDelta){delta=e.wheelDelta/120;if(window.opera&&window.opera.version()<9.2){delta=-delta;}}else if(e.detail){delta=-e.detail/3;}
59729 if(delta){e.xy=this.mousePosition;if(delta<0){this.defaultWheelDown(e);}else{this.defaultWheelUp(e);}}
59730 OpenLayers.Event.stop(e);}},CLASS_NAME:"OpenLayers.Control.MouseDefaults"});OpenLayers.Control.MousePosition=OpenLayers.Class(OpenLayers.Control,{autoActivate:true,element:null,prefix:'',separator:', ',suffix:'',numDigits:5,granularity:10,emptyString:null,lastXy:null,displayProjection:null,initialize:function(options){OpenLayers.Control.prototype.initialize.apply(this,arguments);},destroy:function(){this.deactivate();OpenLayers.Control.prototype.destroy.apply(this,arguments);},activate:function(){if(OpenLayers.Control.prototype.activate.apply(this,arguments)){this.map.events.register('mousemove',this,this.redraw);this.map.events.register('mouseout',this,this.reset);this.redraw();return true;}else{return false;}},deactivate:function(){if(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="";return true;}else{return false;}},draw:function(){OpenLayers.Control.prototype.draw.apply(this,arguments);if(!this.element){this.div.left="";this.div.top="";this.element=this.div;}
59731 return this.div;},redraw:function(evt){var lonLat;if(evt==null){this.reset();return;}else{if(this.lastXy==null||Math.abs(evt.xy.x-this.lastXy.x)>this.granularity||Math.abs(evt.xy.y-this.lastXy.y)>this.granularity)
59732 {this.lastXy=evt.xy;return;}
59733 lonLat=this.map.getLonLatFromPixel(evt.xy);if(!lonLat){return;}
59734 if(this.displayProjection){lonLat.transform(this.map.getProjectionObject(),this.displayProjection);}
59735 this.lastXy=evt.xy;}
59736 var newHtml=this.formatOutput(lonLat);if(newHtml!=this.element.innerHTML){this.element.innerHTML=newHtml;}},reset:function(evt){if(this.emptyString!=null){this.element.innerHTML=this.emptyString;}},formatOutput:function(lonLat){var digits=parseInt(this.numDigits);var newHtml=this.prefix+
59737 lonLat.lon.toFixed(digits)+
59738 this.separator+
59739 lonLat.lat.toFixed(digits)+
59740 this.suffix;return newHtml;},CLASS_NAME:"OpenLayers.Control.MousePosition"});OpenLayers.Control.Pan=OpenLayers.Class(OpenLayers.Control,{slideFactor:50,direction:null,type:OpenLayers.Control.TYPE_BUTTON,initialize:function(direction,options){this.direction=direction;this.CLASS_NAME+=this.direction;OpenLayers.Control.prototype.initialize.apply(this,[options]);},trigger:function(){switch(this.direction){case OpenLayers.Control.Pan.NORTH:this.map.pan(0,-this.slideFactor);break;case OpenLayers.Control.Pan.SOUTH:this.map.pan(0,this.slideFactor);break;case OpenLayers.Control.Pan.WEST:this.map.pan(-this.slideFactor,0);break;case OpenLayers.Control.Pan.EAST:this.map.pan(this.slideFactor,0);break;}},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.Control.PanZoom=OpenLayers.Class(OpenLayers.Control,{slideFactor:50,slideRatio:null,buttons:null,position:null,initialize:function(options){this.position=new OpenLayers.Pixel(OpenLayers.Control.PanZoom.X,OpenLayers.Control.PanZoom.Y);OpenLayers.Control.prototype.initialize.apply(this,arguments);},destroy:function(){OpenLayers.Control.prototype.destroy.apply(this,arguments);this.removeButtons();this.buttons=null;this.position=null;},draw:function(px){OpenLayers.Control.prototype.draw.apply(this,arguments);px=this.position;this.buttons=[];var sz=new OpenLayers.Size(18,18);var centered=new OpenLayers.Pixel(px.x+sz.w/2,px.y);this._addButton("panup","north-mini.png",centered,sz);px.y=centered.y+sz.h;this._addButton("panleft","west-mini.png",px,sz);this._addButton("panright","east-mini.png",px.add(sz.w,0),sz);this._addButton("pandown","south-mini.png",centered.add(0,sz.h*2),sz);this._addButton("zoomin","zoom-plus-mini.png",centered.add(0,sz.h*3+5),sz);this._addButton("zoomworld","zoom-world-mini.png",centered.add(0,sz.h*4+5),sz);this._addButton("zoomout","zoom-minus-mini.png",centered.add(0,sz.h*5+5),sz);return this.div;},_addButton:function(id,img,xy,sz){var imgLocation=OpenLayers.Util.getImagesLocation()+img;var btn=OpenLayers.Util.createAlphaImageDiv(this.id+"_"+id,xy,sz,imgLocation,"absolute");this.div.appendChild(btn);OpenLayers.Event.observe(btn,"mousedown",OpenLayers.Function.bindAsEventListener(this.buttonDown,btn));OpenLayers.Event.observe(btn,"dblclick",OpenLayers.Function.bindAsEventListener(this.doubleClick,btn));OpenLayers.Event.observe(btn,"click",OpenLayers.Function.bindAsEventListener(this.doubleClick,btn));btn.action=id;btn.map=this.map;if(!this.slideRatio){var slideFactorPixels=this.slideFactor;var getSlideFactor=function(){return slideFactorPixels;};}else{var slideRatio=this.slideRatio;var getSlideFactor=function(dim){return this.map.getSize()[dim]*slideRatio;};}
59741 btn.getSlideFactor=getSlideFactor;this.buttons.push(btn);return btn;},_removeButton:function(btn){OpenLayers.Event.stopObservingElement(btn);btn.map=null;btn.getSlideFactor=null;this.div.removeChild(btn);OpenLayers.Util.removeItem(this.buttons,btn);},removeButtons:function(){for(var i=this.buttons.length-1;i>=0;--i){this._removeButton(this.buttons[i]);}},doubleClick:function(evt){OpenLayers.Event.stop(evt);return false;},buttonDown:function(evt){if(!OpenLayers.Event.isLeftClick(evt)){return;}
59742 switch(this.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();break;case"zoomworld":this.map.zoomToMaxExtent();break;}
59743 OpenLayers.Event.stop(evt);},CLASS_NAME:"OpenLayers.Control.PanZoom"});OpenLayers.Control.PanZoom.X=4;OpenLayers.Control.PanZoom.Y=4;OpenLayers.Control.Panel=OpenLayers.Class(OpenLayers.Control,{controls:null,autoActivate:true,defaultControl:null,saveState:false,activeState:null,initialize:function(options){OpenLayers.Control.prototype.initialize.apply(this,[options]);this.controls=[];this.activeState={};},destroy:function(){OpenLayers.Control.prototype.destroy.apply(this,arguments);for(var i=this.controls.length-1;i>=0;i--){if(this.controls[i].events){this.controls[i].events.un({"activate":this.redraw,"deactivate":this.redraw,scope:this});}
59744 OpenLayers.Event.stopObservingElement(this.controls[i].panel_div);this.controls[i].panel_div=null;}
59745 this.activeState=null;},activate:function(){if(OpenLayers.Control.prototype.activate.apply(this,arguments)){var control;for(var i=0,len=this.controls.length;i<len;i++){control=this.controls[i];if(control===this.defaultControl||(this.saveState&&this.activeState[control.id])){control.activate();}}
59746 if(this.saveState===true){this.defaultControl=null;}
59747 this.redraw();return true;}else{return false;}},deactivate:function(){if(OpenLayers.Control.prototype.deactivate.apply(this,arguments)){var control;for(var i=0,len=this.controls.length;i<len;i++){control=this.controls[i];this.activeState[control.id]=control.deactivate();}
59748 return true;}else{return false;}},draw:function(){OpenLayers.Control.prototype.draw.apply(this,arguments);this.addControlsToMap(this.controls);return this.div;},redraw:function(){if(this.div.children.length>0){for(var l=this.div.children.length,i=l-1;i>=0;i--){this.div.removeChild(this.div.children[i]);}}
59749 this.div.innerHTML="";if(this.active){for(var i=0,len=this.controls.length;i<len;i++){var element=this.controls[i].panel_div;if(this.controls[i].active){element.className=this.controls[i].displayClass+"ItemActive";}else{element.className=this.controls[i].displayClass+"ItemInactive";}
59750 this.div.appendChild(element);}}},activateControl:function(control){if(!this.active){return false;}
59751 if(control.type==OpenLayers.Control.TYPE_BUTTON){control.trigger();this.redraw();return;}
59752 if(control.type==OpenLayers.Control.TYPE_TOGGLE){if(control.active){control.deactivate();}else{control.activate();}
59753 this.redraw();return;}
59754 var c;for(var i=0,len=this.controls.length;i<len;i++){c=this.controls[i];if(c!=control&&(c.type===OpenLayers.Control.TYPE_TOOL||c.type==null)){c.deactivate();}}
59755 control.activate();},addControls:function(controls){if(!(controls instanceof Array)){controls=[controls];}
59756 this.controls=this.controls.concat(controls);for(var i=0,len=controls.length;i<len;i++){var element=document.createElement("div");controls[i].panel_div=element;if(controls[i].title!=""){controls[i].panel_div.title=controls[i].title;}
59757 OpenLayers.Event.observe(controls[i].panel_div,"click",OpenLayers.Function.bind(this.onClick,this,controls[i]));OpenLayers.Event.observe(controls[i].panel_div,"dblclick",OpenLayers.Function.bind(this.onDoubleClick,this,controls[i]));OpenLayers.Event.observe(controls[i].panel_div,"mousedown",OpenLayers.Function.bindAsEventListener(OpenLayers.Event.stop));}
59758 if(this.map){this.addControlsToMap(controls);this.redraw();}},addControlsToMap:function(controls){var control;for(var i=0,len=controls.length;i<len;i++){control=controls[i];if(control.autoActivate===true){control.autoActivate=false;this.map.addControl(control);control.autoActivate=true;}else{this.map.addControl(control);control.deactivate();}
59759 control.events.on({"activate":this.redraw,"deactivate":this.redraw,scope:this});}},onClick:function(ctrl,evt){OpenLayers.Event.stop(evt?evt:window.event);this.activateControl(ctrl);},onDoubleClick:function(ctrl,evt){OpenLayers.Event.stop(evt?evt:window.event);},getControlsBy:function(property,match){var test=(typeof match.test=="function");var found=OpenLayers.Array.filter(this.controls,function(item){return item[property]==match||(test&&match.test(item[property]));});return found;},getControlsByName:function(match){return this.getControlsBy("name",match);},getControlsByClass:function(match){return this.getControlsBy("CLASS_NAME",match);},CLASS_NAME:"OpenLayers.Control.Panel"});OpenLayers.Control.Scale=OpenLayers.Class(OpenLayers.Control,{element:null,geodesic:false,initialize:function(element,options){OpenLayers.Control.prototype.initialize.apply(this,[options]);this.element=OpenLayers.Util.getElement(element);},draw:function(){OpenLayers.Control.prototype.draw.apply(this,arguments);if(!this.element){this.element=document.createElement("div");this.div.appendChild(this.element);}
59760 this.map.events.register('moveend',this,this.updateScale);this.updateScale();return this.div;},updateScale:function(){var scale;if(this.geodesic===true){var units=this.map.getUnits();if(!units){return;}
59761 var inches=OpenLayers.INCHES_PER_UNIT;scale=(this.map.getGeodesicPixelSize().w||0.000001)*inches["km"]*OpenLayers.DOTS_PER_INCH;}else{scale=this.map.getScale();}
59762 if(!scale){return;}
59763 if(scale>=9500&&scale<=950000){scale=Math.round(scale/1000)+"K";}else if(scale>=950000){scale=Math.round(scale/1000000)+"M";}else{scale=Math.round(scale);}
59764 this.element.innerHTML=OpenLayers.i18n("scale",{'scaleDenom':scale});},CLASS_NAME:"OpenLayers.Control.Scale"});OpenLayers.Control.ScaleLine=OpenLayers.Class(OpenLayers.Control,{maxWidth:100,topOutUnits:"km",topInUnits:"m",bottomOutUnits:"mi",bottomInUnits:"ft",eTop:null,eBottom:null,geodesic:false,initialize:function(options){OpenLayers.Control.prototype.initialize.apply(this,[options]);},draw:function(){OpenLayers.Control.prototype.draw.apply(this,arguments);if(!this.eTop){this.eTop=document.createElement("div");this.eTop.className=this.displayClass+"Top";var theLen=this.topInUnits.length;this.div.appendChild(this.eTop);if((this.topOutUnits=="")||(this.topInUnits=="")){this.eTop.style.visibility="hidden";}else{this.eTop.style.visibility="visible";}
59765 this.eBottom=document.createElement("div");this.eBottom.className=this.displayClass+"Bottom";this.div.appendChild(this.eBottom);if((this.bottomOutUnits=="")||(this.bottomInUnits=="")){this.eBottom.style.visibility="hidden";}else{this.eBottom.style.visibility="visible";}}
59766 this.map.events.register('moveend',this,this.update);this.update();return this.div;},getBarLen:function(maxLen){var digits=parseInt(Math.log(maxLen)/Math.log(10));var pow10=Math.pow(10,digits);var firstChar=parseInt(maxLen/pow10);var barLen;if(firstChar>5){barLen=5;}else if(firstChar>2){barLen=2;}else{barLen=1;}
59767 return barLen*pow10;},update:function(){var res=this.map.getResolution();if(!res){return;}
59768 var curMapUnits=this.map.getUnits();var inches=OpenLayers.INCHES_PER_UNIT;var maxSizeData=this.maxWidth*res*inches[curMapUnits];var geodesicRatio=1;if(this.geodesic===true){var maxSizeGeodesic=(this.map.getGeodesicPixelSize().w||0.000001)*this.maxWidth;var maxSizeKilometers=maxSizeData/inches["km"];geodesicRatio=maxSizeGeodesic/maxSizeKilometers;maxSizeData*=geodesicRatio;}
59769 var topUnits;var bottomUnits;if(maxSizeData>100000){topUnits=this.topOutUnits;bottomUnits=this.bottomOutUnits;}else{topUnits=this.topInUnits;bottomUnits=this.bottomInUnits;}
59770 var topMax=maxSizeData/inches[topUnits];var bottomMax=maxSizeData/inches[bottomUnits];var topRounded=this.getBarLen(topMax);var bottomRounded=this.getBarLen(bottomMax);topMax=topRounded/inches[curMapUnits]*inches[topUnits];bottomMax=bottomRounded/inches[curMapUnits]*inches[bottomUnits];var topPx=topMax/res/geodesicRatio;var bottomPx=bottomMax/res/geodesicRatio;if(this.eBottom.style.visibility=="visible"){this.eBottom.style.width=Math.round(bottomPx)+"px";this.eBottom.innerHTML=bottomRounded+" "+bottomUnits;}
59771 if(this.eTop.style.visibility=="visible"){this.eTop.style.width=Math.round(topPx)+"px";this.eTop.innerHTML=topRounded+" "+topUnits;}},CLASS_NAME:"OpenLayers.Control.ScaleLine"});OpenLayers.Control.ZoomIn=OpenLayers.Class(OpenLayers.Control,{type:OpenLayers.Control.TYPE_BUTTON,trigger:function(){this.map.zoomIn();},CLASS_NAME:"OpenLayers.Control.ZoomIn"});OpenLayers.Control.ZoomOut=OpenLayers.Class(OpenLayers.Control,{type:OpenLayers.Control.TYPE_BUTTON,trigger:function(){this.map.zoomOut();},CLASS_NAME:"OpenLayers.Control.ZoomOut"});OpenLayers.Control.ZoomToMaxExtent=OpenLayers.Class(OpenLayers.Control,{type:OpenLayers.Control.TYPE_BUTTON,trigger:function(){if(this.map){this.map.zoomToMaxExtent();}},CLASS_NAME:"OpenLayers.Control.ZoomToMaxExtent"});OpenLayers.Event={observers:false,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(event){return event.target||event.srcElement;},isLeftClick:function(event){return(((event.which)&&(event.which==1))||((event.button)&&(event.button==1)));},isRightClick:function(event){return(((event.which)&&(event.which==3))||((event.button)&&(event.button==2)));},stop:function(event,allowDefault){if(!allowDefault){if(event.preventDefault){event.preventDefault();}else{event.returnValue=false;}}
59772 if(event.stopPropagation){event.stopPropagation();}else{event.cancelBubble=true;}},findElement:function(event,tagName){var element=OpenLayers.Event.element(event);while(element.parentNode&&(!element.tagName||(element.tagName.toUpperCase()!=tagName.toUpperCase()))){element=element.parentNode;}
59773 return element;},observe:function(elementParam,name,observer,useCapture){var element=OpenLayers.Util.getElement(elementParam);useCapture=useCapture||false;if(name=='keypress'&&(navigator.appVersion.match(/Konqueror|Safari|KHTML/)||element.attachEvent)){name='keydown';}
59774 if(!this.observers){this.observers={};}
59775 if(!element._eventCacheID){var idPrefix="eventCacheID_";if(element.id){idPrefix=element.id+"_"+idPrefix;}
59776 element._eventCacheID=OpenLayers.Util.createUniqueID(idPrefix);}
59777 var cacheID=element._eventCacheID;if(!this.observers[cacheID]){this.observers[cacheID]=[];}
59778 this.observers[cacheID].push({'element':element,'name':name,'observer':observer,'useCapture':useCapture});if(element.addEventListener){element.addEventListener(name,observer,useCapture);}else if(element.attachEvent){element.attachEvent('on'+name,observer);}},stopObservingElement:function(elementParam){var element=OpenLayers.Util.getElement(elementParam);var cacheID=element._eventCacheID;this._removeElementObservers(OpenLayers.Event.observers[cacheID]);},_removeElementObservers:function(elementObservers){if(elementObservers){for(var i=elementObservers.length-1;i>=0;i--){var entry=elementObservers[i];var args=new Array(entry.element,entry.name,entry.observer,entry.useCapture);var removed=OpenLayers.Event.stopObserving.apply(this,args);}}},stopObserving:function(elementParam,name,observer,useCapture){useCapture=useCapture||false;var element=OpenLayers.Util.getElement(elementParam);var cacheID=element._eventCacheID;if(name=='keypress'){if(navigator.appVersion.match(/Konqueror|Safari|KHTML/)||element.detachEvent){name='keydown';}}
59779 var foundEntry=false;var elementObservers=OpenLayers.Event.observers[cacheID];if(elementObservers){var i=0;while(!foundEntry&&i<elementObservers.length){var cacheEntry=elementObservers[i];if((cacheEntry.name==name)&&(cacheEntry.observer==observer)&&(cacheEntry.useCapture==useCapture)){elementObservers.splice(i,1);if(elementObservers.length==0){delete OpenLayers.Event.observers[cacheID];}
59780 foundEntry=true;break;}
59781 i++;}}
59782 if(foundEntry){if(element.removeEventListener){element.removeEventListener(name,observer,useCapture);}else if(element&&element.detachEvent){element.detachEvent('on'+name,observer);}}
59783 return foundEntry;},unloadCache:function(){if(OpenLayers.Event&&OpenLayers.Event.observers){for(var cacheID in OpenLayers.Event.observers){var elementObservers=OpenLayers.Event.observers[cacheID];OpenLayers.Event._removeElementObservers.apply(this,[elementObservers]);}
59784 OpenLayers.Event.observers=false;}},CLASS_NAME:"OpenLayers.Event"};OpenLayers.Event.observe(window,'unload',OpenLayers.Event.unloadCache,false);if(window.Event){OpenLayers.Util.applyDefaults(window.Event,OpenLayers.Event);}else{var Event=OpenLayers.Event;}
59785 OpenLayers.Events=OpenLayers.Class({BROWSER_EVENTS:["mouseover","mouseout","mousedown","mouseup","mousemove","click","dblclick","rightclick","dblrightclick","resize","focus","blur"],listeners:null,object:null,element:null,eventTypes:null,eventHandler:null,fallThrough:null,includeXY:false,clearMouseListener:null,initialize:function(object,element,eventTypes,fallThrough,options){OpenLayers.Util.extend(this,options);this.object=object;this.fallThrough=fallThrough;this.listeners={};this.eventHandler=OpenLayers.Function.bindAsEventListener(this.handleBrowserEvent,this);this.clearMouseListener=OpenLayers.Function.bind(this.clearMouseCache,this);this.eventTypes=[];if(eventTypes!=null){for(var i=0,len=eventTypes.length;i<len;i++){this.addEventType(eventTypes[i]);}}
59786 if(element!=null){this.attachToElement(element);}},destroy:function(){if(this.element){OpenLayers.Event.stopObservingElement(this.element);if(this.element.hasScrollEvent){OpenLayers.Event.stopObserving(window,"scroll",this.clearMouseListener);}}
59787 this.element=null;this.listeners=null;this.object=null;this.eventTypes=null;this.fallThrough=null;this.eventHandler=null;},addEventType:function(eventName){if(!this.listeners[eventName]){this.eventTypes.push(eventName);this.listeners[eventName]=[];}},attachToElement:function(element){if(this.element){OpenLayers.Event.stopObservingElement(this.element);}
59788 this.element=element;for(var i=0,len=this.BROWSER_EVENTS.length;i<len;i++){var eventType=this.BROWSER_EVENTS[i];this.addEventType(eventType);OpenLayers.Event.observe(element,eventType,this.eventHandler);}
59789 OpenLayers.Event.observe(element,"dragstart",OpenLayers.Event.stop);},on:function(object){for(var type in object){if(type!="scope"){this.register(type,object.scope,object[type]);}}},register:function(type,obj,func){if((func!=null)&&(OpenLayers.Util.indexOf(this.eventTypes,type)!=-1)){if(obj==null){obj=this.object;}
59790 var listeners=this.listeners[type];listeners.push({obj:obj,func:func});}},registerPriority:function(type,obj,func){if(func!=null){if(obj==null){obj=this.object;}
59791 var listeners=this.listeners[type];if(listeners!=null){listeners.unshift({obj:obj,func:func});}}},un:function(object){for(var type in object){if(type!="scope"){this.unregister(type,object.scope,object[type]);}}},unregister:function(type,obj,func){if(obj==null){obj=this.object;}
59792 var listeners=this.listeners[type];if(listeners!=null){for(var i=0,len=listeners.length;i<len;i++){if(listeners[i].obj==obj&&listeners[i].func==func){listeners.splice(i,1);break;}}}},remove:function(type){if(this.listeners[type]!=null){this.listeners[type]=[];}},triggerEvent:function(type,evt){var listeners=this.listeners[type];if(!listeners||listeners.length==0){return;}
59793 if(evt==null){evt={};}
59794 evt.object=this.object;evt.element=this.element;if(!evt.type){evt.type=type;}
59795 var listeners=listeners.slice(),continueChain;for(var i=0,len=listeners.length;i<len;i++){var callback=listeners[i];continueChain=callback.func.apply(callback.obj,[evt]);if((continueChain!=undefined)&&(continueChain==false)){break;}}
59796 if(!this.fallThrough){OpenLayers.Event.stop(evt,true);}
59797 return continueChain;},handleBrowserEvent:function(evt){if(this.includeXY){evt.xy=this.getMousePosition(evt);}
59798 this.triggerEvent(evt.type,evt);},clearMouseCache:function(){this.element.scrolls=null;this.element.lefttop=null;this.element.offsets=null;},getMousePosition:function(evt){if(!this.includeXY){this.clearMouseCache();}else if(!this.element.hasScrollEvent){OpenLayers.Event.observe(window,"scroll",this.clearMouseListener);this.element.hasScrollEvent=true;}
59799 if(!this.element.scrolls){this.element.scrolls=[(document.documentElement.scrollLeft||document.body.scrollLeft),(document.documentElement.scrollTop||document.body.scrollTop)];}
59800 if(!this.element.lefttop){this.element.lefttop=[(document.documentElement.clientLeft||0),(document.documentElement.clientTop||0)];}
59801 if(!this.element.offsets){this.element.offsets=OpenLayers.Util.pagePosition(this.element);this.element.offsets[0]+=this.element.scrolls[0];this.element.offsets[1]+=this.element.scrolls[1];}
59802 return new OpenLayers.Pixel((evt.clientX+this.element.scrolls[0])-this.element.offsets[0]
59803 -this.element.lefttop[0],(evt.clientY+this.element.scrolls[1])-this.element.offsets[1]
59804 -this.element.lefttop[1]);},CLASS_NAME:"OpenLayers.Events"});OpenLayers.Format=OpenLayers.Class({options:null,externalProjection:null,internalProjection:null,data:null,keepData:false,initialize:function(options){OpenLayers.Util.extend(this,options);this.options=options;},destroy:function(){},read:function(data){OpenLayers.Console.userError(OpenLayers.i18n("readNotImplemented"));},write:function(object){OpenLayers.Console.userError(OpenLayers.i18n("writeNotImplemented"));},CLASS_NAME:"OpenLayers.Format"});OpenLayers.Lang["ar"]=OpenLayers.Util.applyDefaults({'permalink':"وصلة دائمة",'baseLayer':"الطبقة الاساسية",'readNotImplemented':"القراءة غير محققة.",'writeNotImplemented':"الكتابة غير محققة",'errorLoadingGML':"خطأ عند تحميل الملف جي ام ال ${url}",'scale':"النسبة = 1 : ${scaleDenom}",'W':"غ",'E':"شر",'N':"شم",'S':"ج"});OpenLayers.Lang["be-tarask"]=OpenLayers.Util.applyDefaults({'unhandledRequest':"Неапрацаваны вынік запыту ${statusText}",'permalink':"Сталая спасылка",'overlays':"Слаі",'baseLayer':"Базавы слой",'sameProjection':"Аглядная мапа працуе толькі калі яна мае тую ж праекцыю, што і асноўная мапа",'readNotImplemented':"Функцыянальнасьць чытаньня ня створаная.",'writeNotImplemented':"Функцыянальнасьць запісу ня створаная.",'noFID':"Немагчыма абнавіць магчымасьць, для якога не існуе FID.",'errorLoadingGML':"Памылка загрузкі файла GML ${url}",'browserNotSupported':"Ваш браўзэр не падтрымлівае вэктарную графіку. У цяперашні момант падтрымліваюцца: ${renderers}",'componentShouldBe':"addFeatures : кампанэнт павінен быць ${geomType}",'getFeatureError':"getFeatureFromEvent выкліканы для слоя бяз рэндэру. Звычайна гэта азначае, што Вы зьнішчылі слой, але пакінулі зьвязаны зь ім апрацоўшчык.",'minZoomLevelError':"Уласьцівасьць minZoomLevel прызначана толькі для выкарыстаньня са слаямі вытворнымі ад FixedZoomLevels. Тое, што  гэты wfs-слой правяраецца на minZoomLevel — рэха прошлага. Але мы ня можам выдаліць гэтую магчымасьць, таму што ад яе залежаць некаторыя заснаваныя на OL дастасаваньні. Тым ня менш, праверка minZoomLevel будзе выдаленая ў вэрсіі 3.0. Калі ласка, выкарыстоўваеце замест яе ўстаноўкі мінімальнага/максымальнага памераў, як апісана тут: http://trac.openlayers.org/wiki/SettingZoomLevels",'commitSuccess':"WFS-транзакцыя: ПОСЬПЕХ ${response}",'commitFailed':"WFS-транзакцыя: ПАМЫЛКА ${response}",'googleWarning':"Не атрымалася загрузіць слой Google. \x3cbr\x3e\x3cbr\x3eКаб пазбавіцца гэтага паведамленьня, выберыце новы базавы слой у сьпісе ў верхнім правым куце.\x3cbr\x3e\x3cbr\x3e Хутчэй за ўсё, прычына ў тым, што скрыпт бібліятэкі Google Maps ня быў уключаныя альбо не ўтрымлівае слушны API-ключ для Вашага сайта.\x3cbr\x3e\x3cbr\x3eРаспрацоўшчыкам: Для таго, каб даведацца як зрабіць так, каб усё працавала, \x3ca href=\'http://trac.openlayers.org/wiki/Google\' target=\'_blank\'\x3eнацісьніце тут\x3c/a\x3e",'getLayerWarning':"Немагчыма загрузіць слой ${layerType}.\x3cbr\x3e\x3cbr\x3eКаб пазбавіцца гэтага паведамленьня, выберыце новы базавы слой у сьпісе ў верхнім правым куце.\x3cbr\x3e\x3cbr\x3eХутчэй за ўсё, прычына ў тым, што скрыпт бібліятэкі ${layerLib} ня быў слушна ўключаны.\x3cbr\x3e\x3cbr\x3eРаспрацоўшчыкам: Для таго, каб даведацца як зрабіць так, каб усё працавала, \x3ca href=\'http://trac.openlayers.org/wiki/${layerLib}\' target=\'_blank\'\x3eнацісьніце тут\x3c/a\x3e",'scale':"Маштаб = 1 : ${scaleDenom}",'W':"З",'E':"У",'N':"Пн",'S':"Пд",'layerAlreadyAdded':"Вы паспрабавалі дадаць слой ${layerName} на мапу, але ён ужо дададзены",'reprojectDeprecated':"Вы выкарыстоўваеце ўстаноўку \'reproject\' для слоя ${layerName}. Гэтая ўстаноўка зьяўляецца састарэлай: яна выкарыстоўвалася для падтрымкі паказу зьвестак на камэрцыйных базавых мапах, але гэта функцыя цяпер рэалізаваная ў убудаванай падтрымцы сфэрычнай праекцыі Мэркатара. Дадатковая інфармацыя ёсьць на http://trac.openlayers.org/wiki/SphericalMercator.",'methodDeprecated':"Гэты мэтад састарэлы і будзе выдалены ў вэрсіі 3.0. Калі ласка, замест яго выкарыстоўвайце ${newMethod}.",'boundsAddError':"Вам неабходна падаць абодва значэньні x і y для функцыі складаньня.",'lonlatAddError':"Вам неабходна падаць абодва значэньні lon і lat для функцыі складаньня.",'pixelAddError':"Вам неабходна падаць абодва значэньні x і y для функцыі складаньня.",'unsupportedGeometryType':"Тып геамэтрыі не падтрымліваецца: ${geomType}",'pagePositionFailed':"OpenLayers.Util.pagePosition failed: верагодна элемэнт з ідэнтыфікатарам ${elemId} займае няслушнае месца.",'filterEvaluateNotImplemented':"evaluate не рэалізаваны для гэтага тыпу фільтру."});OpenLayers.Lang["bg"]=OpenLayers.Util.applyDefaults({'permalink':"Постоянна препратка",'baseLayer':"Основен слой",'errorLoadingGML':"Грешка при зареждане на GML файл ${url}",'scale':"Мащаб = 1 : ${scaleDenom}",'layerAlreadyAdded':"Опитахте да добавите слой ${layerName} в картата, но той вече е добавен",'methodDeprecated':"Този метод е остарял и ще бъде премахват в 3.0. Вместо него използвайте ${newMethod}."});OpenLayers.Lang["br"]=OpenLayers.Util.applyDefaults({'unhandledRequest':"Distro evel reked anveret ${statusText}",'permalink':"Peurliamm",'overlays':"Gwiskadoù",'baseLayer':"Gwiskad diazez",'sameProjection':"Ne\'z ar gartenn lec\'hiañ en-dro nemet pa vez heñvel ar banndres anezhi ha hini ar gartenn bennañ",'readNotImplemented':"N\'eo ket emplementet al lenn.",'writeNotImplemented':"N\'eo ket emplementet ar skrivañ.",'noFID':"N\'haller ket hizivaat un elfenn ma n\'eus ket a niverenn-anaout (FID) eviti.",'errorLoadingGML':"Fazi e-ser kargañ ar restr GML ${url}",'browserNotSupported':"N\'eo ket skoret an daskor vektorel gant ho merdeer. Setu aze an daskorerioù skoret evit ar poent :\n${renderers}",'componentShouldBe':"addFeatures : bez\' e tlefe ar parzh besañ eus ar seurt ${geomType}",'getFeatureError':"Galvet eo bet getFeatureFromEvent called war ur gwiskad hep daskorer. Kement-se a dalvez ez eus bet freuzet ur gwiskad hag hoc\'h eus miret un embreger bennak stag outañ.",'minZoomLevelError':"Ne zleer implijout ar perzh minZoomLevel nemet evit gwiskadoù FixedZoomLevels-descendent. Ar fed ma wiria ar gwiskad WHS-se hag-eñ ez eus eus minZoomLevel zo un aspadenn gozh. Koulskoude n\'omp ket evit e ziverkañ kuit da derriñ arloadoù diazezet war OL a c\'hallfe bezañ stag outañ. Setu perak eo dispredet -- Lamet kuit e vo ar gwiriañ minZoomLevel a-is er stumm 3.0. Ober gant an arventennoù bihanañ/brasañ evel deskrivet amañ e plas : http://trac.openlayers.org/wiki/SettingZoomLevels",'commitSuccess':"Treuzgread WFS : MAT EO ${response}",'commitFailed':"Treuzgread WFS Transaction: C\'HWITET ${response}",'googleWarning':"N\'eus ket bet gallet kargañ ar gwiskad Google ent reizh.\x3cbr\x3e\x3cbr\x3eEvit en em zizober eus ar c\'hemenn-mañ, dibabit ur BaseLayer nevez en diuzer gwiskadoù er c\'horn dehoù el laez.\x3cbr\x3e\x3cbr\x3eSur a-walc\'h eo peogwir n\'eo ket bet ensoc\'het levraoueg Google Maps pe neuze ne glot ket an alc\'hwez API gant ho lec\'hienn.\x3cbr\x3e\x3cbr\x3eDiorroerien : Evit reizhañ an dra-se, \x3ca href=\'http://trac.openlayers.org/wiki/Google\' target=\'_blank\'\x3eclick here\x3c/a\x3e",'getLayerWarning':"N\'haller ket kargañ ar gwiskad ${layerType} ent reizh.\x3cbr\x3e\x3cbr\x3eEvit en em zizober eus ar c\'hemenn-mañ, dibabit ur BaseLayer nevez en diuzer gwiskadoù er c\'horn dehoù el laez.\x3cbr\x3e\x3cbr\x3eSur a-walc\'h eo peogwir n\'eo ket bet ensoc\'het mat al levraoueg ${layerLib}.\x3cbr\x3e\x3cbr\x3eDiorroerien : Evit gouzout penaos reizhañ an dra-se, \x3ca href=\'http://trac.openlayers.org/wiki/${layerLib}\' target=\'_blank\'\x3eclick here\x3c/a\x3e",'scale':"Skeul = 1 : ${scaleDenom}",'W':"K",'E':"R",'N':"N",'S':"S",'layerAlreadyAdded':"Klasket hoc\'h eus ouzhpennañ ar gwiskad : ${layerName} d\'ar gartenn, met ouzhpennet e oa bet c\'hoazh",'reprojectDeprecated':"Emaoc\'h oc\'h implijout an dibarzh \'reproject\' war ar gwiskad ${layerName}. Dispredet eo an dibarzh-mañ : bet eo hag e talveze da ziskwel roadennoù war-c\'horre kartennoù diazez kenwerzhel, un dra hag a c\'haller ober bremañ gant an arc\'hwel dre skor banndres boullek Mercator. Muioc\'h a ditouroù a c\'haller da gaout war http://trac.openlayers.org/wiki/SphericalMercator.",'methodDeprecated':"Dispredet eo an daore-se ha tennet e vo kuit eus ar stumm 3.0. Grit gant ${newMethod} e plas.",'boundsAddError':"Rekis eo tremen an div dalvoudenn x ha y d\'an arc\'hwel add.",'lonlatAddError':"Rekis eo tremen an div dalvoudenn hedred ha ledred d\'an arc\'hwel add.",'pixelAddError':"Rekis eo tremen an div dalvoudenn x ha y d\'an arc\'hwel add.",'unsupportedGeometryType':"Seurt mentoniezh anskoret : ${geomType}",'pagePositionFailed':"C\'hwitet eo OpenLayers.Util.pagePosition : marteze emañ lec\'hiet fall an elfenn id ${elemId}.",'filterEvaluateNotImplemented':"N\'eo ket bet emplementet ar priziañ evit seurt siloù c\'hoazh."});OpenLayers.Lang["el"]=OpenLayers.Util.applyDefaults({'scale':"Κλίμακα ~ 1 : ${scaleDenom}"});OpenLayers.Lang.en={'unhandledRequest':"Unhandled request return ${statusText}",'permalink':"Permalink",'overlays':"Overlays",'baseLayer':"Base Layer",'sameProjection':"The overview map only works when it is in the same projection as the main map",'readNotImplemented':"Read not implemented.",'writeNotImplemented':"Write not implemented.",'noFID':"Can't update a feature for which there is no FID.",'errorLoadingGML':"Error in loading GML file ${url}",'browserNotSupported':"Your browser does not support vector rendering. Currently supported renderers are:\n${renderers}",'componentShouldBe':"addFeatures : component should be an ${geomType}",'getFeatureError':"getFeatureFromEvent called on layer with no renderer. This usually means you "+"destroyed a layer, but not some handler which is associated with it.",'minZoomLevelError':"The minZoomLevel property is only intended for use "+"with the FixedZoomLevels-descendent layers. That this "+"wfs layer checks for minZoomLevel is a relic of the"+"past. We cannot, however, remove it without possibly "+"breaking OL based applications that may depend on it."+" Therefore we are deprecating it -- the minZoomLevel "+"check below will be removed at 3.0. Please instead "+"use min/max resolution setting as described here: "+"http://trac.openlayers.org/wiki/SettingZoomLevels",'commitSuccess':"WFS Transaction: SUCCESS ${response}",'commitFailed':"WFS Transaction: FAILED ${response}",'googleWarning':"The Google Layer was unable to load correctly.<br><br>"+"To get rid of this message, select a new BaseLayer "+"in the layer switcher in the upper-right corner.<br><br>"+"Most likely, this is because the Google Maps library "+"script was either not included, or does not contain the "+"correct API key for your site.<br><br>"+"Developers: For help getting this working correctly, "+"<a href='http://trac.openlayers.org/wiki/Google' "+"target='_blank'>click here</a>",'getLayerWarning':"The ${layerType} Layer was unable to load correctly.<br><br>"+"To get rid of this message, select a new BaseLayer "+"in the layer switcher in the upper-right corner.<br><br>"+"Most likely, this is because the ${layerLib} library "+"script was not correctly included.<br><br>"+"Developers: For help getting this working correctly, "+"<a href='http://trac.openlayers.org/wiki/${layerLib}' "+"target='_blank'>click here</a>",'scale':"Scale = 1 : ${scaleDenom}",'W':'W','E':'E','N':'N','S':'S','graticule':'Graticule','layerAlreadyAdded':"You tried to add the layer: ${layerName} to the map, but it has already been added",'reprojectDeprecated':"You are using the 'reproject' option "+"on the ${layerName} layer. This option is deprecated: "+"its use was designed to support displaying data over commercial "+"basemaps, but that functionality should now be achieved by using "+"Spherical Mercator support. More information is available from "+"http://trac.openlayers.org/wiki/SphericalMercator.",'methodDeprecated':"This method has been deprecated and will be removed in 3.0. "+"Please use ${newMethod} instead.",'boundsAddError':"You must pass both x and y values to the add function.",'lonlatAddError':"You must pass both lon and lat values to the add function.",'pixelAddError':"You must pass both x and y values to the add function.",'unsupportedGeometryType':"Unsupported geometry type: ${geomType}",'pagePositionFailed':"OpenLayers.Util.pagePosition failed: element with id ${elemId} may be misplaced.",'filterEvaluateNotImplemented':"evaluate is not implemented for this filter type.",'end':''};OpenLayers.Lang["fi"]=OpenLayers.Util.applyDefaults({'permalink':"Ikilinkki",'overlays':"Kerrokset",'baseLayer':"Peruskerros",'sameProjection':"Yleiskuvakarttaa voi käyttää vain, kun sillä on sama projektio kuin pääkartalla.",'W':"L",'E':"I",'N':"P",'S':"E"});OpenLayers.Lang["fur"]=OpenLayers.Util.applyDefaults({'permalink':"Leam Permanent",'overlays':"Livei parsore",'baseLayer':"Livel di base",'browserNotSupported':"Il to sgarfadôr nol supuarte la renderizazion vetoriâl. Al moment a son supuartâts:\n${renderers}",'scale':"Scjale = 1 : ${scaleDenom}",'W':"O",'E':"E",'N':"N",'S':"S"});OpenLayers.Lang["gl"]=OpenLayers.Util.applyDefaults({'unhandledRequest':"Solicitude non xerada; a resposta foi: ${statusText}",'permalink':"Ligazón permanente",'overlays':"Capas superpostas",'baseLayer':"Capa base",'sameProjection':"A vista xeral do mapa só funciona cando está na mesma proxección có mapa principal",'readNotImplemented':"Lectura non implementada.",'writeNotImplemented':"Escritura non implementada.",'noFID':"Non se pode actualizar a funcionalidade para a que non hai FID.",'errorLoadingGML':"Erro ao cargar o ficheiro GML ${url}",'browserNotSupported':"O seu navegador non soporta a renderización de vectores. Os renderizadores soportados actualmente son:\n${renderers}",'componentShouldBe':"addFeatures: o compoñente debera ser de tipo ${geomType}",'getFeatureError':"getFeatureFromEvent ten sido chamado a unha capa sen renderizador. Isto normalmente significa que destruíu unha capa, mais non o executador que está asociado con ela.",'minZoomLevelError':"A propiedade minZoomLevel é só para uso conxuntamente coas capas FixedZoomLevels-descendent. O feito de que esa capa wfs verifique o minZoomLevel é unha reliquia do pasado. Non podemos, con todo, eliminala sen a posibilidade de non romper as aplicacións baseadas en OL que poidan depender dela. Por iso a estamos deixando obsoleta (a comprobación minZoomLevel de embaixo será eliminada na versión 3.0). Por favor, no canto diso use o axuste de resolución mín/máx tal e como está descrito aquí: http://trac.openlayers.org/wiki/SettingZoomLevels",'commitSuccess':"Transacción WFS: ÉXITO ${response}",'commitFailed':"Transacción WFS: FALLIDA ${response}",'googleWarning':"A capa do Google non puido cargarse correctamente.\x3cbr\x3e\x3cbr\x3ePara evitar esta mensaxe, escolla unha nova capa base no seleccionador de capas na marxe superior dereita.\x3cbr\x3e\x3cbr\x3eProbablemente, isto acontece porque a escritura da libraría do Google Maps ou ben non foi incluída ou ben non contén a clave API correcta para o seu sitio.\x3cbr\x3e\x3cbr\x3eDesenvolvedores: para axudar a facer funcionar isto correctamente, \x3ca href=\'http://trac.openlayers.org/wiki/Google\' target=\'_blank\'\x3epremede aquí\x3c/a\x3e",'getLayerWarning':"A capa ${layerType} foi incapaz de cargarse correctamente.\x3cbr\x3e\x3cbr\x3ePara evitar esta mensaxe, escolla unha nova capa base no seleccionador de capas na marxe superior dereita.\x3cbr\x3e\x3cbr\x3eProbablemente, isto acontece porque a escritura da libraría ${layerLib} non foi ben incluída.\x3cbr\x3e\x3cbr\x3eDesenvolvedores: para axudar a facer funcionar isto correctamente, \x3ca href=\'http://trac.openlayers.org/wiki/${layerLib}\' target=\'_blank\'\x3epremede aquí\x3c/a\x3e",'scale':"Escala = 1 : ${scaleDenom}",'W':"O",'E':"L",'N':"N",'S':"S",'layerAlreadyAdded':"Intentou engadir a capa: ${layerName} ao mapa, pero xa fora engadida",'reprojectDeprecated':"Está usando a opción \"reproject\" na capa ${layerName}. Esta opción está obsoleta: o seu uso foi deseñado para a visualización de datos sobre mapas base comerciais, pero esta funcionalidade debera agora ser obtida utilizando a proxección Spherical Mercator. Hai dispoñible máis información en http://trac.openlayers.org/wiki/SphericalMercator.",'methodDeprecated':"Este método está obsoleto e será eliminado na versión 3.0. Por favor, no canto deste use ${newMethod}.",'boundsAddError':"Debe achegar os valores x e y á función add.",'lonlatAddError':"Debe achegar tanto o valor lon coma o lat á función add.",'pixelAddError':"Debe achegar os valores x e y á función add.",'unsupportedGeometryType':"Tipo xeométrico non soportado: ${geomType}",'pagePositionFailed':"OpenLayers.Util.pagePosition fallou: o elemento con id ${elemId} pode non estar na súa posición.",'filterEvaluateNotImplemented':"avaliar non está implementado para este tipo de filtro."});OpenLayers.Lang["gsw"]=OpenLayers.Util.applyDefaults({'unhandledRequest':"Nit behandleti Aafrogsruckmäldig ${statusText}",'permalink':"Permalink",'overlays':"Iberlagerige",'baseLayer':"Grundcharte",'sameProjection':"D Ibersichts-Charte funktioniert nume, wänn si di glych Projäktion brucht wie d Hauptcharte",'readNotImplemented':"Läse nit implementiert.",'writeNotImplemented':"Schrybe nit implementiert.",'noFID':"E Feature, wu s kei FID derfir git, cha nit aktualisiert wäre.",'errorLoadingGML':"Fähler bim Lade vu dr GML-Datei ${url}",'browserNotSupported':"Dyy Browser unterstitzt kei Vektordarstellig. Aktuäll unterstitzti Renderer:\n${renderers}",'componentShouldBe':"addFeatures : Komponänt sott dr Typ ${geomType} syy",'getFeatureError':"getFeatureFromEvent isch uf eme Layer ohni Renderer ufgruefe wore. Des heisst normalerwys, ass Du e Layer kaputt gmacht hesch, aber nit dr Handler, wu derzue ghert.",'minZoomLevelError':"D minZoomLevel-Eigeschaft isch nume dänk fir d Layer, wu vu dr FixedZoomLevels abstamme. Ass dää wfs-Layer minZoomLevel prieft, scih e Relikt us dr Vergangeheit. Mir chenne s aber nit ändere ohni OL_basierti Aawändige villicht kaputt gehn, wu dervu abhänge.  Us däm Grund het die Funktion d Eigeschaft \'deprecated\' iberchuu. D minZoomLevel-Priefig unte wird in dr Version 3.0 usegnuu. Bitte verwänd statt däm e min/max-Uflesig wie s do bschriben isch: http://trac.openlayers.org/wiki/SettingZoomLevels",'commitSuccess':"WFS-Transaktion: ERFOLGRYCH ${response}",'commitFailed':"WFS-Transaktion: FÄHLGSCHLAA ${response}",'googleWarning':"Dr Google-Layer het nit korräkt chenne glade wäre.\x3cbr\x3e\x3cbr\x3eGo die Mäldig nimi z kriege, wehl e andere Hintergrundlayer us em LayerSwitcher im rächte obere Ecke.\x3cbr\x3e\x3cbr\x3eDää Fähler git s seli hyfig, wel s Skript vu dr Google-Maps-Bibliothek nit yybunde woren isch oder wel s kei giltige API-Schlissel fir Dyy URL din het.\x3cbr\x3e\x3cbr\x3eEntwickler: Fir Hilf zum korräkte Yybinde vum Google-Layer \x3ca href=\'http://trac.openlayers.org/wiki/Google\' target=\'_blank\'\x3edoo drucke\x3c/a\x3e",'getLayerWarning':"Dr ${layerType}-Layer het nit korräkt chenne glade wäre.\x3cbr\x3e\x3cbr\x3eGo die Mäldig nimi z kriege, wehl e andere Hintergrundlayer us em LayerSwitcher im rächte obere Ecke.\x3cbr\x3e\x3cbr\x3eDää Fähler git s seli hyfig, wel s Skript vu dr \'${layerLib}\'-Bibliothek nit yybunde woren isch oder wel s kei giltige API-Schlissel fir Dyy URL din het.\x3cbr\x3e\x3cbr\x3eEntwickler: Fir Hilf zum korräkte Yybinde vu Layer \x3ca href=\'http://trac.openlayers.org/wiki/${layerLib}\' target=\'_blank\'\x3edoo drucke\x3c/a\x3e",'scale':"Maßstab = 1 : ${scaleDenom}",'W':"W",'E':"O",'N':"N",'S':"S",'layerAlreadyAdded':"Du hesch versuecht dää Layer in d Charte yyzfiege: ${layerName}, aber är isch schoi yygfiegt",'reprojectDeprecated':"Du bruchsch d \'reproject\'-Option bim ${layerName}-Layer. Die Option isch nimi giltig: si isch aagleit wore go   Date iber kommerziälli Grundcharte lege, aber des sott mer jetz mache mit dr Unterstitzig vu Spherical Mercator. Meh Informatione git s uf http://trac.openlayers.org/wiki/SphericalMercator.",'methodDeprecated':"Die Methode isch veraltet un wird us dr Version 3.0 usegnuu. Bitte verwäbnd statt däm ${newMethod}.",'boundsAddError':"Du muesch e x-Wärt un e y-Wärt yygee bi dr Zuefieg-Funktion",'lonlatAddError':"Du meusch e Lengi- un e Breiti-Grad yygee bi dr Zuefieg-Funktion.",'pixelAddError':"Du muesch x- un y-Wärt aagee bi dr Zuefieg-Funktion.",'unsupportedGeometryType':"Nit unterstitze Geometrii-Typ: ${geomType}",'pagePositionFailed':"OpenLayers.Util.pagePosition fählgschlaa: Elemänt mit ID ${elemId} isch villicht falsch gsetzt.",'filterEvaluateNotImplemented':"evaluiere isch nit implemäntiert in däm Filtertyp."});OpenLayers.Lang["hr"]=OpenLayers.Util.applyDefaults({'unhandledRequest':"Nepodržani zahtjev ${statusText}",'permalink':"Permalink",'overlays':"Overlays",'baseLayer':"Osnovna karta",'sameProjection':"Pregledna karta radi jedino kao je u istoj projekciji kao i glava karta",'readNotImplemented':"Čitanje nije implementirano.",'writeNotImplemented':"Pisanje nije implementirano.",'noFID':"Ne mogu ažurirati značajku za koju ne postoji FID.",'errorLoadingGML':"Greška u učitavanju GML datoteke ${url}",'browserNotSupported':"Vaš preglednik ne podržava vektorsko renderiranje. Trenutno podržani rendereri su: ${renderers}",'componentShouldBe':"addFeatures : komponenta bi trebala biti ${geomType}",'getFeatureError':"getFeatureFromEvent je pozvao Layer bez renderera. Ovo obično znači da ste uništiili Layer, a ne neki Handler koji je povezan s njim.",'commitSuccess':"WFS Transakcija: USPJEŠNA ${response}",'commitFailed':"WFS Transakcija: NEUSPJEŠNA ${response}",'scale':"Mjerilo = 1 : ${scaleDenom}",'layerAlreadyAdded':"Pokušali ste dodati layer:  ${layerName} na kartu, ali je već dodan",'methodDeprecated':"Ova metoda nije odobrena i biti će maknuta u 3.0. Koristite ${newMethod}.",'boundsAddError':"Morate dati obje vrijednosti ,  x i y  da bi dodali funkciju.",'lonlatAddError':"Morate dati obje vrijednosti , (lon i lat) da bi dodali funkciju.",'pixelAddError':"Morate dati obje vrijednosti ,  x i y  da bi dodali funkciju.",'unsupportedGeometryType':"Nepodržani tip geometrije: ${geomType}",'pagePositionFailed':"OpenLayers.Util.pagePosition nije uspjelo: element sa id ${elemId} može biti krivo smješten."});OpenLayers.Lang["hsb"]=OpenLayers.Util.applyDefaults({'unhandledRequest':"Wotmołwa njewobdźěłaneho naprašowanja ${statusText}",'permalink':"Trajny wotkaz",'overlays':"Naworštowanja",'baseLayer':"Zakładna runina",'sameProjection':"Přehladowa karta jenož funguje, hdyž je w samsnej projekciji kaž hłowna karta",'readNotImplemented':"Čitanje njeimplementowane.",'writeNotImplemented':"Pisanje njeimplementowane.",'noFID':"Funkcija, za kotruž FID njeje, njeda so aktualizować.",'errorLoadingGML':"Zmylk při začitowanju dataje ${url}",'browserNotSupported':"Twój wobhladowak wektorowe rysowanje njepodpěruje. Tuchwilu podpěrowane rysowaki su:\n${renderers}",'componentShouldBe':"addFeatures: komponenta měła ${geomType} być",'getFeatureError':"getFeatureFromEvent bu na woršće bjez rysowak zawołany. To zwjetša woznamjenja, zo sy worštu zničił, ale nic wobdźěłak, kotryž je z njej zwjazany.",'minZoomLevelError':"Kajkosć minZoomLevel je jenož za wužiwanje z worštami myslena, kotrež wot FixedZoomLevels pochadźeja. Zo tuta woršta wfs za minZoomLevel přepruwuje, je relikt zańdźenosće. Njemóžemy wšak ju wotstronić, bjeztoho zo aplikacije, kotrež na OpenLayers bazěruja a snano tutu kajkosć wužiwaja, hižo njefunguja. Tohodla smy ju jako zestarjenu woznamjenili -- přepruwowanje za minZoomLevel budu so we wersiji 3.0 wotstronjeć. Prošu wužij město toho nastajenje min/max, kaž je tu wopisane: http://trac.openlayers.org/wiki/SettingZoomLevels",'commitSuccess':"WFS-Transakcija: WUSPĚŠNA ${response}",'commitFailed':"WFS-Transakcija: NJEPORADŹENA ${response}",'googleWarning':"Woršta Google njemóžeše so korektnje začitać.\x3cbr\x3e\x3cbr\x3eZo by tutu zdźělenku wotbył, wubjer nowy BaseLayer z wuběra worštow horjeka naprawo.\x3cbr\x3e\x3cbr\x3eNajskerje so to stawa, dokelž skript biblioteki Google Maps pak njebu zapřijaty pak njewobsahuje korektny kluč API za twoje sydło.\x3cbr\x3e\x3cbr\x3eWuwiwarjo: Za pomoc ke korektnemu fungowanju worštow\n\x3ca href=\'http://trac.openlayers.org/wiki/Google\' target=\'_blank\'\x3etu kliknyć\x3c/a\x3e",'getLayerWarning':"Woršta ${layerType} njemóžeše so korektnje začitać.\x3cbr\x3e\x3cbr\x3eZo by tutu zdźělenku wotbył, wubjer nowy BaseLayer z wuběra worštow horjeka naprawo.\x3cbr\x3e\x3cbr\x3eNajskerje so to stawa, dokelž skript biblioteki ${layerLib} njebu korektnje zapřijaty.\x3cbr\x3e\x3cbr\x3eWuwiwarjo: Za pomoc ke korektnemu fungowanju worštow\n\x3ca href=\'http://trac.openlayers.org/wiki/${layerLib}\' target=\'_blank\'\x3etu kliknyć\x3c/a\x3e",'scale':"Měritko = 1 : ${scaleDenom}",'W':"Z",'E':"W",'N':"S",'S':"J",'layerAlreadyAdded':"Sy spytał runinu ${layerName} karće dodać, ale je so hižo dodała",'reprojectDeprecated':"Wužiwaš opciju \"reproject\" wořšty ${layerName}. Tuta opcija je zestarjena: jeje wužiwanje bě myslene, zo by zwobraznjenje datow nad komercielnymi bazowymi kartami podpěrało, ale funkcionalnosć měła so nětko z pomocu Sperical Mercator docpěć. Dalše informacije steja na http://trac.openlayers.org/wiki/SphericalMercator k dispoziciji.",'methodDeprecated':"Tuta metoda je so njeschwaliła a budźe so w 3.0 wotstronjeć. Prošu wužij ${newMethod} město toho.",'boundsAddError':"Dyrbiš hódnotu x kaž tež y funkciji \"add\" přepodać.",'lonlatAddError':"Dyrbiš hódnotu lon kaž tež lat funkciji \"add\" přepodać.",'pixelAddError':"Dyrbiš hódnotu x kaž tež y funkciji \"add\" přepodać.",'unsupportedGeometryType':"Njepodpěrowany geometrijowy typ: ${geomType}",'pagePositionFailed':"OpenLayers.Util.pagePosition je so njeporadźił: element z id ${elemId} bu snano wopak zaměstnjeny.",'filterEvaluateNotImplemented':"wuhódnoćenje njeje za tutón filtrowy typ implementowany."});OpenLayers.Lang["hu"]=OpenLayers.Util.applyDefaults({'unhandledRequest':"Nem kezelt kérés visszatérése ${statusText}",'permalink':"Permalink",'overlays':"Rávetítések",'baseLayer':"Alapréteg",'sameProjection':"Az áttekintő térkép csak abban az esetben működik, ha ugyanazon a vetületen van, mint a fő térkép.",'readNotImplemented':"Olvasás nincs végrehajtva.",'writeNotImplemented':"Írás nincs végrehajtva.",'noFID':"Nem frissíthető olyan jellemző, amely nem rendelkezik FID-del.",'errorLoadingGML':"Hiba GML-fájl betöltésekor ${url}",'browserNotSupported':"A böngészője nem támogatja a vektoros renderelést. A jelenleg támogatott renderelők:\n${renderers}",'componentShouldBe':"addFeatures : az összetevőnek ilyen típusúnak kell lennie: ${geomType}",'getFeatureError':"getFeatureFromEvent réteget hívott meg renderelő nélkül. Ez rendszerint azt jelenti, hogy megsemmisített egy fóliát, de néhány ahhoz társított kezelőt nem.",'minZoomLevelError':"A minZoomLevel tulajdonságot csak a következővel való használatra szánták: FixedZoomLevels-leszármazott fóliák. Ez azt jelenti, hogy a minZoomLevel wfs fólia jelölőnégyzetei már a múlté. Mi azonban nem távolíthatjuk el annak a veszélye nélkül, hogy az esetlegesen ettől függő OL alapú alkalmazásokat tönkretennénk. Ezért ezt érvénytelenítjük -- a minZoomLevel az alul levő jelölőnégyzet a 3.0-s verzióból el lesz távolítva. Kérjük, helyette használja a  min/max felbontás beállítást, amelyről az alábbi helyen talál leírást: http://trac.openlayers.org/wiki/SettingZoomLevels",'commitSuccess':"WFS tranzakció: SIKERES ${response}",'commitFailed':"WFS tranzakció: SIKERTELEN ${response}",'googleWarning':"A Google fólia betöltése sikertelen.\x3cbr\x3e\x3cbr\x3eAhhoz, hogy ez az üzenet eltűnjön, válasszon egy új BaseLayer fóliát a jobb felső sarokban található fóliakapcsoló segítségével.\x3cbr\x3e\x3cbr\x3eNagy valószínűséggel ez azért van, mert a Google Maps könyvtár parancsfájlja nem található, vagy nem tartalmazza az Ön oldalához tartozó megfelelő API-kulcsot.\x3cbr\x3e\x3cbr\x3eFejlesztőknek: A helyes működtetésre vonatkozó segítség az alábbi helyen érhető el, \x3ca href=\'http://trac.openlayers.org/wiki/Google\' target=\'_blank\'\x3ekattintson ide\x3c/a\x3e",'getLayerWarning':"A(z) ${layerType} fólia nem töltődött be helyesen.\x3cbr\x3e\x3cbr\x3eAhhoz, hogy ez az üzenet eltűnjön, válasszon egy új BaseLayer fóliát a jobb felső sarokban található fóliakapcsoló segítségével.\x3cbr\x3e\x3cbr\x3eNagy valószínűséggel ez azért van, mert a(z) ${layerLib} könyvtár parancsfájlja helytelen.\x3cbr\x3e\x3cbr\x3eFejlesztőknek: A helyes működtetésre vonatkozó segítség az alábbi helyen érhető el, \x3ca href=\'http://trac.openlayers.org/wiki/${layerLib}\' target=\'_blank\'\x3ekattintson ide\x3c/a\x3e",'scale':"Lépték = 1 : ${scaleDenom}",'W':"Ny",'E':"K",'N':"É",'S':"D",'layerAlreadyAdded':"Megpróbálta hozzáadni a(z) ${layerName} fóliát a térképhez, de az már hozzá van adva",'reprojectDeprecated':"Ön a \'reproject\' beállítást használja a(z) ${layerName} fólián. Ez a beállítás érvénytelen: használata az üzleti alaptérképek fölötti adatok megjelenítésének támogatására szolgált, de ezt a funkció ezentúl a Gömbi Mercator használatával érhető el. További információ az alábbi helyen érhető el: http://trac.openlayers.org/wiki/SphericalMercator",'methodDeprecated':"Ez a módszer érvénytelenítve lett és a 3.0-s verzióból el lesz távolítva. Használja a(z) ${newMethod} módszert helyette.",'boundsAddError':"Az x és y értékeknek egyaránt meg kell felelnie, hogy a funkciót hozzáadhassa.",'lonlatAddError':"A hossz. és szél. értékeknek egyaránt meg kell felelnie, hogy a funkciót hozzáadhassa.",'pixelAddError':"Az x és y értékeknek egyaránt meg kell felelnie, hogy a funkciót hozzáadhassa.",'unsupportedGeometryType':"Nem támogatott geometriatípus: ${geomType}",'pagePositionFailed':"OpenLayers.Util.pagePosition sikertelen: lehetséges, hogy a(z) ${elemId} azonosítójú elem téves helyre került.",'filterEvaluateNotImplemented':"ennél a szűrőtípusnál kiértékelés nem hajtódik végre."});OpenLayers.Lang["ia"]=OpenLayers.Util.applyDefaults({'unhandledRequest':"Le responsa a un requesta non esseva maneate: ${statusText}",'permalink':"Permaligamine",'overlays':"Superpositiones",'baseLayer':"Strato de base",'sameProjection':"Le mini-carta functiona solmente si illo es in le mesme projection que le carta principal",'readNotImplemented':"Lectura non implementate.",'writeNotImplemented':"Scriptura non implementate.",'noFID':"Non pote actualisar un elemento sin FID.",'errorLoadingGML':"Error al cargamento del file GML ${url}",'browserNotSupported':"Tu navigator non supporta le rendition de vectores. Le renditores actualmente supportate es:\n${renderers}",'componentShouldBe':"addFeatures: le componente debe esser del typo ${geomType}",'getFeatureError':"getFeatureFromEvent ha essite appellate in un strato sin renditor. Isto significa generalmente que tu ha destruite un strato, ma lassava un gestor associate con illo.",'minZoomLevelError':"Le proprietate minZoomLevel es solmente pro uso con le stratos descendente de FixedZoomLevels. Le facto que iste strato WFS verifica minZoomLevel es un reliquia del passato. Nonobstante, si nos lo remove immediatemente, nos pote rumper applicationes a base de OL que depende de illo. Ergo nos lo declara obsolete; le verification de minZoomLevel in basso essera removite in version 3.0. Per favor usa in su loco le configuration de resolutiones min/max como describite a: http://trac.openlayers.org/wiki/SettingZoomLevels",'commitSuccess':"Transaction WFS: SUCCESSO ${response}",'commitFailed':"Transaction WFS: FALLEVA ${response}",'googleWarning':"Le strato Google non poteva esser cargate correctemente.\x3cbr\x3e\x3cbr\x3ePro disfacer te de iste message, selige un nove BaseLayer in le selector de strato in alto a dextra.\x3cbr\x3e\x3cbr\x3eMulto probabilemente, isto es proque le script del libreria de Google Maps non esseva includite o non contine le clave API correcte pro tu sito.\x3cbr\x3e\x3cbr\x3eDisveloppatores: Pro adjuta de corriger isto, \x3ca href=\'http://trac.openlayers.org/wiki/Google\' target=\'_blank\'\x3eclicca hic\x3c/a",'getLayerWarning':"Le strato ${layerType} non poteva esser cargate correctemente.\x3cbr\x3e\x3cbr\x3ePro disfacer te de iste message, selige un nove BaseLayer in le selector de strato in alto a dextra.\x3cbr\x3e\x3cbr\x3eMulto probabilemente, isto es proque le script del libreria de ${layerLib} non esseva correctemente includite.\x3cbr\x3e\x3cbr\x3eDisveloppatores: Pro adjuta de corriger isto, \x3ca href=\'http://trac.openlayers.org/wiki/${layerLib}\' target=\'_blank\'\x3eclicca hic\x3c/a\x3e",'scale':"Scala = 1 : ${scaleDenom}",'W':"W",'E':"E",'N':"N",'S':"S",'layerAlreadyAdded':"Tu tentava adder le strato: ${layerName} al carta, ma illo es ja presente",'reprojectDeprecated':"Tu usa le option \'reproject\' in le strato ${layerName} layer. Iste option es obsolescente: illo esseva pro poter monstrar datos super cartas de base commercial, ma iste functionalitate pote ora esser attingite con le uso de Spherical Mercator. Ulterior information es disponibile a http://trac.openlayers.org/wiki/SphericalMercator.",'methodDeprecated':"Iste methodo ha essite declarate obsolescente e essera removite in version 3.0. Per favor usa ${newMethod} in su loco.",'boundsAddError':"Tu debe passar le duo valores x e y al function add.",'lonlatAddError':"Tu debe passar le duo valores lon e lat al function add.",'pixelAddError':"Tu debe passar le duo valores x e y al function add.",'unsupportedGeometryType':"Typo de geometria non supportate: ${geomType}",'pagePositionFailed':"OpenLayers.Util.pagePosition falleva: le elemento con id ${elemId} pote esser mal placiate.",'filterEvaluateNotImplemented':"\"evaluate\" non es implementate pro iste typo de filtro."});OpenLayers.Lang["id"]=OpenLayers.Util.applyDefaults({'unhandledRequest':"Permintaan yang tak tertangani menghasilkan ${statusText}",'permalink':"Pranala permanen",'overlays':"Hamparan",'baseLayer':"Lapisan Dasar",'sameProjection':"Peta tinjauan hanya bekerja bila dalam proyeksi yang sama dengan peta utama",'readNotImplemented':"Membaca tidak diterapkan.",'writeNotImplemented':"Menyimpan tidak diterapkan.",'noFID':"Tidak dapat memperbarui fitur yang tidak memiliki FID.",'errorLoadingGML':"Kesalahan dalam memuat berkas GML ${url}",'browserNotSupported':"Peramban Anda tidak mendukung penggambaran vektor. Penggambar yang didukung saat ini adalah:\n${renderers}",'componentShouldBe':"addFeatures : komponen harus berupa ${geomType}",'getFeatureError':"getFeatureFromEvent diterapkan pada lapisan tanpa penggambar. Ini biasanya berarti Anda menghapus sebuah lapisan, tetapi tidak menghapus penangan yang terkait dengannya.",'minZoomLevelError':"Properti minZoomLevel hanya ditujukan bekerja dengan lapisan FixedZoomLevels-descendent. Pengecekan minZoomLevel oleh lapisan wfs adalah peninggalan masa lalu. Kami tidak dapat menghapusnya tanpa kemungkinan merusak aplikasi berbasis OL yang mungkin bergantung padanya. Karenanya, kami menganggapnya tidak berlaku -- Cek minZoomLevel di bawah ini akan dihapus pada 3.0. Silakan gunakan penyetelan resolusi min/maks seperti dijabarkan di sini: http://trac.openlayers.org/wiki/SettingZoomLevels",'commitSuccess':"WFS Transaksi: BERHASIL ${respon}",'commitFailed':"WFS Transaksi: GAGAL ${respon}",'googleWarning':"Lapisan Google tidak dapat dimuat dengan benar.\x3cbr\x3e\x3cbr\x3eUntuk menghilangkan pesan ini, pilih suatu BaseLayer baru melalui penukar lapisan (layer switcher) di ujung kanan atas.\x3cbr\x3e\x3cbr\x3eKemungkinan besar ini karena pustaka skrip Google Maps tidak disertakan atau tidak mengandung kunci API yang tepat untuk situs Anda.\x3cbr\x3e\x3cbr\x3ePengembang: Untuk bantuan mengatasi masalah ini, \x3ca href=\'http://trac.openlayers.org/wiki/Google\' target=\'_blank\'\x3eklik di sini\x3c/a\x3e",'getLayerWarning':"Lapisan ${layerType} tidak dapat dimuat dengan benar.\x3cbr\x3e\x3cbr\x3eUntuk menghilangkan pesan ini, pilih suatu BaseLayer baru melalui penukar lapisan (layer switcher) di ujung kanan atas.\x3cbr\x3e\x3cbr\x3eKemungkinan besar ini karena pustaka skrip Google Maps tidak disertakan dengan benar.\x3cbr\x3e\x3cbr\x3ePengembang: Untuk bantuan mengatasi masalah ini, \x3ca href=\'http://trac.openlayers.org/wiki/${layerLib}\' target=\'_blank\'\x3eklik di sini\x3c/a\x3e",'scale':"Sekala = 1 : ${scaleDenom}",'W':"B",'E':"T",'N':"U",'S':"S",'layerAlreadyAdded':"Anda mencoba menambahkan lapisan: ${layerName} ke dalam peta, tapi lapisan itu telah ditambahkan",'reprojectDeprecated':"Anda menggunakan opsi \'reproject\' pada lapisan ${layerName}. Opsi ini telah ditinggalkan: penggunaannya dirancang untuk mendukung tampilan data melalui peta dasar komersial, tapi fungsionalitas tersebut saat ini harus dilakukan dengan menggunakan dukungan Spherical Mercator. Informasi lebih lanjut tersedia di http://trac.openlayers.org/wiki/SphericalMercator.",'methodDeprecated':"Metode ini telah usang dan akan dihapus di 3.0. Sebaliknya, harap gunakan ${newMethod}.",'boundsAddError':"Anda harus memberikan kedua nilai x dan y ke fungsi penambah.",'lonlatAddError':"Anda harus memberikan kedua nilai lon dan lat ke fungsi penambah.",'pixelAddError':"Anda harus memberikan kedua nilai x dan y ke fungsi penambah.",'unsupportedGeometryType':"Tipe geometri tak didukung: ${geomType}",'pagePositionFailed':"OpenLayers.Util.pagePosition gagal: elemen dengan id ${elemId} mungkin salah tempat.",'filterEvaluateNotImplemented':"evaluasi tidak tersedia untuk tipe filter ini."});OpenLayers.Lang["io"]=OpenLayers.Util.applyDefaults({'scale':"Skalo = 1 : ${scaleDenom}"});OpenLayers.Lang["is"]=OpenLayers.Util.applyDefaults({'permalink':"Varanlegur tengill",'overlays':"Þekjur",'baseLayer':"Grunnlag",'sameProjection':"Yfirlitskortið virkar aðeins ef það er í sömu vörpun og aðalkortið",'readNotImplemented':"Skrifun er óútfærð.",'writeNotImplemented':"Lestur er óútfærður.",'errorLoadingGML':"Villa kom upp við að hlaða inn GML skránni ${url}",'scale':"Skali = 1 : ${scaleDenom}",'layerAlreadyAdded':"Þú reyndir að bæta laginu ${layerName} á kortið en það er þegar búið að bæta því við",'methodDeprecated':"Þetta fall hefur verið úrelt og verður fjarlægt í 3.0. Notaðu ${newMethod} í staðin."});OpenLayers.Lang["ja"]=OpenLayers.Util.applyDefaults({'unhandledRequest':"未処理の要求は ${statusText} を返します",'permalink':"パーマリンク",'overlays':"オーバーレイ",'baseLayer':"基底レイヤー",'sameProjection':"概観地図はメインの地図と同じ投影法をとる場合のみ機能します",'readNotImplemented':"読み込みは実装されていません。",'writeNotImplemented':"書き込みは実装されていません。",'noFID':"FID のない地物は更新できません。",'errorLoadingGML':"GML ファイル ${url} の読み込みエラー",'browserNotSupported':"あなたのブラウザはベクターグラフィックスの描写に対応していません。現時点で対応しているソフトウェアは以下のものです。\n${renderers}",'componentShouldBe':"addFeatures: 要素は ${geomType} であるべきです",'getFeatureError':"getFeatureFromEvent がレンダラーのないレイヤーから呼ばれました。通常、これはあなたがレイヤーを、それに関連づけられたいくつかのハンドラを除いて、破壊してしまったことを意味します。",'minZoomLevelError':"minZoomLevel プロパティは FixedZoomLevels を継承するレイヤーでの使用のみを想定しています。この minZoomLevel に対する WFS レイヤーの検査は歴史的なものです。しかしながら、この検査を除去するとそれに依存する OpenLayers ベースのアプリケーションを破壊してしまう可能性があります。よって廃止が予定されており、この minZoomLevel 検査はバージョン3.0で除去されます。代わりに、http://trac.openlayers.org/wiki/SettingZoomLevels で解説されている、最小および最大解像度設定を使用してください。",'commitSuccess':"WFS トランザクション: 成功 ${response}",'commitFailed':"WFS トランザクション: 失敗 ${response}",'googleWarning':"Google レイヤーが正しく読み込みを行えませんでした。\x3cbr\x3e\x3cbr\x3eこのメッセージを消すには、右上の隅にあるレイヤー切り替え部分で新しい基底レイヤーを選んでください。\x3cbr\x3e\x3cbr\x3eおそらく、これは Google マップ用ライブラリのスクリプトが組み込まれていないか、あなたのサイトに対応する正しい API キーが設定されていないためです。\x3cbr\x3e\x3cbr\x3e開発者の方へ: 正しい動作をさせるために\x3ca href=\'http://trac.openlayers.org/wiki/Google\' target=\'_blank\'\x3eこちらのウィキ\x3c/a\x3eを参照してください。",'getLayerWarning':"${layerType} レイヤーが正しく読み込みを行えませんでした。\x3cbr\x3e\x3cbr\x3eこのメッセージを消すには、右上の隅にあるレイヤー切り替え部分で新しい基底レイヤーを選んでください。\x3cbr\x3e\x3cbr\x3eおそらく、これは ${layerLib} ライブラリのスクリプトが正しく組み込まれていないためです。\x3cbr\x3e\x3cbr\x3e開発者の方へ: 正しい動作をさせるために\x3ca href=\'http://trac.openlayers.org/wiki/${layerLib}\' target=\'_blank\'\x3eこちらのウィキ\x3c/a\x3eを参照してください。",'scale':"縮尺 = 1 : ${scaleDenom}",'W':"西",'E':"東",'N':"北",'S':"南",'layerAlreadyAdded':"あなたは「${layerName}」を地図に追加しようと試みましたが、そのレイヤーは既に追加されています",'reprojectDeprecated':"あなたは「${layerName}」レイヤーで reproject オプションを使っています。このオプションは商用の基底地図上に情報を表示する目的で設計されましたが、現在ではその機能は Spherical Mercator サポートを利用して実現されており、このオプションの使用は非推奨です。追加の情報は http://trac.openlayers.org/wiki/SphericalMercator で入手できます。",'methodDeprecated':"このメソッドは廃止が予定されており、バージョン3.0で除去されます。代わりに ${newMethod} を使用してください。",'boundsAddError':"x と y 両方の値を add 関数に渡さなければなりません。",'lonlatAddError':"lon と lat 両方の値を add 関数に渡さなければなりません。",'pixelAddError':"x と y の値両方を add 関数に渡さなければなりません。",'unsupportedGeometryType':"未対応の形状型: ${geomType}",'pagePositionFailed':"OpenLayers.Util.pagePosition が失敗しました: id ${elemId} をもつ要素が誤った位置にある可能性があります。",'filterEvaluateNotImplemented':"このフィルター型について evaluate は実装されていません。"});OpenLayers.Lang["km"]=OpenLayers.Util.applyDefaults({'permalink':"តំណភ្ជាប់អចិន្ត្រៃយ៍",'baseLayer':"ស្រទាប់បាត​",'errorLoadingGML':"កំហុសកំឡុងពេលផ្ទុកឯកសារ GML ${url}",'scale':"មាត្រដ្ឋាន = ១ ៖ ${scaleDenom}"});OpenLayers.Lang["ksh"]=OpenLayers.Util.applyDefaults({'unhandledRequest':"Met dä Antwoot op en Aanfrooch ham_mer nix aanjefange: ${statusText}",'permalink':"Lengk op Duuer",'overlays':"Drövver jelaat",'baseLayer':"Jrund-Nivoh",'sameProjection':"De Övverseeschs_Kaat deiht et bloß, wann se de sälve Projäxjuhn bruche deiht, wi de Houp_Kaat",'readNotImplemented':"„\x3ccode lang=\"en\"\x3eread\x3c/code\x3e“ is em Projramm nit fürjesinn.",'writeNotImplemented':"„\x3ccode lang=\"en\"\x3ewrite\x3c/code\x3e“ is em Projramm nit fürjesinn.",'noFID':"En Saach, woh kein \x3ci lang=\"en\"\x3eFID\x3c/i\x3e för doh es, löht sesch nit ändere.",'errorLoadingGML':"Fähler beim \x3ci lang=\"en\"\x3eGML\x3c/i\x3e-Datei-Laade vun \x3ccode\x3e${url}\x3c/code\x3e",'browserNotSupported':"Dinge Brauser kann kein Väktore ußjävve. De Zoote Ußjaabe, di em Momang jon, sen:\n${renderers}",'componentShouldBe':"\x3ccode lang=\"en\"\x3eaddFeatures\x3c/code\x3e: dä Aandeil sullt vun dä Zoot „\x3ccode lang=\"en\"\x3e${geomType}\x3c/code\x3e“ sin.",'getFeatureError':"\x3ccode lang=\"en\"\x3egetFeatureFromEvent\x3c/code\x3e es vun enem Nivoh opjeroofe woode, woh et kei Projramm zom Ußjävve jit. Dat bedügg för jewöhnlesch, dat De e Nivoh kapott jemaat häs, ävver nit e Projramm för domet ömzejonn, wat domet verbonge es.",'minZoomLevelError':"De Eijeschaff „\x3ccode lang=\"en\"\x3eminZoomLevel\x3c/code\x3e“ es bloß doför jedaach, dat mer se met dä Nivvohß bruch, di vun \x3ccode lang=\"en\"\x3eFixedZoomLevels\x3c/code\x3e affhange don. Dat dat \x3ci lang=\"en\"\x3eWFS\x3c/i\x3e-Nivvoh övverhoup de Eijeschaff „\x3ccode lang=\"en\"\x3eminZoomLevel\x3c/code\x3e“ pröhfe deiht, es noch övveresch vun fröhjer. Mer künne dat ävver jez nit fott lohße, oohne dat mer Jevaa loufe, dat Aanwendunge vun OpenLayers nit mieh loufe, di sesch doh velleijsch noch drop am verlohße sin. Dröm sare mer, dat mer et nit mieh han welle, un de „\x3ccode lang=\"en\"\x3eminZoomLevel\x3c/code\x3e“-Eijeschaff weed hee vun de Version 3.0 af nit mieh jeprööf wäde. Nemm doför de Enstellung för de hühßte un de kleinßte Oplöhsung, esu wi et en http://trac.openlayers.org/wiki/SettingZoomLevels opjeschrevve es.",'commitSuccess':"Dä \x3ci lang=\"en\"\x3eWFS\x3c/i\x3e-Vörjang es joot jeloufe: ${response}",'commitFailed':"Dä \x3ci lang=\"en\"\x3eWFS\x3c/i\x3e-Vörjang es scheif jejange: ${response}",'googleWarning':"Dat Nivvoh \x3ccode lang=\"en\"\x3eGoogle\x3c/code\x3e kunnt nit reschtesch jelaade wääde.\x3cbr /\x3e\x3cbr /\x3eÖm hee di Nohreesch loß ze krijje, donn en ander Jrund-Nivvoh ußsöhke, rähß bovve en de Äk.\x3cbr /\x3e\x3cbr /\x3eWascheinlesch es dat wiel dat \x3ci lang=\"en\"\x3eGoogle-Maps\x3c/i\x3e-Skrepp entweeder nit reschtesch enjebonge wood, udder nit dä reschtejje \x3ci lang=\"en\"\x3eAPI\x3c/i\x3e-Schlößel för Ding Web-ßait scheke deiht.\x3cbr /\x3e\x3cbr /\x3eFör Projrammierer jidd_et Hölp do_drövver, \x3ca href=\"http://trac.openlayers.org/wiki/Google\" target=\"_blank\"\x3ewi mer dat aan et Loufe brengk\x3c/a\x3e.",'getLayerWarning':"Dat Nivvoh \x3ccode\x3e${layerType}\x3c/code\x3e kunnt nit reschtesch jelaade wääde.\x3cbr /\x3e\x3cbr /\x3eÖm hee di Nohreesch loß ze krijje, donn en ander Jrund-Nivvoh ußsöhkre, rähß bovve en de Äk.\x3cbr /\x3e\x3cbr /\x3eWascheinlesch es dat, wiel dat Skrepp \x3ccode\x3e${layerLib}\x3c/code\x3e nit reschtesch enjebonge wood.\x3cbr /\x3e\x3cbr /\x3eFör Projrammierer jidd_Et Hölp do_drövver, \x3ca href=\"http://trac.openlayers.org/wiki/${layerLib}\" target=\"_blank\"\x3ewi mer dat aan et Loufe brengk\x3c/a\x3e.",'scale':"Mohßshtaab = 1 : ${scaleDenom}",'W':"W",'E':"O",'N':"N",'S':"S",'layerAlreadyAdded':"Do häß versöhk, dat Nivvoh \x3ccode\x3e${layerName}\x3c/code\x3e en di Kaat eren ze bränge, et wohr ävver ald do dren.",'reprojectDeprecated':"Do bruchs de Ußwahl \x3ccode\x3ereproject\x3c/code\x3e op däm Nivvoh \x3ccode\x3e${layerName}\x3c/code\x3e. Di Ußwahl es nit mieh jähn jesinn. Se wohr doför jedaach, öm Date op jeschääfsmäßesch eruß jejovve Kaate bovve drop ze moole, wat ävver enzwesche besser met dä Öngershtözung för de ßfääresche Mäkaator Beldscher jeiht. Doh kanns De mieh drövver fenge op dä Sigg: http://trac.openlayers.org/wiki/SphericalMercator.",'methodDeprecated':"Hee di Metood es nim_mih aktoäll un et weed se en dä Version 3.0 nit mieh jävve. Nemm \x3ccode\x3e${newMethod}\x3c/code\x3e doföör.",'boundsAddError':"Do moß beeds vun de \x3ccode\x3ex\x3c/code\x3e un \x3ccode\x3ey\x3c/code\x3e Wääte aan de Fungkßjohn \x3ccode\x3eadd\x3c/code\x3e jävve.",'lonlatAddError':"Do moß beeds \x3ccode\x3elon\x3c/code\x3e un \x3ccode\x3elat\x3c/code\x3e aan de Fungkßjohn \x3ccode\x3eadd\x3c/code\x3e jävve.",'pixelAddError':"Do moß beeds \x3ccode\x3ex\x3c/code\x3e un \x3ccode\x3ey\x3c/code\x3e aan de Fungkßjohn \x3ccode\x3eadd\x3c/code\x3e jävve.",'unsupportedGeometryType':"De Zoot Jommetrii dom_mer nit ongershtöze: \x3ccode\x3e${geomType}\x3c/code\x3e",'pagePositionFailed':"\x3ccode lang=\"en\"\x3eOpenLayers.Util.pagePosition\x3c/code\x3e es donevve jejange: dat Denge met dä Kännong \x3ccode\x3e${elemId}\x3c/code\x3e künnt am verkeehte Plaz sin.",'filterEvaluateNotImplemented':"„\x3ccode lang=\"en\"\x3eevaluate\x3c/code\x3e“ es för di Zoot Fellter nit enjereschdt."});OpenLayers.Lang["nds"]=OpenLayers.Util.applyDefaults({'unhandledRequest':"Unbehannelt Trüchmellels för de Anfraag ${statusText}",'permalink':"Permalink",'overlays':"Overlays",'baseLayer':"Achtergrundkoort",'sameProjection':"De Översichtskoort geiht blot, wenn de sülve Projekschoon as bi de Hööftkoort bruukt warrt",'readNotImplemented':"Lesen is nich inricht.",'writeNotImplemented':"Schrieven is nich inricht.",'noFID':"En Feature, dat keen FID hett, kann nich aktuell maakt warrn.",'errorLoadingGML':"Fehler bi’t Laden vun de GML-Datei ${url}",'browserNotSupported':"Dien Browser ünnerstütt keen Vektorbiller. Ünnerstütt Renderers:\n${renderers}",'componentShouldBe':"addFeatures : Kumponent schull man den Typ ${geomType} hebben",'getFeatureError':"getFeatureFromEvent is von en Laag ahn Render opropen worrn. Dat bedüüdt normalerwies, dat en Laag wegmaakt worrn is, aver nich de Handler, de dor op verwiest.",'commitSuccess':"WFS-Transakschoon: hett klappt ${response}",'commitFailed':"WFS-Transakschoon: hett nich klappt ${response}",'scale':"Skaal = 1 : ${scaleDenom}",'layerAlreadyAdded':"Du versöchst de Laag „${layerName}“ to de Koort totofögen, man de is al toföögt",'methodDeprecated':"Disse Methood is oold un schall dat in 3.0 nich mehr geven. Bruuk dor man beter ${newMethod} för.",'boundsAddError':"De Weert x un y, de mööt all beid an de add-Funkschoon övergeven warrn.",'lonlatAddError':"De Weert lon un lat, de mööt all beid an de add-Funkschoon övergeven warrn.",'pixelAddError':"De Weert x un y, de mööt all beid an de add-Funkschoon övergeven warrn.",'unsupportedGeometryType':"Nich ünnerstütt Geometrie-Typ: ${geomType}",'pagePositionFailed':"OpenLayers.Util.pagePosition güng nich: Element mit de Id ${elemId} is villicht an’n verkehrten Platz."});OpenLayers.Lang["nn"]=OpenLayers.Util.applyDefaults({'scale':"Skala = 1 : ${scaleDenom}",'layerAlreadyAdded':"Du freista å leggja til laget «${layerName}» på kartet, men det har alt vorte lagt til.",'boundsAddError':"Du er nøydd til å gje både ein x- og ein y-verdi til «add»-funksjonen.",'lonlatAddError':"Du er nøydd til å gje både lon- og lat-verdiar til «add»-funksjonen.",'pixelAddError':"Du er nøydd til å gje både ein x- og ein y-verdi til «add»-funksjonen."});OpenLayers.Lang["oc"]=OpenLayers.Util.applyDefaults({'unhandledRequest':"Requèsta pas gerida, retorna ${statusText}",'permalink':"Permaligam",'overlays':"Calques",'baseLayer':"Calc de basa",'sameProjection':"La carta de situacion fonciona pas que quora sa projeccion es la meteissa que la de la carta principala",'readNotImplemented':"Lectura pas implementada.",'writeNotImplemented':"Escritura pas implementada.",'noFID':"Impossible de metre a jorn un objècte sens identificant (fid).",'errorLoadingGML':"Error al cargament del fichièr GML ${url}",'browserNotSupported':"Vòstre navegidor supòrta pas lo rendut vectorial. Los renderers actualament suportats son : \n${renderers}",'componentShouldBe':"addFeatures : lo compausant deuriá èsser de tipe ${geomType}",'getFeatureError':"getFeatureFromEvent es estat apelat sus un calc sens renderer. Aquò significa generalament qu\'avètz destruch aqueste jaç, mas qu\'avètz conservat un handler que li èra associat.",'minZoomLevelError':"La proprietat minZoomLevel deu èsser utilizada solament per de jaces FixedZoomLevels-descendent. Lo fach qu\'aqueste jaç WFS verifique la preséncia de minZoomLevel es una relica del passat. Çaquelà, la podèm suprimir sens copar d\'aplicacions que ne poirián dependre. Es per aquò que la depreciam -- la verificacion del minZoomLevel serà suprimida en version 3.0. A la plaça, mercés d\'utilizar los paramètres de resolucions min/max tal coma descrich sus : http://trac.openlayers.org/wiki/SettingZoomLevels",'commitSuccess':"Transaccion WFS : SUCCES ${response}",'commitFailed':"Transaccion WFS : FRACAS ${response}",'googleWarning':"Lo jaç Google es pas estat en mesura de se cargar corrèctament.\x3cbr\x3e\x3cbr\x3ePer suprimir aqueste messatge, causissètz una BaseLayer novèla dins lo selector de jaç en naut a drecha.\x3cbr\x3e\x3cbr\x3eAquò es possiblament causat par la non-inclusion de la librariá Google Maps, o alara perque que la clau de l\'API correspond pas a vòstre site.\x3cbr\x3e\x3cbr\x3eDesvolopaires : per saber cossí corregir aquò, \x3ca href=\'http://trac.openlayers.org/wiki/Google\' target=\'_blank\'\x3eclicatz aicí\x3c/a\x3e",'getLayerWarning':"Lo jaç ${layerType} es pas en mesura de se cargar corrèctament.\x3cbr\x3e\x3cbr\x3ePer suprimir aqueste messatge, causissètz una  BaseLayer novèla dins lo selector de jaç en naut a drecha.\x3cbr\x3e\x3cbr\x3eAquò es possiblament causat per la non-inclusion de la librariá ${layerLib}.\x3cbr\x3e\x3cbr\x3eDesvolopaires : per saber cossí corregir aquí, \x3ca href=\'http://trac.openlayers.org/wiki/${layerLib}\' target=\'_blank\'\x3eclicatz aicí\x3c/a\x3e",'scale':"Escala ~ 1 : ${scaleDenom}",'W':"O",'E':"È",'N':"N",'S':"S",'layerAlreadyAdded':"Avètz ensajat d\'apondre a la carta lo calc : ${layerName}, mas ja es present",'reprojectDeprecated':"Utilizatz l\'opcion \'reproject\' sul jaç ${layerName}. Aquesta opcion es despreciada : Son usatge permetiá d\'afichar de donadas al dessús de jaces raster comercials. Aquesta foncionalitat ara es suportada en utilizant lo supòrt de la projeccion Mercator Esferica. Mai d\'informacion es disponibla sus http://trac.openlayers.org/wiki/SphericalMercator.",'methodDeprecated':"Aqueste metòde es despreciada, e serà suprimida a la version 3.0. Mercés d\'utilizar ${newMethod} a la plaça.",'boundsAddError':"Vos cal passar las doas valors x e y a la foncion add.",'lonlatAddError':"Vos cal passar las doas valors lon e lat a la foncion add.",'pixelAddError':"Vos cal passar las doas valors x e y a la foncion add.",'unsupportedGeometryType':"Tipe de geometria pas suportat : ${geomType}",'pagePositionFailed':"OpenLayers.Util.pagePosition a fracassat : l\'element d\'id ${elemId} poiriá èsser mal posicionat.",'filterEvaluateNotImplemented':"evaluar es pas encara estat implementat per aqueste tipe de filtre."});OpenLayers.Lang["pt"]=OpenLayers.Util.applyDefaults({'unhandledRequest':"Servidor devolveu erro não contemplado ${statusText}",'permalink':"Ligação permanente",'overlays':"Sobreposições",'baseLayer':"Camada Base",'sameProjection':"O mapa panorâmico só funciona quando está na mesma projeção que o mapa principal",'readNotImplemented':"Leitura não implementada.",'writeNotImplemented':"Escrita não implementada.",'noFID':"Não é possível atualizar um elemento para a qual não há FID.",'errorLoadingGML':"Erro ao carregar ficheiro GML ${url}",'browserNotSupported':"O seu navegador não suporta renderização vetorial. Actualmente os renderizadores suportados são:\n${renderers}",'componentShouldBe':"addFeatures: componente deve ser um(a) ${geomType}",'getFeatureError':"getFeatureFromEvent foi chamado numa camada sem renderizador. Isto normalmente significa que destruiu uma camada, mas não um manipulador \'\'(handler)\'\' que lhe está associado.",'minZoomLevelError':"A propriedade minZoomLevel só deve ser usada com as camadas descendentes da FixedZoomLevels. A verificação da propriedade por esta camada wfs é uma relíquia do passado. No entanto, não podemos removê-la sem correr o risco de afectar aplicações OL que dependam dela. Portanto, estamos a torná-la obsoleta -- a verificação minZoomLevel será removida na versão 3.0. Em vez dela, por favor, use as opções de resolução min/max descritas aqui: http://trac.openlayers.org/wiki/SettingZoomLevels",'commitSuccess':"Transacção WFS: SUCESSO ${response}",'commitFailed':"Transacção WFS: FALHOU ${response}",'googleWarning':"A Camada Google não foi correctamente carregada.\x3cbr\x3e\x3cbr\x3ePara deixar de receber esta mensagem, seleccione uma nova Camada-Base no \'\'switcher\'\' de camadas no canto superior direito.\x3cbr\x3e\x3cbr\x3eProvavelmente, isto acontece porque o \'\'script\'\' da biblioteca do Google Maps não foi incluído ou não contém a chave API correcta para o seu sítio.\x3cbr\x3e\x3cbr\x3eProgramadores: Para ajuda sobre como solucionar o problema \x3ca href=\'http://trac.openlayers.org/wiki/Google\' target=\'_blank\'\x3eclique aqui\x3c/a\x3e .",'getLayerWarning':"A camada ${layerType} não foi correctamente carregada.\x3cbr\x3e\x3cbr\x3ePara desactivar esta mensagem, seleccione uma nova Camada-Base no \'\'switcher\'\' de camadas no canto superior direito.\x3cbr\x3e\x3cbr\x3eProvavelmente, isto acontece porque o \'\'script\'\' da biblioteca ${layerLib} não foi incluído correctamente.\x3cbr\x3e\x3cbr\x3eProgramadores: Para ajuda sobre como solucionar o problema \x3ca href=\'http://trac.openlayers.org/wiki/${layerLib}\' target=\'_blank\'\x3eclique aqui\x3c/a\x3e .",'scale':"Escala = 1 : ${scaleDenom}",'W':"O",'E':"E",'N':"N",'S':"S",'layerAlreadyAdded':"Você tentou adicionar a camada: ${layerName} ao mapa, mas ela já tinha sido adicionada antes",'reprojectDeprecated':"Está usando a opção \'reproject\' na camada ${layerName}. Esta opção é obsoleta: foi concebida para permitir a apresentação de dados sobre mapas-base comerciais, mas esta funcionalidade é agora suportada pelo Mercator Esférico. Mais informação está disponível em http://trac.openlayers.org/wiki/SphericalMercator.",'methodDeprecated':"Este método foi declarado obsoleto e será removido na versão 3.0. Por favor, use ${newMethod} em vez disso.",'boundsAddError':"Você deve passar tanto o valor x como o y à função de adição.",'lonlatAddError':"Você deve passar tanto o valor lon como o lat à função de adição.",'pixelAddError':"Você deve passar tanto o valor x como o y à função de adição.",'unsupportedGeometryType':"Tipo de geometria não suportado: ${geomType}",'pagePositionFailed':"OpenLayers.Util.pagePosition falhou: o elemento com o id ${elemId} poderá estar mal-posicionado.",'filterEvaluateNotImplemented':"avaliar não está implementado para este tipo de filtro."});OpenLayers.Lang["ru"]=OpenLayers.Util.applyDefaults({'unhandledRequest':"Необработанный запрос вернул ${statusText}",'permalink':"Постоянная ссылка",'overlays':"Слои",'baseLayer':"Основной слой",'sameProjection':"Обзорная карта работает только тогда, когда имеет ту же проекцию, что и основная",'readNotImplemented':"Чтение не реализовано.",'writeNotImplemented':"Запись не реализована.",'noFID':"Невозможно обновить объект, для которого нет FID.",'errorLoadingGML':"Ошибка при загрузке файла GML ${url}",'browserNotSupported':"Ваш браузер не поддерживает векторную графику. На данный момент поддерживаются:\n${renderers}",'componentShouldBe':"addFeatures: компонент должен быть ${geomType}",'getFeatureError':"getFeatureFromEvent вызван для слоя без рендерера. Обычно это говорит о том, что вы уничтожили слой, но оставили связанный с ним обработчик.",'minZoomLevelError':"Свойство minZoomLevel предназначено только для использования со слоями, являющимися потомками FixedZoomLevels. То, что этот WFS-слой проверяется на minZoomLevel — реликт прошлого. Однако мы не можем удалить эту функцию, так как, возможно, от неё зависят некоторые основанные на OpenLayers приложения. Функция объявлена устаревшей — проверка minZoomLevel будет удалена в 3.0. Пожалуйста, используйте вместо неё настройку мин/макс разрешения, описанную здесь: http://trac.openlayers.org/wiki/SettingZoomLevels",'commitSuccess':"Транзакция WFS: УСПЕШНО ${response}",'commitFailed':"Транзакция WFS: ОШИБКА ${response}",'googleWarning':"Слой Google не удалось нормально загрузить.\x3cbr\x3e\x3cbr\x3eЧтобы избавиться от этого сообщения, выбите другой основной слой в переключателе в правом верхнем углу.\x3cbr\x3e\x3cbr\x3eСкорее всего, причина в том, что библиотека Google Maps не была включена или не содержит корректного API-ключа для вашего сайта.\x3cbr\x3e\x3cbr\x3eРазработчикам: чтобы узнать, как сделать, чтобы всё заработало, \x3ca href=\'http://trac.openlayers.org/wiki/Google\' target=\'_blank\'\x3eщёлкните тут\x3c/a\x3e",'getLayerWarning':"Слой ${layerType} не удалось нормально загрузить. \x3cbr\x3e\x3cbr\x3eЧтобы избавиться от этого сообщения, выбите другой основной слой в переключателе в правом верхнем углу.\x3cbr\x3e\x3cbr\x3eСкорее всего, причина в том, что библиотека ${layerLib} не была включена или была включена некорректно.\x3cbr\x3e\x3cbr\x3eРазработчикам: чтобы узнать, как сделать, чтобы всё заработало, \x3ca href=\'http://trac.openlayers.org/wiki/${layerLib}\' target=\'_blank\'\x3eщёлкните тут\x3c/a\x3e",'scale':"Масштаб = 1 : ${scaleDenom}",'W':"З",'E':"В",'N':"С",'S':"Ю",'layerAlreadyAdded':"Вы попытались добавить слой «${layerName}» на карту, но он уже был добавлен",'reprojectDeprecated':"Вы используете опцию \'reproject\' для слоя ${layerName}. Эта опция является устаревшей: ее использование предполагалось для поддержки показа данных поверх коммерческих базовых карт, но теперь этот функционал несёт встроенная поддержка сферической проекции Меркатора. Больше сведений доступно на http://trac.openlayers.org/wiki/SphericalMercator.",'methodDeprecated':"Этот метод считается устаревшим и будет удалён в версии 3.0. Пожалуйста, пользуйтесь ${newMethod}.",'boundsAddError':"Функции add надо передавать оба значения, x и y.",'lonlatAddError':"Функции add надо передавать оба значения, lon и lat.",'pixelAddError':"Функции add надо передавать оба значения, x и y.",'unsupportedGeometryType':"Неподдерживаемый тип геометрии: ${geomType}",'pagePositionFailed':"OpenLayers.Util.pagePosition failed: элемент с id ${elemId} может находиться не в нужном месте.",'filterEvaluateNotImplemented':"evaluate не реализовано для фильтра данного типа."});OpenLayers.Lang["sk"]=OpenLayers.Util.applyDefaults({'unhandledRequest':"Neobslúžené požiadavky vracajú ${statusText}",'permalink':"Trvalý odkaz",'overlays':"Prekrytia",'baseLayer':"Základná vrstva",'sameProjection':"Prehľadová mapka funguje iba vtedy, keď je v rovnakej projekcii ako hlavná mapa",'readNotImplemented':"Čítanie nie je implementované.",'writeNotImplemented':"Zápis nie je implementovaný.",'noFID':"Nie je možné aktualizovať vlastnosť, pre ktorú neexistuje FID.",'errorLoadingGML':"Chyba pri načítaní súboru GML ${url}",'browserNotSupported':"Váš prehliadač nepodporuje vykresľovanie vektorov. Momentálne podporované vykresľovače sú:\n${renderers}",'componentShouldBe':"addFeatures: komponent by mal byť ${geomType}",'getFeatureError':"getFeatureFromEvent bola zavolaná na vrstve bez vykresľovača. To zvyčajne znamená, že ste odstránili vrstvu, ale nie niektorú z obslúh, ktorá je s ňou asociovaná.",'minZoomLevelError':"Vlastnosť minZoomLevel je určený iba na použitie s vrstvami odvodenými od FixedZoomLevels. To, že táto wfs vrstva kontroluje minZoomLevel je pozostatok z minulosti. Nemôžeme ho však odstrániť, aby sme sa vyhli možnému porušeniu aplikácií založených na Open Layers, ktoré na tomto môže závisieť. Preto ho označujeme ako zavrhovaný - dolu uvedená kontrola minZoomLevel bude odstránená vo verzii 3.0. Použite prosím namiesto toho kontrolu min./max. rozlíšenia podľa tu uvedeného popisu: http://trac.openlayers.org/wiki/SettingZoomLevels",'commitSuccess':"Transakcia WFS: ÚSPEŠNÁ ${response}",'commitFailed':"Transakcia WFS: ZLYHALA ${response}",'googleWarning':"Vrstvu Google nebolo možné správne načítať.\x3cbr\x3e\x3cbr\x3eAby ste sa tejto správy zbavili vyberte novú BaseLayer v prepínači vrstiev v pravom hornom rohu.\x3cbr\x3e\x3cbr\x3eToto sa stalo pravdepodobne preto, že skript knižnice Google Maps buď nebol načítaný alebo neobsahuje správny kľúč API pre vašu lokalitu.\x3cbr\x3e\x3cbr\x3eVývojári: Tu môžete získať \x3ca href=\'http://trac.openlayers.org/wiki/Google\' target=\'_blank\'\x3epomoc so sfunkčnením\x3c/a\x3e",'getLayerWarning':"Vrstvu ${layerType} nebolo možné správne načítať.\x3cbr\x3e\x3cbr\x3eAby ste sa tejto správy zbavili vyberte novú BaseLayer v prepínači vrstiev v pravom hornom rohu.\x3cbr\x3e\x3cbr\x3eToto sa stalo pravdepodobne preto, že skript knižnice ${layerType} buď nebol načítaný alebo neobsahuje správny kľúč API pre vašu lokalitu.\x3cbr\x3e\x3cbr\x3eVývojári: Tu môžete získať \x3ca href=\'http://trac.openlayers.org/wiki/${layerType}\' target=\'_blank\'\x3epomoc so sfunkčnením\x3c/a\x3e",'scale':"Mierka = 1 : ${scaleDenom}",'layerAlreadyAdded':"Pokúsili ste sa do mapy pridať vrstvu ${layerName}, ale tá už bola pridaná",'reprojectDeprecated':"Používate voľby „reproject“ vrstvy ${layerType}. Táto voľba je zzavrhovaná: jej použitie bolo navrhnuté na podporu zobrazovania údajov nad komerčnými základovými mapami, ale túto funkcionalitu je teraz možné dosiahnuť pomocou Spherical Mercator. Ďalšie informácie získate na stránke http://trac.openlayers.org/wiki/SphericalMercator.",'methodDeprecated':"Táto metóda je zavrhovaná a bude odstránená vo verzii 3.0. Použite prosím namiesto nej metódu ${newMethod}.",'boundsAddError':"Sčítacej funkcii musíte dať hodnoty x aj y.",'lonlatAddError':"Sčítacej funkcii musíte dať hodnoty lon (zem. dĺžka) aj lat (zem. šírka).",'pixelAddError':"Sčítacej funkcii musíte dať hodnoty x aj y.",'unsupportedGeometryType':"Nepodporovaný typ geometrie: ${geomType}",'pagePositionFailed':"OpenLayers.Util.pagePosition zlyhalo: prvok s id ${elemId} môže byť zle umiestnený.",'filterEvaluateNotImplemented':"evaluate nie je implementovaný pre tento typ filtra"});OpenLayers.Lang["te"]=OpenLayers.Util.applyDefaults({'permalink':"స్థిరలింకు",'W':"ప",'E':"తూ",'N':"ఉ",'S':"ద"});OpenLayers.Lang["vi"]=OpenLayers.Util.applyDefaults({'unhandledRequest':"Không xử lý được phản hồi ${statusText} cho yêu cầu",'permalink':"Liên kết thường trực",'overlays':"Lấp bản đồ",'baseLayer':"Lớp nền",'sameProjection':"Bản đồ toàn cảnh chỉ hoạt động khi cùng phép chiếu với bản đồ chính",'readNotImplemented':"Chưa hỗ trợ chức năng đọc.",'writeNotImplemented':"Chưa hỗ trợ chức năng viết.",'noFID':"Không thể cập nhật tính năng thiếu FID.",'errorLoadingGML':"Lỗi tải tập tin GML tại ${url}",'browserNotSupported':"Trình duyệt của bạn không hỗ trợ chức năng vẽ bằng vectơ. Hiện hỗ trợ các bộ kết xuất:\n${renderers}",'componentShouldBe':"addFeatures: bộ phận cần phải là ${geomType}",'getFeatureError':"getFeatureFromEvent được gọi từ lớp không có bộ kết xuất. Thường thì có lẽ lớp bị xóa nhưng một phần xử lý của nó vẫn còn.",'minZoomLevelError':"Chỉ nên sử dụng thuộc tính minZoomLevel với các lớp FixedZoomLevels-descendent. Việc lớp wfs này tìm cho minZoomLevel là di tích còn lại từ xưa. Tuy nhiên, nếu chúng tôi dời nó thì sẽ vỡ các chương trình OpenLayers mà dựa trên nó. Bởi vậy chúng tôi phản đối sử dụng nó\x26nbsp;– bước tìm cho minZoomLevel sẽ được dời vào phiên bản 3.0. Xin sử dụng thiết lập độ phân tích tối thiểu / tối đa thay thế, theo hướng dẫn này: http://trac.openlayers.org/wiki/SettingZoomLevels",'commitSuccess':"Giao dịch WFS: THÀNH CÔNG ${response}",'commitFailed':"Giao dịch WFS: THẤT BẠI ${response}",'googleWarning':"Không thể tải lớp Google đúng đắn.\x3cbr\x3e\x3cbr\x3eĐể tránh thông báo này lần sau, hãy chọn BaseLayer mới dùng điều khiển chọn lớp ở góc trên phải.\x3cbr\x3e\x3cbr\x3eChắc script thư viện Google Maps hoặc không được bao gồm hoặc không chứa khóa API hợp với website của bạn.\x3cbr\x3e\x3cbr\x3e\x3ca href=\'http://trac.openlayers.org/wiki/Google\' target=\'_blank\'\x3eTrợ giúp về tính năng này\x3c/a\x3e cho người phát triển.",'getLayerWarning':"Không thể tải lớp ${layerType} đúng đắn.\x3cbr\x3e\x3cbr\x3eĐể tránh thông báo này lần sau, hãy chọn BaseLayer mới dùng điều khiển chọn lớp ở góc trên phải.\x3cbr\x3e\x3cbr\x3eChắc script thư viện ${layerLib} không được bao gồm đúng kiểu.\x3cbr\x3e\x3cbr\x3e\x3ca href=\'http://trac.openlayers.org/wiki/${layerLib}\' target=\'_blank\'\x3eTrợ giúp về tính năng này\x3c/a\x3e cho người phát triển.",'scale':"Tỷ lệ = 1 : ${scaleDenom}",'W':"T",'E':"Đ",'N':"B",'S':"N",'layerAlreadyAdded':"Bạn muốn thêm lớp ${layerName} vào bản đồ, nhưng lớp này đã được thêm",'reprojectDeprecated':"Bạn đang áp dụng chế độ “reproject” vào lớp ${layerName}. Chế độ này đã bị phản đối: nó có mục đích hỗ trợ lấp dữ liệu trên các nền bản đồ thương mại; nên thực hiện hiệu ứng đó dùng tính năng Mercator Hình cầu. Có sẵn thêm chi tiết tại http://trac.openlayers.org/wiki/SphericalMercator .",'methodDeprecated':"Phương thức này đã bị phản đối và sẽ bị dời vào phiên bản 3.0. Xin hãy sử dụng ${newMethod} thay thế.",'boundsAddError':"Cần phải cho cả giá trị x và y vào hàm add.",'lonlatAddError':"Cần phải cho cả giá trị lon và lat vào hàm add.",'pixelAddError':"Cần phải cho cả giá trị x và y vào hàm add.",'unsupportedGeometryType':"Không hỗ trợ kiểu địa lý: ${geomType}",'pagePositionFailed':"OpenLayers.Util.pagePosition bị thất bại: nguyên tố với ID ${elemId} có thể ở chỗ sai.",'filterEvaluateNotImplemented':"chưa hỗ trợ evaluate cho loại bộ lọc này."});OpenLayers.Popup.AnchoredBubble=OpenLayers.Class(OpenLayers.Popup.Anchored,{rounded:false,initialize:function(id,lonlat,contentSize,contentHTML,anchor,closeBox,closeBoxCallback){this.padding=new OpenLayers.Bounds(0,OpenLayers.Popup.AnchoredBubble.CORNER_SIZE,0,OpenLayers.Popup.AnchoredBubble.CORNER_SIZE);OpenLayers.Popup.Anchored.prototype.initialize.apply(this,arguments);},draw:function(px){OpenLayers.Popup.Anchored.prototype.draw.apply(this,arguments);this.setContentHTML();this.setBackgroundColor();this.setOpacity();return this.div;},updateRelativePosition:function(){this.setRicoCorners();},setSize:function(contentSize){OpenLayers.Popup.Anchored.prototype.setSize.apply(this,arguments);this.setRicoCorners();},setBackgroundColor:function(color){if(color!=undefined){this.backgroundColor=color;}
59805 if(this.div!=null){if(this.contentDiv!=null){this.div.style.background="transparent";OpenLayers.Rico.Corner.changeColor(this.groupDiv,this.backgroundColor);}}},setOpacity:function(opacity){OpenLayers.Popup.Anchored.prototype.setOpacity.call(this,opacity);if(this.div!=null){if(this.groupDiv!=null){OpenLayers.Rico.Corner.changeOpacity(this.groupDiv,this.opacity);}}},setBorder:function(border){this.border=0;},setRicoCorners:function(){var corners=this.getCornersToRound(this.relativePosition);var options={corners:corners,color:this.backgroundColor,bgColor:"transparent",blend:false};if(!this.rounded){OpenLayers.Rico.Corner.round(this.div,options);this.rounded=true;}else{OpenLayers.Rico.Corner.reRound(this.groupDiv,options);this.setBackgroundColor();this.setOpacity();}},getCornersToRound:function(){var corners=['tl','tr','bl','br'];var corner=OpenLayers.Bounds.oppositeQuadrant(this.relativePosition);OpenLayers.Util.removeItem(corners,corner);return corners.join(" ");},CLASS_NAME:"OpenLayers.Popup.AnchoredBubble"});OpenLayers.Popup.AnchoredBubble.CORNER_SIZE=5;OpenLayers.Popup.Framed=OpenLayers.Class(OpenLayers.Popup.Anchored,{imageSrc:null,imageSize:null,isAlphaImage:false,positionBlocks:null,blocks:null,fixedRelativePosition:false,initialize:function(id,lonlat,contentSize,contentHTML,anchor,closeBox,closeBoxCallback){OpenLayers.Popup.Anchored.prototype.initialize.apply(this,arguments);if(this.fixedRelativePosition){this.updateRelativePosition();this.calculateRelativePosition=function(px){return this.relativePosition;};}
59806 this.contentDiv.style.position="absolute";this.contentDiv.style.zIndex=1;if(closeBox){this.closeDiv.style.zIndex=1;}
59807 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.imageSrc=null;this.imageSize=null;this.isAlphaImage=null;this.fixedRelativePosition=false;this.positionBlocks=null;for(var i=0;i<this.blocks.length;i++){var block=this.blocks[i];if(block.image){block.div.removeChild(block.image);}
59808 block.image=null;if(block.div){this.groupDiv.removeChild(block.div);}
59809 block.div=null;}
59810 this.blocks=null;OpenLayers.Popup.Anchored.prototype.destroy.apply(this,arguments);},setBackgroundColor:function(color){},setBorder:function(){},setOpacity:function(opacity){},setSize:function(contentSize){OpenLayers.Popup.Anchored.prototype.setSize.apply(this,arguments);this.updateBlocks();},updateRelativePosition:function(){this.padding=this.positionBlocks[this.relativePosition].padding;if(this.closeDiv){var contentDivPadding=this.getContentDivPadding();this.closeDiv.style.right=contentDivPadding.right+
59811 this.padding.right+"px";this.closeDiv.style.top=contentDivPadding.top+
59812 this.padding.top+"px";}
59813 this.updateBlocks();},calculateNewPx:function(px){var newPx=OpenLayers.Popup.Anchored.prototype.calculateNewPx.apply(this,arguments);newPx=newPx.offset(this.positionBlocks[this.relativePosition].offset);return newPx;},createBlocks:function(){this.blocks=[];var firstPosition=null;for(var key in this.positionBlocks){firstPosition=key;break;}
59814 var position=this.positionBlocks[firstPosition];for(var i=0;i<position.blocks.length;i++){var block={};this.blocks.push(block);var divId=this.id+'_FrameDecorationDiv_'+i;block.div=OpenLayers.Util.createDiv(divId,null,null,null,"absolute",null,"hidden",null);var imgId=this.id+'_FrameDecorationImg_'+i;var imageCreator=(this.isAlphaImage)?OpenLayers.Util.createAlphaImageDiv:OpenLayers.Util.createImage;block.image=imageCreator(imgId,null,this.imageSize,this.imageSrc,"absolute",null,null,null);block.div.appendChild(block.image);this.groupDiv.appendChild(block.div);}},updateBlocks:function(){if(!this.blocks){this.createBlocks();}
59815 if(this.size&&this.relativePosition){var position=this.positionBlocks[this.relativePosition];for(var i=0;i<position.blocks.length;i++){var positionBlock=position.blocks[i];var block=this.blocks[i];var l=positionBlock.anchor.left;var b=positionBlock.anchor.bottom;var r=positionBlock.anchor.right;var t=positionBlock.anchor.top;var w=(isNaN(positionBlock.size.w))?this.size.w-(r+l):positionBlock.size.w;var h=(isNaN(positionBlock.size.h))?this.size.h-(b+t):positionBlock.size.h;block.div.style.width=(w<0?0:w)+'px';block.div.style.height=(h<0?0:h)+'px';block.div.style.left=(l!=null)?l+'px':'';block.div.style.bottom=(b!=null)?b+'px':'';block.div.style.right=(r!=null)?r+'px':'';block.div.style.top=(t!=null)?t+'px':'';block.image.style.left=positionBlock.position.x+'px';block.image.style.top=positionBlock.position.y+'px';}
59816 this.contentDiv.style.left=this.padding.left+"px";this.contentDiv.style.top=this.padding.top+"px";}},CLASS_NAME:"OpenLayers.Popup.Framed"});OpenLayers.Projection=OpenLayers.Class({proj:null,projCode:null,initialize:function(projCode,options){OpenLayers.Util.extend(this,options);this.projCode=projCode;if(window.Proj4js){this.proj=new Proj4js.Proj(projCode);}},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(projection){if(projection&&projection.getCode){return this.getCode()==projection.getCode();}else{return false;}},destroy:function(){delete this.proj;delete this.projCode;},CLASS_NAME:"OpenLayers.Projection"});OpenLayers.Projection.transforms={};OpenLayers.Projection.addTransform=function(from,to,method){if(!OpenLayers.Projection.transforms[from]){OpenLayers.Projection.transforms[from]={};}
59817 OpenLayers.Projection.transforms[from][to]=method;};OpenLayers.Projection.transform=function(point,source,dest){if(source.proj&&dest.proj){point=Proj4js.transform(source.proj,dest.proj,point);}else if(source&&dest&&OpenLayers.Projection.transforms[source.getCode()]&&OpenLayers.Projection.transforms[source.getCode()][dest.getCode()]){OpenLayers.Projection.transforms[source.getCode()][dest.getCode()](point);}
59818 return point;};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,initialize:function(options){OpenLayers.Protocol.prototype.initialize.apply(this,[options]);if(!options.format){this.format=OpenLayers.Format.WFST(OpenLayers.Util.extend({version:this.version,featureType:this.featureType,featureNS:this.featureNS,featurePrefix:this.featurePrefix,geometryName:this.geometryName,srsName:this.srsName,schema:this.schema},this.formatOptions));}
59819 if(!this.featureNS&&this.featurePrefix){var readNode=this.format.readNode;this.format.readNode=function(node,obj){if(!this.featureNS&&node.prefix==this.featurePrefix){this.featureNS=node.namespaceURI;this.setNamespace("feature",this.featureNS);}
59820 return readNode.apply(this,arguments);};}},destroy:function(){if(this.options&&!this.options.format){this.format.destroy();}
59821 this.format=null;OpenLayers.Protocol.prototype.destroy.apply(this);},read:function(options){OpenLayers.Protocol.prototype.read.apply(this,arguments);options=OpenLayers.Util.extend({},options);OpenLayers.Util.applyDefaults(options,this.options||{});var response=new OpenLayers.Protocol.Response({requestType:"read"});var data=OpenLayers.Format.XML.prototype.write.apply(this.format,[this.format.writeNode("wfs:GetFeature",options)]);response.priv=OpenLayers.Request.POST({url:options.url,callback:this.createCallback(this.handleRead,response,options),params:options.params,headers:options.headers,data:data});return response;},handleRead:function(response,options){if(options.callback){var request=response.priv;if(request.status>=200&&request.status<300){response.features=this.parseFeatures(request);response.code=OpenLayers.Protocol.Response.SUCCESS;}else{response.code=OpenLayers.Protocol.Response.FAILURE;}
59822 options.callback.call(options.scope,response);}},parseFeatures:function(request){var doc=request.responseXML;if(!doc||!doc.documentElement){doc=request.responseText;}
59823 if(!doc||doc.length<=0){return null;}
59824 return(this.readFormat!==null)?this.readFormat.read(doc):this.format.read(doc);},commit:function(features,options){options=OpenLayers.Util.extend({},options);OpenLayers.Util.applyDefaults(options,this.options);var response=new OpenLayers.Protocol.Response({requestType:"commit",reqFeatures:features});response.priv=OpenLayers.Request.POST({url:options.url,data:this.format.write(features,options),callback:this.createCallback(this.handleCommit,response,options)});return response;},handleCommit:function(response,options){if(options.callback){var request=response.priv;var data=request.responseXML;if(!data||!data.documentElement){data=request.responseText;}
59825 var obj=this.format.read(data)||{};response.insertIds=obj.insertIds||[];response.code=(obj.success)?OpenLayers.Protocol.Response.SUCCESS:OpenLayers.Protocol.Response.FAILURE;options.callback.call(options.scope,response);}},filterDelete:function(filter,options){options=OpenLayers.Util.extend({},options);OpenLayers.Util.applyDefaults(options,this.options);var response=new OpenLayers.Protocol.Response({requestType:"commit"});var root=this.format.createElementNSPlus("wfs:Transaction",{attributes:{service:"WFS",version:this.version}});var deleteNode=this.format.createElementNSPlus("wfs:Delete",{attributes:{typeName:(options.featureNS?this.featurePrefix+":":"")+
59826 options.featureType}});if(options.featureNS){deleteNode.setAttribute("xmlns:"+this.featurePrefix,options.featureNS);}
59827 var filterNode=this.format.writeNode("ogc:Filter",filter);deleteNode.appendChild(filterNode);root.appendChild(deleteNode);var data=OpenLayers.Format.XML.prototype.write.apply(this.format,[root]);return OpenLayers.Request.POST({url:this.url,callback:options.callback||function(){},data:data});},abort:function(response){if(response){response.priv.abort();}},CLASS_NAME:"OpenLayers.Protocol.WFS.v1"});OpenLayers.Renderer.SVG=OpenLayers.Class(OpenLayers.Renderer.Elements,{xmlns:"http://www.w3.org/2000/svg",xlinkns:"http://www.w3.org/1999/xlink",MAX_PIXEL:15000,translationParameters:null,symbolMetrics:null,isGecko:null,supportUse:null,initialize:function(containerID){if(!this.supported()){return;}
59828 OpenLayers.Renderer.Elements.prototype.initialize.apply(this,arguments);this.translationParameters={x:0,y:0};this.supportUse=(navigator.userAgent.toLowerCase().indexOf("applewebkit/5")==-1);this.isGecko=(navigator.userAgent.toLowerCase().indexOf("gecko/")!=-1);this.symbolMetrics={};},destroy:function(){OpenLayers.Renderer.Elements.prototype.destroy.apply(this,arguments);},supported:function(){var svgFeature="http://www.w3.org/TR/SVG11/feature#";return(document.implementation&&(document.implementation.hasFeature("org.w3c.svg","1.0")||document.implementation.hasFeature(svgFeature+"SVG","1.1")||document.implementation.hasFeature(svgFeature+"BasicStructure","1.1")));},inValidRange:function(x,y,xyOnly){var left=x+(xyOnly?0:this.translationParameters.x);var top=y+(xyOnly?0:this.translationParameters.y);return(left>=-this.MAX_PIXEL&&left<=this.MAX_PIXEL&&top>=-this.MAX_PIXEL&&top<=this.MAX_PIXEL);},setExtent:function(extent,resolutionChanged){OpenLayers.Renderer.Elements.prototype.setExtent.apply(this,arguments);var resolution=this.getResolution();var left=-extent.left/resolution;var top=extent.top/resolution;if(resolutionChanged){this.left=left;this.top=top;var extentString="0 0 "+this.size.w+" "+this.size.h;this.rendererRoot.setAttributeNS(null,"viewBox",extentString);this.translate(0,0);return true;}else{var inRange=this.translate(left-this.left,top-this.top);if(!inRange){this.setExtent(extent,true);}
59829 return inRange;}},translate:function(x,y){if(!this.inValidRange(x,y,true)){return false;}else{var transformString="";if(x||y){transformString="translate("+x+","+y+")";}
59830 this.root.setAttributeNS(null,"transform",transformString);this.translationParameters={x:x,y:y};return true;}},setSize:function(size){OpenLayers.Renderer.prototype.setSize.apply(this,arguments);this.rendererRoot.setAttributeNS(null,"width",this.size.w);this.rendererRoot.setAttributeNS(null,"height",this.size.h);},getNodeType:function(geometry,style){var nodeType=null;switch(geometry.CLASS_NAME){case"OpenLayers.Geometry.Point":if(style.externalGraphic){nodeType="image";}else if(this.isComplexSymbol(style.graphicName)){nodeType=this.supportUse===false?"svg":"use";}else{nodeType="circle";}
59831 break;case"OpenLayers.Geometry.Rectangle":nodeType="rect";break;case"OpenLayers.Geometry.LineString":nodeType="polyline";break;case"OpenLayers.Geometry.LinearRing":nodeType="polygon";break;case"OpenLayers.Geometry.Polygon":case"OpenLayers.Geometry.Curve":case"OpenLayers.Geometry.Surface":nodeType="path";break;default:break;}
59832 return nodeType;},setStyle:function(node,style,options){style=style||node._style;options=options||node._options;var r=parseFloat(node.getAttributeNS(null,"r"));var widthFactor=1;var pos;if(node._geometryClass=="OpenLayers.Geometry.Point"&&r){node.style.visibility="";if(style.graphic===false){node.style.visibility="hidden";}else if(style.externalGraphic){pos=this.getPosition(node);if(style.graphicTitle){node.setAttributeNS(null,"title",style.graphicTitle);}
59833 if(style.graphicWidth&&style.graphicHeight){node.setAttributeNS(null,"preserveAspectRatio","none");}
59834 var width=style.graphicWidth||style.graphicHeight;var height=style.graphicHeight||style.graphicWidth;width=width?width:style.pointRadius*2;height=height?height:style.pointRadius*2;var xOffset=(style.graphicXOffset!=undefined)?style.graphicXOffset:-(0.5*width);var yOffset=(style.graphicYOffset!=undefined)?style.graphicYOffset:-(0.5*height);var opacity=style.graphicOpacity||style.fillOpacity;node.setAttributeNS(null,"x",(pos.x+xOffset).toFixed());node.setAttributeNS(null,"y",(pos.y+yOffset).toFixed());node.setAttributeNS(null,"width",width);node.setAttributeNS(null,"height",height);node.setAttributeNS(this.xlinkns,"href",style.externalGraphic);node.setAttributeNS(null,"style","opacity: "+opacity);}else if(this.isComplexSymbol(style.graphicName)){var offset=style.pointRadius*3;var size=offset*2;var id=this.importSymbol(style.graphicName);pos=this.getPosition(node);widthFactor=this.symbolMetrics[id][0]*3/size;var parent=node.parentNode;var nextSibling=node.nextSibling;if(parent){parent.removeChild(node);}
59835 if(this.supportUse===false){var src=document.getElementById(id);node.firstChild&&node.removeChild(node.firstChild);node.appendChild(src.firstChild.cloneNode(true));node.setAttributeNS(null,"viewBox",src.getAttributeNS(null,"viewBox"));}else{node.setAttributeNS(this.xlinkns,"href","#"+id);}
59836 node.setAttributeNS(null,"width",size);node.setAttributeNS(null,"height",size);node.setAttributeNS(null,"x",pos.x-offset);node.setAttributeNS(null,"y",pos.y-offset);if(nextSibling){parent.insertBefore(node,nextSibling);}else if(parent){parent.appendChild(node);}}else{node.setAttributeNS(null,"r",style.pointRadius);}
59837 var rotation=style.rotation;if((rotation!==undefined||node._rotation!==undefined)&&pos){node._rotation=rotation;rotation|=0;if(node.nodeName!=="svg"){node.setAttributeNS(null,"transform","rotate("+rotation+" "+pos.x+" "+
59838 pos.y+")");}else{var metrics=this.symbolMetrics[id];node.firstChild.setAttributeNS(null,"transform","rotate("+style.rotation+" "+metrics[1]+" "+metrics[2]+")");}}}
59839 if(options.isFilled){node.setAttributeNS(null,"fill",style.fillColor);node.setAttributeNS(null,"fill-opacity",style.fillOpacity);}else{node.setAttributeNS(null,"fill","none");}
59840 if(options.isStroked){node.setAttributeNS(null,"stroke",style.strokeColor);node.setAttributeNS(null,"stroke-opacity",style.strokeOpacity);node.setAttributeNS(null,"stroke-width",style.strokeWidth*widthFactor);node.setAttributeNS(null,"stroke-linecap",style.strokeLinecap||"round");node.setAttributeNS(null,"stroke-linejoin","round");style.strokeDashstyle&&node.setAttributeNS(null,"stroke-dasharray",this.dashStyle(style,widthFactor));}else{node.setAttributeNS(null,"stroke","none");}
59841 if(style.pointerEvents){node.setAttributeNS(null,"pointer-events",style.pointerEvents);}
59842 if(style.cursor!=null){node.setAttributeNS(null,"cursor",style.cursor);}
59843 return node;},dashStyle:function(style,widthFactor){var w=style.strokeWidth*widthFactor;var str=style.strokeDashstyle;switch(str){case'solid':return'none';case'dot':return[1,4*w].join();case'dash':return[4*w,4*w].join();case'dashdot':return[4*w,4*w,1,4*w].join();case'longdash':return[8*w,4*w].join();case'longdashdot':return[8*w,4*w,1,4*w].join();default:return OpenLayers.String.trim(str).replace(/\s+/g,",");}},createNode:function(type,id){var node=document.createElementNS(this.xmlns,type);if(id){node.setAttributeNS(null,"id",id);}
59844 return node;},nodeTypeCompare:function(node,type){return(type==node.nodeName);},createRenderRoot:function(){return this.nodeFactory(this.container.id+"_svgRoot","svg");},createRoot:function(suffix){return this.nodeFactory(this.container.id+suffix,"g");},createDefs:function(){var defs=this.nodeFactory(this.container.id+"_defs","defs");this.rendererRoot.appendChild(defs);return defs;},drawPoint:function(node,geometry){return this.drawCircle(node,geometry,1);},drawCircle:function(node,geometry,radius){var resolution=this.getResolution();var x=(geometry.x/resolution+this.left);var y=(this.top-geometry.y/resolution);if(this.inValidRange(x,y)){node.setAttributeNS(null,"cx",x);node.setAttributeNS(null,"cy",y);node.setAttributeNS(null,"r",radius);return node;}else{return false;}},drawLineString:function(node,geometry){var componentsResult=this.getComponentsString(geometry.components);if(componentsResult.path){node.setAttributeNS(null,"points",componentsResult.path);return(componentsResult.complete?node:null);}else{return false;}},drawLinearRing:function(node,geometry){var componentsResult=this.getComponentsString(geometry.components);if(componentsResult.path){node.setAttributeNS(null,"points",componentsResult.path);return(componentsResult.complete?node:null);}else{return false;}},drawPolygon:function(node,geometry){var d="";var draw=true;var complete=true;var linearRingResult,path;for(var j=0,len=geometry.components.length;j<len;j++){d+=" M";linearRingResult=this.getComponentsString(geometry.components[j].components," ");path=linearRingResult.path;if(path){d+=" "+path;complete=linearRingResult.complete&&complete;}else{draw=false;}}
59845 d+=" z";if(draw){node.setAttributeNS(null,"d",d);node.setAttributeNS(null,"fill-rule","evenodd");return complete?node:null;}else{return false;}},drawRectangle:function(node,geometry){var resolution=this.getResolution();var x=(geometry.x/resolution+this.left);var y=(this.top-geometry.y/resolution);if(this.inValidRange(x,y)){node.setAttributeNS(null,"x",x);node.setAttributeNS(null,"y",y);node.setAttributeNS(null,"width",geometry.width/resolution);node.setAttributeNS(null,"height",geometry.height/resolution);return node;}else{return false;}},drawSurface:function(node,geometry){var d=null;var draw=true;for(var i=0,len=geometry.components.length;i<len;i++){if((i%3)==0&&(i/3)==0){var component=this.getShortString(geometry.components[i]);if(!component){draw=false;}
59846 d="M "+component;}else if((i%3)==1){var component=this.getShortString(geometry.components[i]);if(!component){draw=false;}
59847 d+=" C "+component;}else{var component=this.getShortString(geometry.components[i]);if(!component){draw=false;}
59848 d+=" "+component;}}
59849 d+=" Z";if(draw){node.setAttributeNS(null,"d",d);return node;}else{return false;}},drawText:function(featureId,style,location){var resolution=this.getResolution();var x=(location.x/resolution+this.left);var y=(location.y/resolution-this.top);var label=this.nodeFactory(featureId+this.LABEL_ID_SUFFIX,"text");var tspan=this.nodeFactory(featureId+this.LABEL_ID_SUFFIX+"_tspan","tspan");label.setAttributeNS(null,"x",x);label.setAttributeNS(null,"y",-y);if(style.fontColor){label.setAttributeNS(null,"fill",style.fontColor);}
59850 if(style.fontOpacity){label.setAttributeNS(null,"opacity",style.fontOpacity);}
59851 if(style.fontFamily){label.setAttributeNS(null,"font-family",style.fontFamily);}
59852 if(style.fontSize){label.setAttributeNS(null,"font-size",style.fontSize);}
59853 if(style.fontWeight){label.setAttributeNS(null,"font-weight",style.fontWeight);}
59854 if(style.labelSelect===true){label.setAttributeNS(null,"pointer-events","visible");label._featureId=featureId;tspan._featureId=featureId;tspan._geometry=location;tspan._geometryClass=location.CLASS_NAME;}else{label.setAttributeNS(null,"pointer-events","none");}
59855 var align=style.labelAlign||"cm";label.setAttributeNS(null,"text-anchor",OpenLayers.Renderer.SVG.LABEL_ALIGN[align[0]]||"middle");if(this.isGecko){label.setAttributeNS(null,"dominant-baseline",OpenLayers.Renderer.SVG.LABEL_ALIGN[align[1]]||"central");}else{tspan.setAttributeNS(null,"baseline-shift",OpenLayers.Renderer.SVG.LABEL_VSHIFT[align[1]]||"-35%");}
59856 tspan.textContent=style.label;if(!label.parentNode){label.appendChild(tspan);this.textRoot.appendChild(label);}},getComponentsString:function(components,separator){var renderCmp=[];var complete=true;var len=components.length;var strings=[];var str,component;for(var i=0;i<len;i++){component=components[i];renderCmp.push(component);str=this.getShortString(component);if(str){strings.push(str);}else{if(i>0){if(this.getShortString(components[i-1])){strings.push(this.clipLine(components[i],components[i-1]));}}
59857 if(i<len-1){if(this.getShortString(components[i+1])){strings.push(this.clipLine(components[i],components[i+1]));}}
59858 complete=false;}}
59859 return{path:strings.join(separator||","),complete:complete};},clipLine:function(badComponent,goodComponent){if(goodComponent.equals(badComponent)){return"";}
59860 var resolution=this.getResolution();var maxX=this.MAX_PIXEL-this.translationParameters.x;var maxY=this.MAX_PIXEL-this.translationParameters.y;var x1=goodComponent.x/resolution+this.left;var y1=this.top-goodComponent.y/resolution;var x2=badComponent.x/resolution+this.left;var y2=this.top-badComponent.y/resolution;var k;if(x2<-maxX||x2>maxX){k=(y2-y1)/(x2-x1);x2=x2<0?-maxX:maxX;y2=y1+(x2-x1)*k;}
59861 if(y2<-maxY||y2>maxY){k=(x2-x1)/(y2-y1);y2=y2<0?-maxY:maxY;x2=x1+(y2-y1)*k;}
59862 return x2+","+y2;},getShortString:function(point){var resolution=this.getResolution();var x=(point.x/resolution+this.left);var y=(this.top-point.y/resolution);if(this.inValidRange(x,y)){return x+","+y;}else{return false;}},getPosition:function(node){return({x:parseFloat(node.getAttributeNS(null,"cx")),y:parseFloat(node.getAttributeNS(null,"cy"))});},importSymbol:function(graphicName){if(!this.defs){this.defs=this.createDefs();}
59863 var id=this.container.id+"-"+graphicName;if(document.getElementById(id)!=null){return id;}
59864 var symbol=OpenLayers.Renderer.symbol[graphicName];if(!symbol){throw new Error(graphicName+' is not a valid symbol name');}
59865 var symbolNode=this.nodeFactory(id,"symbol");var node=this.nodeFactory(null,"polygon");symbolNode.appendChild(node);var symbolExtent=new OpenLayers.Bounds(Number.MAX_VALUE,Number.MAX_VALUE,0,0);var points=[];var x,y;for(var i=0;i<symbol.length;i=i+2){x=symbol[i];y=symbol[i+1];symbolExtent.left=Math.min(symbolExtent.left,x);symbolExtent.bottom=Math.min(symbolExtent.bottom,y);symbolExtent.right=Math.max(symbolExtent.right,x);symbolExtent.top=Math.max(symbolExtent.top,y);points.push(x,",",y);}
59866 node.setAttributeNS(null,"points",points.join(" "));var width=symbolExtent.getWidth();var height=symbolExtent.getHeight();var viewBox=[symbolExtent.left-width,symbolExtent.bottom-height,width*3,height*3];symbolNode.setAttributeNS(null,"viewBox",viewBox.join(" "));this.symbolMetrics[id]=[Math.max(width,height),symbolExtent.getCenterLonLat().lon,symbolExtent.getCenterLonLat().lat];this.defs.appendChild(symbolNode);return symbolNode.id;},getFeatureIdFromEvent:function(evt){var featureId=OpenLayers.Renderer.Elements.prototype.getFeatureIdFromEvent.apply(this,arguments);if(this.supportUse===false&&!featureId){var target=evt.target;featureId=target.parentNode&&target!=this.rendererRoot&&target.parentNode._featureId;}
59867 return featureId;},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.VML=OpenLayers.Class(OpenLayers.Renderer.Elements,{xmlns:"urn:schemas-microsoft-com:vml",symbolCache:{},offset:null,initialize:function(containerID){if(!this.supported()){return;}
59868 if(!document.namespaces.olv){document.namespaces.add("olv",this.xmlns);var style=document.createStyleSheet();var shapes=['shape','rect','oval','fill','stroke','imagedata','group','textbox'];for(var i=0,len=shapes.length;i<len;i++){style.addRule('olv\\:'+shapes[i],"behavior: url(#default#VML); "+"position: absolute; display: inline-block;");}}
59869 OpenLayers.Renderer.Elements.prototype.initialize.apply(this,arguments);},destroy:function(){OpenLayers.Renderer.Elements.prototype.destroy.apply(this,arguments);},supported:function(){return!!(document.namespaces);},setExtent:function(extent,resolutionChanged){OpenLayers.Renderer.Elements.prototype.setExtent.apply(this,arguments);var resolution=this.getResolution();var left=(extent.left/resolution)|0;var top=(extent.top/resolution-this.size.h)|0;if(resolutionChanged||!this.offset){this.offset={x:left,y:top};left=0;top=0;}else{left=left-this.offset.x;top=top-this.offset.y;}
59870 var org=left+" "+top;this.root.coordorigin=org;var roots=[this.root,this.vectorRoot,this.textRoot];var root;for(var i=0,len=roots.length;i<len;++i){root=roots[i];var size=this.size.w+" "+this.size.h;root.coordsize=size;}
59871 this.root.style.flip="y";return true;},setSize:function(size){OpenLayers.Renderer.prototype.setSize.apply(this,arguments);var roots=[this.rendererRoot,this.root,this.vectorRoot,this.textRoot];var w=this.size.w+"px";var h=this.size.h+"px";var root;for(var i=0,len=roots.length;i<len;++i){root=roots[i];root.style.width=w;root.style.height=h;}},getNodeType:function(geometry,style){var nodeType=null;switch(geometry.CLASS_NAME){case"OpenLayers.Geometry.Point":if(style.externalGraphic){nodeType="olv:rect";}else if(this.isComplexSymbol(style.graphicName)){nodeType="olv:shape";}else{nodeType="olv:oval";}
59872 break;case"OpenLayers.Geometry.Rectangle":nodeType="olv:rect";break;case"OpenLayers.Geometry.LineString":case"OpenLayers.Geometry.LinearRing":case"OpenLayers.Geometry.Polygon":case"OpenLayers.Geometry.Curve":case"OpenLayers.Geometry.Surface":nodeType="olv:shape";break;default:break;}
59873 return nodeType;},setStyle:function(node,style,options,geometry){style=style||node._style;options=options||node._options;var fillColor=style.fillColor;if(node._geometryClass==="OpenLayers.Geometry.Point"){if(style.externalGraphic){if(style.graphicTitle){node.title=style.graphicTitle;}
59874 var width=style.graphicWidth||style.graphicHeight;var height=style.graphicHeight||style.graphicWidth;width=width?width:style.pointRadius*2;height=height?height:style.pointRadius*2;var resolution=this.getResolution();var xOffset=(style.graphicXOffset!=undefined)?style.graphicXOffset:-(0.5*width);var yOffset=(style.graphicYOffset!=undefined)?style.graphicYOffset:-(0.5*height);node.style.left=(((geometry.x/resolution-this.offset.x)+xOffset)|0)+"px";node.style.top=(((geometry.y/resolution-this.offset.y)-(yOffset+height))|0)+"px";node.style.width=width+"px";node.style.height=height+"px";node.style.flip="y";fillColor="none";options.isStroked=false;}else if(this.isComplexSymbol(style.graphicName)){var cache=this.importSymbol(style.graphicName);node.path=cache.path;node.coordorigin=cache.left+","+cache.bottom;var size=cache.size;node.coordsize=size+","+size;this.drawCircle(node,geometry,style.pointRadius);node.style.flip="y";}else{this.drawCircle(node,geometry,style.pointRadius);}}
59875 if(options.isFilled){node.fillcolor=fillColor;}else{node.filled="false";}
59876 var fills=node.getElementsByTagName("fill");var fill=(fills.length==0)?null:fills[0];if(!options.isFilled){if(fill){node.removeChild(fill);}}else{if(!fill){fill=this.createNode('olv:fill',node.id+"_fill");}
59877 fill.opacity=style.fillOpacity;if(node._geometryClass==="OpenLayers.Geometry.Point"&&style.externalGraphic){if(style.graphicOpacity){fill.opacity=style.graphicOpacity;}
59878 fill.src=style.externalGraphic;fill.type="frame";if(!(style.graphicWidth&&style.graphicHeight)){fill.aspect="atmost";}}
59879 if(fill.parentNode!=node){node.appendChild(fill);}}
59880 var rotation=style.rotation;if((rotation!==undefined||node._rotation!==undefined)){node._rotation=rotation;if(style.externalGraphic){this.graphicRotate(node,xOffset,yOffset,style);fill.opacity=0;}else if(node._geometryClass==="OpenLayers.Geometry.Point"){node.style.rotation=rotation||0;}}
59881 var strokes=node.getElementsByTagName("stroke");var stroke=(strokes.length==0)?null:strokes[0];if(!options.isStroked){node.stroked=false;if(stroke){stroke.on=false;}}else{if(!stroke){stroke=this.createNode('olv:stroke',node.id+"_stroke");node.appendChild(stroke);}
59882 stroke.on=true;stroke.color=style.strokeColor;stroke.weight=style.strokeWidth+"px";stroke.opacity=style.strokeOpacity;stroke.endcap=style.strokeLinecap=='butt'?'flat':(style.strokeLinecap||'round');if(style.strokeDashstyle){stroke.dashstyle=this.dashStyle(style);}}
59883 if(style.cursor!="inherit"&&style.cursor!=null){node.style.cursor=style.cursor;}
59884 return node;},graphicRotate:function(node,xOffset,yOffset,style){var style=style||node._style;var rotation=style.rotation||0;var aspectRatio,size;if(!(style.graphicWidth&&style.graphicHeight)){var img=new Image();img.onreadystatechange=OpenLayers.Function.bind(function(){if(img.readyState=="complete"||img.readyState=="interactive"){aspectRatio=img.width/img.height;size=Math.max(style.pointRadius*2,style.graphicWidth||0,style.graphicHeight||0);xOffset=xOffset*aspectRatio;style.graphicWidth=size*aspectRatio;style.graphicHeight=size;this.graphicRotate(node,xOffset,yOffset,style);}},this);img.src=style.externalGraphic;return;}else{size=Math.max(style.graphicWidth,style.graphicHeight);aspectRatio=style.graphicWidth/style.graphicHeight;}
59885 var width=Math.round(style.graphicWidth||size*aspectRatio);var height=Math.round(style.graphicHeight||size);node.style.width=width+"px";node.style.height=height+"px";var image=document.getElementById(node.id+"_image");if(!image){image=this.createNode("olv:imagedata",node.id+"_image");node.appendChild(image);}
59886 image.style.width=width+"px";image.style.height=height+"px";image.src=style.externalGraphic;image.style.filter="progid:DXImageTransform.Microsoft.AlphaImageLoader("+"src='', sizingMethod='scale')";var rot=rotation*Math.PI/180;var sintheta=Math.sin(rot);var costheta=Math.cos(rot);var filter="progid:DXImageTransform.Microsoft.Matrix(M11="+costheta+",M12="+(-sintheta)+",M21="+sintheta+",M22="+costheta+",SizingMethod='auto expand')\n";var opacity=style.graphicOpacity||style.fillOpacity;if(opacity&&opacity!=1){filter+="progid:DXImageTransform.Microsoft.BasicImage(opacity="+
59887 opacity+")\n";}
59888 node.style.filter=filter;var centerPoint=new OpenLayers.Geometry.Point(-xOffset,-yOffset);var imgBox=new OpenLayers.Bounds(0,0,width,height).toGeometry();imgBox.rotate(style.rotation,centerPoint);var imgBounds=imgBox.getBounds();node.style.left=Math.round(parseInt(node.style.left)+imgBounds.left)+"px";node.style.top=Math.round(parseInt(node.style.top)-imgBounds.bottom)+"px";},postDraw:function(node){node.style.visibility="visible";var fillColor=node._style.fillColor;var strokeColor=node._style.strokeColor;if(fillColor=="none"&&node.fillcolor!=fillColor){node.fillcolor=fillColor;}
59889 if(strokeColor=="none"&&node.strokecolor!=strokeColor){node.strokecolor=strokeColor;}},setNodeDimension:function(node,geometry){var bbox=geometry.getBounds();if(bbox){var resolution=this.getResolution();var scaledBox=new OpenLayers.Bounds((bbox.left/resolution-this.offset.x)|0,(bbox.bottom/resolution-this.offset.y)|0,(bbox.right/resolution-this.offset.x)|0,(bbox.top/resolution-this.offset.y)|0);node.style.left=scaledBox.left+"px";node.style.top=scaledBox.top+"px";node.style.width=scaledBox.getWidth()+"px";node.style.height=scaledBox.getHeight()+"px";node.coordorigin=scaledBox.left+" "+scaledBox.top;node.coordsize=scaledBox.getWidth()+" "+scaledBox.getHeight();}},dashStyle:function(style){var dash=style.strokeDashstyle;switch(dash){case'solid':case'dot':case'dash':case'dashdot':case'longdash':case'longdashdot':return dash;default:var parts=dash.split(/[ ,]/);if(parts.length==2){if(1*parts[0]>=2*parts[1]){return"longdash";}
59890 return(parts[0]==1||parts[1]==1)?"dot":"dash";}else if(parts.length==4){return(1*parts[0]>=2*parts[1])?"longdashdot":"dashdot";}
59891 return"solid";}},createNode:function(type,id){var node=document.createElement(type);if(id){node.id=id;}
59892 node.unselectable='on';node.onselectstart=OpenLayers.Function.False;return node;},nodeTypeCompare:function(node,type){var subType=type;var splitIndex=subType.indexOf(":");if(splitIndex!=-1){subType=subType.substr(splitIndex+1);}
59893 var nodeName=node.nodeName;splitIndex=nodeName.indexOf(":");if(splitIndex!=-1){nodeName=nodeName.substr(splitIndex+1);}
59894 return(subType==nodeName);},createRenderRoot:function(){return this.nodeFactory(this.container.id+"_vmlRoot","div");},createRoot:function(suffix){return this.nodeFactory(this.container.id+suffix,"olv:group");},drawPoint:function(node,geometry){return this.drawCircle(node,geometry,1);},drawCircle:function(node,geometry,radius){if(!isNaN(geometry.x)&&!isNaN(geometry.y)){var resolution=this.getResolution();node.style.left=(((geometry.x/resolution-this.offset.x)|0)-radius)+"px";node.style.top=(((geometry.y/resolution-this.offset.y)|0)-radius)+"px";var diameter=radius*2;node.style.width=diameter+"px";node.style.height=diameter+"px";return node;}
59895 return false;},drawLineString:function(node,geometry){return this.drawLine(node,geometry,false);},drawLinearRing:function(node,geometry){return this.drawLine(node,geometry,true);},drawLine:function(node,geometry,closeLine){this.setNodeDimension(node,geometry);var resolution=this.getResolution();var numComponents=geometry.components.length;var parts=new Array(numComponents);var comp,x,y;for(var i=0;i<numComponents;i++){comp=geometry.components[i];x=(comp.x/resolution-this.offset.x)|0;y=(comp.y/resolution-this.offset.y)|0;parts[i]=" "+x+","+y+" l ";}
59896 var end=(closeLine)?" x e":" e";node.path="m"+parts.join("")+end;return node;},drawPolygon:function(node,geometry){this.setNodeDimension(node,geometry);var resolution=this.getResolution();var path=[];var linearRing,i,j,len,ilen,comp,x,y;for(j=0,len=geometry.components.length;j<len;j++){linearRing=geometry.components[j];path.push("m");for(i=0,ilen=linearRing.components.length;i<ilen;i++){comp=linearRing.components[i];x=(comp.x/resolution-this.offset.x)|0;y=(comp.y/resolution-this.offset.y)|0;path.push(" "+x+","+y);if(i==0){path.push(" l");}}
59897 path.push(" x ");}
59898 path.push("e");node.path=path.join("");return node;},drawRectangle:function(node,geometry){var resolution=this.getResolution();node.style.left=((geometry.x/resolution-this.offset.x)|0)+"px";node.style.top=((geometry.y/resolution-this.offset.y)|0)+"px";node.style.width=((geometry.width/resolution)|0)+"px";node.style.height=((geometry.height/resolution)|0)+"px";return node;},drawText:function(featureId,style,location){var label=this.nodeFactory(featureId+this.LABEL_ID_SUFFIX,"olv:rect");var textbox=this.nodeFactory(featureId+this.LABEL_ID_SUFFIX+"_textbox","olv:textbox");var resolution=this.getResolution();label.style.left=((location.x/resolution-this.offset.x)|0)+"px";label.style.top=((location.y/resolution-this.offset.y)|0)+"px";label.style.flip="y";textbox.innerText=style.label;if(style.fontColor){textbox.style.color=style.fontColor;}
59899 if(style.fontOpacity){textbox.style.filter='alpha(opacity='+(style.fontOpacity*100)+')';}
59900 if(style.fontFamily){textbox.style.fontFamily=style.fontFamily;}
59901 if(style.fontSize){textbox.style.fontSize=style.fontSize;}
59902 if(style.fontWeight){textbox.style.fontWeight=style.fontWeight;}
59903 if(style.labelSelect===true){label._featureId=featureId;textbox._featureId=featureId;textbox._geometry=location;textbox._geometryClass=location.CLASS_NAME;}
59904 textbox.style.whiteSpace="nowrap";textbox.inset="1px,0px,0px,0px";if(!label.parentNode){label.appendChild(textbox);this.textRoot.appendChild(label);}
59905 var align=style.labelAlign||"cm";if(align.length==1){align+="m";}
59906 var xshift=textbox.clientWidth*(OpenLayers.Renderer.VML.LABEL_SHIFT[align.substr(0,1)]);var yshift=textbox.clientHeight*(OpenLayers.Renderer.VML.LABEL_SHIFT[align.substr(1,1)]);label.style.left=parseInt(label.style.left)-xshift-1+"px";label.style.top=parseInt(label.style.top)+yshift+"px";},drawSurface:function(node,geometry){this.setNodeDimension(node,geometry);var resolution=this.getResolution();var path=[];var comp,x,y;for(var i=0,len=geometry.components.length;i<len;i++){comp=geometry.components[i];x=(comp.x/resolution-this.offset.x)|0;y=(comp.y/resolution-this.offset.y)|0;if((i%3)==0&&(i/3)==0){path.push("m");}else if((i%3)==1){path.push(" c");}
59907 path.push(" "+x+","+y);}
59908 path.push(" x e");node.path=path.join("");return node;},moveRoot:function(renderer){var layer=this.map.getLayer(renderer.container.id);if(layer instanceof OpenLayers.Layer.Vector.RootContainer){layer=this.map.getLayer(this.container.id);}
59909 layer&&layer.renderer.clear();OpenLayers.Renderer.Elements.prototype.moveRoot.apply(this,arguments);layer&&layer.redraw();},importSymbol:function(graphicName){var id=this.container.id+"-"+graphicName;var cache=this.symbolCache[id];if(cache){return cache;}
59910 var symbol=OpenLayers.Renderer.symbol[graphicName];if(!symbol){throw new Error(graphicName+' is not a valid symbol name');}
59911 var symbolExtent=new OpenLayers.Bounds(Number.MAX_VALUE,Number.MAX_VALUE,0,0);var pathitems=["m"];for(var i=0;i<symbol.length;i=i+2){var x=symbol[i];var y=symbol[i+1];symbolExtent.left=Math.min(symbolExtent.left,x);symbolExtent.bottom=Math.min(symbolExtent.bottom,y);symbolExtent.right=Math.max(symbolExtent.right,x);symbolExtent.top=Math.max(symbolExtent.top,y);pathitems.push(x);pathitems.push(y);if(i==0){pathitems.push("l");}}
59912 pathitems.push("x e");var path=pathitems.join(" ");var diff=(symbolExtent.getWidth()-symbolExtent.getHeight())/2;if(diff>0){symbolExtent.bottom=symbolExtent.bottom-diff;symbolExtent.top=symbolExtent.top+diff;}else{symbolExtent.left=symbolExtent.left+diff;symbolExtent.right=symbolExtent.right-diff;}
59913 cache={path:path,size:symbolExtent.getWidth(),left:symbolExtent.left,bottom:symbolExtent.bottom};this.symbolCache[id]=cache;return cache;},CLASS_NAME:"OpenLayers.Renderer.VML"});OpenLayers.Renderer.VML.LABEL_SHIFT={"l":0,"c":.5,"r":1,"t":0,"m":.5,"b":1};OpenLayers.Tile=OpenLayers.Class({EVENT_TYPES:["loadstart","loadend","reload","unload"],events:null,id:null,layer:null,url:null,bounds:null,size:null,position:null,isLoading:false,initialize:function(layer,position,bounds,url,size){this.layer=layer;this.position=position.clone();this.bounds=bounds.clone();this.url=url;this.size=size.clone();this.id=OpenLayers.Util.createUniqueID("Tile_");this.events=new OpenLayers.Events(this,null,this.EVENT_TYPES);},unload:function(){if(this.isLoading){this.isLoading=false;this.events.triggerEvent("unload");}},destroy:function(){this.layer=null;this.bounds=null;this.size=null;this.position=null;this.events.destroy();this.events=null;},clone:function(obj){if(obj==null){obj=new OpenLayers.Tile(this.layer,this.position,this.bounds,this.url,this.size);}
59914 OpenLayers.Util.applyDefaults(obj,this);return obj;},draw:function(){var maxExtent=this.layer.maxExtent;var withinMaxExtent=(maxExtent&&this.bounds.intersectsBounds(maxExtent,false));this.shouldDraw=(withinMaxExtent||this.layer.displayOutsideMaxExtent);this.clear();return this.shouldDraw;},moveTo:function(bounds,position,redraw){if(redraw==null){redraw=true;}
59915 this.bounds=bounds.clone();this.position=position.clone();if(redraw){this.draw();}},clear:function(){},getBoundsFromBaseLayer:function(position){var msg=OpenLayers.i18n('reprojectDeprecated',{'layerName':this.layer.name});OpenLayers.Console.warn(msg);var topLeft=this.layer.map.getLonLatFromLayerPx(position);var bottomRightPx=position.clone();bottomRightPx.x+=this.size.w;bottomRightPx.y+=this.size.h;var bottomRight=this.layer.map.getLonLatFromLayerPx(bottomRightPx);if(topLeft.lon>bottomRight.lon){if(topLeft.lon<0){topLeft.lon=-180-(topLeft.lon+180);}else{bottomRight.lon=180+bottomRight.lon+180;}}
59916 var bounds=new OpenLayers.Bounds(topLeft.lon,bottomRight.lat,bottomRight.lon,topLeft.lat);return bounds;},showTile:function(){if(this.shouldDraw){this.show();}},show:function(){},hide:function(){},CLASS_NAME:"OpenLayers.Tile"});OpenLayers.Control.MouseToolbar=OpenLayers.Class(OpenLayers.Control.MouseDefaults,{mode:null,buttons:null,direction:"vertical",buttonClicked:null,initialize:function(position,direction){OpenLayers.Control.prototype.initialize.apply(this,arguments);this.position=new OpenLayers.Pixel(OpenLayers.Control.MouseToolbar.X,OpenLayers.Control.MouseToolbar.Y);if(position){this.position=position;}
59917 if(direction){this.direction=direction;}
59918 this.measureDivs=[];},destroy:function(){for(var btnId in this.buttons){var btn=this.buttons[btnId];btn.map=null;btn.events.destroy();}
59919 OpenLayers.Control.MouseDefaults.prototype.destroy.apply(this,arguments);},draw:function(){OpenLayers.Control.prototype.draw.apply(this,arguments);OpenLayers.Control.MouseDefaults.prototype.draw.apply(this,arguments);this.buttons={};var sz=new OpenLayers.Size(28,28);var centered=new OpenLayers.Pixel(OpenLayers.Control.MouseToolbar.X,0);this._addButton("zoombox","drag-rectangle-off.png","drag-rectangle-on.png",centered,sz,"Shift->Drag to zoom to area");centered=centered.add((this.direction=="vertical"?0:sz.w),(this.direction=="vertical"?sz.h:0));this._addButton("pan","panning-hand-off.png","panning-hand-on.png",centered,sz,"Drag the map to pan.");centered=centered.add((this.direction=="vertical"?0:sz.w),(this.direction=="vertical"?sz.h:0));this.switchModeTo("pan");return this.div;},_addButton:function(id,img,activeImg,xy,sz,title){var imgLocation=OpenLayers.Util.getImagesLocation()+img;var activeImgLocation=OpenLayers.Util.getImagesLocation()+activeImg;var btn=OpenLayers.Util.createAlphaImageDiv("OpenLayers_Control_MouseToolbar_"+id,xy,sz,imgLocation,"absolute");this.div.appendChild(btn);btn.imgLocation=imgLocation;btn.activeImgLocation=activeImgLocation;btn.events=new OpenLayers.Events(this,btn,null,true);btn.events.on({"mousedown":this.buttonDown,"mouseup":this.buttonUp,"dblclick":OpenLayers.Event.stop,scope:this});btn.action=id;btn.title=title;btn.alt=title;btn.map=this.map;this.buttons[id]=btn;return btn;},buttonDown:function(evt){if(!OpenLayers.Event.isLeftClick(evt)){return;}
59920 this.buttonClicked=evt.element.action;OpenLayers.Event.stop(evt);},buttonUp:function(evt){if(!OpenLayers.Event.isLeftClick(evt)){return;}
59921 if(this.buttonClicked!=null){if(this.buttonClicked==evt.element.action){this.switchModeTo(evt.element.action);}
59922 OpenLayers.Event.stop(evt);this.buttonClicked=null;}},defaultDblClick:function(evt){this.switchModeTo("pan");this.performedDrag=false;var newCenter=this.map.getLonLatFromViewPortPx(evt.xy);this.map.setCenter(newCenter,this.map.zoom+1);OpenLayers.Event.stop(evt);return false;},defaultMouseDown:function(evt){if(!OpenLayers.Event.isLeftClick(evt)){return;}
59923 this.mouseDragStart=evt.xy.clone();this.performedDrag=false;this.startViaKeyboard=false;if(evt.shiftKey&&this.mode!="zoombox"){this.switchModeTo("zoombox");this.startViaKeyboard=true;}else if(evt.altKey&&this.mode!="measure"){this.switchModeTo("measure");}else if(!this.mode){this.switchModeTo("pan");}
59924 switch(this.mode){case"zoombox":this.map.div.style.cursor="crosshair";this.zoomBox=OpenLayers.Util.createDiv('zoomBox',this.mouseDragStart,null,null,"absolute","2px solid red");this.zoomBox.style.backgroundColor="white";this.zoomBox.style.filter="alpha(opacity=50)";this.zoomBox.style.opacity="0.50";this.zoomBox.style.fontSize="1px";this.zoomBox.style.zIndex=this.map.Z_INDEX_BASE["Popup"]-1;this.map.viewPortDiv.appendChild(this.zoomBox);this.performedDrag=true;break;case"measure":var distance="";if(this.measureStart){var measureEnd=this.map.getLonLatFromViewPortPx(this.mouseDragStart);distance=OpenLayers.Util.distVincenty(this.measureStart,measureEnd);distance=Math.round(distance*100)/100;distance=distance+"km";this.measureStartBox=this.measureBox;}
59925 this.measureStart=this.map.getLonLatFromViewPortPx(this.mouseDragStart);;this.measureBox=OpenLayers.Util.createDiv(null,this.mouseDragStart.add(-2-parseInt(this.map.layerContainerDiv.style.left),-2-parseInt(this.map.layerContainerDiv.style.top)),null,null,"absolute");this.measureBox.style.width="4px";this.measureBox.style.height="4px";this.measureBox.style.fontSize="1px";this.measureBox.style.backgroundColor="red";this.measureBox.style.zIndex=this.map.Z_INDEX_BASE["Popup"]-1;this.map.layerContainerDiv.appendChild(this.measureBox);if(distance){this.measureBoxDistance=OpenLayers.Util.createDiv(null,this.mouseDragStart.add(-2-parseInt(this.map.layerContainerDiv.style.left),2-parseInt(this.map.layerContainerDiv.style.top)),null,null,"absolute");this.measureBoxDistance.innerHTML=distance;this.measureBoxDistance.style.zIndex=this.map.Z_INDEX_BASE["Popup"]-1;this.map.layerContainerDiv.appendChild(this.measureBoxDistance);this.measureDivs.push(this.measureBoxDistance);}
59926 this.measureBox.style.zIndex=this.map.Z_INDEX_BASE["Popup"]-1;this.map.layerContainerDiv.appendChild(this.measureBox);this.measureDivs.push(this.measureBox);break;default:this.map.div.style.cursor="move";break;}
59927 document.onselectstart=OpenLayers.Function.False;OpenLayers.Event.stop(evt);},switchModeTo:function(mode){if(mode!=this.mode){if(this.mode&&this.buttons[this.mode]){OpenLayers.Util.modifyAlphaImageDiv(this.buttons[this.mode],null,null,null,this.buttons[this.mode].imgLocation);}
59928 if(this.mode=="measure"&&mode!="measure"){for(var i=0,len=this.measureDivs.length;i<len;i++){if(this.measureDivs[i]){this.map.layerContainerDiv.removeChild(this.measureDivs[i]);}}
59929 this.measureDivs=[];this.measureStart=null;}
59930 this.mode=mode;if(this.buttons[mode]){OpenLayers.Util.modifyAlphaImageDiv(this.buttons[mode],null,null,null,this.buttons[mode].activeImgLocation);}
59931 switch(this.mode){case"zoombox":this.map.div.style.cursor="crosshair";break;default:this.map.div.style.cursor="";break;}}},leaveMode:function(){this.switchModeTo("pan");},defaultMouseMove:function(evt){if(this.mouseDragStart!=null){switch(this.mode){case"zoombox":var deltaX=Math.abs(this.mouseDragStart.x-evt.xy.x);var deltaY=Math.abs(this.mouseDragStart.y-evt.xy.y);this.zoomBox.style.width=Math.max(1,deltaX)+"px";this.zoomBox.style.height=Math.max(1,deltaY)+"px";if(evt.xy.x<this.mouseDragStart.x){this.zoomBox.style.left=evt.xy.x+"px";}
59932 if(evt.xy.y<this.mouseDragStart.y){this.zoomBox.style.top=evt.xy.y+"px";}
59933 break;default:var deltaX=this.mouseDragStart.x-evt.xy.x;var deltaY=this.mouseDragStart.y-evt.xy.y;var size=this.map.getSize();var newXY=new OpenLayers.Pixel(size.w/2+deltaX,size.h/2+deltaY);var newCenter=this.map.getLonLatFromViewPortPx(newXY);this.map.setCenter(newCenter,null,true);this.mouseDragStart=evt.xy.clone();}
59934 this.performedDrag=true;}},defaultMouseUp:function(evt){if(!OpenLayers.Event.isLeftClick(evt)){return;}
59935 switch(this.mode){case"zoombox":this.zoomBoxEnd(evt);if(this.startViaKeyboard){this.leaveMode();}
59936 break;case"pan":if(this.performedDrag){this.map.setCenter(this.map.center);}}
59937 document.onselectstart=null;this.mouseDragStart=null;this.map.div.style.cursor="default";},defaultMouseOut:function(evt){if(this.mouseDragStart!=null&&OpenLayers.Util.mouseLeft(evt,this.map.div)){if(this.zoomBox){this.removeZoomBox();if(this.startViaKeyboard){this.leaveMode();}}
59938 this.mouseDragStart=null;this.map.div.style.cursor="default";}},defaultClick:function(evt){if(this.performedDrag){this.performedDrag=false;return false;}},CLASS_NAME:"OpenLayers.Control.MouseToolbar"});OpenLayers.Control.MouseToolbar.X=6;OpenLayers.Control.MouseToolbar.Y=300;OpenLayers.Control.NavigationHistory=OpenLayers.Class(OpenLayers.Control,{type:OpenLayers.Control.TYPE_TOGGLE,previous:null,previousOptions:null,next:null,nextOptions:null,limit:50,autoActivate:true,clearOnDeactivate:false,registry:null,nextStack:null,previousStack:null,listeners:null,restoring:false,initialize:function(options){OpenLayers.Control.prototype.initialize.apply(this,[options]);this.registry=OpenLayers.Util.extend({"moveend":this.getState},this.registry);var previousOptions={trigger:OpenLayers.Function.bind(this.previousTrigger,this),displayClass:this.displayClass+" "+this.displayClass+"Previous"};OpenLayers.Util.extend(previousOptions,this.previousOptions);this.previous=new OpenLayers.Control.Button(previousOptions);var nextOptions={trigger:OpenLayers.Function.bind(this.nextTrigger,this),displayClass:this.displayClass+" "+this.displayClass+"Next"};OpenLayers.Util.extend(nextOptions,this.nextOptions);this.next=new OpenLayers.Control.Button(nextOptions);this.clear();},onPreviousChange:function(state,length){if(state&&!this.previous.active){this.previous.activate();}else if(!state&&this.previous.active){this.previous.deactivate();}},onNextChange:function(state,length){if(state&&!this.next.active){this.next.activate();}else if(!state&&this.next.active){this.next.deactivate();}},destroy:function(){OpenLayers.Control.prototype.destroy.apply(this);this.previous.destroy();this.next.destroy();this.deactivate();for(var prop in this){this[prop]=null;}},setMap:function(map){this.map=map;this.next.setMap(map);this.previous.setMap(map);},draw:function(){OpenLayers.Control.prototype.draw.apply(this,arguments);this.next.draw();this.previous.draw();},previousTrigger:function(){var current=this.previousStack.shift();var state=this.previousStack.shift();if(state!=undefined){this.nextStack.unshift(current);this.previousStack.unshift(state);this.restoring=true;this.restore(state);this.restoring=false;this.onNextChange(this.nextStack[0],this.nextStack.length);this.onPreviousChange(this.previousStack[1],this.previousStack.length-1);}else{this.previousStack.unshift(current);}
59939 return state;},nextTrigger:function(){var state=this.nextStack.shift();if(state!=undefined){this.previousStack.unshift(state);this.restoring=true;this.restore(state);this.restoring=false;this.onNextChange(this.nextStack[0],this.nextStack.length);this.onPreviousChange(this.previousStack[1],this.previousStack.length-1);}
59940 return state;},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(state){var center,zoom;if(this.map.getProjectionObject()==state.projection){zoom=this.map.getZoomForResolution(state.resolution);center=state.center;}else{center=state.center.clone();center.transform(state.projection,this.map.getProjectionObject());var sourceUnits=state.units;var targetUnits=this.map.getProjectionObject().getUnits()||this.map.units||this.map.baseLayer.units;var resolutionFactor=sourceUnits&&targetUnits?OpenLayers.INCHES_PER_UNIT[sourceUnits]/OpenLayers.INCHES_PER_UNIT[targetUnits]:1;zoom=this.map.getZoomForResolution(resolutionFactor*state.resolution);}
59941 this.map.setCenter(center,zoom);},setListeners:function(){this.listeners={};for(var type in this.registry){this.listeners[type]=OpenLayers.Function.bind(function(){if(!this.restoring){var state=this.registry[type].apply(this,arguments);this.previousStack.unshift(state);if(this.previousStack.length>1){this.onPreviousChange(this.previousStack[1],this.previousStack.length-1);}
59942 if(this.previousStack.length>(this.limit+1)){this.previousStack.pop();}
59943 if(this.nextStack.length>0){this.nextStack=[];this.onNextChange(null,0);}}
59944 return true;},this);}},activate:function(){var activated=false;if(this.map){if(OpenLayers.Control.prototype.activate.apply(this)){if(this.listeners==null){this.setListeners();}
59945 for(var type in this.listeners){this.map.events.register(type,this,this.listeners[type]);}
59946 activated=true;if(this.previousStack.length==0){this.initStack();}}}
59947 return activated;},initStack:function(){if(this.map.getCenter()){this.listeners.moveend();}},deactivate:function(){var deactivated=false;if(this.map){if(OpenLayers.Control.prototype.deactivate.apply(this)){for(var type in this.listeners){this.map.events.unregister(type,this,this.listeners[type]);}
59948 if(this.clearOnDeactivate){this.clear();}
59949 deactivated=true;}}
59950 return deactivated;},CLASS_NAME:"OpenLayers.Control.NavigationHistory"});OpenLayers.Control.PanPanel=OpenLayers.Class(OpenLayers.Control.Panel,{slideFactor:50,initialize:function(options){OpenLayers.Control.Panel.prototype.initialize.apply(this,[options]);this.addControls([new OpenLayers.Control.Pan(OpenLayers.Control.Pan.NORTH,{slideFactor:this.slideFactor}),new OpenLayers.Control.Pan(OpenLayers.Control.Pan.SOUTH,{slideFactor:this.slideFactor}),new OpenLayers.Control.Pan(OpenLayers.Control.Pan.EAST,{slideFactor:this.slideFactor}),new OpenLayers.Control.Pan(OpenLayers.Control.Pan.WEST,{slideFactor:this.slideFactor})]);},CLASS_NAME:"OpenLayers.Control.PanPanel"});OpenLayers.Control.PanZoomBar=OpenLayers.Class(OpenLayers.Control.PanZoom,{zoomStopWidth:18,zoomStopHeight:11,slider:null,sliderEvents:null,zoombarDiv:null,divEvents:null,zoomWorldIcon:false,forceFixedZoomLevel:false,mouseDragStart:null,zoomStart:null,initialize:function(){OpenLayers.Control.PanZoom.prototype.initialize.apply(this,arguments);},destroy:function(){this._removeZoomBar();this.map.events.un({"changebaselayer":this.redraw,scope:this});OpenLayers.Control.PanZoom.prototype.destroy.apply(this,arguments);delete this.mouseDragStart;delete this.zoomStart;},setMap:function(map){OpenLayers.Control.PanZoom.prototype.setMap.apply(this,arguments);this.map.events.register("changebaselayer",this,this.redraw);},redraw:function(){if(this.div!=null){this.removeButtons();this._removeZoomBar();}
59951 this.draw();},draw:function(px){OpenLayers.Control.prototype.draw.apply(this,arguments);px=this.position.clone();this.buttons=[];var sz=new OpenLayers.Size(18,18);var centered=new OpenLayers.Pixel(px.x+sz.w/2,px.y);var wposition=sz.w;if(this.zoomWorldIcon){centered=new OpenLayers.Pixel(px.x+sz.w,px.y);}
59952 this._addButton("panup","north-mini.png",centered,sz);px.y=centered.y+sz.h;this._addButton("panleft","west-mini.png",px,sz);if(this.zoomWorldIcon){this._addButton("zoomworld","zoom-world-mini.png",px.add(sz.w,0),sz);wposition*=2;}
59953 this._addButton("panright","east-mini.png",px.add(wposition,0),sz);this._addButton("pandown","south-mini.png",centered.add(0,sz.h*2),sz);this._addButton("zoomin","zoom-plus-mini.png",centered.add(0,sz.h*3+5),sz);centered=this._addZoomBar(centered.add(0,sz.h*4+5));this._addButton("zoomout","zoom-minus-mini.png",centered,sz);return this.div;},_addZoomBar:function(centered){var imgLocation=OpenLayers.Util.getImagesLocation();var id=this.id+"_"+this.map.id;var zoomsToEnd=this.map.getNumZoomLevels()-1-this.map.getZoom();var slider=OpenLayers.Util.createAlphaImageDiv(id,centered.add(-1,zoomsToEnd*this.zoomStopHeight),new OpenLayers.Size(20,9),imgLocation+"slider.png","absolute");this.slider=slider;this.sliderEvents=new OpenLayers.Events(this,slider,null,true,{includeXY:true});this.sliderEvents.on({"mousedown":this.zoomBarDown,"mousemove":this.zoomBarDrag,"mouseup":this.zoomBarUp,"dblclick":this.doubleClick,"click":this.doubleClick});var sz=new OpenLayers.Size();sz.h=this.zoomStopHeight*this.map.getNumZoomLevels();sz.w=this.zoomStopWidth;var div=null;if(OpenLayers.Util.alphaHack()){var id=this.id+"_"+this.map.id;div=OpenLayers.Util.createAlphaImageDiv(id,centered,new OpenLayers.Size(sz.w,this.zoomStopHeight),imgLocation+"zoombar.png","absolute",null,"crop");div.style.height=sz.h+"px";}else{div=OpenLayers.Util.createDiv('OpenLayers_Control_PanZoomBar_Zoombar'+this.map.id,centered,sz,imgLocation+"zoombar.png");}
59954 this.zoombarDiv=div;this.divEvents=new OpenLayers.Events(this,div,null,true,{includeXY:true});this.divEvents.on({"mousedown":this.divClick,"mousemove":this.passEventToSlider,"dblclick":this.doubleClick,"click":this.doubleClick});this.div.appendChild(div);this.startTop=parseInt(div.style.top);this.div.appendChild(slider);this.map.events.register("zoomend",this,this.moveZoomBar);centered=centered.add(0,this.zoomStopHeight*this.map.getNumZoomLevels());return centered;},_removeZoomBar:function(){this.sliderEvents.un({"mousedown":this.zoomBarDown,"mousemove":this.zoomBarDrag,"mouseup":this.zoomBarUp,"dblclick":this.doubleClick,"click":this.doubleClick});this.sliderEvents.destroy();this.divEvents.un({"mousedown":this.divClick,"mousemove":this.passEventToSlider,"dblclick":this.doubleClick,"click":this.doubleClick});this.divEvents.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);},passEventToSlider:function(evt){this.sliderEvents.handleBrowserEvent(evt);},divClick:function(evt){if(!OpenLayers.Event.isLeftClick(evt)){return;}
59955 var y=evt.xy.y;var top=OpenLayers.Util.pagePosition(evt.object)[1];var levels=(y-top)/this.zoomStopHeight;if(this.forceFixedZoomLevel||!this.map.fractionalZoom){levels=Math.floor(levels);}
59956 var zoom=(this.map.getNumZoomLevels()-1)-levels;zoom=Math.min(Math.max(zoom,0),this.map.getNumZoomLevels()-1);this.map.zoomTo(zoom);OpenLayers.Event.stop(evt);},zoomBarDown:function(evt){if(!OpenLayers.Event.isLeftClick(evt)){return;}
59957 this.map.events.on({"mousemove":this.passEventToSlider,"mouseup":this.passEventToSlider,scope:this});this.mouseDragStart=evt.xy.clone();this.zoomStart=evt.xy.clone();this.div.style.cursor="move";this.zoombarDiv.offsets=null;OpenLayers.Event.stop(evt);},zoomBarDrag:function(evt){if(this.mouseDragStart!=null){var deltaY=this.mouseDragStart.y-evt.xy.y;var offsets=OpenLayers.Util.pagePosition(this.zoombarDiv);if((evt.clientY-offsets[1])>0&&(evt.clientY-offsets[1])<parseInt(this.zoombarDiv.style.height)-2){var newTop=parseInt(this.slider.style.top)-deltaY;this.slider.style.top=newTop+"px";this.mouseDragStart=evt.xy.clone();}
59958 OpenLayers.Event.stop(evt);}},zoomBarUp:function(evt){if(!OpenLayers.Event.isLeftClick(evt)){return;}
59959 if(this.mouseDragStart){this.div.style.cursor="";this.map.events.un({"mouseup":this.passEventToSlider,"mousemove":this.passEventToSlider,scope:this});var deltaY=this.zoomStart.y-evt.xy.y;var zoomLevel=this.map.zoom;if(!this.forceFixedZoomLevel&&this.map.fractionalZoom){zoomLevel+=deltaY/this.zoomStopHeight;zoomLevel=Math.min(Math.max(zoomLevel,0),this.map.getNumZoomLevels()-1);}else{zoomLevel+=Math.round(deltaY/this.zoomStopHeight);}
59960 this.map.zoomTo(zoomLevel);this.mouseDragStart=null;this.zoomStart=null;OpenLayers.Event.stop(evt);}},moveZoomBar:function(){var newTop=((this.map.getNumZoomLevels()-1)-this.map.getZoom())*this.zoomStopHeight+this.startTop+1;this.slider.style.top=newTop+"px";},CLASS_NAME:"OpenLayers.Control.PanZoomBar"});OpenLayers.Control.Permalink=OpenLayers.Class(OpenLayers.Control,{argParserClass:OpenLayers.Control.ArgParser,element:null,base:'',displayProjection:null,initialize:function(element,base,options){OpenLayers.Control.prototype.initialize.apply(this,[options]);this.element=OpenLayers.Util.getElement(element);this.base=base||document.location.href;},destroy:function(){if(this.element.parentNode==this.div){this.div.removeChild(this.element);}
59961 this.element=null;this.map.events.unregister('moveend',this,this.updateLink);OpenLayers.Control.prototype.destroy.apply(this,arguments);},setMap:function(map){OpenLayers.Control.prototype.setMap.apply(this,arguments);for(var i=0,len=this.map.controls.length;i<len;i++){var control=this.map.controls[i];if(control.CLASS_NAME==this.argParserClass.CLASS_NAME){if(control.displayProjection!=this.displayProjection){this.displayProjection=control.displayProjection;}
59962 break;}}
59963 if(i==this.map.controls.length){this.map.addControl(new this.argParserClass({'displayProjection':this.displayProjection}));}},draw:function(){OpenLayers.Control.prototype.draw.apply(this,arguments);if(!this.element){this.div.className=this.displayClass;this.element=document.createElement("a");this.element.innerHTML=OpenLayers.i18n("permalink");this.element.href="";this.div.appendChild(this.element);}
59964 this.map.events.on({'moveend':this.updateLink,'changelayer':this.updateLink,'changebaselayer':this.updateLink,scope:this});this.updateLink();return this.div;},updateLink:function(){var href=this.base;if(href.indexOf('?')!=-1){href=href.substring(0,href.indexOf('?'));}
59965 href+='?'+OpenLayers.Util.getParameterString(this.createParams());this.element.href=href;},createParams:function(center,zoom,layers){center=center||this.map.getCenter();var params=OpenLayers.Util.getParameters(this.base);if(center){params.zoom=zoom||this.map.getZoom();var lat=center.lat;var lon=center.lon;if(this.displayProjection){var mapPosition=OpenLayers.Projection.transform({x:lon,y:lat},this.map.getProjectionObject(),this.displayProjection);lon=mapPosition.x;lat=mapPosition.y;}
59966 params.lat=Math.round(lat*100000)/100000;params.lon=Math.round(lon*100000)/100000;layers=layers||this.map.layers;params.layers='';for(var i=0,len=layers.length;i<len;i++){var layer=layers[i];if(layer.isBaseLayer){params.layers+=(layer==this.map.baseLayer)?"B":"0";}else{params.layers+=(layer.getVisibility())?"T":"F";}}}
59967 return params;},CLASS_NAME:"OpenLayers.Control.Permalink"});OpenLayers.Control.ZoomPanel=OpenLayers.Class(OpenLayers.Control.Panel,{initialize:function(options){OpenLayers.Control.Panel.prototype.initialize.apply(this,[options]);this.addControls([new OpenLayers.Control.ZoomIn(),new OpenLayers.Control.ZoomToMaxExtent(),new OpenLayers.Control.ZoomOut()]);},CLASS_NAME:"OpenLayers.Control.ZoomPanel"});OpenLayers.Format.CSWGetDomain=function(options){options=OpenLayers.Util.applyDefaults(options,OpenLayers.Format.CSWGetDomain.DEFAULTS);var cls=OpenLayers.Format.CSWGetDomain["v"+options.version.replace(/\./g,"_")];if(!cls){throw"Unsupported CSWGetDomain version: "+options.version;}
59968 return new cls(options);};OpenLayers.Format.CSWGetDomain.DEFAULTS={"version":"2.0.2"};OpenLayers.Format.CSWGetRecords=function(options){options=OpenLayers.Util.applyDefaults(options,OpenLayers.Format.CSWGetRecords.DEFAULTS);var cls=OpenLayers.Format.CSWGetRecords["v"+options.version.replace(/\./g,"_")];if(!cls){throw"Unsupported CSWGetRecords version: "+options.version;}
59969 return new cls(options);};OpenLayers.Format.CSWGetRecords.DEFAULTS={"version":"2.0.2"};OpenLayers.Format.JSON=OpenLayers.Class(OpenLayers.Format,{indent:"    ",space:" ",newline:"\n",level:0,pretty:false,initialize:function(options){OpenLayers.Format.prototype.initialize.apply(this,[options]);},read:function(json,filter){try{if(/^[\],:{}\s]*$/.test(json.replace(/\\["\\\/bfnrtu]/g,'@').replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,']').replace(/(?:^|:|,)(?:\s*\[)+/g,''))){var object=eval('('+json+')');if(typeof filter==='function'){function walk(k,v){if(v&&typeof v==='object'){for(var i in v){if(v.hasOwnProperty(i)){v[i]=walk(i,v[i]);}}}
59970 return filter(k,v);}
59971 object=walk('',object);}
59972 if(this.keepData){this.data=object;}
59973 return object;}}catch(e){}
59974 return null;},write:function(value,pretty){this.pretty=!!pretty;var json=null;var type=typeof value;if(this.serialize[type]){try{json=this.serialize[type].apply(this,[value]);}catch(err){OpenLayers.Console.error("Trouble serializing: "+err);}}
59975 return json;},writeIndent:function(){var pieces=[];if(this.pretty){for(var i=0;i<this.level;++i){pieces.push(this.indent);}}
59976 return pieces.join('');},writeNewline:function(){return(this.pretty)?this.newline:'';},writeSpace:function(){return(this.pretty)?this.space:'';},serialize:{'object':function(object){if(object==null){return"null";}
59977 if(object.constructor==Date){return this.serialize.date.apply(this,[object]);}
59978 if(object.constructor==Array){return this.serialize.array.apply(this,[object]);}
59979 var pieces=['{'];this.level+=1;var key,keyJSON,valueJSON;var addComma=false;for(key in object){if(object.hasOwnProperty(key)){keyJSON=OpenLayers.Format.JSON.prototype.write.apply(this,[key,this.pretty]);valueJSON=OpenLayers.Format.JSON.prototype.write.apply(this,[object[key],this.pretty]);if(keyJSON!=null&&valueJSON!=null){if(addComma){pieces.push(',');}
59980 pieces.push(this.writeNewline(),this.writeIndent(),keyJSON,':',this.writeSpace(),valueJSON);addComma=true;}}}
59981 this.level-=1;pieces.push(this.writeNewline(),this.writeIndent(),'}');return pieces.join('');},'array':function(array){var json;var pieces=['['];this.level+=1;for(var i=0,len=array.length;i<len;++i){json=OpenLayers.Format.JSON.prototype.write.apply(this,[array[i],this.pretty]);if(json!=null){if(i>0){pieces.push(',');}
59982 pieces.push(this.writeNewline(),this.writeIndent(),json);}}
59983 this.level-=1;pieces.push(this.writeNewline(),this.writeIndent(),']');return pieces.join('');},'string':function(string){var m={'\b':'\\b','\t':'\\t','\n':'\\n','\f':'\\f','\r':'\\r','"':'\\"','\\':'\\\\'};if(/["\\\x00-\x1f]/.test(string)){return'"'+string.replace(/([\x00-\x1f\\"])/g,function(a,b){var c=m[b];if(c){return c;}
59984 c=b.charCodeAt();return'\\u00'+
59985 Math.floor(c/16).toString(16)+
59986 (c%16).toString(16);})+'"';}
59987 return'"'+string+'"';},'number':function(number){return isFinite(number)?String(number):"null";},'boolean':function(bool){return String(bool);},'date':function(date){function format(number){return(number<10)?'0'+number:number;}
59988 return'"'+date.getFullYear()+'-'+
59989 format(date.getMonth()+1)+'-'+
59990 format(date.getDate())+'T'+
59991 format(date.getHours())+':'+
59992 format(date.getMinutes())+':'+
59993 format(date.getSeconds())+'"';}},CLASS_NAME:"OpenLayers.Format.JSON"});OpenLayers.Format.WFST=function(options){options=OpenLayers.Util.applyDefaults(options,OpenLayers.Format.WFST.DEFAULTS);var cls=OpenLayers.Format.WFST["v"+options.version.replace(/\./g,"_")];if(!cls){throw"Unsupported WFST version: "+options.version;}
59994 return new cls(options);};OpenLayers.Format.WFST.DEFAULTS={"version":"1.0.0"};OpenLayers.Format.XML=OpenLayers.Class(OpenLayers.Format,{namespaces:null,namespaceAlias:null,defaultPrefix:null,readers:{},writers:{},xmldom:null,initialize:function(options){if(window.ActiveXObject){this.xmldom=new ActiveXObject("Microsoft.XMLDOM");}
59995 OpenLayers.Format.prototype.initialize.apply(this,[options]);this.namespaces=OpenLayers.Util.extend({},this.namespaces);this.namespaceAlias={};for(var alias in this.namespaces){this.namespaceAlias[this.namespaces[alias]]=alias;}},destroy:function(){this.xmldom=null;OpenLayers.Format.prototype.destroy.apply(this,arguments);},setNamespace:function(alias,uri){this.namespaces[alias]=uri;this.namespaceAlias[uri]=alias;},read:function(text){var index=text.indexOf('<');if(index>0){text=text.substring(index);}
59996 var node=OpenLayers.Util.Try(OpenLayers.Function.bind((function(){var xmldom;if(window.ActiveXObject&&!this.xmldom){xmldom=new ActiveXObject("Microsoft.XMLDOM");}else{xmldom=this.xmldom;}
59997 xmldom.loadXML(text);return xmldom;}),this),function(){return new DOMParser().parseFromString(text,'text/xml');},function(){var req=new XMLHttpRequest();req.open("GET","data:"+"text/xml"+";charset=utf-8,"+encodeURIComponent(text),false);if(req.overrideMimeType){req.overrideMimeType("text/xml");}
59998 req.send(null);return req.responseXML;});if(this.keepData){this.data=node;}
59999 return node;},write:function(node){var data;if(this.xmldom){data=node.xml;}else{var serializer=new XMLSerializer();if(node.nodeType==1){var doc=document.implementation.createDocument("","",null);if(doc.importNode){node=doc.importNode(node,true);}
60000 doc.appendChild(node);data=serializer.serializeToString(doc);}else{data=serializer.serializeToString(node);}}
60001 return data;},createElementNS:function(uri,name){var element;if(this.xmldom){if(typeof uri=="string"){element=this.xmldom.createNode(1,name,uri);}else{element=this.xmldom.createNode(1,name,"");}}else{element=document.createElementNS(uri,name);}
60002 return element;},createTextNode:function(text){var node;if(typeof text!=="string"){text=String(text);}
60003 if(this.xmldom){node=this.xmldom.createTextNode(text);}else{node=document.createTextNode(text);}
60004 return node;},getElementsByTagNameNS:function(node,uri,name){var elements=[];if(node.getElementsByTagNameNS){elements=node.getElementsByTagNameNS(uri,name);}else{var allNodes=node.getElementsByTagName("*");var potentialNode,fullName;for(var i=0,len=allNodes.length;i<len;++i){potentialNode=allNodes[i];fullName=(potentialNode.prefix)?(potentialNode.prefix+":"+name):name;if((name=="*")||(fullName==potentialNode.nodeName)){if((uri=="*")||(uri==potentialNode.namespaceURI)){elements.push(potentialNode);}}}}
60005 return elements;},getAttributeNodeNS:function(node,uri,name){var attributeNode=null;if(node.getAttributeNodeNS){attributeNode=node.getAttributeNodeNS(uri,name);}else{var attributes=node.attributes;var potentialNode,fullName;for(var i=0,len=attributes.length;i<len;++i){potentialNode=attributes[i];if(potentialNode.namespaceURI==uri){fullName=(potentialNode.prefix)?(potentialNode.prefix+":"+name):name;if(fullName==potentialNode.nodeName){attributeNode=potentialNode;break;}}}}
60006 return attributeNode;},getAttributeNS:function(node,uri,name){var attributeValue="";if(node.getAttributeNS){attributeValue=node.getAttributeNS(uri,name)||"";}else{var attributeNode=this.getAttributeNodeNS(node,uri,name);if(attributeNode){attributeValue=attributeNode.nodeValue;}}
60007 return attributeValue;},getChildValue:function(node,def){var value=def||"";if(node){for(var child=node.firstChild;child;child=child.nextSibling){switch(child.nodeType){case 3:case 4:value+=child.nodeValue;}}}
60008 return value;},concatChildValues:function(node,def){var value="";var child=node.firstChild;var childValue;while(child){childValue=child.nodeValue;if(childValue){value+=childValue;}
60009 child=child.nextSibling;}
60010 if(value==""&&def!=undefined){value=def;}
60011 return value;},isSimpleContent:function(node){var simple=true;for(var child=node.firstChild;child;child=child.nextSibling){if(child.nodeType===1){simple=false;break;}}
60012 return simple;},contentType:function(node){var simple=false,complex=false;var type=OpenLayers.Format.XML.CONTENT_TYPE.EMPTY;for(var child=node.firstChild;child;child=child.nextSibling){switch(child.nodeType){case 1:complex=true;break;case 8:break;default:simple=true;}
60013 if(complex&&simple){break;}}
60014 if(complex&&simple){type=OpenLayers.Format.XML.CONTENT_TYPE.MIXED;}else if(complex){return OpenLayers.Format.XML.CONTENT_TYPE.COMPLEX;}else if(simple){return OpenLayers.Format.XML.CONTENT_TYPE.SIMPLE;}
60015 return type;},hasAttributeNS:function(node,uri,name){var found=false;if(node.hasAttributeNS){found=node.hasAttributeNS(uri,name);}else{found=!!this.getAttributeNodeNS(node,uri,name);}
60016 return found;},setAttributeNS:function(node,uri,name,value){if(node.setAttributeNS){node.setAttributeNS(uri,name,value);}else{if(this.xmldom){if(uri){var attribute=node.ownerDocument.createNode(2,name,uri);attribute.nodeValue=value;node.setAttributeNode(attribute);}else{node.setAttribute(name,value);}}else{throw"setAttributeNS not implemented";}}},createElementNSPlus:function(name,options){options=options||{};var uri=options.uri||this.namespaces[options.prefix];if(!uri){var loc=name.indexOf(":");uri=this.namespaces[name.substring(0,loc)];}
60017 if(!uri){uri=this.namespaces[this.defaultPrefix];}
60018 var node=this.createElementNS(uri,name);if(options.attributes){this.setAttributes(node,options.attributes);}
60019 var value=options.value;if(value!=null){node.appendChild(this.createTextNode(value));}
60020 return node;},setAttributes:function(node,obj){var value,uri;for(var name in obj){if(obj[name]!=null&&obj[name].toString){value=obj[name].toString();uri=this.namespaces[name.substring(0,name.indexOf(":"))]||null;this.setAttributeNS(node,uri,name,value);}}},readNode:function(node,obj){if(!obj){obj={};}
60021 var group=this.readers[node.namespaceURI?this.namespaceAlias[node.namespaceURI]:this.defaultPrefix];if(group){var local=node.localName||node.nodeName.split(":").pop();var reader=group[local]||group["*"];if(reader){reader.apply(this,[node,obj]);}}
60022 return obj;},readChildNodes:function(node,obj){if(!obj){obj={};}
60023 var children=node.childNodes;var child;for(var i=0,len=children.length;i<len;++i){child=children[i];if(child.nodeType==1){this.readNode(child,obj);}}
60024 return obj;},writeNode:function(name,obj,parent){var prefix,local;var split=name.indexOf(":");if(split>0){prefix=name.substring(0,split);local=name.substring(split+1);}else{if(parent){prefix=this.namespaceAlias[parent.namespaceURI];}else{prefix=this.defaultPrefix;}
60025 local=name;}
60026 var child=this.writers[prefix][local].apply(this,[obj]);if(parent){parent.appendChild(child);}
60027 return child;},getChildEl:function(node,name,uri){return node&&this.getThisOrNextEl(node.firstChild,name,uri);},getNextEl:function(node,name,uri){return node&&this.getThisOrNextEl(node.nextSibling,name,uri);},getThisOrNextEl:function(node,name,uri){outer:for(var sibling=node;sibling;sibling=sibling.nextSibling){switch(sibling.nodeType){case 1:if((!name||name===(sibling.localName||sibling.nodeName.split(":").pop()))&&(!uri||uri===sibling.namespaceURI)){break outer;}
60028 sibling=null;break outer;case 3:if(/^\s*$/.test(sibling.nodeValue)){break;}
60029 case 4:case 6:case 12:case 10:case 11:sibling=null;break outer;}}
60030 return sibling||null;},lookupNamespaceURI:function(node,prefix){var uri=null;if(node){if(node.lookupNamespaceURI){uri=node.lookupNamespaceURI(prefix);}else{outer:switch(node.nodeType){case 1:if(node.namespaceURI!==null&&node.prefix===prefix){uri=node.namespaceURI;break outer;}
60031 var len=node.attributes.length;if(len){var attr;for(var i=0;i<len;++i){attr=node.attributes[i];if(attr.prefix==="xmlns"&&attr.name==="xmlns:"+prefix){uri=attr.value||null;break outer;}else if(attr.name==="xmlns"&&prefix===null){uri=attr.value||null;break outer;}}}
60032 uri=this.lookupNamespaceURI(node.parentNode,prefix);break outer;case 2:uri=this.lookupNamespaceURI(node.ownerElement,prefix);break outer;case 9:uri=this.lookupNamespaceURI(node.documentElement,prefix);break outer;case 6:case 12:case 10:case 11:break outer;default:uri=this.lookupNamespaceURI(node.parentNode,prefix);break outer;}}}
60033 return uri;},CLASS_NAME:"OpenLayers.Format.XML"});OpenLayers.Format.XML.CONTENT_TYPE={EMPTY:0,SIMPLE:1,COMPLEX:2,MIXED:3};OpenLayers.Format.XML.lookupNamespaceURI=OpenLayers.Function.bind(OpenLayers.Format.XML.prototype.lookupNamespaceURI,OpenLayers.Format.XML.prototype);OpenLayers.Handler=OpenLayers.Class({id:null,control:null,map:null,keyMask:null,active:false,evt:null,initialize:function(control,callbacks,options){OpenLayers.Util.extend(this,options);this.control=control;this.callbacks=callbacks;var map=this.map||control.map;if(map){this.setMap(map);}
60034 this.id=OpenLayers.Util.createUniqueID(this.CLASS_NAME+"_");},setMap:function(map){this.map=map;},checkModifiers:function(evt){if(this.keyMask==null){return true;}
60035 var keyModifiers=(evt.shiftKey?OpenLayers.Handler.MOD_SHIFT:0)|(evt.ctrlKey?OpenLayers.Handler.MOD_CTRL:0)|(evt.altKey?OpenLayers.Handler.MOD_ALT:0);return(keyModifiers==this.keyMask);},activate:function(){if(this.active){return false;}
60036 var events=OpenLayers.Events.prototype.BROWSER_EVENTS;for(var i=0,len=events.length;i<len;i++){if(this[events[i]]){this.register(events[i],this[events[i]]);}}
60037 this.active=true;return true;},deactivate:function(){if(!this.active){return false;}
60038 var events=OpenLayers.Events.prototype.BROWSER_EVENTS;for(var i=0,len=events.length;i<len;i++){if(this[events[i]]){this.unregister(events[i],this[events[i]]);}}
60039 this.active=false;return true;},callback:function(name,args){if(name&&this.callbacks[name]){this.callbacks[name].apply(this.control,args);}},register:function(name,method){this.map.events.registerPriority(name,this,method);this.map.events.registerPriority(name,this,this.setEvent);},unregister:function(name,method){this.map.events.unregister(name,this,method);this.map.events.unregister(name,this,this.setEvent);},setEvent:function(evt){this.evt=evt;return true;},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.Map=OpenLayers.Class({Z_INDEX_BASE:{BaseLayer:100,Overlay:325,Feature:725,Popup:750,Control:1000},EVENT_TYPES:["preaddlayer","addlayer","removelayer","changelayer","movestart","move","moveend","zoomend","popupopen","popupclose","addmarker","removemarker","clearmarkers","mouseover","mouseout","mousemove","dragstart","drag","dragend","changebaselayer"],id:null,fractionalZoom:false,events:null,allOverlays:false,div:null,dragging:false,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,viewRequestID:0,tileSize:null,projection:"EPSG:4326",units:'degrees',resolutions:null,maxResolution:1.40625,minResolution:null,maxScale:null,minScale:null,maxExtent:null,minExtent:null,restrictedExtent:null,numZoomLevels:16,theme:null,displayProjection:null,fallThrough:true,panTween:null,eventListeners:null,panMethod:OpenLayers.Easing.Expo.easeOut,panDuration:50,paddingForPopups:null,initialize:function(div,options){if(arguments.length===1&&typeof div==="object"){options=div;div=options&&options.div;}
60040 this.tileSize=new OpenLayers.Size(OpenLayers.Map.TILE_WIDTH,OpenLayers.Map.TILE_HEIGHT);this.maxExtent=new OpenLayers.Bounds(-180,-90,180,90);this.paddingForPopups=new OpenLayers.Bounds(15,15,15,15);this.theme=OpenLayers._getScriptLocation()?OpenLayers._getScriptLocation()+'theme/default/style.css':null;OpenLayers.Util.extend(this,options);this.layers=[];this.id=OpenLayers.Util.createUniqueID("OpenLayers.Map_");this.div=OpenLayers.Util.getElement(div);if(!this.div){this.div=document.createElement("div");this.div.style.height="1px";this.div.style.width="1px";}
60041 OpenLayers.Element.addClass(this.div,'olMap');var id=this.id+"_OpenLayers_ViewPort";this.viewPortDiv=OpenLayers.Util.createDiv(id,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);id=this.id+"_OpenLayers_Container";this.layerContainerDiv=OpenLayers.Util.createDiv(id);this.layerContainerDiv.style.zIndex=this.Z_INDEX_BASE['Popup']-1;this.viewPortDiv.appendChild(this.layerContainerDiv);this.events=new OpenLayers.Events(this,this.div,this.EVENT_TYPES,this.fallThrough,{includeXY:true});this.updateSize();if(this.eventListeners instanceof Object){this.events.on(this.eventListeners);}
60042 this.events.register("movestart",this,this.updateSize);if(OpenLayers.String.contains(navigator.appName,"Microsoft")){this.events.register("resize",this,this.updateSize);}else{this.updateSizeDestroy=OpenLayers.Function.bind(this.updateSize,this);OpenLayers.Event.observe(window,'resize',this.updateSizeDestroy);}
60043 if(this.theme){var addNode=true;var nodes=document.getElementsByTagName('link');for(var i=0,len=nodes.length;i<len;++i){if(OpenLayers.Util.isEquivalentUrl(nodes.item(i).href,this.theme)){addNode=false;break;}}
60044 if(addNode){var cssNode=document.createElement('link');cssNode.setAttribute('rel','stylesheet');cssNode.setAttribute('type','text/css');cssNode.setAttribute('href',this.theme);document.getElementsByTagName('head')[0].appendChild(cssNode);}}
60045 if(this.controls==null){if(OpenLayers.Control!=null){this.controls=[new OpenLayers.Control.Navigation(),new OpenLayers.Control.PanZoom(),new OpenLayers.Control.ArgParser(),new OpenLayers.Control.Attribution()];}else{this.controls=[];}}
60046 for(var i=0,len=this.controls.length;i<len;i++){this.addControlToMap(this.controls[i]);}
60047 this.popups=[];this.unloadDestroy=OpenLayers.Function.bind(this.destroy,this);OpenLayers.Event.observe(window,'unload',this.unloadDestroy);if(options&&options.layers){this.addLayers(options.layers);if(options.center){this.setCenter(options.center,options.zoom);}}},render:function(div){this.div=OpenLayers.Util.getElement(div);OpenLayers.Element.addClass(this.div,'olMap');this.events.attachToElement(this.div);this.viewPortDiv.parentNode.removeChild(this.viewPortDiv);this.div.appendChild(this.viewPortDiv);this.updateSize();},unloadDestroy:null,updateSizeDestroy:null,destroy:function(){if(!this.unloadDestroy){return false;}
60048 if(this.panTween){this.panTween.stop();this.panTween=null;}
60049 OpenLayers.Event.stopObserving(window,'unload',this.unloadDestroy);this.unloadDestroy=null;if(this.updateSizeDestroy){OpenLayers.Event.stopObserving(window,'resize',this.updateSizeDestroy);}else{this.events.unregister("resize",this,this.updateSize);}
60050 this.paddingForPopups=null;if(this.controls!=null){for(var i=this.controls.length-1;i>=0;--i){this.controls[i].destroy();}
60051 this.controls=null;}
60052 if(this.layers!=null){for(var i=this.layers.length-1;i>=0;--i){this.layers[i].destroy(false);}
60053 this.layers=null;}
60054 if(this.viewPortDiv){this.div.removeChild(this.viewPortDiv);}
60055 this.viewPortDiv=null;if(this.eventListeners){this.events.un(this.eventListeners);this.eventListeners=null;}
60056 this.events.destroy();this.events=null;},setOptions:function(options){OpenLayers.Util.extend(this,options);},getTileSize:function(){return this.tileSize;},getBy:function(array,property,match){var test=(typeof match.test=="function");var found=OpenLayers.Array.filter(this[array],function(item){return item[property]==match||(test&&match.test(item[property]));});return found;},getLayersBy:function(property,match){return this.getBy("layers",property,match);},getLayersByName:function(match){return this.getLayersBy("name",match);},getLayersByClass:function(match){return this.getLayersBy("CLASS_NAME",match);},getControlsBy:function(property,match){return this.getBy("controls",property,match);},getControlsByClass:function(match){return this.getControlsBy("CLASS_NAME",match);},getLayer:function(id){var foundLayer=null;for(var i=0,len=this.layers.length;i<len;i++){var layer=this.layers[i];if(layer.id==id){foundLayer=layer;break;}}
60057 return foundLayer;},setLayerZIndex:function(layer,zIdx){layer.setZIndex(this.Z_INDEX_BASE[layer.isBaseLayer?'BaseLayer':'Overlay']
60058 +zIdx*5);},resetLayersZIndex:function(){for(var i=0,len=this.layers.length;i<len;i++){var layer=this.layers[i];this.setLayerZIndex(layer,i);}},addLayer:function(layer){for(var i=0,len=this.layers.length;i<len;i++){if(this.layers[i]==layer){var msg=OpenLayers.i18n('layerAlreadyAdded',{'layerName':layer.name});OpenLayers.Console.warn(msg);return false;}}
60059 if(this.allOverlays){layer.isBaseLayer=false;}
60060 if(this.events.triggerEvent("preaddlayer",{layer:layer})===false){return;}
60061 layer.div.className="olLayerDiv";layer.div.style.overflow="";this.setLayerZIndex(layer,this.layers.length);if(layer.isFixed){this.viewPortDiv.appendChild(layer.div);}else{this.layerContainerDiv.appendChild(layer.div);}
60062 this.layers.push(layer);layer.setMap(this);if(layer.isBaseLayer||(this.allOverlays&&!this.baseLayer)){if(this.baseLayer==null){this.setBaseLayer(layer);}else{layer.setVisibility(false);}}else{layer.redraw();}
60063 this.events.triggerEvent("addlayer",{layer:layer});layer.afterAdd();},addLayers:function(layers){for(var i=0,len=layers.length;i<len;i++){this.addLayer(layers[i]);}},removeLayer:function(layer,setNewBaseLayer){if(setNewBaseLayer==null){setNewBaseLayer=true;}
60064 if(layer.isFixed){this.viewPortDiv.removeChild(layer.div);}else{this.layerContainerDiv.removeChild(layer.div);}
60065 OpenLayers.Util.removeItem(this.layers,layer);layer.removeMap(this);layer.map=null;if(this.baseLayer==layer){this.baseLayer=null;if(setNewBaseLayer){for(var i=0,len=this.layers.length;i<len;i++){var iLayer=this.layers[i];if(iLayer.isBaseLayer||this.allOverlays){this.setBaseLayer(iLayer);break;}}}}
60066 this.resetLayersZIndex();this.events.triggerEvent("removelayer",{layer:layer});},getNumLayers:function(){return this.layers.length;},getLayerIndex:function(layer){return OpenLayers.Util.indexOf(this.layers,layer);},setLayerIndex:function(layer,idx){var base=this.getLayerIndex(layer);if(idx<0){idx=0;}else if(idx>this.layers.length){idx=this.layers.length;}
60067 if(base!=idx){this.layers.splice(base,1);this.layers.splice(idx,0,layer);for(var i=0,len=this.layers.length;i<len;i++){this.setLayerZIndex(this.layers[i],i);}
60068 this.events.triggerEvent("changelayer",{layer:layer,property:"order"});if(this.allOverlays){if(idx===0){this.setBaseLayer(layer);}else if(this.baseLayer!==this.layers[0]){this.setBaseLayer(this.layers[0]);}}}},raiseLayer:function(layer,delta){var idx=this.getLayerIndex(layer)+delta;this.setLayerIndex(layer,idx);},setBaseLayer:function(newBaseLayer){if(newBaseLayer!=this.baseLayer){if(OpenLayers.Util.indexOf(this.layers,newBaseLayer)!=-1){var center=this.getCenter();var newResolution=OpenLayers.Util.getResolutionFromScale(this.getScale(),newBaseLayer.units);if(this.baseLayer!=null&&!this.allOverlays){this.baseLayer.setVisibility(false);}
60069 this.baseLayer=newBaseLayer;this.viewRequestID++;if(!this.allOverlays||this.baseLayer.visibility){this.baseLayer.setVisibility(true);}
60070 if(center!=null){var newZoom=this.getZoomForResolution(newResolution||this.resolution,true);this.setCenter(center,newZoom,false,true);}
60071 this.events.triggerEvent("changebaselayer",{layer:this.baseLayer});}}},addControl:function(control,px){this.controls.push(control);this.addControlToMap(control,px);},addControls:function(controls,pixels){var pxs=(arguments.length===1)?[]:pixels;for(var i=0,len=controls.length;i<len;i++){var ctrl=controls[i];var px=(pxs[i])?pxs[i]:null;this.addControl(ctrl,px);}},addControlToMap:function(control,px){control.outsideViewport=(control.div!=null);if(this.displayProjection&&!control.displayProjection){control.displayProjection=this.displayProjection;}
60072 control.setMap(this);var div=control.draw(px);if(div){if(!control.outsideViewport){div.style.zIndex=this.Z_INDEX_BASE['Control']+
60073 this.controls.length;this.viewPortDiv.appendChild(div);}}
60074 if(control.autoActivate){control.activate();}},getControl:function(id){var returnControl=null;for(var i=0,len=this.controls.length;i<len;i++){var control=this.controls[i];if(control.id==id){returnControl=control;break;}}
60075 return returnControl;},removeControl:function(control){if((control)&&(control==this.getControl(control.id))){if(control.div&&(control.div.parentNode==this.viewPortDiv)){this.viewPortDiv.removeChild(control.div);}
60076 OpenLayers.Util.removeItem(this.controls,control);}},addPopup:function(popup,exclusive){if(exclusive){for(var i=this.popups.length-1;i>=0;--i){this.removePopup(this.popups[i]);}}
60077 popup.map=this;this.popups.push(popup);var popupDiv=popup.draw();if(popupDiv){popupDiv.style.zIndex=this.Z_INDEX_BASE['Popup']+
60078 this.popups.length;this.layerContainerDiv.appendChild(popupDiv);}},removePopup:function(popup){OpenLayers.Util.removeItem(this.popups,popup);if(popup.div){try{this.layerContainerDiv.removeChild(popup.div);}
60079 catch(e){}}
60080 popup.map=null;},getSize:function(){var size=null;if(this.size!=null){size=this.size.clone();}
60081 return size;},updateSize:function(){var newSize=this.getCurrentSize();if(newSize&&!isNaN(newSize.h)&&!isNaN(newSize.w)){this.events.clearMouseCache();var oldSize=this.getSize();if(oldSize==null){this.size=oldSize=newSize;}
60082 if(!newSize.equals(oldSize)){this.size=newSize;for(var i=0,len=this.layers.length;i<len;i++){this.layers[i].onMapResize();}
60083 var center=this.getCenter();if(this.baseLayer!=null&&center!=null){var zoom=this.getZoom();this.zoom=null;this.setCenter(center,zoom);}}}},getCurrentSize:function(){var size=new OpenLayers.Size(this.div.clientWidth,this.div.clientHeight);if(size.w==0&&size.h==0||isNaN(size.w)&&isNaN(size.h)){size.w=this.div.offsetWidth;size.h=this.div.offsetHeight;}
60084 if(size.w==0&&size.h==0||isNaN(size.w)&&isNaN(size.h)){size.w=parseInt(this.div.style.width);size.h=parseInt(this.div.style.height);}
60085 return size;},calculateBounds:function(center,resolution){var extent=null;if(center==null){center=this.getCenter();}
60086 if(resolution==null){resolution=this.getResolution();}
60087 if((center!=null)&&(resolution!=null)){var size=this.getSize();var w_deg=size.w*resolution;var h_deg=size.h*resolution;extent=new OpenLayers.Bounds(center.lon-w_deg/2,center.lat-h_deg/2,center.lon+w_deg/2,center.lat+h_deg/2);}
60088 return extent;},getCenter:function(){var center=null;if(this.center){center=this.center.clone();}
60089 return center;},getZoom:function(){return this.zoom;},pan:function(dx,dy,options){options=OpenLayers.Util.applyDefaults(options,{animate:true,dragging:false});var centerPx=this.getViewPortPxFromLonLat(this.getCenter());var newCenterPx=centerPx.add(dx,dy);if(!options.dragging||!newCenterPx.equals(centerPx)){var newCenterLonLat=this.getLonLatFromViewPortPx(newCenterPx);if(options.animate){this.panTo(newCenterLonLat);}else{this.setCenter(newCenterLonLat,null,options.dragging);}}},panTo:function(lonlat){if(this.panMethod&&this.getExtent().scale(this.panRatio).containsLonLat(lonlat)){if(!this.panTween){this.panTween=new OpenLayers.Tween(this.panMethod);}
60090 var center=this.getCenter();if(lonlat.lon==center.lon&&lonlat.lat==center.lat){return;}
60091 var from={lon:center.lon,lat:center.lat};var to={lon:lonlat.lon,lat:lonlat.lat};this.panTween.start(from,to,this.panDuration,{callbacks:{start:OpenLayers.Function.bind(function(lonlat){this.events.triggerEvent("movestart");},this),eachStep:OpenLayers.Function.bind(function(lonlat){lonlat=new OpenLayers.LonLat(lonlat.lon,lonlat.lat);this.moveTo(lonlat,this.zoom,{'dragging':true,'noEvent':true});},this),done:OpenLayers.Function.bind(function(lonlat){lonlat=new OpenLayers.LonLat(lonlat.lon,lonlat.lat);this.moveTo(lonlat,this.zoom,{'noEvent':true});this.events.triggerEvent("moveend");},this)}});}else{this.setCenter(lonlat);}},setCenter:function(lonlat,zoom,dragging,forceZoomChange){this.moveTo(lonlat,zoom,{'dragging':dragging,'forceZoomChange':forceZoomChange,'caller':'setCenter'});},moveTo:function(lonlat,zoom,options){if(!options){options={};}
60092 if(zoom!=null){zoom=parseFloat(zoom);if(!this.fractionalZoom){zoom=Math.round(zoom);}}
60093 var dragging=options.dragging;var forceZoomChange=options.forceZoomChange;var noEvent=options.noEvent;if(this.panTween&&options.caller=="setCenter"){this.panTween.stop();}
60094 if(!this.center&&!this.isValidLonLat(lonlat)){lonlat=this.maxExtent.getCenterLonLat();}
60095 if(this.restrictedExtent!=null){if(lonlat==null){lonlat=this.getCenter();}
60096 if(zoom==null){zoom=this.getZoom();}
60097 var resolution=this.getResolutionForZoom(zoom);var extent=this.calculateBounds(lonlat,resolution);if(!this.restrictedExtent.containsBounds(extent)){var maxCenter=this.restrictedExtent.getCenterLonLat();if(extent.getWidth()>this.restrictedExtent.getWidth()){lonlat=new OpenLayers.LonLat(maxCenter.lon,lonlat.lat);}else if(extent.left<this.restrictedExtent.left){lonlat=lonlat.add(this.restrictedExtent.left-
60098 extent.left,0);}else if(extent.right>this.restrictedExtent.right){lonlat=lonlat.add(this.restrictedExtent.right-
60099 extent.right,0);}
60100 if(extent.getHeight()>this.restrictedExtent.getHeight()){lonlat=new OpenLayers.LonLat(lonlat.lon,maxCenter.lat);}else if(extent.bottom<this.restrictedExtent.bottom){lonlat=lonlat.add(0,this.restrictedExtent.bottom-
60101 extent.bottom);}
60102 else if(extent.top>this.restrictedExtent.top){lonlat=lonlat.add(0,this.restrictedExtent.top-
60103 extent.top);}}}
60104 var zoomChanged=forceZoomChange||((this.isValidZoomLevel(zoom))&&(zoom!=this.getZoom()));var centerChanged=(this.isValidLonLat(lonlat))&&(!lonlat.equals(this.center));if(zoomChanged||centerChanged||!dragging){if(!this.dragging&&!noEvent){this.events.triggerEvent("movestart");}
60105 if(centerChanged){if((!zoomChanged)&&(this.center)){this.centerLayerContainer(lonlat);}
60106 this.center=lonlat.clone();}
60107 if((zoomChanged)||(this.layerContainerOrigin==null)){this.layerContainerOrigin=this.center.clone();this.layerContainerDiv.style.left="0px";this.layerContainerDiv.style.top="0px";}
60108 if(zoomChanged){this.zoom=zoom;this.resolution=this.getResolutionForZoom(zoom);this.viewRequestID++;}
60109 var bounds=this.getExtent();if(this.baseLayer.visibility){this.baseLayer.moveTo(bounds,zoomChanged,dragging);if(dragging){this.baseLayer.events.triggerEvent("move");}else{this.baseLayer.events.triggerEvent("moveend",{"zoomChanged":zoomChanged});}}
60110 bounds=this.baseLayer.getExtent();for(var i=0,len=this.layers.length;i<len;i++){var layer=this.layers[i];if(layer!==this.baseLayer&&!layer.isBaseLayer){var inRange=layer.calculateInRange();if(layer.inRange!=inRange){layer.inRange=inRange;if(!inRange){layer.display(false);}
60111 this.events.triggerEvent("changelayer",{layer:layer,property:"visibility"});}
60112 if(inRange&&layer.visibility){layer.moveTo(bounds,zoomChanged,dragging);if(dragging){layer.events.triggerEvent("move");}else{layer.events.triggerEvent("moveend",{"zoomChanged":zoomChanged});}}}}
60113 if(zoomChanged){for(var i=0,len=this.popups.length;i<len;i++){this.popups[i].updatePosition();}}
60114 this.events.triggerEvent("move");if(zoomChanged){this.events.triggerEvent("zoomend");}}
60115 if(!dragging&&!noEvent){this.events.triggerEvent("moveend");}
60116 this.dragging=!!dragging;},centerLayerContainer:function(lonlat){var originPx=this.getViewPortPxFromLonLat(this.layerContainerOrigin);var newPx=this.getViewPortPxFromLonLat(lonlat);if((originPx!=null)&&(newPx!=null)){this.layerContainerDiv.style.left=Math.round(originPx.x-newPx.x)+"px";this.layerContainerDiv.style.top=Math.round(originPx.y-newPx.y)+"px";}},isValidZoomLevel:function(zoomLevel){return((zoomLevel!=null)&&(zoomLevel>=0)&&(zoomLevel<this.getNumZoomLevels()));},isValidLonLat:function(lonlat){var valid=false;if(lonlat!=null){var maxExtent=this.getMaxExtent();valid=maxExtent.containsLonLat(lonlat);}
60117 return valid;},getProjection:function(){var projection=this.getProjectionObject();return projection?projection.getCode():null;},getProjectionObject:function(){var projection=null;if(this.baseLayer!=null){projection=this.baseLayer.projection;}
60118 return projection;},getMaxResolution:function(){var maxResolution=null;if(this.baseLayer!=null){maxResolution=this.baseLayer.maxResolution;}
60119 return maxResolution;},getMaxExtent:function(options){var maxExtent=null;if(options&&options.restricted&&this.restrictedExtent){maxExtent=this.restrictedExtent;}else if(this.baseLayer!=null){maxExtent=this.baseLayer.maxExtent;}
60120 return maxExtent;},getNumZoomLevels:function(){var numZoomLevels=null;if(this.baseLayer!=null){numZoomLevels=this.baseLayer.numZoomLevels;}
60121 return numZoomLevels;},getExtent:function(){var extent=null;if(this.baseLayer!=null){extent=this.baseLayer.getExtent();}
60122 return extent;},getResolution:function(){var resolution=null;if(this.baseLayer!=null){resolution=this.baseLayer.getResolution();}else if(this.allOverlays===true&&this.layers.length>0){resolution=this.layers[0].getResolution();}
60123 return resolution;},getUnits:function(){var units=null;if(this.baseLayer!=null){units=this.baseLayer.units;}
60124 return units;},getScale:function(){var scale=null;if(this.baseLayer!=null){var res=this.getResolution();var units=this.baseLayer.units;scale=OpenLayers.Util.getScaleFromResolution(res,units);}
60125 return scale;},getZoomForExtent:function(bounds,closest){var zoom=null;if(this.baseLayer!=null){zoom=this.baseLayer.getZoomForExtent(bounds,closest);}
60126 return zoom;},getResolutionForZoom:function(zoom){var resolution=null;if(this.baseLayer){resolution=this.baseLayer.getResolutionForZoom(zoom);}
60127 return resolution;},getZoomForResolution:function(resolution,closest){var zoom=null;if(this.baseLayer!=null){zoom=this.baseLayer.getZoomForResolution(resolution,closest);}
60128 return zoom;},zoomTo:function(zoom){if(this.isValidZoomLevel(zoom)){this.setCenter(null,zoom);}},zoomIn:function(){this.zoomTo(this.getZoom()+1);},zoomOut:function(){this.zoomTo(this.getZoom()-1);},zoomToExtent:function(bounds,closest){var center=bounds.getCenterLonLat();if(this.baseLayer.wrapDateLine){var maxExtent=this.getMaxExtent();bounds=bounds.clone();while(bounds.right<bounds.left){bounds.right+=maxExtent.getWidth();}
60129 center=bounds.getCenterLonLat().wrapDateLine(maxExtent);}
60130 this.setCenter(center,this.getZoomForExtent(bounds,closest));},zoomToMaxExtent:function(options){var restricted=(options)?options.restricted:true;var maxExtent=this.getMaxExtent({'restricted':restricted});this.zoomToExtent(maxExtent);},zoomToScale:function(scale,closest){var res=OpenLayers.Util.getResolutionFromScale(scale,this.baseLayer.units);var size=this.getSize();var w_deg=size.w*res;var h_deg=size.h*res;var center=this.getCenter();var extent=new OpenLayers.Bounds(center.lon-w_deg/2,center.lat-h_deg/2,center.lon+w_deg/2,center.lat+h_deg/2);this.zoomToExtent(extent,closest);},getLonLatFromViewPortPx:function(viewPortPx){var lonlat=null;if(this.baseLayer!=null){lonlat=this.baseLayer.getLonLatFromViewPortPx(viewPortPx);}
60131 return lonlat;},getViewPortPxFromLonLat:function(lonlat){var px=null;if(this.baseLayer!=null){px=this.baseLayer.getViewPortPxFromLonLat(lonlat);}
60132 return px;},getLonLatFromPixel:function(px){return this.getLonLatFromViewPortPx(px);},getPixelFromLonLat:function(lonlat){var px=this.getViewPortPxFromLonLat(lonlat);px.x=Math.round(px.x);px.y=Math.round(px.y);return px;},getGeodesicPixelSize:function(px){var lonlat=px?this.getLonLatFromPixel(px):(this.getCenter()||new OpenLayers.LonLat(0,0));var res=this.getResolution();var left=lonlat.add(-res/2,0);var right=lonlat.add(res/2,0);var bottom=lonlat.add(0,-res/2);var top=lonlat.add(0,res/2);var dest=new OpenLayers.Projection("EPSG:4326");var source=this.getProjectionObject()||dest;if(!source.equals(dest)){left.transform(source,dest);right.transform(source,dest);bottom.transform(source,dest);top.transform(source,dest);}
60133 return new OpenLayers.Size(OpenLayers.Util.distVincenty(left,right),OpenLayers.Util.distVincenty(bottom,top));},getViewPortPxFromLayerPx:function(layerPx){var viewPortPx=null;if(layerPx!=null){var dX=parseInt(this.layerContainerDiv.style.left);var dY=parseInt(this.layerContainerDiv.style.top);viewPortPx=layerPx.add(dX,dY);}
60134 return viewPortPx;},getLayerPxFromViewPortPx:function(viewPortPx){var layerPx=null;if(viewPortPx!=null){var dX=-parseInt(this.layerContainerDiv.style.left);var dY=-parseInt(this.layerContainerDiv.style.top);layerPx=viewPortPx.add(dX,dY);if(isNaN(layerPx.x)||isNaN(layerPx.y)){layerPx=null;}}
60135 return layerPx;},getLonLatFromLayerPx:function(px){px=this.getViewPortPxFromLayerPx(px);return this.getLonLatFromViewPortPx(px);},getLayerPxFromLonLat:function(lonlat){var px=this.getPixelFromLonLat(lonlat);return this.getLayerPxFromViewPortPx(px);},CLASS_NAME:"OpenLayers.Map"});OpenLayers.Map.TILE_WIDTH=256;OpenLayers.Map.TILE_HEIGHT=256;OpenLayers.Marker=OpenLayers.Class({icon:null,lonlat:null,events:null,map:null,initialize:function(lonlat,icon){this.lonlat=lonlat;var newIcon=(icon)?icon:OpenLayers.Marker.defaultIcon();if(this.icon==null){this.icon=newIcon;}else{this.icon.url=newIcon.url;this.icon.size=newIcon.size;this.icon.offset=newIcon.offset;this.icon.calculateOffset=newIcon.calculateOffset;}
60136 this.events=new OpenLayers.Events(this,this.icon.imageDiv,null);},destroy:function(){this.erase();this.map=null;this.events.destroy();this.events=null;if(this.icon!=null){this.icon.destroy();this.icon=null;}},draw:function(px){return this.icon.draw(px);},erase:function(){if(this.icon!=null){this.icon.erase();}},moveTo:function(px){if((px!=null)&&(this.icon!=null)){this.icon.moveTo(px);}
60137 this.lonlat=this.map.getLonLatFromLayerPx(px);},isDrawn:function(){var isDrawn=(this.icon&&this.icon.isDrawn());return isDrawn;},onScreen:function(){var onScreen=false;if(this.map){var screenBounds=this.map.getExtent();onScreen=screenBounds.containsLonLat(this.lonlat);}
60138 return onScreen;},inflate:function(inflate){if(this.icon){var newSize=new OpenLayers.Size(this.icon.size.w*inflate,this.icon.size.h*inflate);this.icon.setSize(newSize);}},setOpacity:function(opacity){this.icon.setOpacity(opacity);},setUrl:function(url){this.icon.setUrl(url);},display:function(display){this.icon.display(display);},CLASS_NAME:"OpenLayers.Marker"});OpenLayers.Marker.defaultIcon=function(){var url=OpenLayers.Util.getImagesLocation()+"marker.png";var size=new OpenLayers.Size(21,25);var calculateOffset=function(size){return new OpenLayers.Pixel(-(size.w/2),-size.h);};return new OpenLayers.Icon(url,size,null,calculateOffset);};OpenLayers.Popup.FramedCloud=OpenLayers.Class(OpenLayers.Popup.Framed,{contentDisplayClass:"olFramedCloudPopupContent",autoSize:true,panMapIfOutOfView:true,imageSize:new OpenLayers.Size(1276,736),isAlphaImage:false,fixedRelativePosition:false,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,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','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,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,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,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(id,lonlat,contentSize,contentHTML,anchor,closeBox,closeBoxCallback){this.imageSrc=OpenLayers.Util.getImagesLocation()+'cloud-popup-relative.png';OpenLayers.Popup.Framed.prototype.initialize.apply(this,arguments);this.contentDiv.className=this.contentDisplayClass;},destroy:function(){OpenLayers.Popup.Framed.prototype.destroy.apply(this,arguments);},CLASS_NAME:"OpenLayers.Popup.FramedCloud"});OpenLayers.Request={DEFAULT_CONFIG:{method:"GET",url:window.location.href,async:true,user:undefined,password:undefined,params:null,proxy:OpenLayers.ProxyHost,headers:{},data:null,callback:function(){},success:null,failure:null,scope:null},events:new OpenLayers.Events(this,null,["complete","success","failure"]),issue:function(config){var defaultConfig=OpenLayers.Util.extend(this.DEFAULT_CONFIG,{proxy:OpenLayers.ProxyHost});config=OpenLayers.Util.applyDefaults(config,defaultConfig);var request=new OpenLayers.Request.XMLHttpRequest();var url=config.url;if(config.params){var paramString=OpenLayers.Util.getParameterString(config.params);if(paramString.length>0){var separator=(url.indexOf('?')>-1)?'&':'?';url+=separator+paramString;}}
60139 if(config.proxy&&(url.indexOf("http")==0)){if(typeof config.proxy=="function"){url=config.proxy(url);}else{url=config.proxy+encodeURIComponent(url);}}
60140 request.open(config.method,url,config.async,config.user,config.password);for(var header in config.headers){request.setRequestHeader(header,config.headers[header]);}
60141 var events=this.events;var self=this;request.onreadystatechange=function(){if(request.readyState==OpenLayers.Request.XMLHttpRequest.DONE){var proceed=events.triggerEvent("complete",{request:request,config:config,requestUrl:url});if(proceed!==false){self.runCallbacks({request:request,config:config,requestUrl:url});}}};if(config.async===false){request.send(config.data);}else{window.setTimeout(function(){if(request._aborted!==true){request.send(config.data);}},0);}
60142 return request;},runCallbacks:function(options){var request=options.request;var config=options.config;var complete=(config.scope)?OpenLayers.Function.bind(config.callback,config.scope):config.callback;var success;if(config.success){success=(config.scope)?OpenLayers.Function.bind(config.success,config.scope):config.success;}
60143 var failure;if(config.failure){failure=(config.scope)?OpenLayers.Function.bind(config.failure,config.scope):config.failure;}
60144 complete(request);if(!request.status||(request.status>=200&&request.status<300)){this.events.triggerEvent("success",options);if(success){success(request);}}
60145 if(request.status&&(request.status<200||request.status>=300)){this.events.triggerEvent("failure",options);if(failure){failure(request);}}},GET:function(config){config=OpenLayers.Util.extend(config,{method:"GET"});return OpenLayers.Request.issue(config);},POST:function(config){config=OpenLayers.Util.extend(config,{method:"POST"});config.headers=config.headers?config.headers:{};if(!("CONTENT-TYPE"in OpenLayers.Util.upperCaseObject(config.headers))){config.headers["Content-Type"]="application/xml";}
60146 return OpenLayers.Request.issue(config);},PUT:function(config){config=OpenLayers.Util.extend(config,{method:"PUT"});config.headers=config.headers?config.headers:{};if(!("CONTENT-TYPE"in OpenLayers.Util.upperCaseObject(config.headers))){config.headers["Content-Type"]="application/xml";}
60147 return OpenLayers.Request.issue(config);},DELETE:function(config){config=OpenLayers.Util.extend(config,{method:"DELETE"});return OpenLayers.Request.issue(config);},HEAD:function(config){config=OpenLayers.Util.extend(config,{method:"HEAD"});return OpenLayers.Request.issue(config);},OPTIONS:function(config){config=OpenLayers.Util.extend(config,{method:"OPTIONS"});return OpenLayers.Request.issue(config);}};OpenLayers.Tile.Image=OpenLayers.Class(OpenLayers.Tile,{url:null,imgDiv:null,frame:null,layerAlphaHack:null,isBackBuffer:false,lastRatio:1,isFirstDraw:true,backBufferTile:null,initialize:function(layer,position,bounds,url,size){OpenLayers.Tile.prototype.initialize.apply(this,arguments);this.url=url;this.frame=document.createElement('div');this.frame.style.overflow='hidden';this.frame.style.position='absolute';this.layerAlphaHack=this.layer.alpha&&OpenLayers.Util.alphaHack();},destroy:function(){if(this.imgDiv!=null){if(this.layerAlphaHack){OpenLayers.Event.stopObservingElement(this.imgDiv.childNodes[0]);}
60148 OpenLayers.Event.stopObservingElement(this.imgDiv);if(this.imgDiv.parentNode==this.frame){this.frame.removeChild(this.imgDiv);this.imgDiv.map=null;}
60149 this.imgDiv.urls=null;this.imgDiv.src=OpenLayers.Util.getImagesLocation()+"blank.gif";}
60150 this.imgDiv=null;if((this.frame!=null)&&(this.frame.parentNode==this.layer.div)){this.layer.div.removeChild(this.frame);}
60151 this.frame=null;if(this.backBufferTile){this.backBufferTile.destroy();this.backBufferTile=null;}
60152 this.layer.events.unregister("loadend",this,this.resetBackBuffer);OpenLayers.Tile.prototype.destroy.apply(this,arguments);},clone:function(obj){if(obj==null){obj=new OpenLayers.Tile.Image(this.layer,this.position,this.bounds,this.url,this.size);}
60153 obj=OpenLayers.Tile.prototype.clone.apply(this,[obj]);obj.imgDiv=null;return obj;},draw:function(){if(this.layer!=this.layer.map.baseLayer&&this.layer.reproject){this.bounds=this.getBoundsFromBaseLayer(this.position);}
60154 var drawTile=OpenLayers.Tile.prototype.draw.apply(this,arguments);if((OpenLayers.Util.indexOf(this.layer.SUPPORTED_TRANSITIONS,this.layer.transitionEffect)!=-1)||this.layer.singleTile){if(drawTile){if(!this.backBufferTile){this.backBufferTile=this.clone();this.backBufferTile.hide();this.backBufferTile.isBackBuffer=true;this.events.register('loadend',this,this.resetBackBuffer);this.layer.events.register("loadend",this,this.resetBackBuffer);}
60155 this.startTransition();}else{if(this.backBufferTile){this.backBufferTile.clear();}}}else{if(drawTile&&this.isFirstDraw){this.events.register('loadend',this,this.showTile);this.isFirstDraw=false;}}
60156 if(!drawTile){return false;}
60157 if(this.isLoading){this.events.triggerEvent("reload");}else{this.isLoading=true;this.events.triggerEvent("loadstart");}
60158 return this.renderTile();},resetBackBuffer:function(){this.showTile();if(this.backBufferTile&&(this.isFirstDraw||!this.layer.numLoadingTiles)){this.isFirstDraw=false;var maxExtent=this.layer.maxExtent;var withinMaxExtent=(maxExtent&&this.bounds.intersectsBounds(maxExtent,false));if(withinMaxExtent){this.backBufferTile.position=this.position;this.backBufferTile.bounds=this.bounds;this.backBufferTile.size=this.size;this.backBufferTile.imageSize=this.layer.getImageSize(this.bounds)||this.size;this.backBufferTile.imageOffset=this.layer.imageOffset;this.backBufferTile.resolution=this.layer.getResolution();this.backBufferTile.renderTile();}
60159 this.backBufferTile.hide();}},renderTile:function(){if(this.imgDiv==null){this.initImgDiv();}
60160 this.imgDiv.viewRequestID=this.layer.map.viewRequestID;if(this.layer.async){this.layer.getURLasync(this.bounds,this,"url",this.positionImage);}else{if(this.layer.url instanceof Array){this.imgDiv.urls=this.layer.url.slice();}
60161 this.url=this.layer.getURL(this.bounds);this.positionImage();}
60162 return true;},positionImage:function(){if(this.layer===null){return;}
60163 OpenLayers.Util.modifyDOMElement(this.frame,null,this.position,this.size);var imageSize=this.layer.getImageSize(this.bounds);if(this.layerAlphaHack){OpenLayers.Util.modifyAlphaImageDiv(this.imgDiv,null,null,imageSize,this.url);}else{OpenLayers.Util.modifyDOMElement(this.imgDiv,null,null,imageSize);this.imgDiv.src=this.url;}},clear:function(){if(this.imgDiv){this.hide();if(OpenLayers.Tile.Image.useBlankTile){this.imgDiv.src=OpenLayers.Util.getImagesLocation()+"blank.gif";}}},initImgDiv:function(){var offset=this.layer.imageOffset;var size=this.layer.getImageSize(this.bounds);if(this.layerAlphaHack){this.imgDiv=OpenLayers.Util.createAlphaImageDiv(null,offset,size,null,"relative",null,null,null,true);}else{this.imgDiv=OpenLayers.Util.createImage(null,offset,size,null,"relative",null,null,true);}
60164 this.imgDiv.className='olTileImage';this.frame.style.zIndex=this.isBackBuffer?0:1;this.frame.appendChild(this.imgDiv);this.layer.div.appendChild(this.frame);if(this.layer.opacity!=null){OpenLayers.Util.modifyDOMElement(this.imgDiv,null,null,null,null,null,null,this.layer.opacity);}
60165 this.imgDiv.map=this.layer.map;var onload=function(){if(this.isLoading){this.isLoading=false;this.events.triggerEvent("loadend");}};if(this.layerAlphaHack){OpenLayers.Event.observe(this.imgDiv.childNodes[0],'load',OpenLayers.Function.bind(onload,this));}else{OpenLayers.Event.observe(this.imgDiv,'load',OpenLayers.Function.bind(onload,this));}
60166 var onerror=function(){if(this.imgDiv._attempts>OpenLayers.IMAGE_RELOAD_ATTEMPTS){onload.call(this);}};OpenLayers.Event.observe(this.imgDiv,"error",OpenLayers.Function.bind(onerror,this));},checkImgURL:function(){if(this.layer){var loaded=this.layerAlphaHack?this.imgDiv.firstChild.src:this.imgDiv.src;if(!OpenLayers.Util.isEquivalentUrl(loaded,this.url)){this.hide();}}},startTransition:function(){if(!this.backBufferTile||!this.backBufferTile.imgDiv){return;}
60167 var ratio=1;if(this.backBufferTile.resolution){ratio=this.backBufferTile.resolution/this.layer.getResolution();}
60168 if(ratio!=this.lastRatio){if(this.layer.transitionEffect=='resize'){var upperLeft=new OpenLayers.LonLat(this.backBufferTile.bounds.left,this.backBufferTile.bounds.top);var size=new OpenLayers.Size(this.backBufferTile.size.w*ratio,this.backBufferTile.size.h*ratio);var px=this.layer.map.getLayerPxFromLonLat(upperLeft);OpenLayers.Util.modifyDOMElement(this.backBufferTile.frame,null,px,size);var imageSize=this.backBufferTile.imageSize;imageSize=new OpenLayers.Size(imageSize.w*ratio,imageSize.h*ratio);var imageOffset=this.backBufferTile.imageOffset;if(imageOffset){imageOffset=new OpenLayers.Pixel(imageOffset.x*ratio,imageOffset.y*ratio);}
60169 OpenLayers.Util.modifyDOMElement(this.backBufferTile.imgDiv,null,imageOffset,imageSize);this.backBufferTile.show();}}else{if(this.layer.singleTile){this.backBufferTile.show();}else{this.backBufferTile.hide();}}
60170 this.lastRatio=ratio;},show:function(){this.frame.style.display='';if(OpenLayers.Util.indexOf(this.layer.SUPPORTED_TRANSITIONS,this.layer.transitionEffect)!=-1){if(navigator.userAgent.toLowerCase().indexOf("gecko")!=-1){this.frame.scrollLeft=this.frame.scrollLeft;}}},hide:function(){this.frame.style.display='none';},CLASS_NAME:"OpenLayers.Tile.Image"});OpenLayers.Tile.Image.useBlankTile=(OpenLayers.Util.getBrowserName()=="safari"||OpenLayers.Util.getBrowserName()=="opera");OpenLayers.Control.OverviewMap=OpenLayers.Class(OpenLayers.Control,{element:null,ovmap:null,size:new OpenLayers.Size(180,90),layers:null,minRectSize:15,minRectDisplayClass:"RectReplacement",minRatio:8,maxRatio:32,mapOptions:null,autoPan:false,handlers:null,resolutionFactor:1,maximized:false,initialize:function(options){this.layers=[];this.handlers={};OpenLayers.Control.prototype.initialize.apply(this,[options]);},destroy:function(){if(!this.mapDiv){return;}
60171 if(this.handlers.click){this.handlers.click.destroy();}
60172 if(this.handlers.drag){this.handlers.drag.destroy();}
60173 this.mapDiv.removeChild(this.extentRectangle);this.extentRectangle=null;if(this.rectEvents){this.rectEvents.destroy();this.rectEvents=null;}
60174 if(this.ovmap){this.ovmap.destroy();this.ovmap=null;}
60175 this.element.removeChild(this.mapDiv);this.mapDiv=null;this.div.removeChild(this.element);this.element=null;if(this.maximizeDiv){OpenLayers.Event.stopObservingElement(this.maximizeDiv);this.div.removeChild(this.maximizeDiv);this.maximizeDiv=null;}
60176 if(this.minimizeDiv){OpenLayers.Event.stopObservingElement(this.minimizeDiv);this.div.removeChild(this.minimizeDiv);this.minimizeDiv=null;}
60177 this.map.events.un({"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(!(this.layers.length>0)){if(this.map.baseLayer){var layer=this.map.baseLayer.clone();this.layers=[layer];}else{this.map.events.register("changebaselayer",this,this.baseLayerDraw);return this.div;}}
60178 this.element=document.createElement('div');this.element.className=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=1000;this.extentRectangle.className=this.displayClass+'ExtentRectangle';this.mapDiv.appendChild(this.extentRectangle);this.element.appendChild(this.mapDiv);this.div.appendChild(this.element);if(!this.outsideViewport){this.div.className+=" "+this.displayClass+'Container';var imgLocation=OpenLayers.Util.getImagesLocation();var img=imgLocation+'layer-switcher-maximize.png';this.maximizeDiv=OpenLayers.Util.createAlphaImageDiv(this.displayClass+'MaximizeButton',null,new OpenLayers.Size(18,18),img,'absolute');this.maximizeDiv.style.display='none';this.maximizeDiv.className=this.displayClass+'MaximizeButton';OpenLayers.Event.observe(this.maximizeDiv,'click',OpenLayers.Function.bindAsEventListener(this.maximizeControl,this));this.div.appendChild(this.maximizeDiv);var img=imgLocation+'layer-switcher-minimize.png';this.minimizeDiv=OpenLayers.Util.createAlphaImageDiv('OpenLayers_Control_minimizeDiv',null,new OpenLayers.Size(18,18),img,'absolute');this.minimizeDiv.style.display='none';this.minimizeDiv.className=this.displayClass+'MinimizeButton';OpenLayers.Event.observe(this.minimizeDiv,'click',OpenLayers.Function.bindAsEventListener(this.minimizeControl,this));this.div.appendChild(this.minimizeDiv);var eventsToStop=['dblclick','mousedown'];for(var i=0,len=eventsToStop.length;i<len;i++){OpenLayers.Event.observe(this.maximizeDiv,eventsToStop[i],OpenLayers.Event.stop);OpenLayers.Event.observe(this.minimizeDiv,eventsToStop[i],OpenLayers.Event.stop);}
60179 this.minimizeControl();}else{this.element.style.display='';}
60180 if(this.map.getExtent()){this.update();}
60181 this.map.events.register('moveend',this,this.update);if(this.maximized){this.maximizeControl();}
60182 return this.div;},baseLayerDraw:function(){this.draw();this.map.events.unregister("changebaselayer",this,this.baseLayerDraw);},rectDrag:function(px){var deltaX=this.handlers.drag.last.x-px.x;var deltaY=this.handlers.drag.last.y-px.y;if(deltaX!=0||deltaY!=0){var rectTop=this.rectPxBounds.top;var rectLeft=this.rectPxBounds.left;var rectHeight=Math.abs(this.rectPxBounds.getHeight());var rectWidth=this.rectPxBounds.getWidth();var newTop=Math.max(0,(rectTop-deltaY));newTop=Math.min(newTop,this.ovmap.size.h-this.hComp-rectHeight);var newLeft=Math.max(0,(rectLeft-deltaX));newLeft=Math.min(newLeft,this.ovmap.size.w-this.wComp-rectWidth);this.setRectPxBounds(new OpenLayers.Bounds(newLeft,newTop+rectHeight,newLeft+rectWidth,newTop));}},mapDivClick:function(evt){var pxCenter=this.rectPxBounds.getCenterPixel();var deltaX=evt.xy.x-pxCenter.x;var deltaY=evt.xy.y-pxCenter.y;var top=this.rectPxBounds.top;var left=this.rectPxBounds.left;var height=Math.abs(this.rectPxBounds.getHeight());var width=this.rectPxBounds.getWidth();var newTop=Math.max(0,(top+deltaY));newTop=Math.min(newTop,this.ovmap.size.h-height);var newLeft=Math.max(0,(left+deltaX));newLeft=Math.min(newLeft,this.ovmap.size.w-width);this.setRectPxBounds(new OpenLayers.Bounds(newLeft,newTop+height,newLeft+width,newTop));this.updateMapToRect();},maximizeControl:function(e){this.element.style.display='';this.showToggle(false);if(e!=null){OpenLayers.Event.stop(e);}},minimizeControl:function(e){this.element.style.display='none';this.showToggle(true);if(e!=null){OpenLayers.Event.stop(e);}},showToggle:function(minimize){this.maximizeDiv.style.display=minimize?'':'none';this.minimizeDiv.style.display=minimize?'none':'';},update:function(){if(this.ovmap==null){this.createMap();}
60183 if(this.autoPan||!this.isSuitableOverview()){this.updateOverview();}
60184 this.updateRectToMap();},isSuitableOverview:function(){var mapExtent=this.map.getExtent();var maxExtent=this.map.maxExtent;var testExtent=new OpenLayers.Bounds(Math.max(mapExtent.left,maxExtent.left),Math.max(mapExtent.bottom,maxExtent.bottom),Math.min(mapExtent.right,maxExtent.right),Math.min(mapExtent.top,maxExtent.top));if(this.ovmap.getProjection()!=this.map.getProjection()){testExtent=testExtent.transform(this.map.getProjectionObject(),this.ovmap.getProjectionObject());}
60185 var resRatio=this.ovmap.getResolution()/this.map.getResolution();return((resRatio>this.minRatio)&&(resRatio<=this.maxRatio)&&(this.ovmap.getExtent().containsBounds(testExtent)));},updateOverview:function(){var mapRes=this.map.getResolution();var targetRes=this.ovmap.getResolution();var resRatio=targetRes/mapRes;if(resRatio>this.maxRatio){targetRes=this.minRatio*mapRes;}else if(resRatio<=this.minRatio){targetRes=this.maxRatio*mapRes;}
60186 var center;if(this.ovmap.getProjection()!=this.map.getProjection()){center=this.map.center.clone();center.transform(this.map.getProjectionObject(),this.ovmap.getProjectionObject());}else{center=this.map.center;}
60187 this.ovmap.setCenter(center,this.ovmap.getZoomForResolution(targetRes*this.resolutionFactor));this.updateRectToMap();},createMap:function(){var options=OpenLayers.Util.extend({controls:[],maxResolution:'auto',fallThrough:false},this.mapOptions);this.ovmap=new OpenLayers.Map(this.mapDiv,options);OpenLayers.Event.stopObserving(window,'unload',this.ovmap.unloadDestroy);this.ovmap.addLayers(this.layers);this.ovmap.zoomToMaxExtent();this.wComp=parseInt(OpenLayers.Element.getStyle(this.extentRectangle,'border-left-width'))+
60188 parseInt(OpenLayers.Element.getStyle(this.extentRectangle,'border-right-width'));this.wComp=(this.wComp)?this.wComp:2;this.hComp=parseInt(OpenLayers.Element.getStyle(this.extentRectangle,'border-top-width'))+
60189 parseInt(OpenLayers.Element.getStyle(this.extentRectangle,'border-bottom-width'));this.hComp=(this.hComp)?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},{"single":true,"double":false,"stopSingle":true,"stopDouble":true,"pixelTolerance":1,map:this.ovmap});this.handlers.click.activate();this.rectEvents=new OpenLayers.Events(this,this.extentRectangle,null,true);this.rectEvents.register("mouseover",this,function(e){if(!this.handlers.drag.active&&!this.map.dragging){this.handlers.drag.activate();}});this.rectEvents.register("mouseout",this,function(e){if(!this.handlers.drag.dragging){this.handlers.drag.deactivate();}});if(this.ovmap.getProjection()!=this.map.getProjection()){var sourceUnits=this.map.getProjectionObject().getUnits()||this.map.units||this.map.baseLayer.units;var targetUnits=this.ovmap.getProjectionObject().getUnits()||this.ovmap.units||this.ovmap.baseLayer.units;this.resolutionFactor=sourceUnits&&targetUnits?OpenLayers.INCHES_PER_UNIT[sourceUnits]/OpenLayers.INCHES_PER_UNIT[targetUnits]:1;}},updateRectToMap:function(){var bounds;if(this.ovmap.getProjection()!=this.map.getProjection()){bounds=this.map.getExtent().transform(this.map.getProjectionObject(),this.ovmap.getProjectionObject());}else{bounds=this.map.getExtent();}
60190 var pxBounds=this.getRectBoundsFromMapBounds(bounds);if(pxBounds){this.setRectPxBounds(pxBounds);}},updateMapToRect:function(){var lonLatBounds=this.getMapBoundsFromRectBounds(this.rectPxBounds);if(this.ovmap.getProjection()!=this.map.getProjection()){lonLatBounds=lonLatBounds.transform(this.ovmap.getProjectionObject(),this.map.getProjectionObject());}
60191 this.map.panTo(lonLatBounds.getCenterLonLat());},setRectPxBounds:function(pxBounds){var top=Math.max(pxBounds.top,0);var left=Math.max(pxBounds.left,0);var bottom=Math.min(pxBounds.top+Math.abs(pxBounds.getHeight()),this.ovmap.size.h-this.hComp);var right=Math.min(pxBounds.left+pxBounds.getWidth(),this.ovmap.size.w-this.wComp);var width=Math.max(right-left,0);var height=Math.max(bottom-top,0);if(width<this.minRectSize||height<this.minRectSize){this.extentRectangle.className=this.displayClass+
60192 this.minRectDisplayClass;var rLeft=left+(width/2)-(this.minRectSize/2);var rTop=top+(height/2)-(this.minRectSize/2);this.extentRectangle.style.top=Math.round(rTop)+'px';this.extentRectangle.style.left=Math.round(rLeft)+'px';this.extentRectangle.style.height=this.minRectSize+'px';this.extentRectangle.style.width=this.minRectSize+'px';}else{this.extentRectangle.className=this.displayClass+'ExtentRectangle';this.extentRectangle.style.top=Math.round(top)+'px';this.extentRectangle.style.left=Math.round(left)+'px';this.extentRectangle.style.height=Math.round(height)+'px';this.extentRectangle.style.width=Math.round(width)+'px';}
60193 this.rectPxBounds=new OpenLayers.Bounds(Math.round(left),Math.round(bottom),Math.round(right),Math.round(top));},getRectBoundsFromMapBounds:function(lonLatBounds){var leftBottomLonLat=new OpenLayers.LonLat(lonLatBounds.left,lonLatBounds.bottom);var rightTopLonLat=new OpenLayers.LonLat(lonLatBounds.right,lonLatBounds.top);var leftBottomPx=this.getOverviewPxFromLonLat(leftBottomLonLat);var rightTopPx=this.getOverviewPxFromLonLat(rightTopLonLat);var bounds=null;if(leftBottomPx&&rightTopPx){bounds=new OpenLayers.Bounds(leftBottomPx.x,leftBottomPx.y,rightTopPx.x,rightTopPx.y);}
60194 return bounds;},getMapBoundsFromRectBounds:function(pxBounds){var leftBottomPx=new OpenLayers.Pixel(pxBounds.left,pxBounds.bottom);var rightTopPx=new OpenLayers.Pixel(pxBounds.right,pxBounds.top);var leftBottomLonLat=this.getLonLatFromOverviewPx(leftBottomPx);var rightTopLonLat=this.getLonLatFromOverviewPx(rightTopPx);return new OpenLayers.Bounds(leftBottomLonLat.lon,leftBottomLonLat.lat,rightTopLonLat.lon,rightTopLonLat.lat);},getLonLatFromOverviewPx:function(overviewMapPx){var size=this.ovmap.size;var res=this.ovmap.getResolution();var center=this.ovmap.getExtent().getCenterLonLat();var delta_x=overviewMapPx.x-(size.w/2);var delta_y=overviewMapPx.y-(size.h/2);return new OpenLayers.LonLat(center.lon+delta_x*res,center.lat-delta_y*res);},getOverviewPxFromLonLat:function(lonlat){var res=this.ovmap.getResolution();var extent=this.ovmap.getExtent();var px=null;if(extent){px=new OpenLayers.Pixel(Math.round(1/res*(lonlat.lon-extent.left)),Math.round(1/res*(extent.top-lonlat.lat)));}
60195 return px;},CLASS_NAME:'OpenLayers.Control.OverviewMap'});OpenLayers.Feature=OpenLayers.Class({layer:null,id:null,lonlat:null,data:null,marker:null,popupClass:OpenLayers.Popup.AnchoredBubble,popup:null,initialize:function(layer,lonlat,data){this.layer=layer;this.lonlat=lonlat;this.data=(data!=null)?data:{};this.id=OpenLayers.Util.createUniqueID(this.CLASS_NAME+"_");},destroy:function(){if((this.layer!=null)&&(this.layer.map!=null)){if(this.popup!=null){this.layer.map.removePopup(this.popup);}}
60196 if(this.layer!=null&&this.marker!=null){this.layer.removeMarker(this.marker);}
60197 this.layer=null;this.id=null;this.lonlat=null;this.data=null;if(this.marker!=null){this.destroyMarker(this.marker);this.marker=null;}
60198 if(this.popup!=null){this.destroyPopup(this.popup);this.popup=null;}},onScreen:function(){var onScreen=false;if((this.layer!=null)&&(this.layer.map!=null)){var screenBounds=this.layer.map.getExtent();onScreen=screenBounds.containsLonLat(this.lonlat);}
60199 return onScreen;},createMarker:function(){if(this.lonlat!=null){this.marker=new OpenLayers.Marker(this.lonlat,this.data.icon);}
60200 return this.marker;},destroyMarker:function(){this.marker.destroy();},createPopup:function(closeBox){if(this.lonlat!=null){var id=this.id+"_popup";var anchor=(this.marker)?this.marker.icon:null;if(!this.popup){this.popup=new this.popupClass(id,this.lonlat,this.data.popupSize,this.data.popupContentHTML,anchor,closeBox);}
60201 if(this.data.overflow!=null){this.popup.contentDiv.style.overflow=this.data.overflow;}
60202 this.popup.feature=this;}
60203 return this.popup;},destroyPopup:function(){if(this.popup){this.popup.feature=null;this.popup.destroy();this.popup=null;}},CLASS_NAME:"OpenLayers.Feature"});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,initialize:function(options){OpenLayers.Format.XML.prototype.initialize.apply(this,[options]);},read:function(data){if(typeof data=="string"){data=OpenLayers.Format.XML.prototype.read.apply(this,[data]);}
60204 if(data&&data.nodeType==9){data=data.documentElement;}
60205 var obj={};this.readNode(data,obj);return obj;},readers:{"csw":{"GetDomainResponse":function(node,obj){this.readChildNodes(node,obj);},"DomainValues":function(node,obj){if(!(obj.DomainValues instanceof Array)){obj.DomainValues=[];}
60206 var attrs=node.attributes;var domainValue={};for(var i=0,len=attrs.length;i<len;++i){domainValue[attrs[i].name]=attrs[i].nodeValue;}
60207 this.readChildNodes(node,domainValue);obj.DomainValues.push(domainValue);},"PropertyName":function(node,obj){obj.PropertyName=this.getChildValue(node);},"ParameterName":function(node,obj){obj.ParameterName=this.getChildValue(node);},"ListOfValues":function(node,obj){if(!(obj.ListOfValues instanceof Array)){obj.ListOfValues=[];}
60208 this.readChildNodes(node,obj.ListOfValues);},"Value":function(node,obj){var attrs=node.attributes;var value={}
60209 for(var i=0,len=attrs.length;i<len;++i){value[attrs[i].name]=attrs[i].nodeValue;}
60210 value.value=this.getChildValue(node);obj.push({Value:value});},"ConceptualScheme":function(node,obj){obj.ConceptualScheme={};this.readChildNodes(node,obj.ConceptualScheme);},"Name":function(node,obj){obj.Name=this.getChildValue(node);},"Document":function(node,obj){obj.Document=this.getChildValue(node);},"Authority":function(node,obj){obj.Authority=this.getChildValue(node);},"RangeOfValues":function(node,obj){obj.RangeOfValues={};this.readChildNodes(node,obj.RangeOfValues);},"MinValue":function(node,obj){var attrs=node.attributes;var value={}
60211 for(var i=0,len=attrs.length;i<len;++i){value[attrs[i].name]=attrs[i].nodeValue;}
60212 value.value=this.getChildValue(node);obj.MinValue=value;},"MaxValue":function(node,obj){var attrs=node.attributes;var value={}
60213 for(var i=0,len=attrs.length;i<len;++i){value[attrs[i].name]=attrs[i].nodeValue;}
60214 value.value=this.getChildValue(node);obj.MaxValue=value;}}},write:function(options){var node=this.writeNode("csw:GetDomain",options);return OpenLayers.Format.XML.prototype.write.apply(this,[node]);},writers:{"csw":{"GetDomain":function(options){var node=this.createElementNSPlus("csw:GetDomain",{attributes:{service:"CSW",version:this.version}});if(options.PropertyName||this.PropertyName){this.writeNode("csw:PropertyName",options.PropertyName||this.PropertyName,node);}else if(options.ParameterName||this.ParameterName){this.writeNode("csw:ParameterName",options.ParameterName||this.ParameterName,node);}
60215 this.readChildNodes(node,options);return node;},"PropertyName":function(value){var node=this.createElementNSPlus("csw:PropertyName",{value:value});return node;},"ParameterName":function(value){var node=this.createElementNSPlus("csw:ParameterName",{value:value});return node;}}},CLASS_NAME:"OpenLayers.Format.CSWGetDomain.v2_0_2"});OpenLayers.Format.Context=OpenLayers.Class({version:null,layerOptions:null,layerParams:null,parser:null,initialize:function(options){OpenLayers.Util.extend(this,options);this.options=options;},read:function(data,options){if(typeof data=="string"){data=OpenLayers.Format.XML.prototype.read.apply(this,[data]);}
60216 var root=data.documentElement;var version=this.version;if(!version){version=root.getAttribute("version");}
60217 var parser=this.getParser(version);var context=parser.read(data,options);var map;if(options&&options.map){this.context=context;if(options.map instanceof OpenLayers.Map){map=this.mergeContextToMap(context,options.map);}else{var mapOptions=options.map;if(OpenLayers.Util.isElement(mapOptions)||typeof mapOptions=="string"){mapOptions={div:mapOptions};}
60218 map=this.contextToMap(context,mapOptions);}}else{map=context;}
60219 return map;},getLayerFromContext:function(layerContext){var i,len;var options={queryable:layerContext.queryable,visibility:layerContext.visibility,maxExtent:layerContext.maxExtent,metadata:OpenLayers.Util.applyDefaults(layerContext.metadata,{styles:layerContext.styles}),numZoomLevels:layerContext.numZoomLevels,units:layerContext.units,isBaseLayer:layerContext.isBaseLayer,opacity:layerContext.opacity,displayInLayerSwitcher:layerContext.displayInLayerSwitcher,singleTile:layerContext.singleTile,tileSize:(layerContext.tileSize)?new OpenLayers.Size(layerContext.tileSize.width,layerContext.tileSize.height):undefined,minScale:layerContext.minScale||layerContext.maxScaleDenominator,maxScale:layerContext.maxScale||layerContext.minScaleDenominator};if(this.layerOptions){OpenLayers.Util.applyDefaults(options,this.layerOptions);}
60220 var params={layers:layerContext.name,transparent:layerContext.transparent,version:layerContext.version};if(layerContext.formats&&layerContext.formats.length>0){params.format=layerContext.formats[0].value;for(i=0,len=layerContext.formats.length;i<len;i++){var format=layerContext.formats[i];if(format.current==true){params.format=format.value;break;}}}
60221 if(layerContext.styles&&layerContext.styles.length>0){for(i=0,len=layerContext.styles.length;i<len;i++){var style=layerContext.styles[i];if(style.current==true){if(style.href){params.sld=style.href;}else if(style.body){params.sld_body=style.body;}else{params.styles=style.name;}
60222 break;}}}
60223 if(this.layerParams){OpenLayers.Util.applyDefaults(params,this.layerParams);}
60224 var layer=null;var service=layerContext.service;if(service==OpenLayers.Format.Context.serviceTypes.WFS){options.strategies=[new OpenLayers.Strategy.BBOX()];options.protocol=new OpenLayers.Protocol.WFS({url:layerContext.url,featurePrefix:layerContext.name.split(":")[0],featureType:layerContext.name.split(":").pop()});layer=new OpenLayers.Layer.Vector(layerContext.title||layerContext.name,options);}else if(service==OpenLayers.Format.Context.serviceTypes.KML){options.strategies=[new OpenLayers.Strategy.Fixed()];options.protocol=new OpenLayers.Protocol.HTTP({url:layerContext.url,format:new OpenLayers.Format.KML()});layer=new OpenLayers.Layer.Vector(layerContext.title||layerContext.name,options);}else if(service==OpenLayers.Format.Context.serviceTypes.GML){options.strategies=[new OpenLayers.Strategy.Fixed()];options.protocol=new OpenLayers.Protocol.HTTP({url:layerContext.url,format:new OpenLayers.Format.GML()});layer=new OpenLayers.Layer.Vector(layerContext.title||layerContext.name,options);}else if(layerContext.features){layer=new OpenLayers.Layer.Vector(layerContext.title||layerContext.name,options);layer.addFeatures(layerContext.features);}else if(layerContext.categoryLayer!==true){layer=new OpenLayers.Layer.WMS(layerContext.title||layerContext.name,layerContext.url,params,options);}
60225 return layer;},getLayersFromContext:function(layersContext){var layers=[];for(var i=0,len=layersContext.length;i<len;i++){var layer=this.getLayerFromContext(layersContext[i]);if(layer!==null){layers.push(layer);}}
60226 return layers;},contextToMap:function(context,options){options=OpenLayers.Util.applyDefaults({maxExtent:context.maxExtent,projection:context.projection},options);var map=new OpenLayers.Map(options);map.addLayers(this.getLayersFromContext(context.layersContext));map.setCenter(context.bounds.getCenterLonLat(),map.getZoomForExtent(context.bounds,true));return map;},mergeContextToMap:function(context,map){map.addLayers(this.getLayersFromContext(context.layersContext));return map;},write:function(obj,options){obj=this.toContext(obj);var version=options&&options.version;var parser=this.getParser(version);var context=parser.write(obj,options);return context;},CLASS_NAME:"OpenLayers.Format.Context"});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"};if(!OpenLayers.Format.OWSCommon){OpenLayers.Format.OWSCommon={};}
60227 OpenLayers.Format.OWSCommon.v1=OpenLayers.Class(OpenLayers.Format.XML,{regExes:{trimSpace:(/^\s*|\s*$/g),removeSpace:(/\s*/g),splitSpace:(/\s+/),trimComma:(/\s*,\s*/g)},readers:{"ows":{"ServiceIdentification":function(node,obj){obj.serviceIdentification={};this.readChildNodes(node,obj.serviceIdentification);},"Title":function(node,obj){obj.title=this.getChildValue(node);},"Abstract":function(node,serviceIdentification){serviceIdentification["abstract"]=this.getChildValue(node);},"Keywords":function(node,serviceIdentification){serviceIdentification.keywords={};this.readChildNodes(node,serviceIdentification.keywords);},"Keyword":function(node,keywords){keywords[this.getChildValue(node)]=true;},"ServiceType":function(node,serviceIdentification){serviceIdentification.serviceType={codeSpace:node.getAttribute('codeSpace'),value:this.getChildValue(node)};},"ServiceTypeVersion":function(node,serviceIdentification){serviceIdentification.serviceTypeVersion=this.getChildValue(node);},"Fees":function(node,serviceIdentification){serviceIdentification.fees=this.getChildValue(node);},"AccessConstraints":function(node,serviceIdentification){serviceIdentification.accessConstraints=this.getChildValue(node);},"ServiceProvider":function(node,obj){obj.serviceProvider={};this.readChildNodes(node,obj.serviceProvider);},"ProviderName":function(node,serviceProvider){serviceProvider.providerName=this.getChildValue(node);},"ProviderSite":function(node,serviceProvider){serviceProvider.providerSite=this.getAttributeNS(node,this.namespaces.xlink,"href");},"ServiceContact":function(node,serviceProvider){serviceProvider.serviceContact={};this.readChildNodes(node,serviceProvider.serviceContact);},"IndividualName":function(node,serviceContact){serviceContact.individualName=this.getChildValue(node);},"PositionName":function(node,serviceContact){serviceContact.positionName=this.getChildValue(node);},"ContactInfo":function(node,serviceContact){serviceContact.contactInfo={};this.readChildNodes(node,serviceContact.contactInfo);},"Phone":function(node,contactInfo){contactInfo.phone={};this.readChildNodes(node,contactInfo.phone);},"Voice":function(node,phone){phone.voice=this.getChildValue(node);},"Address":function(node,contactInfo){contactInfo.address={};this.readChildNodes(node,contactInfo.address);},"DeliveryPoint":function(node,address){address.deliveryPoint=this.getChildValue(node);},"City":function(node,address){address.city=this.getChildValue(node);},"AdministrativeArea":function(node,address){address.administrativeArea=this.getChildValue(node);},"PostalCode":function(node,address){address.postalCode=this.getChildValue(node);},"Country":function(node,address){address.country=this.getChildValue(node);},"ElectronicMailAddress":function(node,address){address.electronicMailAddress=this.getChildValue(node);},"Role":function(node,serviceContact){serviceContact.role=this.getChildValue(node);},"OperationsMetadata":function(node,obj){obj.operationsMetadata={};this.readChildNodes(node,obj.operationsMetadata);},"Operation":function(node,operationsMetadata){var name=node.getAttribute("name");operationsMetadata[name]={};this.readChildNodes(node,operationsMetadata[name]);},"DCP":function(node,operation){operation.dcp={};this.readChildNodes(node,operation.dcp);},"HTTP":function(node,dcp){dcp.http={};this.readChildNodes(node,dcp.http);},"Get":function(node,http){http.get=this.getAttributeNS(node,this.namespaces.xlink,"href");},"Post":function(node,http){http.post=this.getAttributeNS(node,this.namespaces.xlink,"href");},"Parameter":function(node,operation){if(!operation.parameters){operation.parameters={};}
60228 var name=node.getAttribute("name");operation.parameters[name]={};this.readChildNodes(node,operation.parameters[name]);},"Value":function(node,allowedValues){allowedValues[this.getChildValue(node)]=true;},"OutputFormat":function(node,obj){obj.formats.push({value:this.getChildValue(node)});this.readChildNodes(node,obj);},"WGS84BoundingBox":function(node,obj){var boundingBox={};boundingBox.crs=node.getAttribute("crs");if(obj.BoundingBox){obj.BoundingBox.push(boundingBox);}else{obj.projection=boundingBox.crs;boundingBox=obj;}
60229 this.readChildNodes(node,boundingBox);},"BoundingBox":function(node,obj){this.readers['ows']['WGS84BoundingBox'].apply(this,[node,obj]);},"LowerCorner":function(node,obj){var str=this.getChildValue(node).replace(this.regExes.trimSpace,"");str=str.replace(this.regExes.trimComma,",");var pointList=str.split(this.regExes.splitSpace);obj.left=pointList[0];obj.bottom=pointList[1];},"UpperCorner":function(node,obj){var str=this.getChildValue(node).replace(this.regExes.trimSpace,"");str=str.replace(this.regExes.trimComma,",");var pointList=str.split(this.regExes.splitSpace);obj.right=pointList[0];obj.top=pointList[1];obj.bounds=new OpenLayers.Bounds(obj.left,obj.bottom,obj.right,obj.top);delete obj.left;delete obj.bottom;delete obj.right;delete obj.top;}}},writers:{"ows":{"BoundingBox":function(options){var node=this.createElementNSPlus("ows:BoundingBox",{attributes:{crs:options.projection}});this.writeNode("ows:LowerCorner",options,node);this.writeNode("ows:UpperCorner",options,node);return node;},"LowerCorner":function(options){var node=this.createElementNSPlus("ows:LowerCorner",{value:options.bounds.left+" "+options.bounds.bottom});return node;},"UpperCorner":function(options){var node=this.createElementNSPlus("ows:UpperCorner",{value:options.bounds.right+" "+options.bounds.top});return node;},"Title":function(title){var node=this.createElementNSPlus("ows:Title",{value:title});return node;},"OutputFormat":function(format){var node=this.createElementNSPlus("ows:OutputFormat",{value:format});return node;}}},CLASS_NAME:"OpenLayers.Format.OWSCommon.v1"});OpenLayers.Format.SOSCapabilities=OpenLayers.Class(OpenLayers.Format.XML,{defaultVersion:"1.0.0",version:null,parser:null,initialize:function(options){OpenLayers.Format.XML.prototype.initialize.apply(this,[options]);this.options=options;},read:function(data){if(typeof data=="string"){data=OpenLayers.Format.XML.prototype.read.apply(this,[data]);}
60230 var root=data.documentElement;var version=this.version||root.getAttribute("version")||this.defaultVersion;if(!this.parser||this.parser.version!==version){var constr=OpenLayers.Format.SOSCapabilities["v"+version.replace(/\./g,"_")];if(!constr){throw"Can't find a SOS capabilities parser for version "+version;}
60231 var parser=new constr(this.options);}
60232 var capabilities=parser.read(data);capabilities.version=version;return capabilities;},CLASS_NAME:"OpenLayers.Format.SOSCapabilities"});OpenLayers.Format.WFSCapabilities=OpenLayers.Class(OpenLayers.Format.XML,{defaultVersion:"1.1.0",version:null,initialize:function(options){OpenLayers.Format.XML.prototype.initialize.apply(this,[options]);this.options=options;},read:function(data){if(typeof data=="string"){data=OpenLayers.Format.XML.prototype.read.apply(this,[data]);}
60233 var root=data.documentElement;var version=this.version;if(!version){version=root.getAttribute("version");if(!version){version=this.defaultVersion;}}
60234 var constr=OpenLayers.Format.WFSCapabilities["v"+version.replace(/\./g,"_")];if(!constr){throw"Can't find a WFS capabilities parser for version "+version;}
60235 var parser=new constr(this.options);var capabilities=parser.read(data);capabilities.version=version;return capabilities;},CLASS_NAME:"OpenLayers.Format.WFSCapabilities"});OpenLayers.Format.WFSDescribeFeatureType=OpenLayers.Class(OpenLayers.Format.XML,{namespaces:{xsd:"http://www.w3.org/2001/XMLSchema"},initialize:function(options){OpenLayers.Format.XML.prototype.initialize.apply(this,[options]);},readers:{"xsd":{"schema":function(node,obj){var complexTypes=[];var customTypes={};var schema={complexTypes:complexTypes,customTypes:customTypes};this.readChildNodes(node,schema);var attributes=node.attributes;var attr,name;for(var i=0,len=attributes.length;i<len;++i){attr=attributes[i];name=attr.name;if(name.indexOf("xmlns")==0){this.setNamespace(name.split(":")[1]||"",attr.value);}else{obj[name]=attr.value;}}
60236 obj.featureTypes=complexTypes;obj.targetPrefix=this.namespaceAlias[obj.targetNamespace];var complexType,customType;for(var i=0,len=complexTypes.length;i<len;++i){complexType=complexTypes[i];customType=customTypes[complexType.typeName];if(customTypes[complexType.typeName]){complexType.typeName=customType.name;}}},"complexType":function(node,obj){var complexType={"typeName":node.getAttribute("name")};this.readChildNodes(node,complexType);obj.complexTypes.push(complexType);},"complexContent":function(node,obj){this.readChildNodes(node,obj);},"extension":function(node,obj){this.readChildNodes(node,obj);},"sequence":function(node,obj){var sequence={elements:[]};this.readChildNodes(node,sequence);obj.properties=sequence.elements;},"element":function(node,obj){if(obj.elements){var element={};var attributes=node.attributes;var attr;for(var i=0,len=attributes.length;i<len;++i){attr=attributes[i];element[attr.name]=attr.value;}
60237 var type=element.type;if(!type){type={};this.readChildNodes(node,type);element.restriction=type;element.type=type.base;}
60238 var fullType=type.base||type;element.localType=fullType.split(":").pop();obj.elements.push(element);}
60239 if(obj.complexTypes){var type=node.getAttribute("type");var localType=type.split(":").pop();obj.customTypes[localType]={"name":node.getAttribute("name"),"type":type};}},"simpleType":function(node,obj){this.readChildNodes(node,obj);},"restriction":function(node,obj){obj.base=node.getAttribute("base");this.readRestriction(node,obj);}}},readRestriction:function(node,obj){var children=node.childNodes;var child,nodeName,value;for(var i=0,len=children.length;i<len;++i){child=children[i];if(child.nodeType==1){nodeName=child.nodeName.split(":").pop();value=child.getAttribute("value");if(!obj[nodeName]){obj[nodeName]=value;}else{if(typeof obj[nodeName]=="string"){obj[nodeName]=[obj[nodeName]];}
60240 obj[nodeName].push(value);}}}},read:function(data){if(typeof data=="string"){data=OpenLayers.Format.XML.prototype.read.apply(this,[data]);}
60241 if(data&&data.nodeType==9){data=data.documentElement;}
60242 var schema={};this.readNode(data,schema);return schema;},CLASS_NAME:"OpenLayers.Format.WFSDescribeFeatureType"});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"},defaultPrefix:"wfs",version:null,schemaLocations:null,srsName:null,extractAttributes:true,xy:true,stateName:null,initialize:function(options){this.stateName={};this.stateName[OpenLayers.State.INSERT]="wfs:Insert";this.stateName[OpenLayers.State.UPDATE]="wfs:Update";this.stateName[OpenLayers.State.DELETE]="wfs:Delete";OpenLayers.Format.XML.prototype.initialize.apply(this,[options]);},getSrsName:function(feature,options){var srsName=options&&options.srsName;if(!srsName){if(feature&&feature.layer){srsName=feature.layer.projection.getCode();}else{srsName=this.srsName;}}
60243 return srsName;},read:function(data,options){options=options||{};OpenLayers.Util.applyDefaults(options,{output:"features"});if(typeof data=="string"){data=OpenLayers.Format.XML.prototype.read.apply(this,[data]);}
60244 if(data&&data.nodeType==9){data=data.documentElement;}
60245 var obj={};if(data){this.readNode(data,obj);}
60246 if(obj.features&&options.output==="features"){obj=obj.features;}
60247 return obj;},readers:{"wfs":{"FeatureCollection":function(node,obj){obj.features=[];this.readChildNodes(node,obj);}}},write:function(features){var node=this.writeNode("wfs:Transaction",features);var value=this.schemaLocationAttr();if(value){this.setAttributeNS(node,this.namespaces["xsi"],"xsi:schemaLocation",value)}
60248 return OpenLayers.Format.XML.prototype.write.apply(this,[node]);},writers:{"wfs":{"GetFeature":function(options){var node=this.createElementNSPlus("wfs:GetFeature",{attributes:{service:"WFS",version:this.version,outputFormat:options&&options.outputFormat,maxFeatures:options&&options.maxFeatures,"xsi:schemaLocation":this.schemaLocationAttr(options)}});if(typeof this.featureType=="string"){this.writeNode("Query",options,node);}else{for(var i=0,len=this.featureType.length;i<len;i++){options.featureType=this.featureType[i];this.writeNode("Query",options,node);}}
60249 return node;},"Transaction":function(features){var node=this.createElementNSPlus("wfs:Transaction",{attributes:{service:"WFS",version:this.version}});if(features){var name,feature;for(var i=0,len=features.length;i<len;++i){feature=features[i];name=this.stateName[feature.state];if(name){this.writeNode(name,feature,node);}}}
60250 return node;},"Insert":function(feature){var node=this.createElementNSPlus("wfs:Insert");this.srsName=this.getSrsName(feature);this.writeNode("feature:_typeName",feature,node);return node;},"Update":function(feature){var node=this.createElementNSPlus("wfs:Update",{attributes:{typeName:(this.featureNS?this.featurePrefix+":":"")+
60251 this.featureType}});if(this.featureNS){node.setAttribute("xmlns:"+this.featurePrefix,this.featureNS);}
60252 if(this.geometryName!==null){this.writeNode("Property",{name:this.geometryName,value:feature},node);}
60253 for(var key in feature.attributes){if(feature.attributes[key]!==undefined){this.writeNode("Property",{name:key,value:feature.attributes[key]},node);}}
60254 this.writeNode("ogc:Filter",new OpenLayers.Filter.FeatureId({fids:[feature.fid]}),node);return node;},"Property":function(obj){var node=this.createElementNSPlus("wfs:Property");this.writeNode("Name",obj.name,node);if(obj.value!==null){this.writeNode("Value",obj.value,node);}
60255 return node;},"Name":function(name){return this.createElementNSPlus("wfs:Name",{value:name});},"Value":function(obj){var node;if(obj instanceof OpenLayers.Feature.Vector){node=this.createElementNSPlus("wfs:Value");this.srsName=this.getSrsName(obj);var geom=this.writeNode("feature:_geometry",obj.geometry).firstChild;node.appendChild(geom);}else{node=this.createElementNSPlus("wfs:Value",{value:obj});}
60256 return node;},"Delete":function(feature){var node=this.createElementNSPlus("wfs:Delete",{attributes:{typeName:(this.featureNS?this.featurePrefix+":":"")+
60257 this.featureType}});if(this.featureNS){node.setAttribute("xmlns:"+this.featurePrefix,this.featureNS);}
60258 this.writeNode("ogc:Filter",new OpenLayers.Filter.FeatureId({fids:[feature.fid]}),node);return node;}}},schemaLocationAttr:function(options){options=OpenLayers.Util.extend({featurePrefix:this.featurePrefix,schema:this.schema},options);var schemaLocations=OpenLayers.Util.extend({},this.schemaLocations);if(options.schema){schemaLocations[options.featurePrefix]=options.schema;}
60259 var parts=[];var uri;for(var key in schemaLocations){uri=this.namespaces[key];if(uri){parts.push(uri+" "+schemaLocations[key]);}}
60260 var value=parts.join(" ")||undefined;return value;},setFilterProperty:function(filter){if(filter.filters){for(var i=0,len=filter.filters.length;i<len;++i){this.setFilterProperty(filter.filters[i]);}}else{if(filter instanceof OpenLayers.Filter.Spatial){filter.property=this.geometryName;}}},CLASS_NAME:"OpenLayers.Format.WFST.v1"});OpenLayers.Format.WMSCapabilities=OpenLayers.Class(OpenLayers.Format.XML,{defaultVersion:"1.1.1",version:null,parser:null,initialize:function(options){OpenLayers.Format.XML.prototype.initialize.apply(this,[options]);this.options=options;},read:function(data){if(typeof data=="string"){data=OpenLayers.Format.XML.prototype.read.apply(this,[data]);}
60261 var root=data.documentElement;var version=this.version||root.getAttribute("version")||this.defaultVersion;if(!this.parser||this.parser.version!==version){var constr=OpenLayers.Format.WMSCapabilities["v"+version.replace(/\./g,"_")];if(!constr){throw"Can't find a WMS capabilities parser for version "+version;}
60262 this.parser=new constr(this.options);}
60263 var capabilities=this.parser.read(data);capabilities.version=version;return capabilities;},CLASS_NAME:"OpenLayers.Format.WMSCapabilities"});OpenLayers.Format.WMSDescribeLayer=OpenLayers.Class(OpenLayers.Format.XML,{defaultVersion:"1.1.1",version:null,initialize:function(options){OpenLayers.Format.XML.prototype.initialize.apply(this,[options]);this.options=options;},read:function(data){if(typeof data=="string"){data=OpenLayers.Format.XML.prototype.read.apply(this,[data]);}
60264 var root=data.documentElement;var version=this.version;if(!version){version=root.getAttribute("version");if(!version){version=this.defaultVersion;}}
60265 if(version=="1.1.1"||version=="1.1.0"){version="1.1";}
60266 var constructor=OpenLayers.Format.WMSDescribeLayer["v"+version.replace(/\./g,"_")];if(!constructor){throw"Can't find a WMS DescribeLayer parser for version "+
60267 version;}
60268 var parser=new constructor(this.options);var describelayer=parser.read(data);describelayer.version=version;return describelayer;},CLASS_NAME:"OpenLayers.Format.WMSDescribeLayer"});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,initialize:function(options){OpenLayers.Format.XML.prototype.initialize.apply(this,arguments);OpenLayers.Util.extend(this,options);this.options=options;},read:function(data){var result;if(typeof data=="string"){data=OpenLayers.Format.XML.prototype.read.apply(this,[data]);}
60269 var root=data.documentElement;if(root){var scope=this;var read=this["read_"+root.nodeName];if(read){result=read.call(this,root);}else{result=new OpenLayers.Format.GML((this.options?this.options:{})).read(data);}}else{result=data;}
60270 return result;},read_msGMLOutput:function(data){var response=[];var layerNodes=this.getSiblingNodesByTagCriteria(data,this.layerIdentifier);if(layerNodes){for(var i=0,len=layerNodes.length;i<len;++i){var node=layerNodes[i];var layerName=node.nodeName;if(node.prefix){layerName=layerName.split(':')[1];}
60271 var layerName=layerName.replace(this.layerIdentifier,'');var featureNodes=this.getSiblingNodesByTagCriteria(node,this.featureIdentifier);if(featureNodes){for(var j=0;j<featureNodes.length;j++){var featureNode=featureNodes[j];var geomInfo=this.parseGeometry(featureNode);var attributes=this.parseAttributes(featureNode);var feature=new OpenLayers.Feature.Vector(geomInfo.geometry,attributes,null);feature.bounds=geomInfo.bounds;feature.type=layerName;response.push(feature);}}}}
60272 return response;},read_FeatureInfoResponse:function(data){var response=[];var featureNodes=this.getElementsByTagNameNS(data,'*','FIELDS');for(var i=0,len=featureNodes.length;i<len;i++){var featureNode=featureNodes[i];var geom=null;var attributes={};for(var j=0,jlen=featureNode.attributes.length;j<jlen;j++){var attribute=featureNode.attributes[j];attributes[attribute.nodeName]=attribute.nodeValue;}
60273 response.push(new OpenLayers.Feature.Vector(geom,attributes,null));}
60274 return response;},getSiblingNodesByTagCriteria:function(node,criteria){var nodes=[];var children,tagName,n,matchNodes,child;if(node&&node.hasChildNodes()){children=node.childNodes;n=children.length;for(var k=0;k<n;k++){child=children[k];while(child&&child.nodeType!=1){child=child.nextSibling;k++;}
60275 tagName=(child?child.nodeName:'');if(tagName.length>0&&tagName.indexOf(criteria)>-1){nodes.push(child);}else{matchNodes=this.getSiblingNodesByTagCriteria(child,criteria);if(matchNodes.length>0){(nodes.length==0)?nodes=matchNodes:nodes.push(matchNodes);}}}}
60276 return nodes;},parseAttributes:function(node){var attributes={};if(node.nodeType==1){var children=node.childNodes;var n=children.length;for(var i=0;i<n;++i){var child=children[i];if(child.nodeType==1){var grandchildren=child.childNodes;if(grandchildren.length==1){var grandchild=grandchildren[0];if(grandchild.nodeType==3||grandchild.nodeType==4){var name=(child.prefix)?child.nodeName.split(":")[1]:child.nodeName;var value=grandchild.nodeValue.replace(this.regExes.trimSpace,"");attributes[name]=value;}}}}}
60277 return attributes;},parseGeometry:function(node){if(!this.gmlFormat){this.gmlFormat=new OpenLayers.Format.GML();}
60278 var feature=this.gmlFormat.parseFeature(node);var geometry,bounds=null;if(feature){geometry=feature.geometry&&feature.geometry.clone();bounds=feature.bounds&&feature.bounds.clone();feature.destroy();}
60279 return{geometry:geometry,bounds:bounds};},CLASS_NAME:"OpenLayers.Format.WMSGetFeatureInfo"});OpenLayers.Format.WMTSCapabilities=OpenLayers.Class(OpenLayers.Format.XML,{defaultVersion:"1.0.0",version:null,parser:null,yx:{"urn:ogc:def:crs:EPSG::4326":true},initialize:function(options){OpenLayers.Format.XML.prototype.initialize.apply(this,[options]);this.options=options;},read:function(data){if(typeof data=="string"){data=OpenLayers.Format.XML.prototype.read.apply(this,[data]);}
60280 var root=data.documentElement;var version=this.version||root.getAttribute("version")||this.defaultVersion;if(!this.parser||this.parser.version!==version){var constr=OpenLayers.Format.WMTSCapabilities["v"+version.replace(/\./g,"_")];if(!constr){throw new Error("Can't find a WMTS capabilities parser for version "+version);}
60281 this.parser=new constr(this.options);}
60282 return this.parser.read(data);},createLayer:function(capabilities,config){var layer;var required={layer:true,matrixSet:true};for(var prop in required){if(!(prop in config)){throw new Error("Missing property '"+prop+"' in layer configuration.");}}
60283 var contents=capabilities.contents;var matrixSet=contents.tileMatrixSets[config.matrixSet];var layers=contents.layers;var layerDef;for(var i=0,ii=contents.layers.length;i<ii;++i){if(contents.layers[i].identifier===config.layer){layerDef=contents.layers[i];break;}}
60284 if(layerDef&&matrixSet){var style;for(var i=0,ii=layerDef.styles.length;i<ii;++i){style=layerDef.styles[i];if(style.isDefault){break;}}
60285 layer=new OpenLayers.Layer.WMTS(OpenLayers.Util.applyDefaults(config,{url:capabilities.operationsMetadata.GetTile.dcp.http.get,name:layerDef.title,style:style,matrixIds:matrixSet.matrixIds}));}
60286 return layer;},CLASS_NAME:"OpenLayers.Format.WMTSCapabilities"});OpenLayers.Handler.Click=OpenLayers.Class(OpenLayers.Handler,{delay:300,single:true,'double':false,pixelTolerance:0,stopSingle:false,stopDouble:false,timerId:null,down:null,rightclickTimerId:null,initialize:function(control,callbacks,options){OpenLayers.Handler.prototype.initialize.apply(this,arguments);if(this.pixelTolerance!=null){this.mousedown=function(evt){this.down=evt.xy;return true;};}},mousedown:null,mouseup:function(evt){var propagate=true;if(this.checkModifiers(evt)&&this.control.handleRightClicks&&OpenLayers.Event.isRightClick(evt)){propagate=this.rightclick(evt);}
60287 return propagate;},rightclick:function(evt){if(this.passesTolerance(evt)){if(this.rightclickTimerId!=null){this.clearTimer();this.callback('dblrightclick',[evt]);return!this.stopDouble;}else{var clickEvent=this['double']?OpenLayers.Util.extend({},evt):this.callback('rightclick',[evt]);var delayedRightCall=OpenLayers.Function.bind(this.delayedRightCall,this,clickEvent);this.rightclickTimerId=window.setTimeout(delayedRightCall,this.delay);}}
60288 return!this.stopSingle;},delayedRightCall:function(evt){this.rightclickTimerId=null;if(evt){this.callback('rightclick',[evt]);}
60289 return!this.stopSingle;},dblclick:function(evt){if(this.passesTolerance(evt)){if(this["double"]){this.callback('dblclick',[evt]);}
60290 this.clearTimer();}
60291 return!this.stopDouble;},click:function(evt){if(this.passesTolerance(evt)){if(this.timerId!=null){this.clearTimer();}else{var clickEvent=this.single?OpenLayers.Util.extend({},evt):null;this.timerId=window.setTimeout(OpenLayers.Function.bind(this.delayedCall,this,clickEvent),this.delay);}}
60292 return!this.stopSingle;},passesTolerance:function(evt){var passes=true;if(this.pixelTolerance!=null&&this.down){var dpx=Math.sqrt(Math.pow(this.down.x-evt.xy.x,2)+
60293 Math.pow(this.down.y-evt.xy.y,2));if(dpx>this.pixelTolerance){passes=false;}}
60294 return passes;},clearTimer:function(){if(this.timerId!=null){window.clearTimeout(this.timerId);this.timerId=null;}
60295 if(this.rightclickTimerId!=null){window.clearTimeout(this.rightclickTimerId);this.rightclickTimerId=null;}},delayedCall:function(evt){this.timerId=null;if(evt){this.callback('click',[evt]);}},deactivate:function(){var deactivated=false;if(OpenLayers.Handler.prototype.deactivate.apply(this,arguments)){this.clearTimer();this.down=null;deactivated=true;}
60296 return deactivated;},CLASS_NAME:"OpenLayers.Handler.Click"});OpenLayers.Handler.Drag=OpenLayers.Class(OpenLayers.Handler,{started:false,stopDown:true,dragging:false,last:null,start:null,oldOnselectstart:null,interval:0,timeoutId:null,documentDrag:false,documentEvents:null,initialize:function(control,callbacks,options){OpenLayers.Handler.prototype.initialize.apply(this,arguments);},down:function(evt){},move:function(evt){},up:function(evt){},out:function(evt){},mousedown:function(evt){var propagate=true;this.dragging=false;if(this.checkModifiers(evt)&&OpenLayers.Event.isLeftClick(evt)){this.started=true;this.start=evt.xy;this.last=evt.xy;OpenLayers.Element.addClass(this.map.viewPortDiv,"olDragDown");this.down(evt);this.callback("down",[evt.xy]);OpenLayers.Event.stop(evt);if(!this.oldOnselectstart){this.oldOnselectstart=(document.onselectstart)?document.onselectstart:OpenLayers.Function.True;}
60297 document.onselectstart=OpenLayers.Function.False;propagate=!this.stopDown;}else{this.started=false;this.start=null;this.last=null;}
60298 return propagate;},mousemove:function(evt){if(this.started&&!this.timeoutId&&(evt.xy.x!=this.last.x||evt.xy.y!=this.last.y)){if(this.documentDrag===true&&this.documentEvents){if(evt.element===document){this.adjustXY(evt);this.setEvent(evt);}else{this.destroyDocumentEvents();}}
60299 if(this.interval>0){this.timeoutId=setTimeout(OpenLayers.Function.bind(this.removeTimeout,this),this.interval);}
60300 this.dragging=true;this.move(evt);this.callback("move",[evt.xy]);if(!this.oldOnselectstart){this.oldOnselectstart=document.onselectstart;document.onselectstart=OpenLayers.Function.False;}
60301 this.last=this.evt.xy;}
60302 return true;},removeTimeout:function(){this.timeoutId=null;},mouseup:function(evt){if(this.started){if(this.documentDrag===true&&this.documentEvents){this.adjustXY(evt);this.destroyDocumentEvents();}
60303 var dragged=(this.start!=this.last);this.started=false;this.dragging=false;OpenLayers.Element.removeClass(this.map.viewPortDiv,"olDragDown");this.up(evt);this.callback("up",[evt.xy]);if(dragged){this.callback("done",[evt.xy]);}
60304 document.onselectstart=this.oldOnselectstart;}
60305 return true;},mouseout:function(evt){if(this.started&&OpenLayers.Util.mouseLeft(evt,this.map.div)){if(this.documentDrag===true){this.documentEvents=new OpenLayers.Events(this,document,null,null,{includeXY:true});this.documentEvents.on({mousemove:this.mousemove,mouseup:this.mouseup});OpenLayers.Element.addClass(document.body,"olDragDown");}else{var dragged=(this.start!=this.last);this.started=false;this.dragging=false;OpenLayers.Element.removeClass(this.map.viewPortDiv,"olDragDown");this.out(evt);this.callback("out",[]);if(dragged){this.callback("done",[evt.xy]);}
60306 if(document.onselectstart){document.onselectstart=this.oldOnselectstart;}}}
60307 return true;},click:function(evt){return(this.start==this.last);},activate:function(){var activated=false;if(OpenLayers.Handler.prototype.activate.apply(this,arguments)){this.dragging=false;activated=true;}
60308 return activated;},deactivate:function(){var deactivated=false;if(OpenLayers.Handler.prototype.deactivate.apply(this,arguments)){this.started=false;this.dragging=false;this.start=null;this.last=null;deactivated=true;OpenLayers.Element.removeClass(this.map.viewPortDiv,"olDragDown");}
60309 return deactivated;},adjustXY:function(evt){var pos=OpenLayers.Util.pagePosition(this.map.div);evt.xy.x-=pos[0];evt.xy.y-=pos[1];},destroyDocumentEvents:function(){OpenLayers.Element.removeClass(document.body,"olDragDown");this.documentEvents.destroy();this.documentEvents=null;},CLASS_NAME:"OpenLayers.Handler.Drag"});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}},feature:null,lastFeature:null,down:null,up:null,clickTolerance:4,geometryTypes:null,stopClick:true,stopDown:true,stopUp:false,initialize:function(control,layer,callbacks,options){OpenLayers.Handler.prototype.initialize.apply(this,[control,callbacks,options]);this.layer=layer;},mousedown:function(evt){this.down=evt.xy;return this.handle(evt)?!this.stopDown:true;},mouseup:function(evt){this.up=evt.xy;return this.handle(evt)?!this.stopUp:true;},click:function(evt){return this.handle(evt)?!this.stopClick:true;},mousemove:function(evt){if(!this.callbacks['over']&&!this.callbacks['out']){return true;}
60310 this.handle(evt);return true;},dblclick:function(evt){return!this.handle(evt);},geometryTypeMatches:function(feature){return this.geometryTypes==null||OpenLayers.Util.indexOf(this.geometryTypes,feature.geometry.CLASS_NAME)>-1;},handle:function(evt){if(this.feature&&!this.feature.layer){this.feature=null;}
60311 var type=evt.type;var handled=false;var previouslyIn=!!(this.feature);var click=(type=="click"||type=="dblclick");this.feature=this.layer.getFeatureFromEvent(evt);if(this.feature&&!this.feature.layer){this.feature=null;}
60312 if(this.lastFeature&&!this.lastFeature.layer){this.lastFeature=null;}
60313 if(this.feature){var inNew=(this.feature!=this.lastFeature);if(this.geometryTypeMatches(this.feature)){if(previouslyIn&&inNew){if(this.lastFeature){this.triggerCallback(type,'out',[this.lastFeature]);}
60314 this.triggerCallback(type,'in',[this.feature]);}else if(!previouslyIn||click){this.triggerCallback(type,'in',[this.feature]);}
60315 this.lastFeature=this.feature;handled=true;}else{if(this.lastFeature&&(previouslyIn&&inNew||click)){this.triggerCallback(type,'out',[this.lastFeature]);}
60316 this.feature=null;}}else{if(this.lastFeature&&(previouslyIn||click)){this.triggerCallback(type,'out',[this.lastFeature]);}}
60317 return handled;},triggerCallback:function(type,mode,args){var key=this.EVENTMAP[type][mode];if(key){if(type=='click'&&this.up&&this.down){var dpx=Math.sqrt(Math.pow(this.up.x-this.down.x,2)+
60318 Math.pow(this.up.y-this.down.y,2));if(dpx<=this.clickTolerance){this.callback(key,args);}}else{this.callback(key,args);}}},activate:function(){var activated=false;if(OpenLayers.Handler.prototype.activate.apply(this,arguments)){this.moveLayerToTop();this.map.events.on({"removelayer":this.handleMapEvents,"changelayer":this.handleMapEvents,scope:this});activated=true;}
60319 return activated;},deactivate:function(){var deactivated=false;if(OpenLayers.Handler.prototype.deactivate.apply(this,arguments)){this.moveLayerBack();this.feature=null;this.lastFeature=null;this.down=null;this.up=null;this.map.events.un({"removelayer":this.handleMapEvents,"changelayer":this.handleMapEvents,scope:this});deactivated=true;}
60320 return deactivated;},handleMapEvents:function(evt){if(!evt.property||evt.property=="order"){this.moveLayerToTop();}},moveLayerToTop:function(){var index=Math.max(this.map.Z_INDEX_BASE['Feature']-1,this.layer.getZIndex())+1;this.layer.setZIndex(index);},moveLayerBack:function(){var index=this.layer.getZIndex()-1;if(index>=this.map.Z_INDEX_BASE['Feature']){this.layer.setZIndex(index);}else{this.map.setLayerZIndex(this.layer,this.map.getLayerIndex(this.layer));}},CLASS_NAME:"OpenLayers.Handler.Feature"});OpenLayers.Handler.Hover=OpenLayers.Class(OpenLayers.Handler,{delay:500,pixelTolerance:null,stopMove:false,px:null,timerId:null,initialize:function(control,callbacks,options){OpenLayers.Handler.prototype.initialize.apply(this,arguments);},mousemove:function(evt){if(this.passesTolerance(evt.xy)){this.clearTimer();this.callback('move',[evt]);this.px=evt.xy;evt=OpenLayers.Util.extend({},evt);this.timerId=window.setTimeout(OpenLayers.Function.bind(this.delayedCall,this,evt),this.delay);}
60321 return!this.stopMove;},mouseout:function(evt){if(OpenLayers.Util.mouseLeft(evt,this.map.div)){this.clearTimer();this.callback('move',[evt]);}
60322 return true;},passesTolerance:function(px){var passes=true;if(this.pixelTolerance&&this.px){var dpx=Math.sqrt(Math.pow(this.px.x-px.x,2)+
60323 Math.pow(this.px.y-px.y,2));if(dpx<this.pixelTolerance){passes=false;}}
60324 return passes;},clearTimer:function(){if(this.timerId!=null){window.clearTimeout(this.timerId);this.timerId=null;}},delayedCall:function(evt){this.callback('pause',[evt]);},deactivate:function(){var deactivated=false;if(OpenLayers.Handler.prototype.deactivate.apply(this,arguments)){this.clearTimer();deactivated=true;}
60325 return deactivated;},CLASS_NAME:"OpenLayers.Handler.Hover"});OpenLayers.Handler.Keyboard=OpenLayers.Class(OpenLayers.Handler,{KEY_EVENTS:["keydown","keyup"],eventListener:null,initialize:function(control,callbacks,options){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,arguments)){for(var i=0,len=this.KEY_EVENTS.length;i<len;i++){OpenLayers.Event.observe(document,this.KEY_EVENTS[i],this.eventListener);}
60326 return true;}else{return false;}},deactivate:function(){var deactivated=false;if(OpenLayers.Handler.prototype.deactivate.apply(this,arguments)){for(var i=0,len=this.KEY_EVENTS.length;i<len;i++){OpenLayers.Event.stopObserving(document,this.KEY_EVENTS[i],this.eventListener);}
60327 deactivated=true;}
60328 return deactivated;},handleKeyEvent:function(evt){if(this.checkModifiers(evt)){this.callback(evt.type,[evt]);}},CLASS_NAME:"OpenLayers.Handler.Keyboard"});OpenLayers.Handler.MouseWheel=OpenLayers.Class(OpenLayers.Handler,{wheelListener:null,mousePosition:null,interval:0,delta:0,cumulative:true,initialize:function(control,callbacks,options){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(e){if(!this.map||!this.checkModifiers(e)){return;}
60329 var overScrollableDiv=false;var overLayerDiv=false;var overMapDiv=false;var elem=OpenLayers.Event.element(e);while((elem!=null)&&!overMapDiv&&!overScrollableDiv){if(!overScrollableDiv){try{if(elem.currentStyle){overflow=elem.currentStyle["overflow"];}else{var style=document.defaultView.getComputedStyle(elem,null);var overflow=style.getPropertyValue("overflow");}
60330 overScrollableDiv=(overflow&&(overflow=="auto")||(overflow=="scroll"));}catch(err){}}
60331 if(!overLayerDiv){for(var i=0,len=this.map.layers.length;i<len;i++){if(elem==this.map.layers[i].div||elem==this.map.layers[i].pane){overLayerDiv=true;break;}}}
60332 overMapDiv=(elem==this.map.div);elem=elem.parentNode;}
60333 if(!overScrollableDiv&&overMapDiv){if(overLayerDiv){var delta=0;if(!e){e=window.event;}
60334 if(e.wheelDelta){delta=e.wheelDelta/120;if(window.opera&&window.opera.version()<9.2){delta=-delta;}}else if(e.detail){delta=-e.detail/3;}
60335 this.delta=this.delta+delta;if(this.interval){window.clearTimeout(this._timeoutId);this._timeoutId=window.setTimeout(OpenLayers.Function.bind(function(){this.wheelZoom(e);},this),this.interval);}else{this.wheelZoom(e);}}
60336 OpenLayers.Event.stop(e);}},wheelZoom:function(e){var delta=this.delta;this.delta=0;if(delta){if(this.mousePosition){e.xy=this.mousePosition;}
60337 if(!e.xy){e.xy=this.map.getPixelFromLonLat(this.map.getCenter());}
60338 if(delta<0){this.callback("down",[e,this.cumulative?delta:-1]);}else{this.callback("up",[e,this.cumulative?delta:1]);}}},mousemove:function(evt){this.mousePosition=evt.xy;},activate:function(evt){if(OpenLayers.Handler.prototype.activate.apply(this,arguments)){var wheelListener=this.wheelListener;OpenLayers.Event.observe(window,"DOMMouseScroll",wheelListener);OpenLayers.Event.observe(window,"mousewheel",wheelListener);OpenLayers.Event.observe(document,"mousewheel",wheelListener);return true;}else{return false;}},deactivate:function(evt){if(OpenLayers.Handler.prototype.deactivate.apply(this,arguments)){var wheelListener=this.wheelListener;OpenLayers.Event.stopObserving(window,"DOMMouseScroll",wheelListener);OpenLayers.Event.stopObserving(window,"mousewheel",wheelListener);OpenLayers.Event.stopObserving(document,"mousewheel",wheelListener);return true;}else{return false;}},CLASS_NAME:"OpenLayers.Handler.MouseWheel"});OpenLayers.Layer=OpenLayers.Class({id:null,name:null,div:null,opacity:null,alwaysInRange:null,EVENT_TYPES:["loadstart","loadend","loadcancel","visibilitychanged","move","moveend"],RESOLUTION_PROPERTIES:['scales','resolutions','maxScale','minScale','maxResolution','minResolution','numZoomLevels','maxZoomLevel'],events:null,map:null,isBaseLayer:false,alpha:false,displayInLayerSwitcher:true,visibility:true,attribution:null,inRange:false,imageSize:null,imageOffset:null,options:null,eventListeners:null,gutter:0,projection:null,units:null,scales:null,resolutions:null,maxExtent:null,minExtent:null,maxResolution:null,minResolution:null,numZoomLevels:null,minScale:null,maxScale:null,displayOutsideMaxExtent:false,wrapDateLine:false,transitionEffect:null,SUPPORTED_TRANSITIONS:['resize'],metadata:{},initialize:function(name,options){this.addOptions(options);this.name=name;if(this.id==null){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,this.div,this.EVENT_TYPES);if(this.eventListeners instanceof Object){this.events.on(this.eventListeners);}}
60339 if(this.wrapDateLine){this.displayOutsideMaxExtent=true;}},destroy:function(setNewBaseLayer){if(setNewBaseLayer==null){setNewBaseLayer=true;}
60340 if(this.map!=null){this.map.removeLayer(this,setNewBaseLayer);}
60341 this.projection=null;this.map=null;this.name=null;this.div=null;this.options=null;if(this.events){if(this.eventListeners){this.events.un(this.eventListeners);}
60342 this.events.destroy();}
60343 this.eventListeners=null;this.events=null;},clone:function(obj){if(obj==null){obj=new OpenLayers.Layer(this.name,this.getOptions());}
60344 OpenLayers.Util.applyDefaults(obj,this);obj.map=null;return obj;},getOptions:function(){var options={};for(var o in this.options){options[o]=this[o];}
60345 return options;},setName:function(newName){if(newName!=this.name){this.name=newName;if(this.map!=null){this.map.events.triggerEvent("changelayer",{layer:this,property:"name"});}}},addOptions:function(newOptions){if(this.options==null){this.options={};}
60346 OpenLayers.Util.extend(this.options,newOptions);OpenLayers.Util.extend(this,newOptions);if(typeof this.projection=="string"){this.projection=new OpenLayers.Projection(this.projection);}
60347 if(this.projection&&this.projection.getUnits()){this.units=this.projection.getUnits();}
60348 if(this.map){var properties=this.RESOLUTION_PROPERTIES.concat(["projection","units","minExtent","maxExtent"]);for(var o in newOptions){if(newOptions.hasOwnProperty(o)&&OpenLayers.Util.indexOf(properties,o)>=0){this.initResolutions();break;}}}},onMapResize:function(){},redraw:function(){var redrawn=false;if(this.map){this.inRange=this.calculateInRange();var extent=this.getExtent();if(extent&&this.inRange&&this.visibility){var zoomChanged=true;this.moveTo(extent,zoomChanged,false);this.events.triggerEvent("moveend",{"zoomChanged":zoomChanged});redrawn=true;}}
60349 return redrawn;},moveTo:function(bounds,zoomChanged,dragging){var display=this.visibility;if(!this.isBaseLayer){display=display&&this.inRange;}
60350 this.display(display);},setMap:function(map){if(this.map==null){this.map=map;this.maxExtent=this.maxExtent||this.map.maxExtent;this.minExtent=this.minExtent||this.map.minExtent;this.projection=this.projection||this.map.projection;if(typeof this.projection=="string"){this.projection=new OpenLayers.Projection(this.projection);}
60351 this.units=this.projection.getUnits()||this.units||this.map.units;this.initResolutions();if(!this.isBaseLayer){this.inRange=this.calculateInRange();var show=((this.visibility)&&(this.inRange));this.div.style.display=show?"":"none";}
60352 this.setTileSize();}},afterAdd:function(){},removeMap:function(map){},getImageSize:function(bounds){return(this.imageSize||this.tileSize);},setTileSize:function(size){var tileSize=(size)?size:((this.tileSize)?this.tileSize:this.map.getTileSize());this.tileSize=tileSize;if(this.gutter){this.imageOffset=new OpenLayers.Pixel(-this.gutter,-this.gutter);this.imageSize=new OpenLayers.Size(tileSize.w+(2*this.gutter),tileSize.h+(2*this.gutter));}},getVisibility:function(){return this.visibility;},setVisibility:function(visibility){if(visibility!=this.visibility){this.visibility=visibility;this.display(visibility);this.redraw();if(this.map!=null){this.map.events.triggerEvent("changelayer",{layer:this,property:"visibility"});}
60353 this.events.triggerEvent("visibilitychanged");}},display:function(display){if(display!=(this.div.style.display!="none")){this.div.style.display=(display&&this.calculateInRange())?"block":"none";}},calculateInRange:function(){var inRange=false;if(this.alwaysInRange){inRange=true;}else{if(this.map){var resolution=this.map.getResolution();inRange=((resolution>=this.minResolution)&&(resolution<=this.maxResolution));}}
60354 return inRange;},setIsBaseLayer:function(isBaseLayer){if(isBaseLayer!=this.isBaseLayer){this.isBaseLayer=isBaseLayer;if(this.map!=null){this.map.events.triggerEvent("changebaselayer",{layer:this});}}},initResolutions:function(){var i,len;var props={},alwaysInRange=true;for(i=0,len=this.RESOLUTION_PROPERTIES.length;i<len;i++){var p=this.RESOLUTION_PROPERTIES[i];props[p]=this.options[p];if(alwaysInRange&&this.options[p]){alwaysInRange=false;}}
60355 if(this.alwaysInRange==null){this.alwaysInRange=alwaysInRange;}
60356 if(props.resolutions==null){props.resolutions=this.resolutionsFromScales(props.scales);}
60357 if(props.resolutions==null){props.resolutions=this.calculateResolutions(props);}
60358 if(props.resolutions==null){for(i=0,len=this.RESOLUTION_PROPERTIES.length;i<len;i++){var p=this.RESOLUTION_PROPERTIES[i];props[p]=this.options[p]!=null?this.options[p]:this.map[p];}
60359 if(props.resolutions==null){props.resolutions=this.resolutionsFromScales(props.scales);}
60360 if(props.resolutions==null){props.resolutions=this.calculateResolutions(props);}}
60361 var maxResolution;if(this.options.maxResolution&&this.options.maxResolution!=="auto"){maxResolution=this.options.maxResolution;}
60362 if(this.options.minScale){maxResolution=OpenLayers.Util.getResolutionFromScale(this.options.minScale,this.units);}
60363 var minResolution;if(this.options.minResolution&&this.options.minResolution!=="auto"){minResolution=this.options.minResolution;}
60364 if(this.options.maxScale){minResolution=OpenLayers.Util.getResolutionFromScale(this.options.maxScale,this.units);}
60365 if(props.resolutions){props.resolutions.sort(function(a,b){return(b-a);});if(!maxResolution){maxResolution=props.resolutions[0];}
60366 if(!minResolution){var lastIdx=props.resolutions.length-1;minResolution=props.resolutions[lastIdx];}}
60367 this.resolutions=props.resolutions;if(this.resolutions){len=this.resolutions.length;this.scales=new Array(len);for(i=0;i<len;i++){this.scales[i]=OpenLayers.Util.getScaleFromResolution(this.resolutions[i],this.units);}
60368 this.numZoomLevels=len;}
60369 this.minResolution=minResolution;if(minResolution){this.maxScale=OpenLayers.Util.getScaleFromResolution(minResolution,this.units);}
60370 this.maxResolution=maxResolution;if(maxResolution){this.minScale=OpenLayers.Util.getScaleFromResolution(maxResolution,this.units);}},resolutionsFromScales:function(scales){if(scales==null){return;}
60371 var resolutions,i,len;len=scales.length;resolutions=new Array(len);for(i=0;i<len;i++){resolutions[i]=OpenLayers.Util.getResolutionFromScale(scales[i],this.units);}
60372 return resolutions;},calculateResolutions:function(props){var maxResolution=props.maxResolution;if(props.minScale!=null){maxResolution=OpenLayers.Util.getResolutionFromScale(props.minScale,this.units);}else if(maxResolution=="auto"&&this.maxExtent!=null){var viewSize=this.map.getSize();var wRes=this.maxExtent.getWidth()/viewSize.w;var hRes=this.maxExtent.getHeight()/viewSize.h;maxResolution=Math.max(wRes,hRes);}
60373 var minResolution=props.minResolution;if(props.maxScale!=null){minResolution=OpenLayers.Util.getResolutionFromScale(props.maxScale,this.units);}else if(props.minResolution=="auto"&&this.minExtent!=null){var viewSize=this.map.getSize();var wRes=this.minExtent.getWidth()/viewSize.w;var hRes=this.minExtent.getHeight()/viewSize.h;minResolution=Math.max(wRes,hRes);}
60374 var maxZoomLevel=props.maxZoomLevel;var numZoomLevels=props.numZoomLevels;if(typeof minResolution==="number"&&typeof maxResolution==="number"&&numZoomLevels===undefined){var ratio=maxResolution/minResolution;numZoomLevels=Math.floor(Math.log(ratio)/Math.log(2))+1;}else if(numZoomLevels===undefined&&maxZoomLevel!=null){numZoomLevels=maxZoomLevel+1;}
60375 if(typeof numZoomLevels!=="number"||numZoomLevels<=0||(typeof maxResolution!=="number"&&typeof minResolution!=="number")){return;}
60376 var resolutions=new Array(numZoomLevels);var base=2;if(typeof minResolution=="number"&&typeof maxResolution=="number"){base=Math.pow((maxResolution/minResolution),(1/(numZoomLevels-1)));}
60377 var i;if(typeof maxResolution==="number"){for(i=0;i<numZoomLevels;i++){resolutions[i]=maxResolution/Math.pow(base,i);}}else{for(i=0;i<numZoomLevels;i++){resolutions[numZoomLevels-1-i]=minResolution*Math.pow(base,i);}}
60378 return resolutions;},getResolution:function(){var zoom=this.map.getZoom();return this.getResolutionForZoom(zoom);},getExtent:function(){return this.map.calculateBounds();},getZoomForExtent:function(extent,closest){var viewSize=this.map.getSize();var idealResolution=Math.max(extent.getWidth()/viewSize.w,extent.getHeight()/viewSize.h);return this.getZoomForResolution(idealResolution,closest);},getDataExtent:function(){},getResolutionForZoom:function(zoom){zoom=Math.max(0,Math.min(zoom,this.resolutions.length-1));var resolution;if(this.map.fractionalZoom){var low=Math.floor(zoom);var high=Math.ceil(zoom);resolution=this.resolutions[low]-
60379 ((zoom-low)*(this.resolutions[low]-this.resolutions[high]));}else{resolution=this.resolutions[Math.round(zoom)];}
60380 return resolution;},getZoomForResolution:function(resolution,closest){var zoom;if(this.map.fractionalZoom){var lowZoom=0;var highZoom=this.resolutions.length-1;var highRes=this.resolutions[lowZoom];var lowRes=this.resolutions[highZoom];var res;for(var i=0,len=this.resolutions.length;i<len;++i){res=this.resolutions[i];if(res>=resolution){highRes=res;lowZoom=i;}
60381 if(res<=resolution){lowRes=res;highZoom=i;break;}}
60382 var dRes=highRes-lowRes;if(dRes>0){zoom=lowZoom+((highRes-resolution)/dRes);}else{zoom=lowZoom;}}else{var diff;var minDiff=Number.POSITIVE_INFINITY;for(var i=0,len=this.resolutions.length;i<len;i++){if(closest){diff=Math.abs(this.resolutions[i]-resolution);if(diff>minDiff){break;}
60383 minDiff=diff;}else{if(this.resolutions[i]<resolution){break;}}}
60384 zoom=Math.max(0,i-1);}
60385 return zoom;},getLonLatFromViewPortPx:function(viewPortPx){var lonlat=null;if(viewPortPx!=null){var size=this.map.getSize();var center=this.map.getCenter();if(center){var res=this.map.getResolution();var delta_x=viewPortPx.x-(size.w/2);var delta_y=viewPortPx.y-(size.h/2);lonlat=new OpenLayers.LonLat(center.lon+delta_x*res,center.lat-delta_y*res);if(this.wrapDateLine){lonlat=lonlat.wrapDateLine(this.maxExtent);}}}
60386 return lonlat;},getViewPortPxFromLonLat:function(lonlat){var px=null;if(lonlat!=null){var resolution=this.map.getResolution();var extent=this.map.getExtent();px=new OpenLayers.Pixel((1/resolution*(lonlat.lon-extent.left)),(1/resolution*(extent.top-lonlat.lat)));}
60387 return px;},setOpacity:function(opacity){if(opacity!=this.opacity){this.opacity=opacity;for(var i=0,len=this.div.childNodes.length;i<len;++i){var element=this.div.childNodes[i].firstChild;OpenLayers.Util.modifyDOMElement(element,null,null,null,null,null,null,opacity);}
60388 if(this.map!=null){this.map.events.triggerEvent("changelayer",{layer:this,property:"opacity"});}}},getZIndex:function(){return this.div.style.zIndex;},setZIndex:function(zIndex){this.div.style.zIndex=zIndex;},adjustBounds:function(bounds){if(this.gutter){var mapGutter=this.gutter*this.map.getResolution();bounds=new OpenLayers.Bounds(bounds.left-mapGutter,bounds.bottom-mapGutter,bounds.right+mapGutter,bounds.top+mapGutter);}
60389 if(this.wrapDateLine){var wrappingOptions={'rightTolerance':this.getResolution()};bounds=bounds.wrapDateLine(this.maxExtent,wrappingOptions);}
60390 return bounds;},CLASS_NAME:"OpenLayers.Layer"});OpenLayers.Marker.Box=OpenLayers.Class(OpenLayers.Marker,{bounds:null,div:null,initialize:function(bounds,borderColor,borderWidth){this.bounds=bounds;this.div=OpenLayers.Util.createDiv();this.div.style.overflow='hidden';this.events=new OpenLayers.Events(this,this.div,null);this.setBorder(borderColor,borderWidth);},destroy:function(){this.bounds=null;this.div=null;OpenLayers.Marker.prototype.destroy.apply(this,arguments);},setBorder:function(color,width){if(!color){color="red";}
60391 if(!width){width=2;}
60392 this.div.style.border=width+"px solid "+color;},draw:function(px,sz){OpenLayers.Util.modifyDOMElement(this.div,null,px,sz);return this.div;},onScreen:function(){var onScreen=false;if(this.map){var screenBounds=this.map.getExtent();onScreen=screenBounds.containsBounds(this.bounds,true,true);}
60393 return onScreen;},display:function(display){this.div.style.display=(display)?"":"none";},CLASS_NAME:"OpenLayers.Marker.Box"});(function(){var oXMLHttpRequest=window.XMLHttpRequest;var bGecko=!!window.controllers,bIE=window.document.all&&!window.opera,bIE7=bIE&&window.navigator.userAgent.match(/MSIE ([\.0-9]+)/)&&RegExp.$1==7;function cXMLHttpRequest(){this._object=oXMLHttpRequest&&!bIE7?new oXMLHttpRequest:new window.ActiveXObject("Microsoft.XMLHTTP");this._listeners=[];};if(bGecko&&oXMLHttpRequest.wrapped)
60394 cXMLHttpRequest.wrapped=oXMLHttpRequest.wrapped;cXMLHttpRequest.UNSENT=0;cXMLHttpRequest.OPENED=1;cXMLHttpRequest.HEADERS_RECEIVED=2;cXMLHttpRequest.LOADING=3;cXMLHttpRequest.DONE=4;cXMLHttpRequest.prototype.readyState=cXMLHttpRequest.UNSENT;cXMLHttpRequest.prototype.responseText='';cXMLHttpRequest.prototype.responseXML=null;cXMLHttpRequest.prototype.status=0;cXMLHttpRequest.prototype.statusText='';cXMLHttpRequest.prototype.onreadystatechange=null;cXMLHttpRequest.onreadystatechange=null;cXMLHttpRequest.onopen=null;cXMLHttpRequest.onsend=null;cXMLHttpRequest.onabort=null;cXMLHttpRequest.prototype.open=function(sMethod,sUrl,bAsync,sUser,sPassword){delete this._headers;if(arguments.length<3)
60395 bAsync=true;this._async=bAsync;var oRequest=this,nState=this.readyState,fOnUnload;if(bIE&&bAsync){fOnUnload=function(){if(nState!=cXMLHttpRequest.DONE){fCleanTransport(oRequest);oRequest.abort();}};window.attachEvent("onunload",fOnUnload);}
60396 if(cXMLHttpRequest.onopen)
60397 cXMLHttpRequest.onopen.apply(this,arguments);if(arguments.length>4)
60398 this._object.open(sMethod,sUrl,bAsync,sUser,sPassword);else
60399 if(arguments.length>3)
60400 this._object.open(sMethod,sUrl,bAsync,sUser);else
60401 this._object.open(sMethod,sUrl,bAsync);if(!bGecko&&!bIE){this.readyState=cXMLHttpRequest.OPENED;fReadyStateChange(this);}
60402 this._object.onreadystatechange=function(){if(bGecko&&!bAsync)
60403 return;oRequest.readyState=oRequest._object.readyState;fSynchronizeValues(oRequest);if(oRequest._aborted){oRequest.readyState=cXMLHttpRequest.UNSENT;return;}
60404 if(oRequest.readyState==cXMLHttpRequest.DONE){fCleanTransport(oRequest);if(bIE&&bAsync)
60405 window.detachEvent("onunload",fOnUnload);}
60406 if(nState!=oRequest.readyState)
60407 fReadyStateChange(oRequest);nState=oRequest.readyState;}};cXMLHttpRequest.prototype.send=function(vData){if(cXMLHttpRequest.onsend)
60408 cXMLHttpRequest.onsend.apply(this,arguments);if(vData&&vData.nodeType){vData=window.XMLSerializer?new window.XMLSerializer().serializeToString(vData):vData.xml;if(!this._headers["Content-Type"])
60409 this._object.setRequestHeader("Content-Type","application/xml");}
60410 this._object.send(vData);if(bGecko&&!this._async){this.readyState=cXMLHttpRequest.OPENED;fSynchronizeValues(this);while(this.readyState<cXMLHttpRequest.DONE){this.readyState++;fReadyStateChange(this);if(this._aborted)
60411 return;}}};cXMLHttpRequest.prototype.abort=function(){if(cXMLHttpRequest.onabort)
60412 cXMLHttpRequest.onabort.apply(this,arguments);if(this.readyState>cXMLHttpRequest.UNSENT)
60413 this._aborted=true;this._object.abort();fCleanTransport(this);};cXMLHttpRequest.prototype.getAllResponseHeaders=function(){return this._object.getAllResponseHeaders();};cXMLHttpRequest.prototype.getResponseHeader=function(sName){return this._object.getResponseHeader(sName);};cXMLHttpRequest.prototype.setRequestHeader=function(sName,sValue){if(!this._headers)
60414 this._headers={};this._headers[sName]=sValue;return this._object.setRequestHeader(sName,sValue);};cXMLHttpRequest.prototype.addEventListener=function(sName,fHandler,bUseCapture){for(var nIndex=0,oListener;oListener=this._listeners[nIndex];nIndex++)
60415 if(oListener[0]==sName&&oListener[1]==fHandler&&oListener[2]==bUseCapture)
60416 return;this._listeners.push([sName,fHandler,bUseCapture]);};cXMLHttpRequest.prototype.removeEventListener=function(sName,fHandler,bUseCapture){for(var nIndex=0,oListener;oListener=this._listeners[nIndex];nIndex++)
60417 if(oListener[0]==sName&&oListener[1]==fHandler&&oListener[2]==bUseCapture)
60418 break;if(oListener)
60419 this._listeners.splice(nIndex,1);};cXMLHttpRequest.prototype.dispatchEvent=function(oEvent){var oEventPseudo={'type':oEvent.type,'target':this,'currentTarget':this,'eventPhase':2,'bubbles':oEvent.bubbles,'cancelable':oEvent.cancelable,'timeStamp':oEvent.timeStamp,'stopPropagation':function(){},'preventDefault':function(){},'initEvent':function(){}};if(oEventPseudo.type=="readystatechange"&&this.onreadystatechange)
60420 (this.onreadystatechange.handleEvent||this.onreadystatechange).apply(this,[oEventPseudo]);for(var nIndex=0,oListener;oListener=this._listeners[nIndex];nIndex++)
60421 if(oListener[0]==oEventPseudo.type&&!oListener[2])
60422 (oListener[1].handleEvent||oListener[1]).apply(this,[oEventPseudo]);};cXMLHttpRequest.prototype.toString=function(){return'['+"object"+' '+"XMLHttpRequest"+']';};cXMLHttpRequest.toString=function(){return'['+"XMLHttpRequest"+']';};function fReadyStateChange(oRequest){if(cXMLHttpRequest.onreadystatechange)
60423 cXMLHttpRequest.onreadystatechange.apply(oRequest);oRequest.dispatchEvent({'type':"readystatechange",'bubbles':false,'cancelable':false,'timeStamp':new Date+0});};function fGetDocument(oRequest){var oDocument=oRequest.responseXML,sResponse=oRequest.responseText;if(bIE&&sResponse&&oDocument&&!oDocument.documentElement&&oRequest.getResponseHeader("Content-Type").match(/[^\/]+\/[^\+]+\+xml/)){oDocument=new window.ActiveXObject("Microsoft.XMLDOM");oDocument.async=false;oDocument.validateOnParse=false;oDocument.loadXML(sResponse);}
60424 if(oDocument)
60425 if((bIE&&oDocument.parseError!=0)||!oDocument.documentElement||(oDocument.documentElement&&oDocument.documentElement.tagName=="parsererror"))
60426 return null;return oDocument;};function fSynchronizeValues(oRequest){try{oRequest.responseText=oRequest._object.responseText;}catch(e){}
60427 try{oRequest.responseXML=fGetDocument(oRequest._object);}catch(e){}
60428 try{oRequest.status=oRequest._object.status;}catch(e){}
60429 try{oRequest.statusText=oRequest._object.statusText;}catch(e){}};function fCleanTransport(oRequest){oRequest._object.onreadystatechange=new window.Function;};if(!window.Function.prototype.apply){window.Function.prototype.apply=function(oRequest,oArguments){if(!oArguments)
60430 oArguments=[];oRequest.__func=this;oRequest.__func(oArguments[0],oArguments[1],oArguments[2],oArguments[3],oArguments[4]);delete oRequest.__func;};};OpenLayers.Request.XMLHttpRequest=cXMLHttpRequest;})();OpenLayers.Tile.Image.IFrame=OpenLayers.Class(OpenLayers.Tile.Image,{initialize:function(layer,position,bounds,url,size){OpenLayers.Tile.Image.prototype.initialize.apply(this,arguments);this.layerAlphaHack=false;},destroy:function(){if(this.imgDiv!=null){OpenLayers.Event.stopObservingElement(this.imgDiv.firstChild);}
60431 OpenLayers.Tile.Image.prototype.destroy.apply(this,arguments);},clear:function(){if(this.imgDiv){var iFrame=this.imgDiv.firstChild;OpenLayers.Event.stopObservingElement(iFrame);this.imgDiv.removeChild(iFrame);}},clone:function(obj){if(obj==null){obj=new OpenLayers.Tile.Image.IFrame(this.layer,this.position,this.bounds,this.url,this.size);}
60432 obj=OpenLayers.Tile.Image.prototype.clone.apply(this,[obj]);return obj;},renderTile:function(){if(OpenLayers.Tile.Image.prototype.renderTile.apply(this,arguments)){var form=this.createRequestForm();this.imgDiv.appendChild(form);form.submit();this.imgDiv.removeChild(form);}},initImgDiv:function(){this.imgDiv=this.createImgDiv();OpenLayers.Util.modifyDOMElement(this.imgDiv,this.id,null,this.layer.getImageSize(),"relative");this.imgDiv.className='olTileImage';this.frame.appendChild(this.imgDiv);this.layer.div.appendChild(this.frame);if(this.layer.opacity!=null){OpenLayers.Util.modifyDOMElement(this.imgDiv,null,null,null,null,null,null,this.layer.opacity);}
60433 this.imgDiv.map=this.layer.map;},createImgDiv:function(){var eventPane=document.createElement("div");if(OpenLayers.Util.getBrowserName()=="msie"){eventPane.style.backgroundColor='#FFFFFF';eventPane.style.filter='chroma(color=#FFFFFF)';}
60434 OpenLayers.Util.modifyDOMElement(eventPane,null,new OpenLayers.Pixel(0,0),this.layer.getImageSize(),"absolute");var imgDiv=document.createElement("div");imgDiv.appendChild(eventPane);return imgDiv;},createIFrame:function(){var id=this.id+'_iFrame';var iframe;if(OpenLayers.Util.getBrowserName()=="msie"){iframe=document.createElement('<iframe name="'+id+'">');iframe.style.backgroundColor='#FFFFFF';iframe.style.filter='chroma(color=#FFFFFF)';}
60435 else{iframe=document.createElement('iframe');iframe.style.backgroundColor='transparent';iframe.name=id;}
60436 iframe.id=id;iframe.scrolling='no';iframe.marginWidth='0px';iframe.marginHeight='0px';iframe.frameBorder='0';OpenLayers.Util.modifyDOMElement(iframe,id,new OpenLayers.Pixel(0,0),this.layer.getImageSize(),"absolute");var onload=function(){this.show();if(this.isLoading){this.isLoading=false;this.events.triggerEvent("loadend");}};OpenLayers.Event.observe(iframe,'load',OpenLayers.Function.bind(onload,this));return iframe;},createRequestForm:function(){var form=document.createElement('form');form.method='POST';var cacheId=this.layer.params["_OLSALT"];cacheId=(cacheId?cacheId+"_":"")+this.bounds.toBBOX();form.action=OpenLayers.Util.urlAppend(this.layer.url,cacheId);this.imgDiv.insertBefore(this.createIFrame(),this.imgDiv.firstChild);form.target=this.id+'_iFrame';var imageSize=this.layer.getImageSize();var params=OpenLayers.Util.extend({"BBOX":this.encodeBBOX?this.bounds.toBBOX():this.bounds.toArray(),"WIDTH":imageSize.w,"HEIGHT":imageSize.h},this.layer.params);for(var par in params){var field=document.createElement('input');field.type='hidden';field.name=par;field.value=params[par];form.appendChild(field);}
60437 return form;},CLASS_NAME:"OpenLayers.Tile.Image.IFrame"});OpenLayers.ProxyHost="";OpenLayers.nullHandler=function(request){OpenLayers.Console.userError(OpenLayers.i18n("unhandledRequest",{'statusText':request.statusText}));};OpenLayers.loadURL=function(uri,params,caller,onComplete,onFailure){if(typeof params=='string'){params=OpenLayers.Util.getParameters(params);}
60438 var success=(onComplete)?onComplete:OpenLayers.nullHandler;var failure=(onFailure)?onFailure:OpenLayers.nullHandler;return OpenLayers.Request.GET({url:uri,params:params,success:success,failure:failure,scope:caller});};OpenLayers.parseXMLString=function(text){var index=text.indexOf('<');if(index>0){text=text.substring(index);}
60439 var ajaxResponse=OpenLayers.Util.Try(function(){var xmldom=new ActiveXObject('Microsoft.XMLDOM');xmldom.loadXML(text);return xmldom;},function(){return new DOMParser().parseFromString(text,'text/xml');},function(){var req=new XMLHttpRequest();req.open("GET","data:"+"text/xml"+";charset=utf-8,"+encodeURIComponent(text),false);if(req.overrideMimeType){req.overrideMimeType("text/xml");}
60440 req.send(null);return req.responseXML;});return ajaxResponse;};OpenLayers.Ajax={emptyFunction:function(){},getTransport:function(){return OpenLayers.Util.Try(function(){return new XMLHttpRequest();},function(){return new ActiveXObject('Msxml2.XMLHTTP');},function(){return new ActiveXObject('Microsoft.XMLHTTP');})||false;},activeRequestCount:0};OpenLayers.Ajax.Responders={responders:[],register:function(responderToAdd){for(var i=0;i<this.responders.length;i++){if(responderToAdd==this.responders[i]){return;}}
60441 this.responders.push(responderToAdd);},unregister:function(responderToRemove){OpenLayers.Util.removeItem(this.reponders,responderToRemove);},dispatch:function(callback,request,transport){var responder;for(var i=0;i<this.responders.length;i++){responder=this.responders[i];if(responder[callback]&&typeof responder[callback]=='function'){try{responder[callback].apply(responder,[request,transport]);}catch(e){}}}}};OpenLayers.Ajax.Responders.register({onCreate:function(){OpenLayers.Ajax.activeRequestCount++;},onComplete:function(){OpenLayers.Ajax.activeRequestCount--;}});OpenLayers.Ajax.Base=OpenLayers.Class({initialize:function(options){this.options={method:'post',asynchronous:true,contentType:'application/xml',parameters:''};OpenLayers.Util.extend(this.options,options||{});this.options.method=this.options.method.toLowerCase();if(typeof this.options.parameters=='string'){this.options.parameters=OpenLayers.Util.getParameters(this.options.parameters);}}});OpenLayers.Ajax.Request=OpenLayers.Class(OpenLayers.Ajax.Base,{_complete:false,initialize:function(url,options){OpenLayers.Ajax.Base.prototype.initialize.apply(this,[options]);if(OpenLayers.ProxyHost&&OpenLayers.String.startsWith(url,"http")){url=OpenLayers.ProxyHost+encodeURIComponent(url);}
60442 this.transport=OpenLayers.Ajax.getTransport();this.request(url);},request:function(url){this.url=url;this.method=this.options.method;var params=OpenLayers.Util.extend({},this.options.parameters);if(this.method!='get'&&this.method!='post'){params['_method']=this.method;this.method='post';}
60443 this.parameters=params;if(params=OpenLayers.Util.getParameterString(params)){if(this.method=='get'){this.url+=((this.url.indexOf('?')>-1)?'&':'?')+params;}else if(/Konqueror|Safari|KHTML/.test(navigator.userAgent)){params+='&_=';}}
60444 try{var response=new OpenLayers.Ajax.Response(this);if(this.options.onCreate){this.options.onCreate(response);}
60445 OpenLayers.Ajax.Responders.dispatch('onCreate',this,response);this.transport.open(this.method.toUpperCase(),this.url,this.options.asynchronous);if(this.options.asynchronous){window.setTimeout(OpenLayers.Function.bind(this.respondToReadyState,this,1),10);}
60446 this.transport.onreadystatechange=OpenLayers.Function.bind(this.onStateChange,this);this.setRequestHeaders();this.body=this.method=='post'?(this.options.postBody||params):null;this.transport.send(this.body);if(!this.options.asynchronous&&this.transport.overrideMimeType){this.onStateChange();}}catch(e){this.dispatchException(e);}},onStateChange:function(){var readyState=this.transport.readyState;if(readyState>1&&!((readyState==4)&&this._complete)){this.respondToReadyState(this.transport.readyState);}},setRequestHeaders:function(){var headers={'X-Requested-With':'XMLHttpRequest','Accept':'text/javascript, text/html, application/xml, text/xml, */*','OpenLayers':true};if(this.method=='post'){headers['Content-type']=this.options.contentType+
60447 (this.options.encoding?'; charset='+this.options.encoding:'');if(this.transport.overrideMimeType&&(navigator.userAgent.match(/Gecko\/(\d{4})/)||[0,2005])[1]<2005){headers['Connection']='close';}}
60448 if(typeof this.options.requestHeaders=='object'){var extras=this.options.requestHeaders;if(typeof extras.push=='function'){for(var i=0,length=extras.length;i<length;i+=2){headers[extras[i]]=extras[i+1];}}else{for(var i in extras){headers[i]=extras[i];}}}
60449 for(var name in headers){this.transport.setRequestHeader(name,headers[name]);}},success:function(){var status=this.getStatus();return!status||(status>=200&&status<300);},getStatus:function(){try{return this.transport.status||0;}catch(e){return 0;}},respondToReadyState:function(readyState){var state=OpenLayers.Ajax.Request.Events[readyState];var response=new OpenLayers.Ajax.Response(this);if(state=='Complete'){try{this._complete=true;(this.options['on'+response.status]||this.options['on'+(this.success()?'Success':'Failure')]||OpenLayers.Ajax.emptyFunction)(response);}catch(e){this.dispatchException(e);}
60450 var contentType=response.getHeader('Content-type');}
60451 try{(this.options['on'+state]||OpenLayers.Ajax.emptyFunction)(response);OpenLayers.Ajax.Responders.dispatch('on'+state,this,response);}catch(e){this.dispatchException(e);}
60452 if(state=='Complete'){this.transport.onreadystatechange=OpenLayers.Ajax.emptyFunction;}},getHeader:function(name){try{return this.transport.getResponseHeader(name);}catch(e){return null;}},dispatchException:function(exception){var handler=this.options.onException;if(handler){handler(this,exception);OpenLayers.Ajax.Responders.dispatch('onException',this,exception);}else{var listener=false;var responders=OpenLayers.Ajax.Responders.responders;for(var i=0;i<responders.length;i++){if(responders[i].onException){listener=true;break;}}
60453 if(listener){OpenLayers.Ajax.Responders.dispatch('onException',this,exception);}else{throw exception;}}}});OpenLayers.Ajax.Request.Events=['Uninitialized','Loading','Loaded','Interactive','Complete'];OpenLayers.Ajax.Response=OpenLayers.Class({status:0,statusText:'',initialize:function(request){this.request=request;var transport=this.transport=request.transport,readyState=this.readyState=transport.readyState;if((readyState>2&&!(!!(window.attachEvent&&!window.opera)))||readyState==4){this.status=this.getStatus();this.statusText=this.getStatusText();this.responseText=transport.responseText==null?'':String(transport.responseText);}
60454 if(readyState==4){var xml=transport.responseXML;this.responseXML=xml===undefined?null:xml;}},getStatus:OpenLayers.Ajax.Request.prototype.getStatus,getStatusText:function(){try{return this.transport.statusText||'';}catch(e){return'';}},getHeader:OpenLayers.Ajax.Request.prototype.getHeader,getResponseHeader:function(name){return this.transport.getResponseHeader(name);}});OpenLayers.Ajax.getElementsByTagNameNS=function(parentnode,nsuri,nsprefix,tagname){var elem=null;if(parentnode.getElementsByTagNameNS){elem=parentnode.getElementsByTagNameNS(nsuri,tagname);}else{elem=parentnode.getElementsByTagName(nsprefix+':'+tagname);}
60455 return elem;};OpenLayers.Ajax.serializeXMLToString=function(xmldom){var serializer=new XMLSerializer();var data=serializer.serializeToString(xmldom);return data;};OpenLayers.Control.DragFeature=OpenLayers.Class(OpenLayers.Control,{geometryTypes:null,onStart:function(feature,pixel){},onDrag:function(feature,pixel){},onComplete:function(feature,pixel){},documentDrag:false,layer:null,feature:null,dragCallbacks:{},featureCallbacks:{},lastPixel:null,initialize:function(layer,options){OpenLayers.Control.prototype.initialize.apply(this,[options]);this.layer=layer;this.handlers={drag:new OpenLayers.Handler.Drag(this,OpenLayers.Util.extend({down:this.downFeature,move:this.moveFeature,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({over:this.overFeature,out:this.outFeature},this.featureCallbacks),{geometryTypes:this.geometryTypes})};},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=false;this.lastPixel=null;OpenLayers.Element.removeClass(this.map.viewPortDiv,this.displayClass+"Over");return OpenLayers.Control.prototype.deactivate.apply(this,arguments);},overFeature:function(feature){if(!this.handlers.drag.dragging){this.feature=feature;this.handlers.drag.activate();this.over=true;OpenLayers.Element.addClass(this.map.viewPortDiv,this.displayClass+"Over");}else{if(this.feature.id==feature.id){this.over=true;}else{this.over=false;}}},downFeature:function(pixel){this.lastPixel=pixel;this.onStart(this.feature,pixel);},moveFeature:function(pixel){var res=this.map.getResolution();this.feature.geometry.move(res*(pixel.x-this.lastPixel.x),res*(this.lastPixel.y-pixel.y));this.layer.drawFeature(this.feature);this.lastPixel=pixel;this.onDrag(this.feature,pixel);},upFeature:function(pixel){if(!this.over){this.handlers.drag.deactivate();}},doneDragging:function(pixel){this.onComplete(this.feature,pixel);},outFeature:function(feature){if(!this.handlers.drag.dragging){this.over=false;this.handlers.drag.deactivate();OpenLayers.Element.removeClass(this.map.viewPortDiv,this.displayClass+"Over");this.feature=null;}else{if(this.feature.id==feature.id){this.over=false;}}},cancel:function(){this.handlers.drag.deactivate();this.over=false;},setMap:function(map){this.handlers.drag.setMap(map);this.handlers.feature.setMap(map);OpenLayers.Control.prototype.setMap.apply(this,arguments);},CLASS_NAME:"OpenLayers.Control.DragFeature"});OpenLayers.Control.DragPan=OpenLayers.Class(OpenLayers.Control,{type:OpenLayers.Control.TYPE_TOOL,panned:false,interval:25,documentDrag:false,draw:function(){this.handler=new OpenLayers.Handler.Drag(this,{"move":this.panMap,"done":this.panMapDone},{interval:this.interval,documentDrag:this.documentDrag});},panMap:function(xy){this.panned=true;this.map.pan(this.handler.last.x-xy.x,this.handler.last.y-xy.y,{dragging:this.handler.dragging,animate:false});},panMapDone:function(xy){if(this.panned){this.panMap(xy);this.panned=false;}},CLASS_NAME:"OpenLayers.Control.DragPan"});OpenLayers.Control.KeyboardDefaults=OpenLayers.Class(OpenLayers.Control,{autoActivate:true,slideFactor:75,initialize:function(){OpenLayers.Control.prototype.initialize.apply(this,arguments);},destroy:function(){if(this.handler){this.handler.destroy();}
60456 this.handler=null;OpenLayers.Control.prototype.destroy.apply(this,arguments);},draw:function(){this.handler=new OpenLayers.Handler.Keyboard(this,{"keydown":this.defaultKeyPress});},defaultKeyPress:function(evt){switch(evt.keyCode){case OpenLayers.Event.KEY_LEFT:this.map.pan(-this.slideFactor,0);break;case OpenLayers.Event.KEY_RIGHT:this.map.pan(this.slideFactor,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:var size=this.map.getSize();this.map.pan(0,-0.75*size.h);break;case 34:var size=this.map.getSize();this.map.pan(0,0.75*size.h);break;case 35:var size=this.map.getSize();this.map.pan(0.75*size.w,0);break;case 36:var size=this.map.getSize();this.map.pan(-0.75*size.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();break;}},CLASS_NAME:"OpenLayers.Control.KeyboardDefaults"});OpenLayers.Control.WMSGetFeatureInfo=OpenLayers.Class(OpenLayers.Control,{hover:false,drillDown:false,maxFeatures:10,clickCallback:"click",layers:null,queryVisible:false,url:null,layerUrls:null,infoFormat:'text/html',vendorParams:{},format:null,formatOptions:null,handlerOptions:null,handler:null,hoverRequest:null,EVENT_TYPES:["beforegetfeatureinfo","nogetfeatureinfo","getfeatureinfo"],initialize:function(options){this.EVENT_TYPES=OpenLayers.Control.WMSGetFeatureInfo.prototype.EVENT_TYPES.concat(OpenLayers.Control.prototype.EVENT_TYPES);options=options||{};options.handlerOptions=options.handlerOptions||{};OpenLayers.Control.prototype.initialize.apply(this,[options]);if(!this.format){this.format=new OpenLayers.Format.WMSGetFeatureInfo(options.formatOptions);}
60457 if(this.drillDown===true){this.hover=false;}
60458 if(this.hover){this.handler=new OpenLayers.Handler.Hover(this,{'move':this.cancelHover,'pause':this.getInfoForHover},OpenLayers.Util.extend(this.handlerOptions.hover||{},{'delay':250}));}else{var callbacks={};callbacks[this.clickCallback]=this.getInfoForClick;this.handler=new OpenLayers.Handler.Click(this,callbacks,this.handlerOptions.click||{});}},activate:function(){if(!this.active){this.handler.activate();}
60459 return OpenLayers.Control.prototype.activate.apply(this,arguments);},deactivate:function(){return OpenLayers.Control.prototype.deactivate.apply(this,arguments);},getInfoForClick:function(evt){this.events.triggerEvent("beforegetfeatureinfo",{xy:evt.xy});OpenLayers.Element.addClass(this.map.viewPortDiv,"olCursorWait");this.request(evt.xy,{});},getInfoForHover:function(evt){this.events.triggerEvent("beforegetfeatureinfo",{xy:evt.xy});this.request(evt.xy,{hover:true});},cancelHover:function(){if(this.hoverRequest){this.hoverRequest.abort();this.hoverRequest=null;}},findLayers:function(){var candidates=this.layers||this.map.layers;var layers=[];var layer,url;for(var i=0,len=candidates.length;i<len;++i){layer=candidates[i];if(layer instanceof OpenLayers.Layer.WMS&&(!this.queryVisible||layer.getVisibility())){url=layer.url instanceof Array?layer.url[0]:layer.url;if(this.drillDown===false&&!this.url){this.url=url;}
60460 if(this.drillDown===true||this.urlMatches(url)){layers.push(layer);}}}
60461 return layers;},urlMatches:function(url){var matches=OpenLayers.Util.isEquivalentUrl(this.url,url);if(!matches&&this.layerUrls){for(var i=0,len=this.layerUrls.length;i<len;++i){if(OpenLayers.Util.isEquivalentUrl(this.layerUrls[i],url)){matches=true;break;}}}
60462 return matches;},buildWMSOptions:function(url,layers,clickPosition,format){var layerNames=[],styleNames=[];for(var i=0,len=layers.length;i<len;i++){layerNames=layerNames.concat(layers[i].params.LAYERS);styleNames=styleNames.concat(this.getStyleNames(layers[i]));}
60463 var params=OpenLayers.Util.extend({service:"WMS",version:layers[0].params.VERSION,request:"GetFeatureInfo",layers:layerNames,query_layers:layerNames,styles:styleNames,bbox:this.map.getExtent().toBBOX(null,layers[0].reverseAxisOrder()),feature_count:this.maxFeatures,height:this.map.getSize().h,width:this.map.getSize().w,format:format,info_format:this.infoFormat},(parseFloat(layers[0].params.VERSION)>=1.3)?{crs:this.map.getProjection(),i:clickPosition.x,j:clickPosition.y}:{srs:this.map.getProjection(),x:clickPosition.x,y:clickPosition.y});OpenLayers.Util.applyDefaults(params,this.vendorParams);return{url:url,params:OpenLayers.Util.upperCaseObject(params),callback:function(request){this.handleResponse(clickPosition,request);},scope:this};},getStyleNames:function(layer){var styleNames;if(layer.params.STYLES){styleNames=layer.params.STYLES;}else{if(layer.params.LAYERS instanceof Array){styleNames=new Array(layer.params.LAYERS.length);}else{styleNames=layer.params.LAYERS.replace(/[^,]/g,"");}}
60464 return styleNames;},request:function(clickPosition,options){var layers=this.findLayers();if(layers.length==0){this.events.triggerEvent("nogetfeatureinfo");OpenLayers.Element.removeClass(this.map.viewPortDiv,"olCursorWait");return;}
60465 options=options||{};if(this.drillDown===false){var wmsOptions=this.buildWMSOptions(this.url,layers,clickPosition,layers[0].params.FORMAT);var request=OpenLayers.Request.GET(wmsOptions);if(options.hover===true){this.hoverRequest=request;}}else{this._requestCount=0;this._numRequests=0;this.features=[];var services={},url;for(var i=0,len=layers.length;i<len;i++){var layer=layers[i];var service,found=false;url=layer.url instanceof Array?layer.url[0]:layer.url;if(url in services){services[url].push(layer);}else{this._numRequests++;services[url]=[layer];}}
60466 var layers;for(var url in services){layers=services[url];var wmsOptions=this.buildWMSOptions(url,layers,clickPosition,layers[0].params.FORMAT);OpenLayers.Request.GET(wmsOptions);}}},triggerGetFeatureInfo:function(request,xy,features){this.events.triggerEvent("getfeatureinfo",{text:request.responseText,features:features,request:request,xy:xy});OpenLayers.Element.removeClass(this.map.viewPortDiv,"olCursorWait");},handleResponse:function(xy,request){var doc=request.responseXML;if(!doc||!doc.documentElement){doc=request.responseText;}
60467 var features=this.format.read(doc);if(this.drillDown===false){this.triggerGetFeatureInfo(request,xy,features);}else{this._requestCount++;this._features=(this._features||[]).concat(features);if(this._requestCount===this._numRequests){this.triggerGetFeatureInfo(request,xy,this._features.concat());delete this._features;delete this._requestCount;delete this._numRequests;}}},CLASS_NAME:"OpenLayers.Control.WMSGetFeatureInfo"});OpenLayers.Control.WMTSGetFeatureInfo=OpenLayers.Class(OpenLayers.Control,{hover:false,requestEncoding:"KVP",drillDown:false,maxFeatures:10,clickCallback:"click",layers:null,queryVisible:true,infoFormat:'text/html',vendorParams:{},format:null,formatOptions:null,handlerOptions:null,handler:null,hoverRequest:null,EVENT_TYPES:["beforegetfeatureinfo","getfeatureinfo","exception"],pending:0,initialize:function(options){this.EVENT_TYPES=OpenLayers.Control.WMTSGetFeatureInfo.prototype.EVENT_TYPES.concat(OpenLayers.Control.prototype.EVENT_TYPES);options=options||{};options.handlerOptions=options.handlerOptions||{};OpenLayers.Control.prototype.initialize.apply(this,[options]);if(!this.format){this.format=new OpenLayers.Format.WMSGetFeatureInfo(options.formatOptions);}
60468 if(this.drillDown===true){this.hover=false;}
60469 if(this.hover){this.handler=new OpenLayers.Handler.Hover(this,{move:this.cancelHover,pause:this.getInfoForHover},OpenLayers.Util.extend(this.handlerOptions.hover||{},{delay:250}));}else{var callbacks={};callbacks[this.clickCallback]=this.getInfoForClick;this.handler=new OpenLayers.Handler.Click(this,callbacks,this.handlerOptions.click||{});}},activate:function(){if(!this.active){this.handler.activate();}
60470 return OpenLayers.Control.prototype.activate.apply(this,arguments);},deactivate:function(){return OpenLayers.Control.prototype.deactivate.apply(this,arguments);},getInfoForClick:function(evt){this.request(evt.xy,{});},getInfoForHover:function(evt){this.request(evt.xy,{hover:true});},cancelHover:function(){if(this.hoverRequest){--this.pending;if(this.pending<=0){OpenLayers.Element.removeClass(this.map.viewPortDiv,"olCursorWait");this.pending=0;}
60471 this.hoverRequest.abort();this.hoverRequest=null;}},findLayers:function(){var candidates=this.layers||this.map.layers;var layers=[];var layer;for(var i=candidates.length-1;i>=0;--i){layer=candidates[i];if(layer instanceof OpenLayers.Layer.WMTS&&layer.requestEncoding===this.requestEncoding&&(!this.queryVisible||layer.getVisibility())){layers.push(layer);if(!this.drillDown||this.hover){break;}}}
60472 return layers;},buildRequestOptions:function(layer,xy){var loc=this.map.getLonLatFromPixel(xy);var getTileUrl=layer.getURL(new OpenLayers.Bounds(loc.lon,loc.lat,loc.lon,loc.lat));var params=OpenLayers.Util.getParameters(getTileUrl);var tileInfo=layer.getTileInfo(loc);OpenLayers.Util.extend(params,{service:"WMTS",version:layer.version,request:"GetFeatureInfo",infoFormat:this.infoFormat,i:tileInfo.i,j:tileInfo.j});OpenLayers.Util.applyDefaults(params,this.vendorParams);return{url:layer.url instanceof Array?layer.url[0]:layer.url,params:OpenLayers.Util.upperCaseObject(params),callback:function(request){this.handleResponse(xy,request,layer);},scope:this};},request:function(xy,options){options=options||{};var layers=this.findLayers();if(layers.length>0){var issue,layer;for(var i=0,len=layers.length;i<len;i++){layer=layers[i];issue=this.events.triggerEvent("beforegetfeatureinfo",{xy:xy,layer:layer});if(issue!==false){++this.pending;var requestOptions=this.buildRequestOptions(layer,xy);var request=OpenLayers.Request.GET(requestOptions);if(options.hover===true){this.hoverRequest=request;}}}
60473 if(this.pending>0){OpenLayers.Element.addClass(this.map.viewPortDiv,"olCursorWait");}}},handleResponse:function(xy,request,layer){--this.pending;if(this.pending<=0){OpenLayers.Element.removeClass(this.map.viewPortDiv,"olCursorWait");this.pending=0;}
60474 if(request.status&&(request.status<200||request.status>=300)){this.events.triggerEvent("exception",{xy:xy,request:request,layer:layer});}else{var doc=request.responseXML;if(!doc||!doc.documentElement){doc=request.responseText;}
60475 var features,except;try{features=this.format.read(doc);}catch(error){except=true;this.events.triggerEvent("exception",{xy:xy,request:request,error:error,layer:layer});}
60476 if(!except){this.events.triggerEvent("getfeatureinfo",{text:request.responseText,features:features,request:request,xy:xy,layer:layer});}}},setMap:function(map){this.handler.setMap(map);OpenLayers.Control.prototype.setMap.apply(this,arguments);},CLASS_NAME:"OpenLayers.Control.WMTSGetFeatureInfo"});OpenLayers.State={UNKNOWN:'Unknown',INSERT:'Insert',UPDATE:'Update',DELETE:'Delete'};OpenLayers.Feature.Vector=OpenLayers.Class(OpenLayers.Feature,{fid:null,geometry:null,attributes:null,bounds:null,state:null,style:null,url:null,renderIntent:"default",initialize:function(geometry,attributes,style){OpenLayers.Feature.prototype.initialize.apply(this,[null,null,attributes]);this.lonlat=null;this.geometry=geometry?geometry:null;this.state=null;this.attributes={};if(attributes){this.attributes=OpenLayers.Util.extend(this.attributes,attributes);}
60477 this.style=style?style:null;},destroy:function(){if(this.layer){this.layer.removeFeatures(this);this.layer=null;}
60478 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(boundsOnly){var onScreen=false;if(this.layer&&this.layer.map){var screenBounds=this.layer.map.getExtent();if(boundsOnly){var featureBounds=this.geometry.getBounds();onScreen=screenBounds.intersectsBounds(featureBounds);}else{var screenPoly=screenBounds.toGeometry();onScreen=screenPoly.intersects(this.geometry);}}
60479 return onScreen;},getVisibility:function(){return!(this.style&&this.style.display=='none'||!this.layer||this.layer&&this.layer.styleMap&&this.layer.styleMap.createSymbolizer(this,this.renderIntent).display=='none'||this.layer&&!this.layer.getVisibility());},createMarker:function(){return null;},destroyMarker:function(){},createPopup:function(){return null;},atPoint:function(lonlat,toleranceLon,toleranceLat){var atPoint=false;if(this.geometry){atPoint=this.geometry.atPoint(lonlat,toleranceLon,toleranceLat);}
60480 return atPoint;},destroyPopup:function(){},move:function(location){if(!this.layer||!this.geometry.move){return;}
60481 var pixel;if(location.CLASS_NAME=="OpenLayers.LonLat"){pixel=this.layer.getViewPortPxFromLonLat(location);}else{pixel=location;}
60482 var lastPixel=this.layer.getViewPortPxFromLonLat(this.geometry.getBounds().getCenterLonLat());var res=this.layer.map.getResolution();this.geometry.move(res*(pixel.x-lastPixel.x),res*(lastPixel.y-pixel.y));this.layer.drawFeature(this);return lastPixel;},toState:function(state){if(state==OpenLayers.State.UPDATE){switch(this.state){case OpenLayers.State.UNKNOWN:case OpenLayers.State.DELETE:this.state=state;break;case OpenLayers.State.UPDATE:case OpenLayers.State.INSERT:break;}}else if(state==OpenLayers.State.INSERT){switch(this.state){case OpenLayers.State.UNKNOWN:break;default:this.state=state;break;}}else if(state==OpenLayers.State.DELETE){switch(this.state){case OpenLayers.State.INSERT:break;case OpenLayers.State.DELETE:break;case OpenLayers.State.UNKNOWN:case OpenLayers.State.UPDATE:this.state=state;break;}}else if(state==OpenLayers.State.UNKNOWN){this.state=state;}},CLASS_NAME:"OpenLayers.Feature.Vector"});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"},'select':{fillColor:"blue",fillOpacity:0.4,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"},'temporary':{fillColor:"#66cccc",fillOpacity:0.2,hoverFillColor:"white",hoverFillOpacity:0.8,strokeColor:"#66cccc",strokeOpacity:1,strokeLinecap:"round",strokeWidth:2,strokeDashstyle:"solid",hoverStrokeColor:"red",hoverStrokeOpacity:1,hoverStrokeWidth:0.2,pointRadius:6,hoverPointRadius:1,hoverPointUnit:"%",pointerEvents:"visiblePainted",cursor:"inherit"},'delete':{display:"none"}};OpenLayers.Feature.WFS=OpenLayers.Class(OpenLayers.Feature,{initialize:function(layer,xmlNode){var newArguments=arguments;var data=this.processXMLNode(xmlNode);newArguments=new Array(layer,data.lonlat,data);OpenLayers.Feature.prototype.initialize.apply(this,newArguments);this.createMarker();this.layer.addMarker(this.marker);},destroy:function(){if(this.marker!=null){this.layer.removeMarker(this.marker);}
60483 OpenLayers.Feature.prototype.destroy.apply(this,arguments);},processXMLNode:function(xmlNode){var point=OpenLayers.Ajax.getElementsByTagNameNS(xmlNode,"http://www.opengis.net/gml","gml","Point");var text=OpenLayers.Util.getXmlNodeValue(OpenLayers.Ajax.getElementsByTagNameNS(point[0],"http://www.opengis.net/gml","gml","coordinates")[0]);var floats=text.split(",");return{lonlat:new OpenLayers.LonLat(parseFloat(floats[0]),parseFloat(floats[1])),id:null};},CLASS_NAME:"OpenLayers.Feature.WFS"});OpenLayers.Format.OWSCommon.v1_0_0=OpenLayers.Class(OpenLayers.Format.OWSCommon.v1,{namespaces:{ows:"http://www.opengis.net/ows/1.0",xlink:"http://www.w3.org/1999/xlink"},readers:{"ows":OpenLayers.Format.OWSCommon.v1.prototype.readers["ows"]},writers:{"ows":OpenLayers.Format.OWSCommon.v1.prototype.writers["ows"]},CLASS_NAME:"OpenLayers.Format.OWSCommon.v1_1_0"});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({"AllowedValues":function(node,parameter){parameter.allowedValues={};this.readChildNodes(node,parameter.allowedValues);},"AnyValue":function(node,parameter){parameter.anyValue=true;},"Range":function(node,allowedValues){allowedValues.range={};this.readChildNodes(node,allowedValues.range);},"MinimumValue":function(node,range){range.minValue=this.getChildValue(node);},"MaximumValue":function(node,range){range.maxValue=this.getChildValue(node);},"Identifier":function(node,obj){obj.identifier=this.getChildValue(node);},"SupportedCRS":function(node,obj){obj.supportedCRS=this.getChildValue(node);}},OpenLayers.Format.OWSCommon.v1.prototype.readers["ows"])},CLASS_NAME:"OpenLayers.Format.OWSCommon.v1_1_0"});OpenLayers.Format.OWSContext=OpenLayers.Class(OpenLayers.Format.Context,{defaultVersion:"0.3.1",getParser:function(version){var v=version||this.version||this.defaultVersion;if(v==="0.3.0"){v=this.defaultVersion;}
60484 if(!this.parser||this.parser.VERSION!=v){var format=OpenLayers.Format.OWSContext["v"+v.replace(/\./g,"_")];if(!format){throw"Can't find a OWSContext parser for version "+v;}
60485 this.parser=new format(this.options);}
60486 return this.parser;},toContext:function(obj){var context={};if(obj.CLASS_NAME=="OpenLayers.Map"){context.bounds=obj.getExtent();context.maxExtent=obj.maxExtent;context.projection=obj.projection;context.size=obj.getSize();context.layers=obj.layers;}
60487 return context;},CLASS_NAME:"OpenLayers.Format.OWSContext"});OpenLayers.Format.WFSCapabilities.v1=OpenLayers.Class(OpenLayers.Format.WFSCapabilities,{initialize:function(options){OpenLayers.Format.XML.prototype.initialize.apply(this,[options]);this.options=options;},read:function(data){if(typeof data=="string"){data=OpenLayers.Format.XML.prototype.read.apply(this,[data]);}
60488 var capabilities={};var root=data.documentElement;this.runChildNodes(capabilities,root);return capabilities;},runChildNodes:function(obj,node){var children=node.childNodes;var childNode,processor;for(var i=0;i<children.length;++i){childNode=children[i];if(childNode.nodeType==1){processor=this["read_cap_"+childNode.nodeName];if(processor){processor.apply(this,[obj,childNode]);}}}},read_cap_FeatureTypeList:function(request,node){var featureTypeList={featureTypes:[]};this.runChildNodes(featureTypeList,node);request.featureTypeList=featureTypeList;},read_cap_FeatureType:function(featureTypeList,node,parentLayer){var featureType={};this.runChildNodes(featureType,node);featureTypeList.featureTypes.push(featureType);},read_cap_Name:function(obj,node){var name=this.getChildValue(node);if(name){var parts=name.split(":");obj.name=parts.pop();if(parts.length>0){obj.featureNS=this.lookupNamespaceURI(node,parts[0]);}}},read_cap_Title:function(obj,node){var title=this.getChildValue(node);if(title){obj.title=title;}},read_cap_Abstract:function(obj,node){var abst=this.getChildValue(node);if(abst){obj["abstract"]=abst;}},CLASS_NAME:"OpenLayers.Format.WFSCapabilities.v1"});OpenLayers.Format.WMC=OpenLayers.Class(OpenLayers.Format.Context,{defaultVersion:"1.1.0",getParser:function(version){var v=version||this.version||this.defaultVersion;if(!this.parser||this.parser.VERSION!=v){var format=OpenLayers.Format.WMC["v"+v.replace(/\./g,"_")];if(!format){throw"Can't find a WMC parser for version "+v;}
60489 this.parser=new format(this.options);}
60490 return this.parser;},layerToContext:function(layer){var parser=this.getParser();var layerContext={queryable:layer.queryable,visibility:layer.visibility,name:layer.params["LAYERS"],title:layer.name,metadataURL:layer.metadataURL,version:layer.params["VERSION"],url:layer.url,maxExtent:layer.maxExtent,transparent:layer.params["TRANSPARENT"],numZoomLevels:layer.numZoomLevels,units:layer.units,isBaseLayer:layer.isBaseLayer,opacity:layer.opacity,displayInLayerSwitcher:layer.displayInLayerSwitcher,singleTile:layer.singleTile,tileSize:(layer.singleTile||!layer.tileSize)?undefined:{width:layer.tileSize.w,height:layer.tileSize.h},minScale:(layer.options.resolutions||layer.options.scales||layer.options.maxResolution||layer.options.minScale)?layer.minScale:undefined,maxScale:(layer.options.resolutions||layer.options.scales||layer.options.minResolution||layer.options.maxScale)?layer.maxScale:undefined,formats:[{value:layer.params["FORMAT"],current:true}],styles:[{href:layer.params["SLD"],body:layer.params["SLD_BODY"],name:layer.params["STYLES"]||parser.defaultStyleName,title:parser.defaultStyleTitle,current:true}]};return layerContext;},toContext:function(obj){var context={};var layers=obj.layers;if(obj.CLASS_NAME=="OpenLayers.Map"){context.bounds=obj.getExtent();context.maxExtent=obj.maxExtent;context.projection=obj.projection;context.size=obj.getSize();}
60491 else{OpenLayers.Util.applyDefaults(context,obj);if(context.layers!=undefined){delete(context.layers);}}
60492 if(context.layersContext==undefined){context.layersContext=[];}
60493 if(layers!=undefined&&layers instanceof Array){for(var i=0,len=layers.length;i<len;i++){var layer=layers[i];if(layer instanceof OpenLayers.Layer.WMS){context.layersContext.push(this.layerToContext(layer));}}}
60494 return context;},CLASS_NAME:"OpenLayers.Format.WMC"});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",initialize:function(options){OpenLayers.Format.XML.prototype.initialize.apply(this,[options]);},read:function(data){if(typeof data=="string"){data=OpenLayers.Format.XML.prototype.read.apply(this,[data]);}
60495 if(data&&data.nodeType==9){data=data.documentElement;}
60496 var capabilities={};this.readNode(data,capabilities);this.postProcessLayers(capabilities);return capabilities;},postProcessLayers:function(capabilities){if(capabilities.capability){capabilities.capability.layers=[];var layers=capabilities.capability.nestedLayers;for(var i=0,len=layers.length;i<len;++i){var layer=layers[i];this.processLayer(capabilities.capability,layer);}}},processLayer:function(capability,layer,parentLayer){if(layer.formats===undefined){layer.formats=capability.request.getmap.formats;}
60497 if(parentLayer){layer.styles=layer.styles.concat(parentLayer.styles);var attributes=["queryable","cascaded","fixedWidth","fixedHeight","opaque","noSubsets","llbbox","minScale","maxScale","attribution"];var complexAttr=["srs","bbox","dimensions","authorityURLs"];var key;for(var j=0;j<attributes.length;j++){key=attributes[j];if(key in parentLayer){if(layer[key]==null){layer[key]=parentLayer[key];}
60498 if(layer[key]==null){var intAttr=["cascaded","fixedWidth","fixedHeight"];var boolAttr=["queryable","opaque","noSubsets"];if(OpenLayers.Util.indexOf(intAttr,key)!=-1){layer[key]=0;}
60499 if(OpenLayers.Util.indexOf(boolAttr,key)!=-1){layer[key]=false;}}}}
60500 for(var j=0;j<complexAttr.length;j++){key=complexAttr[j];layer[key]=OpenLayers.Util.extend(layer[key],parentLayer[key]);}}
60501 for(var i=0,len=layer.nestedLayers.length;i<len;i++){var childLayer=layer.nestedLayers[i];this.processLayer(capability,childLayer,layer);}
60502 if(layer.name){capability.layers.push(layer);}},readers:{"wms":{"Service":function(node,obj){obj.service={};this.readChildNodes(node,obj.service);},"Name":function(node,obj){obj.name=this.getChildValue(node);},"Title":function(node,obj){obj.title=this.getChildValue(node);},"Abstract":function(node,obj){obj["abstract"]=this.getChildValue(node);},"BoundingBox":function(node,obj){var bbox={};bbox.bbox=[parseFloat(node.getAttribute("minx")),parseFloat(node.getAttribute("miny")),parseFloat(node.getAttribute("maxx")),parseFloat(node.getAttribute("maxy"))];var res={x:parseFloat(node.getAttribute("resx")),y:parseFloat(node.getAttribute("resy"))};if(!(isNaN(res.x)&&isNaN(res.y))){bbox.res=res;}
60503 return bbox;},"OnlineResource":function(node,obj){obj.href=this.getAttributeNS(node,this.namespaces.xlink,"href");},"ContactInformation":function(node,obj){obj.contactInformation={};this.readChildNodes(node,obj.contactInformation);},"ContactPersonPrimary":function(node,obj){obj.personPrimary={};this.readChildNodes(node,obj.personPrimary);},"ContactPerson":function(node,obj){obj.person=this.getChildValue(node);},"ContactOrganization":function(node,obj){obj.organization=this.getChildValue(node);},"ContactPosition":function(node,obj){obj.position=this.getChildValue(node);},"ContactAddress":function(node,obj){obj.contactAddress={};this.readChildNodes(node,obj.contactAddress);},"AddressType":function(node,obj){obj.type=this.getChildValue(node);},"Address":function(node,obj){obj.address=this.getChildValue(node);},"City":function(node,obj){obj.city=this.getChildValue(node);},"StateOrProvince":function(node,obj){obj.stateOrProvince=this.getChildValue(node);},"PostCode":function(node,obj){obj.postcode=this.getChildValue(node);},"Country":function(node,obj){obj.country=this.getChildValue(node);},"ContactVoiceTelephone":function(node,obj){obj.phone=this.getChildValue(node);},"ContactFacsimileTelephone":function(node,obj){obj.fax=this.getChildValue(node);},"ContactElectronicMailAddress":function(node,obj){obj.email=this.getChildValue(node);},"Fees":function(node,obj){var fees=this.getChildValue(node);if(fees&&fees.toLowerCase()!="none"){obj.fees=fees;}},"AccessConstraints":function(node,obj){var constraints=this.getChildValue(node);if(constraints&&constraints.toLowerCase()!="none"){obj.accessConstraints=constraints;}},"Capability":function(node,obj){obj.capability={nestedLayers:[]};this.readChildNodes(node,obj.capability);},"Request":function(node,obj){obj.request={};this.readChildNodes(node,obj.request);},"GetCapabilities":function(node,obj){obj.getcapabilities={formats:[]};this.readChildNodes(node,obj.getcapabilities);},"Format":function(node,obj){if(obj.formats instanceof Array){obj.formats.push(this.getChildValue(node));}else{obj.format=this.getChildValue(node);}},"DCPType":function(node,obj){this.readChildNodes(node,obj);},"HTTP":function(node,obj){this.readChildNodes(node,obj);},"Get":function(node,obj){this.readChildNodes(node,obj);},"Post":function(node,obj){this.readChildNodes(node,obj);},"GetMap":function(node,obj){obj.getmap={formats:[]};this.readChildNodes(node,obj.getmap);},"GetFeatureInfo":function(node,obj){obj.getfeatureinfo={formats:[]};this.readChildNodes(node,obj.getfeatureinfo);},"Exception":function(node,obj){obj.exception={formats:[]};this.readChildNodes(node,obj.exception);},"Layer":function(node,obj){var attrNode=node.getAttributeNode("queryable");var queryable=(attrNode&&attrNode.specified)?node.getAttribute("queryable"):null;attrNode=node.getAttributeNode("cascaded");var cascaded=(attrNode&&attrNode.specified)?node.getAttribute("cascaded"):null;attrNode=node.getAttributeNode("opaque");var opaque=(attrNode&&attrNode.specified)?node.getAttribute('opaque'):null;var noSubsets=node.getAttribute('noSubsets');var fixedWidth=node.getAttribute('fixedWidth');var fixedHeight=node.getAttribute('fixedHeight');var layer={nestedLayers:[],styles:[],srs:{},metadataURLs:[],bbox:{},dimensions:{},authorityURLs:{},identifiers:{},keywords:[],queryable:(queryable&&queryable!=="")?(queryable==="1"||queryable==="true"):null,cascaded:(cascaded!==null)?parseInt(cascaded):null,opaque:opaque?(opaque==="1"||opaque==="true"):null,noSubsets:(noSubsets!==null)?(noSubsets==="1"||noSubsets==="true"):null,fixedWidth:(fixedWidth!=null)?parseInt(fixedWidth):null,fixedHeight:(fixedHeight!=null)?parseInt(fixedHeight):null};obj.nestedLayers.push(layer);this.readChildNodes(node,layer);if(layer.name){var parts=layer.name.split(":");if(parts.length>0){layer.prefix=parts[0];}}},"Attribution":function(node,obj){obj.attribution={};this.readChildNodes(node,obj.attribution);},"LogoURL":function(node,obj){obj.logo={width:node.getAttribute("width"),height:node.getAttribute("height")};this.readChildNodes(node,obj.logo);},"Style":function(node,obj){var style={};obj.styles.push(style);this.readChildNodes(node,style);},"LegendURL":function(node,obj){var legend={width:node.getAttribute("width"),height:node.getAttribute("height")};obj.legend=legend;this.readChildNodes(node,legend);},"MetadataURL":function(node,obj){var metadataURL={type:node.getAttribute("type")};obj.metadataURLs.push(metadataURL);this.readChildNodes(node,metadataURL);},"DataURL":function(node,obj){obj.dataURL={};this.readChildNodes(node,obj.dataURL);},"FeatureListURL":function(node,obj){obj.featureListURL={};this.readChildNodes(node,obj.featureListURL);},"AuthorityURL":function(node,obj){var name=node.getAttribute("name");var authority={};this.readChildNodes(node,authority);obj.authorityURLs[name]=authority.href;},"Identifier":function(node,obj){var authority=node.getAttribute("authority");obj.identifiers[authority]=this.getChildValue(node);},"KeywordList":function(node,obj){this.readChildNodes(node,obj);},"SRS":function(node,obj){obj.srs[this.getChildValue(node)]=true;}}},CLASS_NAME:"OpenLayers.Format.WMSCapabilities.v1"});OpenLayers.Format.WMSDescribeLayer.v1_1=OpenLayers.Class(OpenLayers.Format.WMSDescribeLayer,{initialize:function(options){OpenLayers.Format.WMSDescribeLayer.prototype.initialize.apply(this,[options]);},read:function(data){if(typeof data=="string"){data=OpenLayers.Format.XML.prototype.read.apply(this,[data]);}
60504 var root=data.documentElement;var children=root.childNodes;var describelayer=[];var childNode,nodeName;for(var i=0;i<children.length;++i){childNode=children[i];nodeName=childNode.nodeName;if(nodeName=='LayerDescription'){var layerName=childNode.getAttribute('name');var owsType='';var owsURL='';var typeName='';if(childNode.getAttribute('owsType')){owsType=childNode.getAttribute('owsType');owsURL=childNode.getAttribute('owsURL');}else{if(childNode.getAttribute('wfs')!=''){owsType='WFS';owsURL=childNode.getAttribute('wfs');}else if(childNode.getAttribute('wcs')!=''){owsType='WCS';owsURL=childNode.getAttribute('wcs');}}
60505 var query=childNode.getElementsByTagName('Query');if(query.length>0){typeName=query[0].getAttribute('typeName');if(!typeName){typeName=query[0].getAttribute('typename');}}
60506 describelayer.push({layerName:layerName,owsType:owsType,owsURL:owsURL,typeName:typeName});}}
60507 return describelayer;},CLASS_NAME:"OpenLayers.Format.WMSDescribeLayer.v1_1"});OpenLayers.Handler.Box=OpenLayers.Class(OpenLayers.Handler,{dragHandler:null,boxDivClassName:'olHandlerBoxZoomBox',boxCharacteristics:null,initialize:function(control,callbacks,options){OpenLayers.Handler.prototype.initialize.apply(this,arguments);var callbacks={"down":this.startBox,"move":this.moveBox,"out":this.removeBox,"up":this.endBox};this.dragHandler=new OpenLayers.Handler.Drag(this,callbacks,{keyMask:this.keyMask});},destroy:function(){if(this.dragHandler){this.dragHandler.destroy();this.dragHandler=null;}
60508 OpenLayers.Handler.prototype.destroy.apply(this,arguments);},setMap:function(map){OpenLayers.Handler.prototype.setMap.apply(this,arguments);if(this.dragHandler){this.dragHandler.setMap(map);}},startBox:function(xy){this.zoomBox=OpenLayers.Util.createDiv('zoomBox',this.dragHandler.start);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(xy){var startX=this.dragHandler.start.x;var startY=this.dragHandler.start.y;var deltaX=Math.abs(startX-xy.x);var deltaY=Math.abs(startY-xy.y);this.zoomBox.style.width=Math.max(1,deltaX)+"px";this.zoomBox.style.height=Math.max(1,deltaY)+"px";this.zoomBox.style.left=xy.x<startX?xy.x+"px":startX+"px";this.zoomBox.style.top=xy.y<startY?xy.y+"px":startY+"px";var box=this.getBoxCharacteristics();if(box.newBoxModel){if(xy.x>startX){this.zoomBox.style.width=Math.max(1,deltaX-box.xOffset)+"px";}
60509 if(xy.y>startY){this.zoomBox.style.height=Math.max(1,deltaY-box.yOffset)+"px";}}},endBox:function(end){var result;if(Math.abs(this.dragHandler.start.x-end.x)>5||Math.abs(this.dragHandler.start.y-end.y)>5){var start=this.dragHandler.start;var top=Math.min(start.y,end.y);var bottom=Math.max(start.y,end.y);var left=Math.min(start.x,end.x);var right=Math.max(start.x,end.x);result=new OpenLayers.Bounds(left,bottom,right,top);}else{result=this.dragHandler.start.clone();}
60510 this.removeBox();this.callback("done",[result]);},removeBox:function(){this.map.viewPortDiv.removeChild(this.zoomBox);this.zoomBox=null;this.boxCharacteristics=null;OpenLayers.Element.removeClass(this.map.viewPortDiv,"olDrawBox");},activate:function(){if(OpenLayers.Handler.prototype.activate.apply(this,arguments)){this.dragHandler.activate();return true;}else{return false;}},deactivate:function(){if(OpenLayers.Handler.prototype.deactivate.apply(this,arguments)){this.dragHandler.deactivate();return true;}else{return false;}},getBoxCharacteristics:function(){if(!this.boxCharacteristics){var xOffset=parseInt(OpenLayers.Element.getStyle(this.zoomBox,"border-left-width"))+parseInt(OpenLayers.Element.getStyle(this.zoomBox,"border-right-width"))+1;var yOffset=parseInt(OpenLayers.Element.getStyle(this.zoomBox,"border-top-width"))+parseInt(OpenLayers.Element.getStyle(this.zoomBox,"border-bottom-width"))+1;var newBoxModel=OpenLayers.Util.getBrowserName()=="msie"?document.compatMode!="BackCompat":true;this.boxCharacteristics={xOffset:xOffset,yOffset:yOffset,newBoxModel:newBoxModel};}
60511 return this.boxCharacteristics;},CLASS_NAME:"OpenLayers.Handler.Box"});OpenLayers.Handler.RegularPolygon=OpenLayers.Class(OpenLayers.Handler.Drag,{sides:4,radius:null,snapAngle:null,snapToggle:'shiftKey',layerOptions:null,persist:false,irregular:false,angle:null,fixedRadius:false,feature:null,layer:null,origin:null,initialize:function(control,callbacks,options){if(!(options&&options.layerOptions&&options.layerOptions.styleMap)){this.style=OpenLayers.Util.extend(OpenLayers.Feature.Vector.style['default'],{});}
60512 OpenLayers.Handler.prototype.initialize.apply(this,[control,callbacks,options]);this.options=(options)?options:{};},setOptions:function(newOptions){OpenLayers.Util.extend(this.options,newOptions);OpenLayers.Util.extend(this,newOptions);},activate:function(){var activated=false;if(OpenLayers.Handler.prototype.activate.apply(this,arguments)){var options=OpenLayers.Util.extend({displayInLayerSwitcher:false,calculateInRange:OpenLayers.Function.True},this.layerOptions);this.layer=new OpenLayers.Layer.Vector(this.CLASS_NAME,options);this.map.addLayer(this.layer);activated=true;}
60513 return activated;},deactivate:function(){var deactivated=false;if(OpenLayers.Handler.Drag.prototype.deactivate.apply(this,arguments)){if(this.dragging){this.cancel();}
60514 if(this.layer.map!=null){this.layer.destroy(false);if(this.feature){this.feature.destroy();}}
60515 this.layer=null;this.feature=null;deactivated=true;}
60516 return deactivated;},down:function(evt){this.fixedRadius=!!(this.radius);var maploc=this.map.getLonLatFromPixel(evt.xy);this.origin=new OpenLayers.Geometry.Point(maploc.lon,maploc.lat);if(!this.fixedRadius||this.irregular){this.radius=this.map.getResolution();}
60517 if(this.persist){this.clear();}
60518 this.feature=new OpenLayers.Feature.Vector();this.createGeometry();this.callback("create",[this.origin,this.feature]);this.layer.addFeatures([this.feature],{silent:true});this.layer.drawFeature(this.feature,this.style);},move:function(evt){var maploc=this.map.getLonLatFromPixel(evt.xy);var point=new OpenLayers.Geometry.Point(maploc.lon,maploc.lat);if(this.irregular){var ry=Math.sqrt(2)*Math.abs(point.y-this.origin.y)/2;this.radius=Math.max(this.map.getResolution()/2,ry);}else if(this.fixedRadius){this.origin=point;}else{this.calculateAngle(point,evt);this.radius=Math.max(this.map.getResolution()/2,point.distanceTo(this.origin));}
60519 this.modifyGeometry();if(this.irregular){var dx=point.x-this.origin.x;var dy=point.y-this.origin.y;var ratio;if(dy==0){ratio=dx/(this.radius*Math.sqrt(2));}else{ratio=dx/dy;}
60520 this.feature.geometry.resize(1,this.origin,ratio);this.feature.geometry.move(dx/2,dy/2);}
60521 this.layer.drawFeature(this.feature,this.style);},up:function(evt){this.finalize();if(this.start==this.last){this.callback("done",[evt.xy]);}},out:function(evt){this.finalize();},createGeometry:function(){this.angle=Math.PI*((1/this.sides)-(1/2));if(this.snapAngle){this.angle+=this.snapAngle*(Math.PI/180);}
60522 this.feature.geometry=OpenLayers.Geometry.Polygon.createRegularPolygon(this.origin,this.radius,this.sides,this.snapAngle);},modifyGeometry:function(){var angle,point;var ring=this.feature.geometry.components[0];if(ring.components.length!=(this.sides+1)){this.createGeometry();ring=this.feature.geometry.components[0];}
60523 for(var i=0;i<this.sides;++i){point=ring.components[i];angle=this.angle+(i*2*Math.PI/this.sides);point.x=this.origin.x+(this.radius*Math.cos(angle));point.y=this.origin.y+(this.radius*Math.sin(angle));point.clearBounds();}},calculateAngle:function(point,evt){var alpha=Math.atan2(point.y-this.origin.y,point.x-this.origin.x);if(this.snapAngle&&(this.snapToggle&&!evt[this.snapToggle])){var snapAngleRad=(Math.PI/180)*this.snapAngle;this.angle=Math.round(alpha/snapAngleRad)*snapAngleRad;}else{this.angle=alpha;}},cancel:function(){this.callback("cancel",null);this.finalize();},finalize:function(){this.origin=null;this.radius=this.options.radius;},clear:function(){if(this.layer){this.layer.renderer.clear();this.layer.destroyFeatures();}},callback:function(name,args){if(this.callbacks[name]){this.callbacks[name].apply(this.control,[this.feature.geometry.clone()]);}
60524 if(!this.persist&&(name=="done"||name=="cancel")){this.clear();}},CLASS_NAME:"OpenLayers.Handler.RegularPolygon"});OpenLayers.Layer.EventPane=OpenLayers.Class(OpenLayers.Layer,{smoothDragPan:true,isBaseLayer:true,isFixed:true,pane:null,mapObject:null,initialize:function(name,options){OpenLayers.Layer.prototype.initialize.apply(this,arguments);if(this.pane==null){this.pane=OpenLayers.Util.createDiv(this.div.id+"_EventPane");}},destroy:function(){this.mapObject=null;this.pane=null;OpenLayers.Layer.prototype.destroy.apply(this,arguments);},setMap:function(map){OpenLayers.Layer.prototype.setMap.apply(this,arguments);this.pane.style.zIndex=parseInt(this.div.style.zIndex)+1;this.pane.style.display=this.div.style.display;this.pane.style.width="100%";this.pane.style.height="100%";if(OpenLayers.Util.getBrowserName()=="msie"){this.pane.style.background="url("+OpenLayers.Util.getImagesLocation()+"blank.gif)";}
60525 if(this.isFixed){this.map.viewPortDiv.appendChild(this.pane);}else{this.map.layerContainerDiv.appendChild(this.pane);}
60526 this.loadMapObject();if(this.mapObject==null){this.loadWarningMessage();}},removeMap:function(map){if(this.pane&&this.pane.parentNode){this.pane.parentNode.removeChild(this.pane);}
60527 OpenLayers.Layer.prototype.removeMap.apply(this,arguments);},loadWarningMessage:function(){this.div.style.backgroundColor="darkblue";var viewSize=this.map.getSize();var msgW=Math.min(viewSize.w,300);var msgH=Math.min(viewSize.h,200);var size=new OpenLayers.Size(msgW,msgH);var centerPx=new OpenLayers.Pixel(viewSize.w/2,viewSize.h/2);var topLeft=centerPx.add(-size.w/2,-size.h/2);var div=OpenLayers.Util.createDiv(this.name+"_warning",topLeft,size,null,null,null,"auto");div.style.padding="7px";div.style.backgroundColor="yellow";div.innerHTML=this.getWarningHTML();this.div.appendChild(div);},getWarningHTML:function(){return"";},display:function(display){OpenLayers.Layer.prototype.display.apply(this,arguments);this.pane.style.display=this.div.style.display;},setZIndex:function(zIndex){OpenLayers.Layer.prototype.setZIndex.apply(this,arguments);this.pane.style.zIndex=parseInt(this.div.style.zIndex)+1;},moveTo:function(bounds,zoomChanged,dragging){OpenLayers.Layer.prototype.moveTo.apply(this,arguments);if(this.mapObject!=null){var newCenter=this.map.getCenter();var newZoom=this.map.getZoom();if(newCenter!=null){var moOldCenter=this.getMapObjectCenter();var oldCenter=this.getOLLonLatFromMapObjectLonLat(moOldCenter);var moOldZoom=this.getMapObjectZoom();var oldZoom=this.getOLZoomFromMapObjectZoom(moOldZoom);if(!(newCenter.equals(oldCenter))||!(newZoom==oldZoom)){if(dragging&&this.dragPanMapObject&&this.smoothDragPan){var oldPx=this.map.getViewPortPxFromLonLat(oldCenter);var newPx=this.map.getViewPortPxFromLonLat(newCenter);this.dragPanMapObject(newPx.x-oldPx.x,oldPx.y-newPx.y);}else{var center=this.getMapObjectLonLatFromOLLonLat(newCenter);var zoom=this.getMapObjectZoomFromOLZoom(newZoom);this.setMapObjectCenter(center,zoom,dragging);}}}}},getLonLatFromViewPortPx:function(viewPortPx){var lonlat=null;if((this.mapObject!=null)&&(this.getMapObjectCenter()!=null)){var moPixel=this.getMapObjectPixelFromOLPixel(viewPortPx);var moLonLat=this.getMapObjectLonLatFromMapObjectPixel(moPixel);lonlat=this.getOLLonLatFromMapObjectLonLat(moLonLat);}
60528 return lonlat;},getViewPortPxFromLonLat:function(lonlat){var viewPortPx=null;if((this.mapObject!=null)&&(this.getMapObjectCenter()!=null)){var moLonLat=this.getMapObjectLonLatFromOLLonLat(lonlat);var moPixel=this.getMapObjectPixelFromMapObjectLonLat(moLonLat);viewPortPx=this.getOLPixelFromMapObjectPixel(moPixel);}
60529 return viewPortPx;},getOLLonLatFromMapObjectLonLat:function(moLonLat){var olLonLat=null;if(moLonLat!=null){var lon=this.getLongitudeFromMapObjectLonLat(moLonLat);var lat=this.getLatitudeFromMapObjectLonLat(moLonLat);olLonLat=new OpenLayers.LonLat(lon,lat);}
60530 return olLonLat;},getMapObjectLonLatFromOLLonLat:function(olLonLat){var moLatLng=null;if(olLonLat!=null){moLatLng=this.getMapObjectLonLatFromLonLat(olLonLat.lon,olLonLat.lat);}
60531 return moLatLng;},getOLPixelFromMapObjectPixel:function(moPixel){var olPixel=null;if(moPixel!=null){var x=this.getXFromMapObjectPixel(moPixel);var y=this.getYFromMapObjectPixel(moPixel);olPixel=new OpenLayers.Pixel(x,y);}
60532 return olPixel;},getMapObjectPixelFromOLPixel:function(olPixel){var moPixel=null;if(olPixel!=null){moPixel=this.getMapObjectPixelFromXY(olPixel.x,olPixel.y);}
60533 return moPixel;},CLASS_NAME:"OpenLayers.Layer.EventPane"});OpenLayers.Layer.FixedZoomLevels=OpenLayers.Class({initialize:function(){},initResolutions:function(){var props=new Array('minZoomLevel','maxZoomLevel','numZoomLevels');for(var i=0,len=props.length;i<len;i++){var property=props[i];this[property]=(this.options[property]!=null)?this.options[property]:this.map[property];}
60534 if((this.minZoomLevel==null)||(this.minZoomLevel<this.MIN_ZOOM_LEVEL)){this.minZoomLevel=this.MIN_ZOOM_LEVEL;}
60535 var desiredZoomLevels;var limitZoomLevels=this.MAX_ZOOM_LEVEL-this.minZoomLevel+1;if(((this.options.numZoomLevels==null)&&(this.options.maxZoomLevel!=null))||((this.numZoomLevels==null)&&(this.maxZoomLevel!=null))){desiredZoomLevels=this.maxZoomLevel-this.minZoomLevel+1;}else{desiredZoomLevels=this.numZoomLevels;}
60536 if(desiredZoomLevels!=null){this.numZoomLevels=Math.min(desiredZoomLevels,limitZoomLevels);}else{this.numZoomLevels=limitZoomLevels;}
60537 this.maxZoomLevel=this.minZoomLevel+this.numZoomLevels-1;if(this.RESOLUTIONS!=null){var resolutionsIndex=0;this.resolutions=[];for(var i=this.minZoomLevel;i<=this.maxZoomLevel;i++){this.resolutions[resolutionsIndex++]=this.RESOLUTIONS[i];}
60538 this.maxResolution=this.resolutions[0];this.minResolution=this.resolutions[this.resolutions.length-1];}},getResolution:function(){if(this.resolutions!=null){return OpenLayers.Layer.prototype.getResolution.apply(this,arguments);}else{var resolution=null;var viewSize=this.map.getSize();var extent=this.getExtent();if((viewSize!=null)&&(extent!=null)){resolution=Math.max(extent.getWidth()/viewSize.w,extent.getHeight()/viewSize.h);}
60539 return resolution;}},getExtent:function(){var extent=null;var size=this.map.getSize();var tlPx=new OpenLayers.Pixel(0,0);var tlLL=this.getLonLatFromViewPortPx(tlPx);var brPx=new OpenLayers.Pixel(size.w,size.h);var brLL=this.getLonLatFromViewPortPx(brPx);if((tlLL!=null)&&(brLL!=null)){extent=new OpenLayers.Bounds(tlLL.lon,brLL.lat,brLL.lon,tlLL.lat);}
60540 return extent;},getZoomForResolution:function(resolution){if(this.resolutions!=null){return OpenLayers.Layer.prototype.getZoomForResolution.apply(this,arguments);}else{var extent=OpenLayers.Layer.prototype.getExtent.apply(this,[]);return this.getZoomForExtent(extent);}},getOLZoomFromMapObjectZoom:function(moZoom){var zoom=null;if(moZoom!=null){zoom=moZoom-this.minZoomLevel;}
60541 return zoom;},getMapObjectZoomFromOLZoom:function(olZoom){var zoom=null;if(olZoom!=null){zoom=olZoom+this.minZoomLevel;}
60542 return zoom;},CLASS_NAME:"OpenLayers.Layer.FixedZoomLevels"});OpenLayers.Layer.HTTPRequest=OpenLayers.Class(OpenLayers.Layer,{URL_HASH_FACTOR:(Math.sqrt(5)-1)/2,url:null,params:null,reproject:false,initialize:function(name,url,params,options){var newArguments=arguments;newArguments=[name,options];OpenLayers.Layer.prototype.initialize.apply(this,newArguments);this.url=url;this.params=OpenLayers.Util.extend({},params);},destroy:function(){this.url=null;this.params=null;OpenLayers.Layer.prototype.destroy.apply(this,arguments);},clone:function(obj){if(obj==null){obj=new OpenLayers.Layer.HTTPRequest(this.name,this.url,this.params,this.getOptions());}
60543 obj=OpenLayers.Layer.prototype.clone.apply(this,[obj]);return obj;},setUrl:function(newUrl){this.url=newUrl;},mergeNewParams:function(newParams){this.params=OpenLayers.Util.extend(this.params,newParams);var ret=this.redraw();if(this.map!=null){this.map.events.triggerEvent("changelayer",{layer:this,property:"params"});}
60544 return ret;},redraw:function(force){if(force){return this.mergeNewParams({"_olSalt":Math.random()});}else{return OpenLayers.Layer.prototype.redraw.apply(this,[]);}},selectUrl:function(paramString,urls){var product=1;for(var i=0,len=paramString.length;i<len;i++){product*=paramString.charCodeAt(i)*this.URL_HASH_FACTOR;product-=Math.floor(product);}
60545 return urls[Math.floor(product*urls.length)];},getFullRequestString:function(newParams,altUrl){var url=altUrl||this.url;var allParams=OpenLayers.Util.extend({},this.params);allParams=OpenLayers.Util.extend(allParams,newParams);var paramsString=OpenLayers.Util.getParameterString(allParams);if(url instanceof Array){url=this.selectUrl(paramsString,url);}
60546 var urlParams=OpenLayers.Util.upperCaseObject(OpenLayers.Util.getParameters(url));for(var key in allParams){if(key.toUpperCase()in urlParams){delete allParams[key];}}
60547 paramsString=OpenLayers.Util.getParameterString(allParams);return OpenLayers.Util.urlAppend(url,paramsString);},CLASS_NAME:"OpenLayers.Layer.HTTPRequest"});OpenLayers.Layer.Image=OpenLayers.Class(OpenLayers.Layer,{isBaseLayer:true,url:null,extent:null,size:null,tile:null,aspectRatio:null,initialize:function(name,url,extent,size,options){this.url=url;this.extent=extent;this.maxExtent=extent;this.size=size;OpenLayers.Layer.prototype.initialize.apply(this,[name,options]);this.aspectRatio=(this.extent.getHeight()/this.size.h)/(this.extent.getWidth()/this.size.w);},destroy:function(){if(this.tile){this.removeTileMonitoringHooks(this.tile);this.tile.destroy();this.tile=null;}
60548 OpenLayers.Layer.prototype.destroy.apply(this,arguments);},clone:function(obj){if(obj==null){obj=new OpenLayers.Layer.Image(this.name,this.url,this.extent,this.size,this.getOptions());}
60549 obj=OpenLayers.Layer.prototype.clone.apply(this,[obj]);return obj;},setMap:function(map){if(this.options.maxResolution==null){this.options.maxResolution=this.aspectRatio*this.extent.getWidth()/this.size.w;}
60550 OpenLayers.Layer.prototype.setMap.apply(this,arguments);},moveTo:function(bounds,zoomChanged,dragging){OpenLayers.Layer.prototype.moveTo.apply(this,arguments);var firstRendering=(this.tile==null);if(zoomChanged||firstRendering){this.setTileSize();var ul=new OpenLayers.LonLat(this.extent.left,this.extent.top);var ulPx=this.map.getLayerPxFromLonLat(ul);if(firstRendering){this.tile=new OpenLayers.Tile.Image(this,ulPx,this.extent,null,this.tileSize);this.addTileMonitoringHooks(this.tile);}else{this.tile.size=this.tileSize.clone();this.tile.position=ulPx.clone();}
60551 this.tile.draw();}},setTileSize:function(){var tileWidth=this.extent.getWidth()/this.map.getResolution();var tileHeight=this.extent.getHeight()/this.map.getResolution();this.tileSize=new OpenLayers.Size(tileWidth,tileHeight);},addTileMonitoringHooks:function(tile){tile.onLoadStart=function(){this.events.triggerEvent("loadstart");};tile.events.register("loadstart",this,tile.onLoadStart);tile.onLoadEnd=function(){this.events.triggerEvent("loadend");};tile.events.register("loadend",this,tile.onLoadEnd);tile.events.register("unload",this,tile.onLoadEnd);},removeTileMonitoringHooks:function(tile){tile.unload();tile.events.un({"loadstart":tile.onLoadStart,"loadend":tile.onLoadEnd,"unload":tile.onLoadEnd,scope:this});},setUrl:function(newUrl){this.url=newUrl;this.tile.draw();},getURL:function(bounds){return this.url;},CLASS_NAME:"OpenLayers.Layer.Image"});OpenLayers.Layer.Markers=OpenLayers.Class(OpenLayers.Layer,{isBaseLayer:false,markers:null,drawn:false,initialize:function(name,options){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(opacity){if(opacity!=this.opacity){this.opacity=opacity;for(var i=0,len=this.markers.length;i<len;i++){this.markers[i].setOpacity(this.opacity);}}},moveTo:function(bounds,zoomChanged,dragging){OpenLayers.Layer.prototype.moveTo.apply(this,arguments);if(zoomChanged||!this.drawn){for(var i=0,len=this.markers.length;i<len;i++){this.drawMarker(this.markers[i]);}
60552 this.drawn=true;}},addMarker:function(marker){this.markers.push(marker);if(this.opacity!=null){marker.setOpacity(this.opacity);}
60553 if(this.map&&this.map.getExtent()){marker.map=this.map;this.drawMarker(marker);}},removeMarker:function(marker){if(this.markers&&this.markers.length){OpenLayers.Util.removeItem(this.markers,marker);marker.erase();}},clearMarkers:function(){if(this.markers!=null){while(this.markers.length>0){this.removeMarker(this.markers[0]);}}},drawMarker:function(marker){var px=this.map.getLayerPxFromLonLat(marker.lonlat);if(px==null){marker.display(false);}else{if(!marker.isDrawn()){var markerImg=marker.draw(px);this.div.appendChild(markerImg);}else if(marker.icon){marker.icon.moveTo(px);}}},getDataExtent:function(){var maxExtent=null;if(this.markers&&(this.markers.length>0)){var maxExtent=new OpenLayers.Bounds();for(var i=0,len=this.markers.length;i<len;i++){var marker=this.markers[i];maxExtent.extend(marker.lonlat);}}
60554 return maxExtent;},CLASS_NAME:"OpenLayers.Layer.Markers"});OpenLayers.Layer.SphericalMercator={getExtent:function(){var extent=null;if(this.sphericalMercator){extent=this.map.calculateBounds();}else{extent=OpenLayers.Layer.FixedZoomLevels.prototype.getExtent.apply(this);}
60555 return extent;},getLonLatFromViewPortPx:function(viewPortPx){return OpenLayers.Layer.prototype.getLonLatFromViewPortPx.apply(this,arguments);},getViewPortPxFromLonLat:function(lonlat){return OpenLayers.Layer.prototype.getViewPortPxFromLonLat.apply(this,arguments);},initMercatorParameters:function(){this.RESOLUTIONS=[];var maxResolution=156543.0339;for(var zoom=0;zoom<=this.MAX_ZOOM_LEVEL;++zoom){this.RESOLUTIONS[zoom]=maxResolution/Math.pow(2,zoom);}
60556 this.units="m";this.projection=this.projection||"EPSG:900913";},forwardMercator:function(lon,lat){var x=lon*20037508.34/180;var y=Math.log(Math.tan((90+lat)*Math.PI/360))/(Math.PI/180);y=y*20037508.34/180;return new OpenLayers.LonLat(x,y);},inverseMercator:function(x,y){var lon=(x/20037508.34)*180;var lat=(y/20037508.34)*180;lat=180/Math.PI*(2*Math.atan(Math.exp(lat*Math.PI/180))-Math.PI/2);return new OpenLayers.LonLat(lon,lat);},projectForward:function(point){var lonlat=OpenLayers.Layer.SphericalMercator.forwardMercator(point.x,point.y);point.x=lonlat.lon;point.y=lonlat.lat;return point;},projectInverse:function(point){var lonlat=OpenLayers.Layer.SphericalMercator.inverseMercator(point.x,point.y);point.x=lonlat.lon;point.y=lonlat.lat;return point;}};OpenLayers.Projection.addTransform("EPSG:4326","EPSG:900913",OpenLayers.Layer.SphericalMercator.projectForward);OpenLayers.Projection.addTransform("EPSG:900913","EPSG:4326",OpenLayers.Layer.SphericalMercator.projectInverse);OpenLayers.Tile.WFS=OpenLayers.Class(OpenLayers.Tile,{features:null,url:null,request:null,initialize:function(layer,position,bounds,url,size){OpenLayers.Tile.prototype.initialize.apply(this,arguments);this.url=url;this.features=[];},destroy:function(){OpenLayers.Tile.prototype.destroy.apply(this,arguments);this.destroyAllFeatures();this.features=null;this.url=null;if(this.request){this.request.abort();this.request=null;}},clear:function(){this.destroyAllFeatures();},draw:function(){if(OpenLayers.Tile.prototype.draw.apply(this,arguments)){if(this.isLoading){this.events.triggerEvent("reload");}else{this.isLoading=true;this.events.triggerEvent("loadstart");}
60557 this.loadFeaturesForRegion(this.requestSuccess);}},loadFeaturesForRegion:function(success,failure){if(this.request){this.request.abort();}
60558 this.request=OpenLayers.Request.GET({url:this.url,success:success,failure:failure,scope:this});},requestSuccess:function(request){if(this.features){var doc=request.responseXML;if(!doc||!doc.documentElement){doc=request.responseText;}
60559 if(this.layer.vectorMode){this.layer.addFeatures(this.layer.formatObject.read(doc));}else{var xml=new OpenLayers.Format.XML();if(typeof doc=="string"){doc=xml.read(doc);}
60560 var resultFeatures=xml.getElementsByTagNameNS(doc,"http://www.opengis.net/gml","featureMember");this.addResults(resultFeatures);}}
60561 if(this.events){this.events.triggerEvent("loadend");}
60562 this.request=null;},addResults:function(results){for(var i=0;i<results.length;i++){var feature=new this.layer.featureClass(this.layer,results[i]);this.features.push(feature);}},destroyAllFeatures:function(){while(this.features.length>0){var feature=this.features.shift();feature.destroy();}},CLASS_NAME:"OpenLayers.Tile.WFS"});OpenLayers.Control.DrawFeature=OpenLayers.Class(OpenLayers.Control,{layer:null,callbacks:null,EVENT_TYPES:["featureadded"],multi:false,featureAdded:function(){},handlerOptions:null,initialize:function(layer,handler,options){this.EVENT_TYPES=OpenLayers.Control.DrawFeature.prototype.EVENT_TYPES.concat(OpenLayers.Control.prototype.EVENT_TYPES);OpenLayers.Control.prototype.initialize.apply(this,[options]);this.callbacks=OpenLayers.Util.extend({done:this.drawFeature,modify:function(vertex,feature){this.layer.events.triggerEvent("sketchmodified",{vertex:vertex,feature:feature});},create:function(vertex,feature){this.layer.events.triggerEvent("sketchstarted",{vertex:vertex,feature:feature});}},this.callbacks);this.layer=layer;this.handlerOptions=this.handlerOptions||{};if(!("multi"in this.handlerOptions)){this.handlerOptions.multi=this.multi;}
60563 var sketchStyle=this.layer.styleMap&&this.layer.styleMap.styles.temporary;if(sketchStyle){this.handlerOptions.layerOptions=OpenLayers.Util.applyDefaults(this.handlerOptions.layerOptions,{styleMap:new OpenLayers.StyleMap({"default":sketchStyle})});}
60564 this.handler=new handler(this,this.callbacks,this.handlerOptions);},drawFeature:function(geometry){var feature=new OpenLayers.Feature.Vector(geometry);var proceed=this.layer.events.triggerEvent("sketchcomplete",{feature:feature});if(proceed!==false){feature.state=OpenLayers.State.INSERT;this.layer.addFeatures([feature]);this.featureAdded(feature);this.events.triggerEvent("featureadded",{feature:feature});}},CLASS_NAME:"OpenLayers.Control.DrawFeature"});OpenLayers.Control.Measure=OpenLayers.Class(OpenLayers.Control,{EVENT_TYPES:['measure','measurepartial'],handlerOptions:null,callbacks:null,displaySystem:'metric',geodesic:false,displaySystemUnits:{geographic:['dd'],english:['mi','ft','in'],metric:['km','m']},partialDelay:300,delayedTrigger:null,persist:false,initialize:function(handler,options){this.EVENT_TYPES=OpenLayers.Control.Measure.prototype.EVENT_TYPES.concat(OpenLayers.Control.prototype.EVENT_TYPES);OpenLayers.Control.prototype.initialize.apply(this,[options]);this.callbacks=OpenLayers.Util.extend({done:this.measureComplete,point:this.measurePartial},this.callbacks);this.handlerOptions=OpenLayers.Util.extend({persist:this.persist},this.handlerOptions);this.handler=new handler(this,this.callbacks,this.handlerOptions);},cancel:function(){this.handler.cancel();},updateHandler:function(handler,options){var active=this.active;if(active){this.deactivate();}
60565 this.handler=new handler(this,this.callbacks,options);if(active){this.activate();}},measureComplete:function(geometry){if(this.delayedTrigger){window.clearTimeout(this.delayedTrigger);}
60566 this.measure(geometry,"measure");},measurePartial:function(point,geometry){if(geometry.getLength()>0){geometry=geometry.clone();this.delayedTrigger=window.setTimeout(OpenLayers.Function.bind(function(){this.measure(geometry,"measurepartial");},this),this.partialDelay);}},measure:function(geometry,eventType){var stat,order;if(geometry.CLASS_NAME.indexOf('LineString')>-1){stat=this.getBestLength(geometry);order=1;}else{stat=this.getBestArea(geometry);order=2;}
60567 this.events.triggerEvent(eventType,{measure:stat[0],units:stat[1],order:order,geometry:geometry});},getBestArea:function(geometry){var units=this.displaySystemUnits[this.displaySystem];var unit,area;for(var i=0,len=units.length;i<len;++i){unit=units[i];area=this.getArea(geometry,unit);if(area>1){break;}}
60568 return[area,unit];},getArea:function(geometry,units){var area,geomUnits;if(this.geodesic){area=geometry.getGeodesicArea(this.map.getProjectionObject());geomUnits="m";}else{area=geometry.getArea();geomUnits=this.map.getUnits();}
60569 var inPerDisplayUnit=OpenLayers.INCHES_PER_UNIT[units];if(inPerDisplayUnit){var inPerMapUnit=OpenLayers.INCHES_PER_UNIT[geomUnits];area*=Math.pow((inPerMapUnit/inPerDisplayUnit),2);}
60570 return area;},getBestLength:function(geometry){var units=this.displaySystemUnits[this.displaySystem];var unit,length;for(var i=0,len=units.length;i<len;++i){unit=units[i];length=this.getLength(geometry,unit);if(length>1){break;}}
60571 return[length,unit];},getLength:function(geometry,units){var length,geomUnits;if(this.geodesic){length=geometry.getGeodesicLength(this.map.getProjectionObject());geomUnits="m";}else{length=geometry.getLength();geomUnits=this.map.getUnits();}
60572 var inPerDisplayUnit=OpenLayers.INCHES_PER_UNIT[units];if(inPerDisplayUnit){var inPerMapUnit=OpenLayers.INCHES_PER_UNIT[geomUnits];length*=(inPerMapUnit/inPerDisplayUnit);}
60573 return length;},CLASS_NAME:"OpenLayers.Control.Measure"});OpenLayers.Control.ZoomBox=OpenLayers.Class(OpenLayers.Control,{type:OpenLayers.Control.TYPE_TOOL,out:false,alwaysZoom:false,draw:function(){this.handler=new OpenLayers.Handler.Box(this,{done:this.zoomBox},{keyMask:this.keyMask});},zoomBox:function(position){if(position instanceof OpenLayers.Bounds){var bounds;if(!this.out){var minXY=this.map.getLonLatFromPixel(new OpenLayers.Pixel(position.left,position.bottom));var maxXY=this.map.getLonLatFromPixel(new OpenLayers.Pixel(position.right,position.top));bounds=new OpenLayers.Bounds(minXY.lon,minXY.lat,maxXY.lon,maxXY.lat);}else{var pixWidth=Math.abs(position.right-position.left);var pixHeight=Math.abs(position.top-position.bottom);var zoomFactor=Math.min((this.map.size.h/pixHeight),(this.map.size.w/pixWidth));var extent=this.map.getExtent();var center=this.map.getLonLatFromPixel(position.getCenterPixel());var xmin=center.lon-(extent.getWidth()/2)*zoomFactor;var xmax=center.lon+(extent.getWidth()/2)*zoomFactor;var ymin=center.lat-(extent.getHeight()/2)*zoomFactor;var ymax=center.lat+(extent.getHeight()/2)*zoomFactor;bounds=new OpenLayers.Bounds(xmin,ymin,xmax,ymax);}
60574 var lastZoom=this.map.getZoom();this.map.zoomToExtent(bounds);if(lastZoom==this.map.getZoom()&&this.alwaysZoom==true){this.map.zoomTo(lastZoom+(this.out?-1:1));}}else{if(!this.out){this.map.setCenter(this.map.getLonLatFromPixel(position),this.map.getZoom()+1);}else{this.map.setCenter(this.map.getLonLatFromPixel(position),this.map.getZoom()-1);}}},CLASS_NAME:"OpenLayers.Control.ZoomBox"});OpenLayers.Format.WFSCapabilities.v1_0_0=OpenLayers.Class(OpenLayers.Format.WFSCapabilities.v1,{initialize:function(options){OpenLayers.Format.WFSCapabilities.v1.prototype.initialize.apply(this,[options]);},read_cap_Service:function(capabilities,node){var service={};this.runChildNodes(service,node);capabilities.service=service;},read_cap_Fees:function(service,node){var fees=this.getChildValue(node);if(fees&&fees.toLowerCase()!="none"){service.fees=fees;}},read_cap_AccessConstraints:function(service,node){var constraints=this.getChildValue(node);if(constraints&&constraints.toLowerCase()!="none"){service.accessConstraints=constraints;}},read_cap_OnlineResource:function(service,node){var onlineResource=this.getChildValue(node);if(onlineResource&&onlineResource.toLowerCase()!="none"){service.onlineResource=onlineResource;}},read_cap_Keywords:function(service,node){var keywords=this.getChildValue(node);if(keywords&&keywords.toLowerCase()!="none"){service.keywords=keywords.split(', ');}},read_cap_Capability:function(capabilities,node){var capability={};this.runChildNodes(capability,node);capabilities.capability=capability;},read_cap_Request:function(obj,node){var request={};this.runChildNodes(request,node);obj.request=request;},read_cap_GetFeature:function(request,node){var getfeature={href:{},formats:[]};this.runChildNodes(getfeature,node);request.getfeature=getfeature;},read_cap_ResultFormat:function(obj,node){var children=node.childNodes;var childNode;for(var i=0;i<children.length;i++){childNode=children[i];if(childNode.nodeType==1){obj.formats.push(childNode.nodeName);}}},read_cap_DCPType:function(obj,node){this.runChildNodes(obj,node);},read_cap_HTTP:function(obj,node){this.runChildNodes(obj.href,node);},read_cap_Get:function(obj,node){obj.get=node.getAttribute("onlineResource");},read_cap_Post:function(obj,node){obj.post=node.getAttribute("onlineResource");},CLASS_NAME:"OpenLayers.Format.WFSCapabilities.v1_0_0"});OpenLayers.Format.WFSCapabilities.v1_1_0=OpenLayers.Class(OpenLayers.Format.WFSCapabilities.v1,{initialize:function(options){OpenLayers.Format.WFSCapabilities.v1.prototype.initialize.apply(this,[options]);},CLASS_NAME:"OpenLayers.Format.WFSCapabilities.v1_1_0"});OpenLayers.Format.WKT=OpenLayers.Class(OpenLayers.Format,{initialize:function(options){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,[options]);},read:function(wkt){var features,type,str;var matches=this.regExes.typeStr.exec(wkt);if(matches){type=matches[1].toLowerCase();str=matches[2];if(this.parse[type]){features=this.parse[type].apply(this,[str]);}
60575 if(this.internalProjection&&this.externalProjection){if(features&&features.CLASS_NAME=="OpenLayers.Feature.Vector"){features.geometry.transform(this.externalProjection,this.internalProjection);}else if(features&&type!="geometrycollection"&&typeof features=="object"){for(var i=0,len=features.length;i<len;i++){var component=features[i];component.geometry.transform(this.externalProjection,this.internalProjection);}}}}
60576 return features;},write:function(features){var collection,geometry,type,data,isCollection;if(features.constructor==Array){collection=features;isCollection=true;}else{collection=[features];isCollection=false;}
60577 var pieces=[];if(isCollection){pieces.push('GEOMETRYCOLLECTION(');}
60578 for(var i=0,len=collection.length;i<len;++i){if(isCollection&&i>0){pieces.push(',');}
60579 geometry=collection[i].geometry;type=geometry.CLASS_NAME.split('.')[2].toLowerCase();if(!this.extract[type]){return null;}
60580 if(this.internalProjection&&this.externalProjection){geometry=geometry.clone();geometry.transform(this.internalProjection,this.externalProjection);}
60581 data=this.extract[type].apply(this,[geometry]);pieces.push(type.toUpperCase()+'('+data+')');}
60582 if(isCollection){pieces.push(')');}
60583 return pieces.join('');},extract:{'point':function(point){return point.x+' '+point.y;},'multipoint':function(multipoint){var array=[];for(var i=0,len=multipoint.components.length;i<len;++i){array.push('('+
60584 this.extract.point.apply(this,[multipoint.components[i]])+')');}
60585 return array.join(',');},'linestring':function(linestring){var array=[];for(var i=0,len=linestring.components.length;i<len;++i){array.push(this.extract.point.apply(this,[linestring.components[i]]));}
60586 return array.join(',');},'multilinestring':function(multilinestring){var array=[];for(var i=0,len=multilinestring.components.length;i<len;++i){array.push('('+
60587 this.extract.linestring.apply(this,[multilinestring.components[i]])+')');}
60588 return array.join(',');},'polygon':function(polygon){var array=[];for(var i=0,len=polygon.components.length;i<len;++i){array.push('('+
60589 this.extract.linestring.apply(this,[polygon.components[i]])+')');}
60590 return array.join(',');},'multipolygon':function(multipolygon){var array=[];for(var i=0,len=multipolygon.components.length;i<len;++i){array.push('('+
60591 this.extract.polygon.apply(this,[multipolygon.components[i]])+')');}
60592 return array.join(',');}},parse:{'point':function(str){var coords=OpenLayers.String.trim(str).split(this.regExes.spaces);return new OpenLayers.Feature.Vector(new OpenLayers.Geometry.Point(coords[0],coords[1]));},'multipoint':function(str){var point;var points=OpenLayers.String.trim(str).split(this.regExes.parenComma);var components=[];for(var i=0,len=points.length;i<len;++i){point=points[i].replace(this.regExes.trimParens,'$1');components.push(this.parse.point.apply(this,[point]).geometry);}
60593 return new OpenLayers.Feature.Vector(new OpenLayers.Geometry.MultiPoint(components));},'linestring':function(str){var points=OpenLayers.String.trim(str).split(',');var components=[];for(var i=0,len=points.length;i<len;++i){components.push(this.parse.point.apply(this,[points[i]]).geometry);}
60594 return new OpenLayers.Feature.Vector(new OpenLayers.Geometry.LineString(components));},'multilinestring':function(str){var line;var lines=OpenLayers.String.trim(str).split(this.regExes.parenComma);var components=[];for(var i=0,len=lines.length;i<len;++i){line=lines[i].replace(this.regExes.trimParens,'$1');components.push(this.parse.linestring.apply(this,[line]).geometry);}
60595 return new OpenLayers.Feature.Vector(new OpenLayers.Geometry.MultiLineString(components));},'polygon':function(str){var ring,linestring,linearring;var rings=OpenLayers.String.trim(str).split(this.regExes.parenComma);var components=[];for(var i=0,len=rings.length;i<len;++i){ring=rings[i].replace(this.regExes.trimParens,'$1');linestring=this.parse.linestring.apply(this,[ring]).geometry;linearring=new OpenLayers.Geometry.LinearRing(linestring.components);components.push(linearring);}
60596 return new OpenLayers.Feature.Vector(new OpenLayers.Geometry.Polygon(components));},'multipolygon':function(str){var polygon;var polygons=OpenLayers.String.trim(str).split(this.regExes.doubleParenComma);var components=[];for(var i=0,len=polygons.length;i<len;++i){polygon=polygons[i].replace(this.regExes.trimParens,'$1');components.push(this.parse.polygon.apply(this,[polygon]).geometry);}
60597 return new OpenLayers.Feature.Vector(new OpenLayers.Geometry.MultiPolygon(components));},'geometrycollection':function(str){str=str.replace(/,\s*([A-Za-z])/g,'|$1');var wktArray=OpenLayers.String.trim(str).split('|');var components=[];for(var i=0,len=wktArray.length;i<len;++i){components.push(OpenLayers.Format.WKT.prototype.read.apply(this,[wktArray[i]]));}
60598 return components;}},CLASS_NAME:"OpenLayers.Format.WKT"});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(uri){var prefix=null;if(uri==null){prefix=this.namespaces[this.defaultPrefix];}else{for(prefix in this.namespaces){if(this.namespaces[prefix]==uri){break;}}}
60599 return prefix;},defaultPrefix:"wmc",rootPrefix:null,defaultStyleName:"",defaultStyleTitle:"Default",initialize:function(options){OpenLayers.Format.XML.prototype.initialize.apply(this,[options]);},read:function(data){if(typeof data=="string"){data=OpenLayers.Format.XML.prototype.read.apply(this,[data]);}
60600 var root=data.documentElement;this.rootPrefix=root.prefix;var context={version:root.getAttribute("version")};this.runChildNodes(context,root);return context;},runChildNodes:function(obj,node){var children=node.childNodes;var childNode,processor,prefix,local;for(var i=0,len=children.length;i<len;++i){childNode=children[i];if(childNode.nodeType==1){prefix=this.getNamespacePrefix(childNode.namespaceURI);local=childNode.nodeName.split(":").pop();processor=this["read_"+prefix+"_"+local];if(processor){processor.apply(this,[obj,childNode]);}}}},read_wmc_General:function(context,node){this.runChildNodes(context,node);},read_wmc_BoundingBox:function(context,node){context.projection=node.getAttribute("SRS");context.bounds=new OpenLayers.Bounds(parseFloat(node.getAttribute("minx")),parseFloat(node.getAttribute("miny")),parseFloat(node.getAttribute("maxx")),parseFloat(node.getAttribute("maxy")));},read_wmc_LayerList:function(context,node){context.layersContext=[];this.runChildNodes(context,node);},read_wmc_Layer:function(context,node){var layerContext={visibility:(node.getAttribute("hidden")!="1"),queryable:(node.getAttribute("queryable")=="1"),formats:[],styles:[]};this.runChildNodes(layerContext,node);context.layersContext.push(layerContext);},read_wmc_Extension:function(obj,node){this.runChildNodes(obj,node);},read_ol_units:function(layerContext,node){layerContext.units=this.getChildValue(node);},read_ol_maxExtent:function(obj,node){var bounds=new OpenLayers.Bounds(node.getAttribute("minx"),node.getAttribute("miny"),node.getAttribute("maxx"),node.getAttribute("maxy"));obj.maxExtent=bounds;},read_ol_transparent:function(layerContext,node){layerContext.transparent=this.getChildValue(node);},read_ol_numZoomLevels:function(layerContext,node){layerContext.numZoomLevels=parseInt(this.getChildValue(node));},read_ol_opacity:function(layerContext,node){layerContext.opacity=parseFloat(this.getChildValue(node));},read_ol_singleTile:function(layerContext,node){layerContext.singleTile=(this.getChildValue(node)=="true");},read_ol_tileSize:function(layerContext,node){var obj={"width":node.getAttribute("width"),"height":node.getAttribute("height")};layerContext.tileSize=obj;},read_ol_isBaseLayer:function(layerContext,node){layerContext.isBaseLayer=(this.getChildValue(node)=="true");},read_ol_displayInLayerSwitcher:function(layerContext,node){layerContext.displayInLayerSwitcher=(this.getChildValue(node)=="true");},read_wmc_Server:function(layerContext,node){layerContext.version=node.getAttribute("version");var server={};var links=node.getElementsByTagName("OnlineResource");if(links.length>0){this.read_wmc_OnlineResource(server,links[0]);}
60601 layerContext.url=server.href;},read_wmc_FormatList:function(layerContext,node){this.runChildNodes(layerContext,node);},read_wmc_Format:function(layerContext,node){var format={value:this.getChildValue(node)};if(node.getAttribute("current")=="1"){format.current=true;}
60602 layerContext.formats.push(format);},read_wmc_StyleList:function(layerContext,node){this.runChildNodes(layerContext,node);},read_wmc_Style:function(layerContext,node){var style={};this.runChildNodes(style,node);if(node.getAttribute("current")=="1"){style.current=true;}
60603 layerContext.styles.push(style);},read_wmc_SLD:function(style,node){this.runChildNodes(style,node);},read_sld_StyledLayerDescriptor:function(sld,node){var xml=OpenLayers.Format.XML.prototype.write.apply(this,[node]);sld.body=xml;},read_wmc_OnlineResource:function(obj,node){obj.href=this.getAttributeNS(node,this.namespaces.xlink,"href");},read_wmc_Name:function(obj,node){var name=this.getChildValue(node);if(name){obj.name=name;}},read_wmc_Title:function(obj,node){var title=this.getChildValue(node);if(title){obj.title=title;}},read_wmc_MetadataURL:function(layerContext,node){var metadataURL={};var links=node.getElementsByTagName("OnlineResource");if(links.length>0){this.read_wmc_OnlineResource(metadataURL,links[0]);}
60604 layerContext.metadataURL=metadataURL.href;},read_wmc_Abstract:function(obj,node){var abst=this.getChildValue(node);if(abst){obj["abstract"]=abst;}},read_wmc_LegendURL:function(style,node){var legend={width:node.getAttribute('width'),height:node.getAttribute('height')};var links=node.getElementsByTagName("OnlineResource");if(links.length>0){this.read_wmc_OnlineResource(legend,links[0]);}
60605 style.legend=legend;},write:function(context,options){var root=this.createElementDefaultNS("ViewContext");this.setAttributes(root,{version:this.VERSION,id:(options&&typeof options.id=="string")?options.id:OpenLayers.Util.createUniqueID("OpenLayers_Context_")});this.setAttributeNS(root,this.namespaces.xsi,"xsi:schemaLocation",this.schemaLocation);root.appendChild(this.write_wmc_General(context));root.appendChild(this.write_wmc_LayerList(context));return OpenLayers.Format.XML.prototype.write.apply(this,[root]);},createElementDefaultNS:function(name,childValue,attributes){var node=this.createElementNS(this.namespaces[this.defaultPrefix],name);if(childValue){node.appendChild(this.createTextNode(childValue));}
60606 if(attributes){this.setAttributes(node,attributes);}
60607 return node;},setAttributes:function(node,obj){var value;for(var name in obj){value=obj[name].toString();if(value.match(/[A-Z]/)){this.setAttributeNS(node,null,name,value);}else{node.setAttribute(name,value);}}},write_wmc_General:function(context){var node=this.createElementDefaultNS("General");if(context.size){node.appendChild(this.createElementDefaultNS("Window",null,{width:context.size.w,height:context.size.h}));}
60608 var bounds=context.bounds;node.appendChild(this.createElementDefaultNS("BoundingBox",null,{minx:bounds.left.toPrecision(18),miny:bounds.bottom.toPrecision(18),maxx:bounds.right.toPrecision(18),maxy:bounds.top.toPrecision(18),SRS:context.projection}));node.appendChild(this.createElementDefaultNS("Title",context.title));node.appendChild(this.write_ol_MapExtension(context));return node;},write_ol_MapExtension:function(context){var node=this.createElementDefaultNS("Extension");var bounds=context.maxExtent;if(bounds){var maxExtent=this.createElementNS(this.namespaces.ol,"ol:maxExtent");this.setAttributes(maxExtent,{minx:bounds.left.toPrecision(18),miny:bounds.bottom.toPrecision(18),maxx:bounds.right.toPrecision(18),maxy:bounds.top.toPrecision(18)});node.appendChild(maxExtent);}
60609 return node;},write_wmc_LayerList:function(context){var list=this.createElementDefaultNS("LayerList");for(var i=0,len=context.layersContext.length;i<len;++i){list.appendChild(this.write_wmc_Layer(context.layersContext[i]));}
60610 return list;},write_wmc_Layer:function(context){var node=this.createElementDefaultNS("Layer",null,{queryable:context.queryable?"1":"0",hidden:context.visibility?"0":"1"});node.appendChild(this.write_wmc_Server(context));node.appendChild(this.createElementDefaultNS("Name",context.name));node.appendChild(this.createElementDefaultNS("Title",context.title));if(context.metadataURL){node.appendChild(this.write_wmc_MetadataURL(context.metadataURL));}
60611 return node;},write_wmc_LayerExtension:function(context){var node=this.createElementDefaultNS("Extension");var bounds=context.maxExtent;var maxExtent=this.createElementNS(this.namespaces.ol,"ol:maxExtent");this.setAttributes(maxExtent,{minx:bounds.left.toPrecision(18),miny:bounds.bottom.toPrecision(18),maxx:bounds.right.toPrecision(18),maxy:bounds.top.toPrecision(18)});node.appendChild(maxExtent);if(context.tileSize&&!context.singleTile){var size=this.createElementNS(this.namespaces.ol,"ol:tileSize");this.setAttributes(size,context.tileSize);node.appendChild(size);}
60612 var properties=["transparent","numZoomLevels","units","isBaseLayer","opacity","displayInLayerSwitcher","singleTile"];var child;for(var i=0,len=properties.length;i<len;++i){child=this.createOLPropertyNode(context,properties[i]);if(child){node.appendChild(child);}}
60613 return node;},createOLPropertyNode:function(obj,prop){var node=null;if(obj[prop]!=null){node=this.createElementNS(this.namespaces.ol,"ol:"+prop);node.appendChild(this.createTextNode(obj[prop].toString()));}
60614 return node;},write_wmc_Server:function(context){var node=this.createElementDefaultNS("Server");this.setAttributes(node,{service:"OGC:WMS",version:context.version});node.appendChild(this.write_wmc_OnlineResource(context.url));return node;},write_wmc_MetadataURL:function(metadataURL){var node=this.createElementDefaultNS("MetadataURL");node.appendChild(this.write_wmc_OnlineResource(metadataURL));return node;},write_wmc_FormatList:function(context){var node=this.createElementDefaultNS("FormatList");for(var i=0,len=context.formats.length;i<len;i++){var format=context.formats[i];node.appendChild(this.createElementDefaultNS("Format",format.value,(format.current&&format.current==true)?{current:"1"}:null));}
60615 return node;},write_wmc_StyleList:function(layer){var node=this.createElementDefaultNS("StyleList");var styles=layer.styles;if(styles&&styles instanceof Array){var sld;for(var i=0,len=styles.length;i<len;i++){var s=styles[i];var style=this.createElementDefaultNS("Style",null,(s.current&&s.current==true)?{current:"1"}:null);if(s.href){sld=this.createElementDefaultNS("SLD");var link=this.write_wmc_OnlineResource(s.href);sld.appendChild(link);sld.appendChild(this.createElementDefaultNS("Name",s.name));if(s.title){sld.appendChild(this.createElementDefaultNS("Title",s.title));}
60616 style.appendChild(sld);}else if(s.body){sld=this.createElementDefaultNS("SLD");var doc=OpenLayers.Format.XML.prototype.read.apply(this,[s.body]);var imported=doc.documentElement;if(sld.ownerDocument&&sld.ownerDocument.importNode){imported=sld.ownerDocument.importNode(imported,true);}
60617 sld.appendChild(imported);sld.appendChild(this.createElementDefaultNS("Name",s.name));if(s.title){sld.appendChild(this.createElementDefaultNS("Title",s.title));}
60618 style.appendChild(sld);}else{style.appendChild(this.createElementDefaultNS("Name",s.name));style.appendChild(this.createElementDefaultNS("Title",s.title));if(s['abstract']){style.appendChild(this.createElementDefaultNS("Abstract",s['abstract']));}}
60619 node.appendChild(style);}}
60620 return node;},write_wmc_OnlineResource:function(href){var node=this.createElementDefaultNS("OnlineResource");this.setAttributeNS(node,this.namespaces.xlink,"xlink:type","simple");this.setAttributeNS(node,this.namespaces.xlink,"xlink:href",href);return node;},CLASS_NAME:"OpenLayers.Format.WMC.v1"});OpenLayers.Format.WMSCapabilities.v1_1=OpenLayers.Class(OpenLayers.Format.WMSCapabilities.v1,{readers:{"wms":OpenLayers.Util.applyDefaults({"WMT_MS_Capabilities":function(node,obj){this.readChildNodes(node,obj);},"Keyword":function(node,obj){if(obj.keywords){obj.keywords.push(this.getChildValue(node));}},"DescribeLayer":function(node,obj){obj.describelayer={formats:[]};this.readChildNodes(node,obj.describelayer);},"GetLegendGraphic":function(node,obj){obj.getlegendgraphic={formats:[]};this.readChildNodes(node,obj.getlegendgraphic);},"GetStyles":function(node,obj){obj.getstyles={formats:[]};this.readChildNodes(node,obj.getstyles);},"PutStyles":function(node,obj){obj.putstyles={formats:[]};this.readChildNodes(node,obj.putstyles);},"UserDefinedSymbolization":function(node,obj){var userSymbols={supportSLD:parseInt(node.getAttribute("SupportSLD"))==1,userLayer:parseInt(node.getAttribute("UserLayer"))==1,userStyle:parseInt(node.getAttribute("UserStyle"))==1,remoteWFS:parseInt(node.getAttribute("RemoteWFS"))==1};obj.userSymbols=userSymbols;},"LatLonBoundingBox":function(node,obj){obj.llbbox=[parseFloat(node.getAttribute("minx")),parseFloat(node.getAttribute("miny")),parseFloat(node.getAttribute("maxx")),parseFloat(node.getAttribute("maxy"))];},"BoundingBox":function(node,obj){var bbox=OpenLayers.Format.WMSCapabilities.v1.prototype.readers["wms"].BoundingBox.apply(this,[node,obj]);bbox.srs=node.getAttribute("SRS");obj.bbox[bbox.srs]=bbox;},"ScaleHint":function(node,obj){var min=node.getAttribute("min");var max=node.getAttribute("max");var rad2=Math.pow(2,0.5);var ipm=OpenLayers.INCHES_PER_UNIT["m"];obj.maxScale=parseFloat(((min/rad2)*ipm*OpenLayers.DOTS_PER_INCH).toPrecision(13));obj.minScale=parseFloat(((max/rad2)*ipm*OpenLayers.DOTS_PER_INCH).toPrecision(13));},"Dimension":function(node,obj){var name=node.getAttribute("name").toLowerCase();var dim={name:name,units:node.getAttribute("units"),unitsymbol:node.getAttribute("unitSymbol")};obj.dimensions[dim.name]=dim;},"Extent":function(node,obj){var name=node.getAttribute("name").toLowerCase();if(name in obj["dimensions"]){var extent=obj.dimensions[name];extent.nearestVal=node.getAttribute("nearestValue")==="1";extent.multipleVal=node.getAttribute("multipleValues")==="1";extent.current=node.getAttribute("current")==="1";extent["default"]=node.getAttribute("default")||"";var values=this.getChildValue(node);extent.values=values.split(",");}}},OpenLayers.Format.WMSCapabilities.v1.prototype.readers["wms"])},CLASS_NAME:"OpenLayers.Format.WMSCapabilities.v1_1"});OpenLayers.Format.WMSCapabilities.v1_3=OpenLayers.Class(OpenLayers.Format.WMSCapabilities.v1,{readers:{"wms":OpenLayers.Util.applyDefaults({"WMS_Capabilities":function(node,obj){this.readChildNodes(node,obj);},"LayerLimit":function(node,obj){obj.layerLimit=parseInt(this.getChildValue(node));},"MaxWidth":function(node,obj){obj.maxWidth=parseInt(this.getChildValue(node));},"MaxHeight":function(node,obj){obj.maxHeight=parseInt(this.getChildValue(node));},"BoundingBox":function(node,obj){var bbox=OpenLayers.Format.WMSCapabilities.v1.prototype.readers["wms"].BoundingBox.apply(this,[node,obj]);bbox.srs=node.getAttribute("CRS");obj.bbox[bbox.srs]=bbox;},"CRS":function(node,obj){this.readers.wms.SRS.apply(this,[node,obj]);},"EX_GeographicBoundingBox":function(node,obj){obj.llbbox=[];this.readChildNodes(node,obj.llbbox);},"westBoundLongitude":function(node,obj){obj[0]=this.getChildValue(node);},"eastBoundLongitude":function(node,obj){obj[2]=this.getChildValue(node);},"southBoundLatitude":function(node,obj){obj[1]=this.getChildValue(node);},"northBoundLatitude":function(node,obj){obj[3]=this.getChildValue(node);},"MinScaleDenominator":function(node,obj){obj.maxScale=parseFloat(this.getChildValue(node)).toPrecision(16);},"MaxScaleDenominator":function(node,obj){obj.minScale=parseFloat(this.getChildValue(node)).toPrecision(16);},"Dimension":function(node,obj){var name=node.getAttribute("name").toLowerCase();var dim={name:name,units:node.getAttribute("units"),unitsymbol:node.getAttribute("unitSymbol"),nearestVal:node.getAttribute("nearestValue")==="1",multipleVal:node.getAttribute("multipleValues")==="1","default":node.getAttribute("default")||"",current:node.getAttribute("current")==="1",values:this.getChildValue(node).split(",")};obj.dimensions[dim.name]=dim;},"Keyword":function(node,obj){var keyword={value:this.getChildValue(node),vocabulary:node.getAttribute("vocabulary")};if(obj.keywords){obj.keywords.push(keyword);}}},OpenLayers.Format.WMSCapabilities.v1.prototype.readers["wms"]),"sld":{"UserDefinedSymbolization":function(node,obj){this.readers.wms.UserDefinedSymbolization.apply(this,[node,obj]);obj.userSymbols.inlineFeature=parseInt(node.getAttribute("InlineFeature"))==1;obj.userSymbols.remoteWCS=parseInt(node.getAttribute("RemoteWCS"))==1;},"DescribeLayer":function(node,obj){this.readers.wms.DescribeLayer.apply(this,[node,obj]);},"GetLegendGraphic":function(node,obj){this.readers.wms.GetLegendGraphic.apply(this,[node,obj]);}}},CLASS_NAME:"OpenLayers.Format.WMSCapabilities.v1_3"});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(options){OpenLayers.Format.XML.prototype.initialize.apply(this,[options]);this.options=options;var yx=OpenLayers.Util.extend({},OpenLayers.Format.WMTSCapabilities.prototype.yx);this.yx=OpenLayers.Util.extend(yx,this.yx);},read:function(data){if(typeof data=="string"){data=OpenLayers.Format.XML.prototype.read.apply(this,[data]);}
60621 if(data&&data.nodeType==9){data=data.documentElement;}
60622 var capabilities={};this.readNode(data,capabilities);capabilities.version=this.version;return capabilities;},readers:{"wmts":{"Capabilities":function(node,obj){this.readChildNodes(node,obj);},"Contents":function(node,obj){obj.contents={};obj.contents.layers=[];obj.contents.tileMatrixSets={};this.readChildNodes(node,obj.contents);},"Layer":function(node,obj){var layer={styles:[],formats:[],tileMatrixSetLinks:[]};layer.layers=[];this.readChildNodes(node,layer);obj.layers.push(layer);},"Style":function(node,obj){var style={};style.isDefault=(node.getAttribute("isDefault")==="true");this.readChildNodes(node,style);obj.styles.push(style);},"Format":function(node,obj){obj.formats.push(this.getChildValue(node));},"TileMatrixSetLink":function(node,obj){var tileMatrixSetLink={};this.readChildNodes(node,tileMatrixSetLink);obj.tileMatrixSetLinks.push(tileMatrixSetLink);},"TileMatrixSet":function(node,obj){if(obj.layers){var tileMatrixSet={matrixIds:[]};this.readChildNodes(node,tileMatrixSet);obj.tileMatrixSets[tileMatrixSet.identifier]=tileMatrixSet;}else{obj.tileMatrixSet=this.getChildValue(node);}},"TileMatrix":function(node,obj){var tileMatrix={supportedCRS:obj.supportedCRS};this.readChildNodes(node,tileMatrix);obj.matrixIds.push(tileMatrix);},"ScaleDenominator":function(node,obj){obj.scaleDenominator=parseFloat(this.getChildValue(node));},"TopLeftCorner":function(node,obj){var topLeftCorner=this.getChildValue(node);var coords=topLeftCorner.split(" ");var yx;if(obj.supportedCRS){var crs=obj.supportedCRS.replace(/urn:ogc:def:crs:(\w+):.+:(\w+)$/,"urn:ogc:def:crs:$1::$2");yx=!!this.yx[crs];}
60623 if(yx){obj.topLeftCorner=new OpenLayers.LonLat(coords[1],coords[0]);}else{obj.topLeftCorner=new OpenLayers.LonLat(coords[0],coords[1]);}},"TileWidth":function(node,obj){obj.tileWidth=parseInt(this.getChildValue(node));},"TileHeight":function(node,obj){obj.tileHeight=parseInt(this.getChildValue(node));},"MatrixWidth":function(node,obj){obj.matrixWidth=parseInt(this.getChildValue(node));},"MatrixHeight":function(node,obj){obj.matrixHeight=parseInt(this.getChildValue(node));},"WSDL":function(node,obj){obj.wsdl={};obj.wsdl.href=node.getAttribute("xlink:href");},"ServiceMetadataURL":function(node,obj){obj.serviceMetadataUrl={};obj.serviceMetadataUrl.href=node.getAttribute("xlink:href");}},"ows":OpenLayers.Format.OWSCommon.v1_1_0.prototype.readers["ows"]},CLASS_NAME:"OpenLayers.Format.WMTSCapabilities.v1_0_0"});OpenLayers.Layer.Boxes=OpenLayers.Class(OpenLayers.Layer.Markers,{initialize:function(name,options){OpenLayers.Layer.Markers.prototype.initialize.apply(this,arguments);},drawMarker:function(marker){var bounds=marker.bounds;var topleft=this.map.getLayerPxFromLonLat(new OpenLayers.LonLat(bounds.left,bounds.top));var botright=this.map.getLayerPxFromLonLat(new OpenLayers.LonLat(bounds.right,bounds.bottom));if(botright==null||topleft==null){marker.display(false);}else{var sz=new OpenLayers.Size(Math.max(1,botright.x-topleft.x),Math.max(1,botright.y-topleft.y));var markerDiv=marker.draw(topleft,sz);if(!marker.drawn){this.div.appendChild(markerDiv);marker.drawn=true;}}},removeMarker:function(marker){OpenLayers.Util.removeItem(this.markers,marker);if((marker.div!=null)&&(marker.div.parentNode==this.div)){this.div.removeChild(marker.div);}},CLASS_NAME:"OpenLayers.Layer.Boxes"});OpenLayers.Layer.GeoRSS=OpenLayers.Class(OpenLayers.Layer.Markers,{location:null,features:null,formatOptions:null,selectedFeature:null,icon:null,popupSize:null,useFeedTitle:true,initialize:function(name,location,options){OpenLayers.Layer.Markers.prototype.initialize.apply(this,[name,options]);this.location=location;this.features=[];},destroy:function(){OpenLayers.Layer.Markers.prototype.destroy.apply(this,arguments);this.clearFeatures();this.features=null;},loadRSS:function(){if(!this.loaded){this.events.triggerEvent("loadstart");OpenLayers.Request.GET({url:this.location,success:this.parseData,scope:this});this.loaded=true;}},moveTo:function(bounds,zoomChanged,minor){OpenLayers.Layer.Markers.prototype.moveTo.apply(this,arguments);if(this.visibility&&!this.loaded){this.loadRSS();}},parseData:function(ajaxRequest){var doc=ajaxRequest.responseXML;if(!doc||!doc.documentElement){doc=OpenLayers.Format.XML.prototype.read(ajaxRequest.responseText);}
60624 if(this.useFeedTitle){var name=null;try{name=doc.getElementsByTagNameNS('*','title')[0].firstChild.nodeValue;}
60625 catch(e){name=doc.getElementsByTagName('title')[0].firstChild.nodeValue;}
60626 if(name){this.setName(name);}}
60627 var options={};OpenLayers.Util.extend(options,this.formatOptions);if(this.map&&!this.projection.equals(this.map.getProjectionObject())){options.externalProjection=this.projection;options.internalProjection=this.map.getProjectionObject();}
60628 var format=new OpenLayers.Format.GeoRSS(options);var features=format.read(doc);for(var i=0,len=features.length;i<len;i++){var data={};var feature=features[i];if(!feature.geometry){continue;}
60629 var title=feature.attributes.title?feature.attributes.title:"Untitled";var description=feature.attributes.description?feature.attributes.description:"No description.";var link=feature.attributes.link?feature.attributes.link:"";var location=feature.geometry.getBounds().getCenterLonLat();data.icon=this.icon==null?OpenLayers.Marker.defaultIcon():this.icon.clone();data.popupSize=this.popupSize?this.popupSize.clone():new OpenLayers.Size(250,120);if(title||description){data.title=title;data.description=description;var contentHTML='<div class="olLayerGeoRSSClose">[x]</div>';contentHTML+='<div class="olLayerGeoRSSTitle">';if(link){contentHTML+='<a class="link" href="'+link+'" target="_blank">';}
60630 contentHTML+=title;if(link){contentHTML+='</a>';}
60631 contentHTML+='</div>';contentHTML+='<div style="" class="olLayerGeoRSSDescription">';contentHTML+=description;contentHTML+='</div>';data['popupContentHTML']=contentHTML;}
60632 var feature=new OpenLayers.Feature(this,location,data);this.features.push(feature);var marker=feature.createMarker();marker.events.register('click',feature,this.markerClick);this.addMarker(marker);}
60633 this.events.triggerEvent("loadend");},markerClick:function(evt){var sameMarkerClicked=(this==this.layer.selectedFeature);this.layer.selectedFeature=(!sameMarkerClicked)?this:null;for(var i=0,len=this.layer.map.popups.length;i<len;i++){this.layer.map.removePopup(this.layer.map.popups[i]);}
60634 if(!sameMarkerClicked){var popup=this.createPopup();OpenLayers.Event.observe(popup.div,"click",OpenLayers.Function.bind(function(){for(var i=0,len=this.layer.map.popups.length;i<len;i++){this.layer.map.removePopup(this.layer.map.popups[i]);}},this));this.layer.map.addPopup(popup);}
60635 OpenLayers.Event.stop(evt);},clearFeatures:function(){if(this.features!=null){while(this.features.length>0){var feature=this.features[0];OpenLayers.Util.removeItem(this.features,feature);feature.destroy();}}},CLASS_NAME:"OpenLayers.Layer.GeoRSS"});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,0.0006866455078125,0.00034332275390625,0.000171661376953125,0.0000858306884765625,0.00004291534423828125,0.00002145767211914062,0.00001072883605957031,0.00000536441802978515,0.00000268220901489257,0.0000013411045074462891,0.00000067055225372314453],type:null,wrapDateLine:true,sphericalMercator:false,version:null,initialize:function(name,options){options=options||{};if(!options.version){options.version=typeof GMap2==="function"?"2":"3";}
60636 var mixin=OpenLayers.Layer.Google["v"+
60637 options.version.replace(/\./g,"_")];if(mixin){OpenLayers.Util.applyDefaults(options,mixin);}else{throw"Unsupported Google Maps API version: "+options.version;}
60638 OpenLayers.Util.applyDefaults(options,mixin.DEFAULTS);if(options.maxExtent){options.maxExtent=options.maxExtent.clone();}
60639 OpenLayers.Layer.EventPane.prototype.initialize.apply(this,[name,options]);OpenLayers.Layer.FixedZoomLevels.prototype.initialize.apply(this,[name,options]);if(this.sphericalMercator){OpenLayers.Util.extend(this,OpenLayers.Layer.SphericalMercator);this.initMercatorParameters();}},clone:function(){return new OpenLayers.Layer.Google(this.name,this.getOptions());},setVisibility:function(visible){var opacity=this.opacity==null?1:this.opacity;OpenLayers.Layer.EventPane.prototype.setVisibility.apply(this,arguments);this.setOpacity(opacity);},display:function(visible){if(!this._dragging){this.setGMapVisibility(visible);}
60640 OpenLayers.Layer.EventPane.prototype.display.apply(this,arguments);},moveTo:function(bounds,zoomChanged,dragging){this._dragging=dragging;OpenLayers.Layer.EventPane.prototype.moveTo.apply(this,arguments);delete this._dragging;},setOpacity:function(opacity){if(opacity!==this.opacity){if(this.map!=null){this.map.events.triggerEvent("changelayer",{layer:this,property:"opacity"});}
60641 this.opacity=opacity;}
60642 if(this.getVisibility()){var container=this.getMapContainer();OpenLayers.Util.modifyDOMElement(container,null,null,null,null,null,null,opacity);}},destroy:function(){if(this.map){this.setGMapVisibility(false);var cache=OpenLayers.Layer.Google.cache[this.map.id];if(cache&&cache.count<=1){this.removeGMapElements();}}
60643 OpenLayers.Layer.EventPane.prototype.destroy.apply(this,arguments);},removeGMapElements:function(){var cache=OpenLayers.Layer.Google.cache[this.map.id];if(cache){var container=this.mapObject&&this.getMapContainer();if(container&&container.parentNode){container.parentNode.removeChild(container);}
60644 var termsOfUse=cache.termsOfUse;if(termsOfUse&&termsOfUse.parentNode){termsOfUse.parentNode.removeChild(termsOfUse);}
60645 var poweredBy=cache.poweredBy;if(poweredBy&&poweredBy.parentNode){poweredBy.parentNode.removeChild(poweredBy);}}},removeMap:function(map){if(this.visibility&&this.mapObject){this.setGMapVisibility(false);}
60646 var cache=OpenLayers.Layer.Google.cache[map.id];if(cache){if(cache.count<=1){this.removeGMapElements();delete OpenLayers.Layer.Google.cache[map.id];}else{--cache.count;}}
60647 delete this.termsOfUse;delete this.poweredBy;delete this.mapObject;delete this.dragObject;OpenLayers.Layer.EventPane.prototype.removeMap.apply(this,arguments);},getOLBoundsFromMapObjectBounds:function(moBounds){var olBounds=null;if(moBounds!=null){var sw=moBounds.getSouthWest();var ne=moBounds.getNorthEast();if(this.sphericalMercator){sw=this.forwardMercator(sw.lng(),sw.lat());ne=this.forwardMercator(ne.lng(),ne.lat());}else{sw=new OpenLayers.LonLat(sw.lng(),sw.lat());ne=new OpenLayers.LonLat(ne.lng(),ne.lat());}
60648 olBounds=new OpenLayers.Bounds(sw.lon,sw.lat,ne.lon,ne.lat);}
60649 return olBounds;},getWarningHTML:function(){return OpenLayers.i18n("googleWarning");},getMapObjectCenter:function(){return this.mapObject.getCenter();},getMapObjectZoom:function(){return this.mapObject.getZoom();},getLongitudeFromMapObjectLonLat:function(moLonLat){return this.sphericalMercator?this.forwardMercator(moLonLat.lng(),moLonLat.lat()).lon:moLonLat.lng();},getLatitudeFromMapObjectLonLat:function(moLonLat){var lat=this.sphericalMercator?this.forwardMercator(moLonLat.lng(),moLonLat.lat()).lat:moLonLat.lat();return lat;},getXFromMapObjectPixel:function(moPixel){return moPixel.x;},getYFromMapObjectPixel:function(moPixel){return moPixel.y;},CLASS_NAME:"OpenLayers.Layer.Google"});OpenLayers.Layer.Google.cache={};OpenLayers.Layer.Google.v2={termsOfUse:null,poweredBy:null,dragObject:null,loadMapObject:function(){if(!this.type){this.type=G_NORMAL_MAP;}
60650 var mapObject,termsOfUse,poweredBy;var cache=OpenLayers.Layer.Google.cache[this.map.id];if(cache){mapObject=cache.mapObject;termsOfUse=cache.termsOfUse;poweredBy=cache.poweredBy;++cache.count;}else{var container=this.map.viewPortDiv;var div=document.createElement("div");div.id=this.map.id+"_GMap2Container";div.style.position="absolute";div.style.width="100%";div.style.height="100%";container.appendChild(div);try{mapObject=new GMap2(div);termsOfUse=div.lastChild;container.appendChild(termsOfUse);termsOfUse.style.zIndex="1100";termsOfUse.style.right="";termsOfUse.style.bottom="";termsOfUse.className="olLayerGoogleCopyright";poweredBy=div.lastChild;container.appendChild(poweredBy);poweredBy.style.zIndex="1100";poweredBy.style.right="";poweredBy.style.bottom="";poweredBy.className="olLayerGooglePoweredBy gmnoprint";}catch(e){throw(e);}
60651 OpenLayers.Layer.Google.cache[this.map.id]={mapObject:mapObject,termsOfUse:termsOfUse,poweredBy:poweredBy,count:1};}
60652 this.mapObject=mapObject;this.termsOfUse=termsOfUse;this.poweredBy=poweredBy;if(OpenLayers.Util.indexOf(this.mapObject.getMapTypes(),this.type)===-1){this.mapObject.addMapType(this.type);}
60653 if(typeof mapObject.getDragObject=="function"){this.dragObject=mapObject.getDragObject();}else{this.dragPanMapObject=null;}
60654 if(this.isBaseLayer===false){this.setGMapVisibility(this.div.style.display!=="none");}},onMapResize:function(){if(this.visibility&&this.mapObject.isLoaded()){this.mapObject.checkResize();}else{if(!this._resized){var layer=this;var handle=GEvent.addListener(this.mapObject,"load",function(){GEvent.removeListener(handle);delete layer._resized;layer.mapObject.checkResize();layer.moveTo(layer.map.getCenter(),layer.map.getZoom());});}
60655 this._resized=true;}},setGMapVisibility:function(visible){var cache=OpenLayers.Layer.Google.cache[this.map.id];if(cache){var container=this.mapObject.getContainer();if(visible===true){this.mapObject.setMapType(this.type);container.style.display="";this.termsOfUse.style.left="";this.termsOfUse.style.display="";this.poweredBy.style.display="";cache.displayed=this.id;}else{if(cache.displayed===this.id){delete cache.displayed;}
60656 if(!cache.displayed){container.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(olBounds){var moBounds=null;if(olBounds!=null){var sw=this.sphericalMercator?this.inverseMercator(olBounds.bottom,olBounds.left):new OpenLayers.LonLat(olBounds.bottom,olBounds.left);var ne=this.sphericalMercator?this.inverseMercator(olBounds.top,olBounds.right):new OpenLayers.LonLat(olBounds.top,olBounds.right);moBounds=new GLatLngBounds(new GLatLng(sw.lat,sw.lon),new GLatLng(ne.lat,ne.lon));}
60657 return moBounds;},setMapObjectCenter:function(center,zoom){this.mapObject.setCenter(center,zoom);},dragPanMapObject:function(dX,dY){this.dragObject.moveBy(new GSize(-dX,dY));},getMapObjectLonLatFromMapObjectPixel:function(moPixel){return this.mapObject.fromContainerPixelToLatLng(moPixel);},getMapObjectPixelFromMapObjectLonLat:function(moLonLat){return this.mapObject.fromLatLngToContainerPixel(moLonLat);},getMapObjectZoomFromMapObjectBounds:function(moBounds){return this.mapObject.getBoundsZoomLevel(moBounds);},getMapObjectLonLatFromLonLat:function(lon,lat){var gLatLng;if(this.sphericalMercator){var lonlat=this.inverseMercator(lon,lat);gLatLng=new GLatLng(lonlat.lat,lonlat.lon);}else{gLatLng=new GLatLng(lat,lon);}
60658 return gLatLng;},getMapObjectPixelFromXY:function(x,y){return new GPoint(x,y);}};OpenLayers.Layer.Grid=OpenLayers.Class(OpenLayers.Layer.HTTPRequest,{tileSize:null,grid:null,singleTile:false,ratio:1.5,buffer:2,numLoadingTiles:0,initialize:function(name,url,params,options){OpenLayers.Layer.HTTPRequest.prototype.initialize.apply(this,arguments);this.events.addEventType("tileloaded");this.grid=[];},destroy:function(){this.clearGrid();this.grid=null;this.tileSize=null;OpenLayers.Layer.HTTPRequest.prototype.destroy.apply(this,arguments);},clearGrid:function(){if(this.grid){for(var iRow=0,len=this.grid.length;iRow<len;iRow++){var row=this.grid[iRow];for(var iCol=0,clen=row.length;iCol<clen;iCol++){var tile=row[iCol];this.removeTileMonitoringHooks(tile);tile.destroy();}}
60659 this.grid=[];}},clone:function(obj){if(obj==null){obj=new OpenLayers.Layer.Grid(this.name,this.url,this.params,this.getOptions());}
60660 obj=OpenLayers.Layer.HTTPRequest.prototype.clone.apply(this,[obj]);if(this.tileSize!=null){obj.tileSize=this.tileSize.clone();}
60661 obj.grid=[];return obj;},moveTo:function(bounds,zoomChanged,dragging){OpenLayers.Layer.HTTPRequest.prototype.moveTo.apply(this,arguments);bounds=bounds||this.map.getExtent();if(bounds!=null){var forceReTile=!this.grid.length||zoomChanged;var tilesBounds=this.getTilesBounds();if(this.singleTile){if(forceReTile||(!dragging&&!tilesBounds.containsBounds(bounds))){this.initSingleTile(bounds);}}else{if(forceReTile||!tilesBounds.containsBounds(bounds,true)){this.initGriddedTiles(bounds);}else{this.moveGriddedTiles(bounds);}}}},setTileSize:function(size){if(this.singleTile){size=this.map.getSize();size.h=parseInt(size.h*this.ratio);size.w=parseInt(size.w*this.ratio);}
60662 OpenLayers.Layer.HTTPRequest.prototype.setTileSize.apply(this,[size]);},getGridBounds:function(){var msg="The getGridBounds() function is deprecated. It will be "+"removed in 3.0. Please use getTilesBounds() instead.";OpenLayers.Console.warn(msg);return this.getTilesBounds();},getTilesBounds:function(){var bounds=null;if(this.grid.length){var bottom=this.grid.length-1;var bottomLeftTile=this.grid[bottom][0];var right=this.grid[0].length-1;var topRightTile=this.grid[0][right];bounds=new OpenLayers.Bounds(bottomLeftTile.bounds.left,bottomLeftTile.bounds.bottom,topRightTile.bounds.right,topRightTile.bounds.top);}
60663 return bounds;},initSingleTile:function(bounds){var center=bounds.getCenterLonLat();var tileWidth=bounds.getWidth()*this.ratio;var tileHeight=bounds.getHeight()*this.ratio;var tileBounds=new OpenLayers.Bounds(center.lon-(tileWidth/2),center.lat-(tileHeight/2),center.lon+(tileWidth/2),center.lat+(tileHeight/2));var ul=new OpenLayers.LonLat(tileBounds.left,tileBounds.top);var px=this.map.getLayerPxFromLonLat(ul);if(!this.grid.length){this.grid[0]=[];}
60664 var tile=this.grid[0][0];if(!tile){tile=this.addTile(tileBounds,px);this.addTileMonitoringHooks(tile);tile.draw();this.grid[0][0]=tile;}else{tile.moveTo(tileBounds,px);}
60665 this.removeExcessTiles(1,1);},calculateGridLayout:function(bounds,extent,resolution){var tilelon=resolution*this.tileSize.w;var tilelat=resolution*this.tileSize.h;var offsetlon=bounds.left-extent.left;var tilecol=Math.floor(offsetlon/tilelon)-this.buffer;var tilecolremain=offsetlon/tilelon-tilecol;var tileoffsetx=-tilecolremain*this.tileSize.w;var tileoffsetlon=extent.left+tilecol*tilelon;var offsetlat=bounds.top-(extent.bottom+tilelat);var tilerow=Math.ceil(offsetlat/tilelat)+this.buffer;var tilerowremain=tilerow-offsetlat/tilelat;var tileoffsety=-tilerowremain*this.tileSize.h;var tileoffsetlat=extent.bottom+tilerow*tilelat;return{tilelon:tilelon,tilelat:tilelat,tileoffsetlon:tileoffsetlon,tileoffsetlat:tileoffsetlat,tileoffsetx:tileoffsetx,tileoffsety:tileoffsety};},initGriddedTiles:function(bounds){var viewSize=this.map.getSize();var minRows=Math.ceil(viewSize.h/this.tileSize.h)+
60666 Math.max(1,2*this.buffer);var minCols=Math.ceil(viewSize.w/this.tileSize.w)+
60667 Math.max(1,2*this.buffer);var extent=this.getMaxExtent();var resolution=this.map.getResolution();var tileLayout=this.calculateGridLayout(bounds,extent,resolution);var tileoffsetx=Math.round(tileLayout.tileoffsetx);var tileoffsety=Math.round(tileLayout.tileoffsety);var tileoffsetlon=tileLayout.tileoffsetlon;var tileoffsetlat=tileLayout.tileoffsetlat;var tilelon=tileLayout.tilelon;var tilelat=tileLayout.tilelat;this.origin=new OpenLayers.Pixel(tileoffsetx,tileoffsety);var startX=tileoffsetx;var startLon=tileoffsetlon;var rowidx=0;var layerContainerDivLeft=parseInt(this.map.layerContainerDiv.style.left);var layerContainerDivTop=parseInt(this.map.layerContainerDiv.style.top);do{var row=this.grid[rowidx++];if(!row){row=[];this.grid.push(row);}
60668 tileoffsetlon=startLon;tileoffsetx=startX;var colidx=0;do{var tileBounds=new OpenLayers.Bounds(tileoffsetlon,tileoffsetlat,tileoffsetlon+tilelon,tileoffsetlat+tilelat);var x=tileoffsetx;x-=layerContainerDivLeft;var y=tileoffsety;y-=layerContainerDivTop;var px=new OpenLayers.Pixel(x,y);var tile=row[colidx++];if(!tile){tile=this.addTile(tileBounds,px);this.addTileMonitoringHooks(tile);row.push(tile);}else{tile.moveTo(tileBounds,px,false);}
60669 tileoffsetlon+=tilelon;tileoffsetx+=this.tileSize.w;}while((tileoffsetlon<=bounds.right+tilelon*this.buffer)||colidx<minCols);tileoffsetlat-=tilelat;tileoffsety+=this.tileSize.h;}while((tileoffsetlat>=bounds.bottom-tilelat*this.buffer)||rowidx<minRows);this.removeExcessTiles(rowidx,colidx);this.spiralTileLoad();},getMaxExtent:function(){return this.maxExtent;},spiralTileLoad:function(){var tileQueue=[];var directions=["right","down","left","up"];var iRow=0;var iCell=-1;var direction=OpenLayers.Util.indexOf(directions,"right");var directionsTried=0;while(directionsTried<directions.length){var testRow=iRow;var testCell=iCell;switch(directions[direction]){case"right":testCell++;break;case"down":testRow++;break;case"left":testCell--;break;case"up":testRow--;break;}
60670 var tile=null;if((testRow<this.grid.length)&&(testRow>=0)&&(testCell<this.grid[0].length)&&(testCell>=0)){tile=this.grid[testRow][testCell];}
60671 if((tile!=null)&&(!tile.queued)){tileQueue.unshift(tile);tile.queued=true;directionsTried=0;iRow=testRow;iCell=testCell;}else{direction=(direction+1)%4;directionsTried++;}}
60672 for(var i=0,len=tileQueue.length;i<len;i++){var tile=tileQueue[i];tile.draw();tile.queued=false;}},addTile:function(bounds,position){},addTileMonitoringHooks:function(tile){tile.onLoadStart=function(){if(this.numLoadingTiles==0){this.events.triggerEvent("loadstart");}
60673 this.numLoadingTiles++;};tile.events.register("loadstart",this,tile.onLoadStart);tile.onLoadEnd=function(){this.numLoadingTiles--;this.events.triggerEvent("tileloaded");if(this.numLoadingTiles==0){this.events.triggerEvent("loadend");}};tile.events.register("loadend",this,tile.onLoadEnd);tile.events.register("unload",this,tile.onLoadEnd);},removeTileMonitoringHooks:function(tile){tile.unload();tile.events.un({"loadstart":tile.onLoadStart,"loadend":tile.onLoadEnd,"unload":tile.onLoadEnd,scope:this});},moveGriddedTiles:function(bounds){var buffer=this.buffer||1;while(true){var tlLayer=this.grid[0][0].position;var tlViewPort=this.map.getViewPortPxFromLayerPx(tlLayer);if(tlViewPort.x>-this.tileSize.w*(buffer-1)){this.shiftColumn(true);}else if(tlViewPort.x<-this.tileSize.w*buffer){this.shiftColumn(false);}else if(tlViewPort.y>-this.tileSize.h*(buffer-1)){this.shiftRow(true);}else if(tlViewPort.y<-this.tileSize.h*buffer){this.shiftRow(false);}else{break;}};},shiftRow:function(prepend){var modelRowIndex=(prepend)?0:(this.grid.length-1);var grid=this.grid;var modelRow=grid[modelRowIndex];var resolution=this.map.getResolution();var deltaY=(prepend)?-this.tileSize.h:this.tileSize.h;var deltaLat=resolution*-deltaY;var row=(prepend)?grid.pop():grid.shift();for(var i=0,len=modelRow.length;i<len;i++){var modelTile=modelRow[i];var bounds=modelTile.bounds.clone();var position=modelTile.position.clone();bounds.bottom=bounds.bottom+deltaLat;bounds.top=bounds.top+deltaLat;position.y=position.y+deltaY;row[i].moveTo(bounds,position);}
60674 if(prepend){grid.unshift(row);}else{grid.push(row);}},shiftColumn:function(prepend){var deltaX=(prepend)?-this.tileSize.w:this.tileSize.w;var resolution=this.map.getResolution();var deltaLon=resolution*deltaX;for(var i=0,len=this.grid.length;i<len;i++){var row=this.grid[i];var modelTileIndex=(prepend)?0:(row.length-1);var modelTile=row[modelTileIndex];var bounds=modelTile.bounds.clone();var position=modelTile.position.clone();bounds.left=bounds.left+deltaLon;bounds.right=bounds.right+deltaLon;position.x=position.x+deltaX;var tile=prepend?this.grid[i].pop():this.grid[i].shift();tile.moveTo(bounds,position);if(prepend){row.unshift(tile);}else{row.push(tile);}}},removeExcessTiles:function(rows,columns){while(this.grid.length>rows){var row=this.grid.pop();for(var i=0,l=row.length;i<l;i++){var tile=row[i];this.removeTileMonitoringHooks(tile);tile.destroy();}}
60675 while(this.grid[0].length>columns){for(var i=0,l=this.grid.length;i<l;i++){var row=this.grid[i];var tile=row.pop();this.removeTileMonitoringHooks(tile);tile.destroy();}}},onMapResize:function(){if(this.singleTile){this.clearGrid();this.setTileSize();}},getTileBounds:function(viewPortPx){var maxExtent=this.maxExtent;var resolution=this.getResolution();var tileMapWidth=resolution*this.tileSize.w;var tileMapHeight=resolution*this.tileSize.h;var mapPoint=this.getLonLatFromViewPortPx(viewPortPx);var tileLeft=maxExtent.left+(tileMapWidth*Math.floor((mapPoint.lon-
60676 maxExtent.left)/tileMapWidth));var tileBottom=maxExtent.bottom+(tileMapHeight*Math.floor((mapPoint.lat-
60677 maxExtent.bottom)/tileMapHeight));return new OpenLayers.Bounds(tileLeft,tileBottom,tileLeft+tileMapWidth,tileBottom+tileMapHeight);},CLASS_NAME:"OpenLayers.Layer.Grid"});OpenLayers.Layer.MultiMap=OpenLayers.Class(OpenLayers.Layer.EventPane,OpenLayers.Layer.FixedZoomLevels,{MIN_ZOOM_LEVEL:1,MAX_ZOOM_LEVEL:17,RESOLUTIONS:[9,1.40625,0.703125,0.3515625,0.17578125,0.087890625,0.0439453125,0.02197265625,0.010986328125,0.0054931640625,0.00274658203125,0.001373291015625,0.0006866455078125,0.00034332275390625,0.000171661376953125,0.0000858306884765625,0.00004291534423828125],type:null,initialize:function(name,options){OpenLayers.Layer.EventPane.prototype.initialize.apply(this,arguments);OpenLayers.Layer.FixedZoomLevels.prototype.initialize.apply(this,arguments);if(this.sphericalMercator){OpenLayers.Util.extend(this,OpenLayers.Layer.SphericalMercator);this.initMercatorParameters();this.RESOLUTIONS.unshift(10);}},loadMapObject:function(){try{this.mapObject=new MultimapViewer(this.div);}catch(e){}},getWarningHTML:function(){return OpenLayers.i18n("getLayerWarning",{'layerType':"MM",'layerLib':"MultiMap"});},setMapObjectCenter:function(center,zoom){this.mapObject.goToPosition(center,zoom);},getMapObjectCenter:function(){return this.mapObject.getCurrentPosition();},getMapObjectZoom:function(){return this.mapObject.getZoomFactor();},getMapObjectLonLatFromMapObjectPixel:function(moPixel){moPixel.x=moPixel.x-(this.map.getSize().w/2);moPixel.y=moPixel.y-(this.map.getSize().h/2);return this.mapObject.getMapPositionAt(moPixel);},getMapObjectPixelFromMapObjectLonLat:function(moLonLat){return this.mapObject.geoPosToContainerPixels(moLonLat);},getLongitudeFromMapObjectLonLat:function(moLonLat){return this.sphericalMercator?this.forwardMercator(moLonLat.lon,moLonLat.lat).lon:moLonLat.lon;},getLatitudeFromMapObjectLonLat:function(moLonLat){return this.sphericalMercator?this.forwardMercator(moLonLat.lon,moLonLat.lat).lat:moLonLat.lat;},getMapObjectLonLatFromLonLat:function(lon,lat){var mmLatLon;if(this.sphericalMercator){var lonlat=this.inverseMercator(lon,lat);mmLatLon=new MMLatLon(lonlat.lat,lonlat.lon);}else{mmLatLon=new MMLatLon(lat,lon);}
60678 return mmLatLon;},getXFromMapObjectPixel:function(moPixel){return moPixel.x;},getYFromMapObjectPixel:function(moPixel){return moPixel.y;},getMapObjectPixelFromXY:function(x,y){return new MMPoint(x,y);},CLASS_NAME:"OpenLayers.Layer.MultiMap"});OpenLayers.Layer.VirtualEarth=OpenLayers.Class(OpenLayers.Layer.EventPane,OpenLayers.Layer.FixedZoomLevels,{MIN_ZOOM_LEVEL:1,MAX_ZOOM_LEVEL:19,RESOLUTIONS:[1.40625,0.703125,0.3515625,0.17578125,0.087890625,0.0439453125,0.02197265625,0.010986328125,0.0054931640625,0.00274658203125,0.001373291015625,0.0006866455078125,0.00034332275390625,0.000171661376953125,0.0000858306884765625,0.00004291534423828125,0.00002145767211914062,0.00001072883605957031,0.00000536441802978515],type:null,wrapDateLine:true,sphericalMercator:false,animationEnabled:true,initialize:function(name,options){OpenLayers.Layer.EventPane.prototype.initialize.apply(this,arguments);OpenLayers.Layer.FixedZoomLevels.prototype.initialize.apply(this,arguments);if(this.sphericalMercator){OpenLayers.Util.extend(this,OpenLayers.Layer.SphericalMercator);this.initMercatorParameters();}},loadMapObject:function(){var veDiv=OpenLayers.Util.createDiv(this.name);var sz=this.map.getSize();veDiv.style.width=sz.w+"px";veDiv.style.height=sz.h+"px";this.div.appendChild(veDiv);try{this.mapObject=new VEMap(this.name);}catch(e){}
60679 if(this.mapObject!=null){try{this.mapObject.LoadMap(null,null,this.type,true);this.mapObject.AttachEvent("onmousedown",OpenLayers.Function.True);}catch(e){}
60680 this.mapObject.HideDashboard();if(typeof this.mapObject.SetAnimationEnabled=="function"){this.mapObject.SetAnimationEnabled(this.animationEnabled);}}
60681 if(!this.mapObject||!this.mapObject.vemapcontrol||!this.mapObject.vemapcontrol.PanMap||(typeof this.mapObject.vemapcontrol.PanMap!="function")){this.dragPanMapObject=null;}},onMapResize:function(){this.mapObject.Resize(this.map.size.w,this.map.size.h);},getWarningHTML:function(){return OpenLayers.i18n("getLayerWarning",{'layerType':'VE','layerLib':'VirtualEarth'});},setMapObjectCenter:function(center,zoom){this.mapObject.SetCenterAndZoom(center,zoom);},getMapObjectCenter:function(){return this.mapObject.GetCenter();},dragPanMapObject:function(dX,dY){this.mapObject.vemapcontrol.PanMap(dX,-dY);},getMapObjectZoom:function(){return this.mapObject.GetZoomLevel();},getMapObjectLonLatFromMapObjectPixel:function(moPixel){return(typeof VEPixel!='undefined')?this.mapObject.PixelToLatLong(moPixel):this.mapObject.PixelToLatLong(moPixel.x,moPixel.y);},getMapObjectPixelFromMapObjectLonLat:function(moLonLat){return this.mapObject.LatLongToPixel(moLonLat);},getLongitudeFromMapObjectLonLat:function(moLonLat){return this.sphericalMercator?this.forwardMercator(moLonLat.Longitude,moLonLat.Latitude).lon:moLonLat.Longitude;},getLatitudeFromMapObjectLonLat:function(moLonLat){return this.sphericalMercator?this.forwardMercator(moLonLat.Longitude,moLonLat.Latitude).lat:moLonLat.Latitude;},getMapObjectLonLatFromLonLat:function(lon,lat){var veLatLong;if(this.sphericalMercator){var lonlat=this.inverseMercator(lon,lat);veLatLong=new VELatLong(lonlat.lat,lonlat.lon);}else{veLatLong=new VELatLong(lat,lon);}
60682 return veLatLong;},getXFromMapObjectPixel:function(moPixel){return moPixel.x;},getYFromMapObjectPixel:function(moPixel){return moPixel.y;},getMapObjectPixelFromXY:function(x,y){return(typeof VEPixel!='undefined')?new VEPixel(x,y):new Msn.VE.Pixel(x,y);},CLASS_NAME:"OpenLayers.Layer.VirtualEarth"});OpenLayers.Layer.Yahoo=OpenLayers.Class(OpenLayers.Layer.EventPane,OpenLayers.Layer.FixedZoomLevels,{MIN_ZOOM_LEVEL:0,MAX_ZOOM_LEVEL:17,RESOLUTIONS:[1.40625,0.703125,0.3515625,0.17578125,0.087890625,0.0439453125,0.02197265625,0.010986328125,0.0054931640625,0.00274658203125,0.001373291015625,0.0006866455078125,0.00034332275390625,0.000171661376953125,0.0000858306884765625,0.00004291534423828125,0.00002145767211914062,0.00001072883605957031],type:null,wrapDateLine:true,sphericalMercator:false,initialize:function(name,options){OpenLayers.Layer.EventPane.prototype.initialize.apply(this,arguments);OpenLayers.Layer.FixedZoomLevels.prototype.initialize.apply(this,arguments);if(this.sphericalMercator){OpenLayers.Util.extend(this,OpenLayers.Layer.SphericalMercator);this.initMercatorParameters();}},loadMapObject:function(){try{var size=this.getMapObjectSizeFromOLSize(this.map.getSize());this.mapObject=new YMap(this.div,this.type,size);this.mapObject.disableKeyControls();this.mapObject.disableDragMap();if(!this.mapObject.moveByXY||(typeof this.mapObject.moveByXY!="function")){this.dragPanMapObject=null;}}catch(e){}},onMapResize:function(){try{var size=this.getMapObjectSizeFromOLSize(this.map.getSize());this.mapObject.resizeTo(size);}catch(e){}},setMap:function(map){OpenLayers.Layer.EventPane.prototype.setMap.apply(this,arguments);this.map.events.register("moveend",this,this.fixYahooEventPane);},fixYahooEventPane:function(){var yahooEventPane=OpenLayers.Util.getElement("ygddfdiv");if(yahooEventPane!=null){if(yahooEventPane.parentNode!=null){yahooEventPane.parentNode.removeChild(yahooEventPane);}
60683 this.map.events.unregister("moveend",this,this.fixYahooEventPane);}},getWarningHTML:function(){return OpenLayers.i18n("getLayerWarning",{'layerType':'Yahoo','layerLib':'Yahoo'});},getOLZoomFromMapObjectZoom:function(moZoom){var zoom=null;if(moZoom!=null){zoom=OpenLayers.Layer.FixedZoomLevels.prototype.getOLZoomFromMapObjectZoom.apply(this,[moZoom]);zoom=18-zoom;}
60684 return zoom;},getMapObjectZoomFromOLZoom:function(olZoom){var zoom=null;if(olZoom!=null){zoom=OpenLayers.Layer.FixedZoomLevels.prototype.getMapObjectZoomFromOLZoom.apply(this,[olZoom]);zoom=18-zoom;}
60685 return zoom;},setMapObjectCenter:function(center,zoom){this.mapObject.drawZoomAndCenter(center,zoom);},getMapObjectCenter:function(){return this.mapObject.getCenterLatLon();},dragPanMapObject:function(dX,dY){this.mapObject.moveByXY({'x':-dX,'y':dY});},getMapObjectZoom:function(){return this.mapObject.getZoomLevel();},getMapObjectLonLatFromMapObjectPixel:function(moPixel){return this.mapObject.convertXYLatLon(moPixel);},getMapObjectPixelFromMapObjectLonLat:function(moLonLat){return this.mapObject.convertLatLonXY(moLonLat);},getLongitudeFromMapObjectLonLat:function(moLonLat){return this.sphericalMercator?this.forwardMercator(moLonLat.Lon,moLonLat.Lat).lon:moLonLat.Lon;},getLatitudeFromMapObjectLonLat:function(moLonLat){return this.sphericalMercator?this.forwardMercator(moLonLat.Lon,moLonLat.Lat).lat:moLonLat.Lat;},getMapObjectLonLatFromLonLat:function(lon,lat){var yLatLong;if(this.sphericalMercator){var lonlat=this.inverseMercator(lon,lat);yLatLong=new YGeoPoint(lonlat.lat,lonlat.lon);}else{yLatLong=new YGeoPoint(lat,lon);}
60686 return yLatLong;},getXFromMapObjectPixel:function(moPixel){return moPixel.x;},getYFromMapObjectPixel:function(moPixel){return moPixel.y;},getMapObjectPixelFromXY:function(x,y){return new YCoordPoint(x,y);},getMapObjectSizeFromOLSize:function(olSize){return new YSize(olSize.w,olSize.h);},CLASS_NAME:"OpenLayers.Layer.Yahoo"});OpenLayers.Style=OpenLayers.Class({id:null,name:null,title:null,description:null,layerName:null,isDefault:false,rules:null,context:null,defaultStyle:null,defaultsPerSymbolizer:false,propertyStyles:null,initialize:function(style,options){OpenLayers.Util.extend(this,options);this.rules=[];if(options&&options.rules){this.addRules(options.rules);}
60687 this.setDefaultStyle(style||OpenLayers.Feature.Vector.style["default"]);this.id=OpenLayers.Util.createUniqueID(this.CLASS_NAME+"_");},destroy:function(){for(var i=0,len=this.rules.length;i<len;i++){this.rules[i].destroy();this.rules[i]=null;}
60688 this.rules=null;this.defaultStyle=null;},createSymbolizer:function(feature){var style=this.defaultsPerSymbolizer?{}:this.createLiterals(OpenLayers.Util.extend({},this.defaultStyle),feature);var rules=this.rules;var rule,context;var elseRules=[];var appliedRules=false;for(var i=0,len=rules.length;i<len;i++){rule=rules[i];var applies=rule.evaluate(feature);if(applies){if(rule instanceof OpenLayers.Rule&&rule.elseFilter){elseRules.push(rule);}else{appliedRules=true;this.applySymbolizer(rule,style,feature);}}}
60689 if(appliedRules==false&&elseRules.length>0){appliedRules=true;for(var i=0,len=elseRules.length;i<len;i++){this.applySymbolizer(elseRules[i],style,feature);}}
60690 if(rules.length>0&&appliedRules==false){style.display="none";}
60691 return style;},applySymbolizer:function(rule,style,feature){var symbolizerPrefix=feature.geometry?this.getSymbolizerPrefix(feature.geometry):OpenLayers.Style.SYMBOLIZER_PREFIXES[0];var symbolizer=rule.symbolizer[symbolizerPrefix]||rule.symbolizer;if(this.defaultsPerSymbolizer===true){var defaults=this.defaultStyle;OpenLayers.Util.applyDefaults(symbolizer,{pointRadius:defaults.pointRadius});if(symbolizer.stroke===true||symbolizer.graphic===true){OpenLayers.Util.applyDefaults(symbolizer,{strokeWidth:defaults.strokeWidth,strokeColor:defaults.strokeColor,strokeOpacity:defaults.strokeOpacity,strokeDashstyle:defaults.strokeDashstyle,strokeLinecap:defaults.strokeLinecap});}
60692 if(symbolizer.fill===true||symbolizer.graphic===true){OpenLayers.Util.applyDefaults(symbolizer,{fillColor:defaults.fillColor,fillOpacity:defaults.fillOpacity});}
60693 if(symbolizer.graphic===true){OpenLayers.Util.applyDefaults(symbolizer,{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});}}
60694 return this.createLiterals(OpenLayers.Util.extend(style,symbolizer),feature);},createLiterals:function(style,feature){var context=OpenLayers.Util.extend({},feature.attributes||feature.data);OpenLayers.Util.extend(context,this.context);for(var i in this.propertyStyles){style[i]=OpenLayers.Style.createLiteral(style[i],context,feature,i);}
60695 return style;},findPropertyStyles:function(){var propertyStyles={};var style=this.defaultStyle;this.addPropertyStyles(propertyStyles,style);var rules=this.rules;var symbolizer,value;for(var i=0,len=rules.length;i<len;i++){symbolizer=rules[i].symbolizer;for(var key in symbolizer){value=symbolizer[key];if(typeof value=="object"){this.addPropertyStyles(propertyStyles,value);}else{this.addPropertyStyles(propertyStyles,symbolizer);break;}}}
60696 return propertyStyles;},addPropertyStyles:function(propertyStyles,symbolizer){var property;for(var key in symbolizer){property=symbolizer[key];if(typeof property=="string"&&property.match(/\$\{\w+\}/)){propertyStyles[key]=true;}}
60697 return propertyStyles;},addRules:function(rules){Array.prototype.push.apply(this.rules,rules);this.propertyStyles=this.findPropertyStyles();},setDefaultStyle:function(style){this.defaultStyle=style;this.propertyStyles=this.findPropertyStyles();},getSymbolizerPrefix:function(geometry){var prefixes=OpenLayers.Style.SYMBOLIZER_PREFIXES;for(var i=0,len=prefixes.length;i<len;i++){if(geometry.CLASS_NAME.indexOf(prefixes[i])!=-1){return prefixes[i];}}},clone:function(){var options=OpenLayers.Util.extend({},this);if(this.rules){options.rules=[];for(var i=0,len=this.rules.length;i<len;++i){options.rules.push(this.rules[i].clone());}}
60698 options.context=this.context&&OpenLayers.Util.extend({},this.context);var defaultStyle=OpenLayers.Util.extend({},this.defaultStyle);return new OpenLayers.Style(defaultStyle,options);},CLASS_NAME:"OpenLayers.Style"});OpenLayers.Style.createLiteral=function(value,context,feature,property){if(typeof value=="string"&&value.indexOf("${")!=-1){value=OpenLayers.String.format(value,context,[feature,property]);value=(isNaN(value)||!value)?value:parseFloat(value);}
60699 return value;};OpenLayers.Style.SYMBOLIZER_PREFIXES=['Point','Line','Polygon','Text','Raster'];OpenLayers.Control.Navigation=OpenLayers.Class(OpenLayers.Control,{dragPan:null,dragPanOptions:null,documentDrag:false,zoomBox:null,zoomBoxEnabled:true,zoomWheelEnabled:true,mouseWheelOptions:null,handleRightClicks:false,zoomBoxKeyMask:OpenLayers.Handler.MOD_SHIFT,autoActivate:true,initialize:function(options){this.handlers={};OpenLayers.Control.prototype.initialize.apply(this,arguments);},destroy:function(){this.deactivate();if(this.dragPan){this.dragPan.destroy();}
60700 this.dragPan=null;if(this.zoomBox){this.zoomBox.destroy();}
60701 this.zoomBox=null;OpenLayers.Control.prototype.destroy.apply(this,arguments);},activate:function(){this.dragPan.activate();if(this.zoomWheelEnabled){this.handlers.wheel.activate();}
60702 this.handlers.click.activate();if(this.zoomBoxEnabled){this.zoomBox.activate();}
60703 return OpenLayers.Control.prototype.activate.apply(this,arguments);},deactivate:function(){this.zoomBox.deactivate();this.dragPan.deactivate();this.handlers.click.deactivate();this.handlers.wheel.deactivate();return OpenLayers.Control.prototype.deactivate.apply(this,arguments);},draw:function(){if(this.handleRightClicks){this.map.viewPortDiv.oncontextmenu=OpenLayers.Function.False;}
60704 var clickCallbacks={'dblclick':this.defaultDblClick,'dblrightclick':this.defaultDblRightClick};var clickOptions={'double':true,'stopDouble':true};this.handlers.click=new OpenLayers.Handler.Click(this,clickCallbacks,clickOptions);this.dragPan=new OpenLayers.Control.DragPan(OpenLayers.Util.extend({map:this.map,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},this.mouseWheelOptions);},defaultDblClick:function(evt){var newCenter=this.map.getLonLatFromViewPortPx(evt.xy);this.map.setCenter(newCenter,this.map.zoom+1);},defaultDblRightClick:function(evt){var newCenter=this.map.getLonLatFromViewPortPx(evt.xy);this.map.setCenter(newCenter,this.map.zoom-1);},wheelChange:function(evt,deltaZ){var currentZoom=this.map.getZoom();var newZoom=this.map.getZoom()+Math.round(deltaZ);newZoom=Math.max(newZoom,0);newZoom=Math.min(newZoom,this.map.getNumZoomLevels());if(newZoom===currentZoom){return;}
60705 var size=this.map.getSize();var deltaX=size.w/2-evt.xy.x;var deltaY=evt.xy.y-size.h/2;var newRes=this.map.baseLayer.getResolutionForZoom(newZoom);var zoomPoint=this.map.getLonLatFromPixel(evt.xy);var newCenter=new OpenLayers.LonLat(zoomPoint.lon+deltaX*newRes,zoomPoint.lat+deltaY*newRes);this.map.setCenter(newCenter,newZoom);},wheelUp:function(evt,delta){this.wheelChange(evt,delta||1);},wheelDown:function(evt,delta){this.wheelChange(evt,delta||-1);},disableZoomBox:function(){this.zoomBoxEnabled=false;this.zoomBox.deactivate();},enableZoomBox:function(){this.zoomBoxEnabled=true;if(this.active){this.zoomBox.activate();}},disableZoomWheel:function(){this.zoomWheelEnabled=false;this.handlers.wheel.deactivate();},enableZoomWheel:function(){this.zoomWheelEnabled=true;if(this.active){this.handlers.wheel.activate();}},CLASS_NAME:"OpenLayers.Control.Navigation"});OpenLayers.Filter=OpenLayers.Class({initialize:function(options){OpenLayers.Util.extend(this,options);},destroy:function(){},evaluate:function(context){return true;},clone:function(){return null;},CLASS_NAME:"OpenLayers.Filter"});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(options){OpenLayers.Format.WMC.v1.prototype.initialize.apply(this,[options]);},write_wmc_Layer:function(context){var node=OpenLayers.Format.WMC.v1.prototype.write_wmc_Layer.apply(this,[context]);node.appendChild(this.write_wmc_FormatList(context));node.appendChild(this.write_wmc_StyleList(context));node.appendChild(this.write_wmc_LayerExtension(context));},CLASS_NAME:"OpenLayers.Format.WMC.v1_0_0"});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(options){OpenLayers.Format.WMC.v1.prototype.initialize.apply(this,[options]);},read_sld_MinScaleDenominator:function(layerContext,node){var minScaleDenominator=parseFloat(this.getChildValue(node));if(minScaleDenominator>0){layerContext.maxScale=minScaleDenominator;}},read_sld_MaxScaleDenominator:function(layerContext,node){layerContext.minScale=parseFloat(this.getChildValue(node));},write_wmc_Layer:function(context){var node=OpenLayers.Format.WMC.v1.prototype.write_wmc_Layer.apply(this,[context]);if(context.maxScale){var minSD=this.createElementNS(this.namespaces.sld,"sld:MinScaleDenominator");minSD.appendChild(this.createTextNode(context.maxScale.toPrecision(16)));node.appendChild(minSD);}
60706 if(context.minScale){var maxSD=this.createElementNS(this.namespaces.sld,"sld:MaxScaleDenominator");maxSD.appendChild(this.createTextNode(context.minScale.toPrecision(16)));node.appendChild(maxSD);}
60707 node.appendChild(this.write_wmc_FormatList(context));node.appendChild(this.write_wmc_StyleList(context));node.appendChild(this.write_wmc_LayerExtension(context));return node;},CLASS_NAME:"OpenLayers.Format.WMC.v1_1_0"});OpenLayers.Format.WMSCapabilities.v1_1_0=OpenLayers.Class(OpenLayers.Format.WMSCapabilities.v1_1,{version:"1.1.0",initialize:function(options){OpenLayers.Format.WMSCapabilities.v1_1.prototype.initialize.apply(this,[options]);},readers:{"wms":OpenLayers.Util.applyDefaults({"SRS":function(node,obj){var srs=this.getChildValue(node);var values=srs.split(/ +/);for(var i=0,len=values.length;i<len;i++){obj.srs[values[i]]=true;}}},OpenLayers.Format.WMSCapabilities.v1_1.prototype.readers["wms"])},CLASS_NAME:"OpenLayers.Format.WMSCapabilities.v1_1_0"});OpenLayers.Format.WMSCapabilities.v1_1_1=OpenLayers.Class(OpenLayers.Format.WMSCapabilities.v1_1,{version:"1.1.1",initialize:function(options){OpenLayers.Format.WMSCapabilities.v1_1.prototype.initialize.apply(this,[options]);},readers:{"wms":OpenLayers.Util.applyDefaults({"SRS":function(node,obj){obj.srs[this.getChildValue(node)]=true;}},OpenLayers.Format.WMSCapabilities.v1_1.prototype.readers["wms"])},CLASS_NAME:"OpenLayers.Format.WMSCapabilities.v1_1_1"});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.Geometry=OpenLayers.Class({id:null,parent:null,bounds:null,initialize:function(){this.id=OpenLayers.Util.createUniqueID(this.CLASS_NAME+"_");},destroy:function(){this.id=null;this.bounds=null;},clone:function(){return new OpenLayers.Geometry();},setBounds:function(bounds){if(bounds){this.bounds=bounds.clone();}},clearBounds:function(){this.bounds=null;if(this.parent){this.parent.clearBounds();}},extendBounds:function(newBounds){var bounds=this.getBounds();if(!bounds){this.setBounds(newBounds);}else{this.bounds.extend(newBounds);}},getBounds:function(){if(this.bounds==null){this.calculateBounds();}
60708 return this.bounds;},calculateBounds:function(){},distanceTo:function(geometry,options){},getVertices:function(nodes){},atPoint:function(lonlat,toleranceLon,toleranceLat){var atPoint=false;var bounds=this.getBounds();if((bounds!=null)&&(lonlat!=null)){var dX=(toleranceLon!=null)?toleranceLon:0;var dY=(toleranceLat!=null)?toleranceLat:0;var toleranceBounds=new OpenLayers.Bounds(this.bounds.left-dX,this.bounds.bottom-dY,this.bounds.right+dX,this.bounds.top+dY);atPoint=toleranceBounds.containsLonLat(lonlat);}
60709 return atPoint;},getLength:function(){return 0.0;},getArea:function(){return 0.0;},getCentroid:function(){return null;},toString:function(){return OpenLayers.Format.WKT.prototype.write(new OpenLayers.Feature.Vector(this));},CLASS_NAME:"OpenLayers.Geometry"});OpenLayers.Geometry.fromWKT=function(wkt){var format=arguments.callee.format;if(!format){format=new OpenLayers.Format.WKT();arguments.callee.format=format;}
60710 var geom;var result=format.read(wkt);if(result instanceof OpenLayers.Feature.Vector){geom=result.geometry;}else if(result instanceof Array){var len=result.length;var components=new Array(len);for(var i=0;i<len;++i){components[i]=result[i].geometry;}
60711 geom=new OpenLayers.Geometry.Collection(components);}
60712 return geom;};OpenLayers.Geometry.segmentsIntersect=function(seg1,seg2,options){var point=options&&options.point;var tolerance=options&&options.tolerance;var intersection=false;var x11_21=seg1.x1-seg2.x1;var y11_21=seg1.y1-seg2.y1;var x12_11=seg1.x2-seg1.x1;var y12_11=seg1.y2-seg1.y1;var y22_21=seg2.y2-seg2.y1;var x22_21=seg2.x2-seg2.x1;var d=(y22_21*x12_11)-(x22_21*y12_11);var n1=(x22_21*y11_21)-(y22_21*x11_21);var n2=(x12_11*y11_21)-(y12_11*x11_21);if(d==0){if(n1==0&&n2==0){intersection=true;}}else{var along1=n1/d;var along2=n2/d;if(along1>=0&&along1<=1&&along2>=0&&along2<=1){if(!point){intersection=true;}else{var x=seg1.x1+(along1*x12_11);var y=seg1.y1+(along1*y12_11);intersection=new OpenLayers.Geometry.Point(x,y);}}}
60713 if(tolerance){var dist;if(intersection){if(point){var segs=[seg1,seg2];var seg,x,y;outer:for(var i=0;i<2;++i){seg=segs[i];for(var j=1;j<3;++j){x=seg["x"+j];y=seg["y"+j];dist=Math.sqrt(Math.pow(x-intersection.x,2)+
60714 Math.pow(y-intersection.y,2));if(dist<tolerance){intersection.x=x;intersection.y=y;break outer;}}}}}else{var segs=[seg1,seg2];var source,target,x,y,p,result;outer:for(var i=0;i<2;++i){source=segs[i];target=segs[(i+1)%2];for(var j=1;j<3;++j){p={x:source["x"+j],y:source["y"+j]};result=OpenLayers.Geometry.distanceToSegment(p,target);if(result.distance<tolerance){if(point){intersection=new OpenLayers.Geometry.Point(p.x,p.y);}else{intersection=true;}
60715 break outer;}}}}}
60716 return intersection;};OpenLayers.Geometry.distanceToSegment=function(point,segment){var x0=point.x;var y0=point.y;var x1=segment.x1;var y1=segment.y1;var x2=segment.x2;var y2=segment.y2;var dx=x2-x1;var dy=y2-y1;var along=((dx*(x0-x1))+(dy*(y0-y1)))/(Math.pow(dx,2)+Math.pow(dy,2));var x,y;if(along<=0.0){x=x1;y=y1;}else if(along>=1.0){x=x2;y=y2;}else{x=x1+along*dx;y=y1+along*dy;}
60717 return{distance:Math.sqrt(Math.pow(x-x0,2)+Math.pow(y-y0,2)),x:x,y:y};};OpenLayers.Layer.ArcGIS93Rest=OpenLayers.Class(OpenLayers.Layer.Grid,{DEFAULT_PARAMS:{format:"png"},isBaseLayer:true,initialize:function(name,url,params,options){var newArguments=[];params=OpenLayers.Util.upperCaseObject(params);newArguments.push(name,url,params,options);OpenLayers.Layer.Grid.prototype.initialize.apply(this,newArguments);OpenLayers.Util.applyDefaults(this.params,OpenLayers.Util.upperCaseObject(this.DEFAULT_PARAMS));if(this.params.TRANSPARENT&&this.params.TRANSPARENT.toString().toLowerCase()=="true"){if((options==null)||(!options.isBaseLayer)){this.isBaseLayer=false;}
60718 if(this.params.FORMAT=="jpg"){this.params.FORMAT=OpenLayers.Util.alphaHack()?"gif":"png";}}},destroy:function(){OpenLayers.Layer.Grid.prototype.destroy.apply(this,arguments);},clone:function(obj){if(obj==null){obj=new OpenLayers.Layer.ArcGIS93Rest(this.name,this.url,this.params,this.getOptions());}
60719 obj=OpenLayers.Layer.Grid.prototype.clone.apply(this,[obj]);return obj;},getURL:function(bounds){bounds=this.adjustBounds(bounds);var projWords=this.projection.getCode().split(":");var srid=projWords[projWords.length-1];var imageSize=this.getImageSize();var newParams={'BBOX':bounds.toBBOX(),'SIZE':imageSize.w+","+imageSize.h,'F':"image",'BBOXSR':srid,'IMAGESR':srid};if(this.layerDefs){var layerDefStrList=[];var layerID;for(layerID in this.layerDefs){if(this.layerDefs.hasOwnProperty(layerID)){if(this.layerDefs[layerID]){layerDefStrList.push(layerID);layerDefStrList.push(":");layerDefStrList.push(this.layerDefs[layerID]);layerDefStrList.push(";");}}}
60720 if(layerDefStrList.length>0){newParams['LAYERDEFS']=layerDefStrList.join("");}}
60721 var requestString=this.getFullRequestString(newParams);return requestString;},setLayerFilter:function(id,queryDef){if(!this.layerDefs){this.layerDefs={};}
60722 if(queryDef){this.layerDefs[id]=queryDef;}else{delete this.layerDefs[id];}},clearLayerFilter:function(id){if(id){delete this.layerDefs[id];}else{delete this.layerDefs;}},mergeNewParams:function(newParams){var upperParams=OpenLayers.Util.upperCaseObject(newParams);var newArguments=[upperParams];return OpenLayers.Layer.Grid.prototype.mergeNewParams.apply(this,newArguments);},addTile:function(bounds,position){return new OpenLayers.Tile.Image(this,position,bounds,null,this.tileSize);},CLASS_NAME:"OpenLayers.Layer.ArcGIS93Rest"});OpenLayers.Layer.Google.v3={DEFAULTS:{maxExtent:new OpenLayers.Bounds(-128*156543.0339,-128*156543.0339,128*156543.0339,128*156543.0339),sphericalMercator:true,maxResolution:156543.0339,units:"m",projection:"EPSG:900913"},loadMapObject:function(){if(!this.type){this.type=google.maps.MapTypeId.ROADMAP;}
60723 var mapObject;var cache=OpenLayers.Layer.Google.cache[this.map.id];if(cache){mapObject=cache.mapObject;++cache.count;}else{var container=this.map.viewPortDiv;var div=document.createElement("div");div.id=this.map.id+"_GMapContainer";div.style.position="absolute";div.style.width="100%";div.style.height="100%";container.appendChild(div);var center=this.map.getCenter();mapObject=new google.maps.Map(div,{center:center?new google.maps.LatLng(center.lat,center.lon):new google.maps.LatLng(0,0),zoom:this.map.getZoom()||0,mapTypeId:this.type,disableDefaultUI:true,keyboardShortcuts:false,draggable:false,disableDoubleClickZoom:true,scrollwheel:false});cache={mapObject:mapObject,count:1};OpenLayers.Layer.Google.cache[this.map.id]=cache;this.repositionListener=google.maps.event.addListenerOnce(mapObject,"center_changed",OpenLayers.Function.bind(this.repositionMapElements,this));}
60724 this.mapObject=mapObject;this.setGMapVisibility(this.visibility);},repositionMapElements:function(){google.maps.event.trigger(this.mapObject,"resize");var div=this.mapObject.getDiv().firstChild;if(!div||div.childNodes.length<3){this.repositionTimer=window.setTimeout(OpenLayers.Function.bind(this.repositionMapElements,this),250);return false;}
60725 var cache=OpenLayers.Layer.Google.cache[this.map.id];var container=this.map.viewPortDiv;var termsOfUse=div.lastChild;container.appendChild(termsOfUse);termsOfUse.style.zIndex="1100";termsOfUse.style.bottom="";termsOfUse.className="olLayerGoogleCopyright olLayerGoogleV3";termsOfUse.style.display="";cache.termsOfUse=termsOfUse;var poweredBy=div.lastChild;container.appendChild(poweredBy);poweredBy.style.zIndex="1100";poweredBy.style.bottom="";poweredBy.className="olLayerGooglePoweredBy olLayerGoogleV3 gmnoprint";poweredBy.style.display="";cache.poweredBy=poweredBy;this.setGMapVisibility(this.visibility);},onMapResize:function(){if(this.visibility){google.maps.event.trigger(this.mapObject,"resize");}else{if(!this._resized){var layer=this;google.maps.event.addListenerOnce(this.mapObject,"tilesloaded",function(){delete layer._resized;google.maps.event.trigger(layer.mapObject,"resize");layer.moveTo(layer.map.getCenter(),layer.map.getZoom());});}
60726 this._resized=true;}},setGMapVisibility:function(visible){var cache=OpenLayers.Layer.Google.cache[this.map.id];if(cache){var type=this.type;var layers=this.map.layers;var layer;for(var i=layers.length-1;i>=0;--i){layer=layers[i];if(layer instanceof OpenLayers.Layer.Google&&layer.visibility===true&&layer.inRange===true){type=layer.type;visible=true;break;}}
60727 var container=this.mapObject.getDiv();if(visible===true){this.mapObject.setMapTypeId(type);container.style.left="";if(cache.termsOfUse&&cache.termsOfUse.style){cache.termsOfUse.style.left="";cache.termsOfUse.style.display="";cache.poweredBy.style.display="";}
60728 cache.displayed=this.id;}else{delete cache.displayed;container.style.left="-9999px";if(cache.termsOfUse&&cache.termsOfUse.style){cache.termsOfUse.style.display="none";cache.termsOfUse.style.left="-9999px";cache.poweredBy.style.display="none";}}}},getMapContainer:function(){return this.mapObject.getDiv();},getMapObjectBoundsFromOLBounds:function(olBounds){var moBounds=null;if(olBounds!=null){var sw=this.sphericalMercator?this.inverseMercator(olBounds.bottom,olBounds.left):new OpenLayers.LonLat(olBounds.bottom,olBounds.left);var ne=this.sphericalMercator?this.inverseMercator(olBounds.top,olBounds.right):new OpenLayers.LonLat(olBounds.top,olBounds.right);moBounds=new google.maps.LatLngBounds(new google.maps.LatLng(sw.lat,sw.lon),new google.maps.LatLng(ne.lat,ne.lon));}
60729 return moBounds;},getMapObjectLonLatFromMapObjectPixel:function(moPixel){var size=this.map.getSize();var lon=this.getLongitudeFromMapObjectLonLat(this.mapObject.center);var lat=this.getLatitudeFromMapObjectLonLat(this.mapObject.center);var res=this.map.getResolution();var delta_x=moPixel.x-(size.w/2);var delta_y=moPixel.y-(size.h/2);var lonlat=new OpenLayers.LonLat(lon+delta_x*res,lat-delta_y*res);if(this.wrapDateLine){lonlat=lonlat.wrapDateLine(this.maxExtent);}
60730 return this.getMapObjectLonLatFromLonLat(lonlat.lon,lonlat.lat);},getMapObjectPixelFromMapObjectLonLat:function(moLonLat){var lon=this.getLongitudeFromMapObjectLonLat(moLonLat);var lat=this.getLatitudeFromMapObjectLonLat(moLonLat);var res=this.map.getResolution();var extent=this.map.getExtent();var px=new OpenLayers.Pixel((1/res*(lon-extent.left)),(1/res*(extent.top-lat)));return this.getMapObjectPixelFromXY(px.x,px.y);},setMapObjectCenter:function(center,zoom){this.mapObject.setOptions({center:center,zoom:zoom});},getMapObjectZoomFromMapObjectBounds:function(moBounds){return this.mapObject.getBoundsZoomLevel(moBounds);},getMapObjectLonLatFromLonLat:function(lon,lat){var gLatLng;if(this.sphericalMercator){var lonlat=this.inverseMercator(lon,lat);gLatLng=new google.maps.LatLng(lonlat.lat,lonlat.lon);}else{gLatLng=new google.maps.LatLng(lat,lon);}
60731 return gLatLng;},getMapObjectPixelFromXY:function(x,y){return new google.maps.Point(x,y);},destroy:function(){if(this.repositionListener){google.maps.event.removeListener(this.repositionListener);}
60732 if(this.repositionTimer){window.clearTimeout(this.repositionTimer);}
60733 OpenLayers.Layer.Google.prototype.destroy.apply(this,arguments);}};OpenLayers.Layer.KaMap=OpenLayers.Class(OpenLayers.Layer.Grid,{isBaseLayer:true,units:null,resolution:OpenLayers.DOTS_PER_INCH,DEFAULT_PARAMS:{i:'jpeg',map:''},initialize:function(name,url,params,options){var newArguments=[];newArguments.push(name,url,params,options);OpenLayers.Layer.Grid.prototype.initialize.apply(this,newArguments);this.params=OpenLayers.Util.applyDefaults(this.params,this.DEFAULT_PARAMS);},getURL:function(bounds){bounds=this.adjustBounds(bounds);var mapRes=this.map.getResolution();var scale=Math.round((this.map.getScale()*10000))/10000;var pX=Math.round(bounds.left/mapRes);var pY=-Math.round(bounds.top/mapRes);return this.getFullRequestString({t:pY,l:pX,s:scale});},addTile:function(bounds,position){var url=this.getURL(bounds);return new OpenLayers.Tile.Image(this,position,bounds,url,this.tileSize);},calculateGridLayout:function(bounds,extent,resolution){var tilelon=resolution*this.tileSize.w;var tilelat=resolution*this.tileSize.h;var offsetlon=bounds.left;var tilecol=Math.floor(offsetlon/tilelon)-this.buffer;var tilecolremain=offsetlon/tilelon-tilecol;var tileoffsetx=-tilecolremain*this.tileSize.w;var tileoffsetlon=tilecol*tilelon;var offsetlat=bounds.top;var tilerow=Math.ceil(offsetlat/tilelat)+this.buffer;var tilerowremain=tilerow-offsetlat/tilelat;var tileoffsety=-(tilerowremain+1)*this.tileSize.h;var tileoffsetlat=tilerow*tilelat;return{tilelon:tilelon,tilelat:tilelat,tileoffsetlon:tileoffsetlon,tileoffsetlat:tileoffsetlat,tileoffsetx:tileoffsetx,tileoffsety:tileoffsety};},clone:function(obj){if(obj==null){obj=new OpenLayers.Layer.KaMap(this.name,this.url,this.params,this.getOptions());}
60734 obj=OpenLayers.Layer.Grid.prototype.clone.apply(this,[obj]);if(this.tileSize!=null){obj.tileSize=this.tileSize.clone();}
60735 obj.grid=[];return obj;},getTileBounds:function(viewPortPx){var resolution=this.getResolution();var tileMapWidth=resolution*this.tileSize.w;var tileMapHeight=resolution*this.tileSize.h;var mapPoint=this.getLonLatFromViewPortPx(viewPortPx);var tileLeft=tileMapWidth*Math.floor(mapPoint.lon/tileMapWidth);var tileBottom=tileMapHeight*Math.floor(mapPoint.lat/tileMapHeight);return new OpenLayers.Bounds(tileLeft,tileBottom,tileLeft+tileMapWidth,tileBottom+tileMapHeight);},CLASS_NAME:"OpenLayers.Layer.KaMap"});OpenLayers.Layer.MapGuide=OpenLayers.Class(OpenLayers.Layer.Grid,{isBaseLayer:true,useHttpTile:false,singleTile:false,useOverlay:false,useAsyncOverlay:true,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,300),initialize:function(name,url,params,options){OpenLayers.Layer.Grid.prototype.initialize.apply(this,arguments);if(options==null||options.isBaseLayer==null){this.isBaseLayer=((this.transparent!="true")&&(this.transparent!=true));}
60736 if(options&&options.useOverlay!=null){this.useOverlay=options.useOverlay;}
60737 if(this.singleTile){if(this.useOverlay){OpenLayers.Util.applyDefaults(this.params,this.OVERLAY_PARAMS);if(!this.useAsyncOverlay){this.params.version="1.0.0";}}else{OpenLayers.Util.applyDefaults(this.params,this.SINGLE_TILE_PARAMS);}}else{if(this.useHttpTile){OpenLayers.Util.applyDefaults(this.params,this.FOLDER_PARAMS);}else{OpenLayers.Util.applyDefaults(this.params,this.TILE_PARAMS);}
60738 this.setTileSize(this.defaultSize);}},clone:function(obj){if(obj==null){obj=new OpenLayers.Layer.MapGuide(this.name,this.url,this.params,this.getOptions());}
60739 obj=OpenLayers.Layer.Grid.prototype.clone.apply(this,[obj]);return obj;},addTile:function(bounds,position){return new OpenLayers.Tile.Image(this,position,bounds,null,this.tileSize);},getURL:function(bounds){var url;var center=bounds.getCenterLonLat();var mapSize=this.map.getSize();if(this.singleTile){var params={setdisplaydpi:OpenLayers.DOTS_PER_INCH,setdisplayheight:mapSize.h*this.ratio,setdisplaywidth:mapSize.w*this.ratio,setviewcenterx:center.lon,setviewcentery:center.lat,setviewscale:this.map.getScale()};if(this.useOverlay&&!this.useAsyncOverlay){var getVisParams={};getVisParams=OpenLayers.Util.extend(getVisParams,params);getVisParams.operation="GETVISIBLEMAPEXTENT";getVisParams.version="1.0.0";getVisParams.session=this.params.session;getVisParams.mapName=this.params.mapName;getVisParams.format='text/xml';url=this.getFullRequestString(getVisParams);OpenLayers.Request.GET({url:url,async:false});}
60740 url=this.getFullRequestString(params);}else{var currentRes=this.map.getResolution();var colidx=Math.floor((bounds.left-this.maxExtent.left)/currentRes);colidx=Math.round(colidx/this.tileSize.w);var rowidx=Math.floor((this.maxExtent.top-bounds.top)/currentRes);rowidx=Math.round(rowidx/this.tileSize.h);if(this.useHttpTile){url=this.getImageFilePath({tilecol:colidx,tilerow:rowidx,scaleindex:this.resolutions.length-this.map.zoom-1});}else{url=this.getFullRequestString({tilecol:colidx,tilerow:rowidx,scaleindex:this.resolutions.length-this.map.zoom-1});}}
60741 return url;},getFullRequestString:function(newParams,altUrl){var url=(altUrl==null)?this.url:altUrl;if(typeof url=="object"){url=url[Math.floor(Math.random()*url.length)];}
60742 var requestString=url;var allParams=OpenLayers.Util.extend({},this.params);allParams=OpenLayers.Util.extend(allParams,newParams);var urlParams=OpenLayers.Util.upperCaseObject(OpenLayers.Util.getParameters(url));for(var key in allParams){if(key.toUpperCase()in urlParams){delete allParams[key];}}
60743 var paramsString=OpenLayers.Util.getParameterString(allParams);paramsString=paramsString.replace(/,/g,"+");if(paramsString!=""){var lastServerChar=url.charAt(url.length-1);if((lastServerChar=="&")||(lastServerChar=="?")){requestString+=paramsString;}else{if(url.indexOf('?')==-1){requestString+='?'+paramsString;}else{requestString+='&'+paramsString;}}}
60744 return requestString;},getImageFilePath:function(newParams,altUrl){var url=(altUrl==null)?this.url:altUrl;if(typeof url=="object"){url=url[Math.floor(Math.random()*url.length)];}
60745 var requestString=url;var tileRowGroup="";var tileColGroup="";if(newParams.tilerow<0){tileRowGroup='-';}
60746 if(newParams.tilerow==0){tileRowGroup+='0';}else{tileRowGroup+=Math.floor(Math.abs(newParams.tilerow/this.params.tileRowsPerFolder))*this.params.tileRowsPerFolder;}
60747 if(newParams.tilecol<0){tileColGroup='-';}
60748 if(newParams.tilecol==0){tileColGroup+='0';}else{tileColGroup+=Math.floor(Math.abs(newParams.tilecol/this.params.tileColumnsPerFolder))*this.params.tileColumnsPerFolder;}
60749 var tilePath='/S'+Math.floor(newParams.scaleindex)
60750 +'/'+this.params.basemaplayergroupname
60751 +'/R'+tileRowGroup
60752 +'/C'+tileColGroup
60753 +'/'+(newParams.tilerow%this.params.tileRowsPerFolder)
60754 +'_'+(newParams.tilecol%this.params.tileColumnsPerFolder)
60755 +'.'+this.params.format;if(this.params.querystring){tilePath+="?"+this.params.querystring;}
60756 requestString+=tilePath;return requestString;},calculateGridLayout:function(bounds,extent,resolution){var tilelon=resolution*this.tileSize.w;var tilelat=resolution*this.tileSize.h;var offsetlon=bounds.left-extent.left;var tilecol=Math.floor(offsetlon/tilelon)-this.buffer;var tilecolremain=offsetlon/tilelon-tilecol;var tileoffsetx=-tilecolremain*this.tileSize.w;var tileoffsetlon=extent.left+tilecol*tilelon;var offsetlat=extent.top-bounds.top+tilelat;var tilerow=Math.floor(offsetlat/tilelat)-this.buffer;var tilerowremain=tilerow-offsetlat/tilelat;var tileoffsety=tilerowremain*this.tileSize.h;var tileoffsetlat=extent.top-tilelat*tilerow;return{tilelon:tilelon,tilelat:tilelat,tileoffsetlon:tileoffsetlon,tileoffsetlat:tileoffsetlat,tileoffsetx:tileoffsetx,tileoffsety:tileoffsety};},CLASS_NAME:"OpenLayers.Layer.MapGuide"});OpenLayers.Layer.MapServer=OpenLayers.Class(OpenLayers.Layer.Grid,{DEFAULT_PARAMS:{mode:"map",map_imagetype:"png"},initialize:function(name,url,params,options){var newArguments=[];newArguments.push(name,url,params,options);OpenLayers.Layer.Grid.prototype.initialize.apply(this,newArguments);this.params=OpenLayers.Util.applyDefaults(this.params,this.DEFAULT_PARAMS);if(options==null||options.isBaseLayer==null){this.isBaseLayer=((this.params.transparent!="true")&&(this.params.transparent!=true));}},clone:function(obj){if(obj==null){obj=new OpenLayers.Layer.MapServer(this.name,this.url,this.params,this.getOptions());}
60757 obj=OpenLayers.Layer.Grid.prototype.clone.apply(this,[obj]);return obj;},addTile:function(bounds,position){return new OpenLayers.Tile.Image(this,position,bounds,null,this.tileSize);},getURL:function(bounds){bounds=this.adjustBounds(bounds);var extent=[bounds.left,bounds.bottom,bounds.right,bounds.top];var imageSize=this.getImageSize();var url=this.getFullRequestString({mapext:extent,imgext:extent,map_size:[imageSize.w,imageSize.h],imgx:imageSize.w/2,imgy:imageSize.h/2,imgxy:[imageSize.w,imageSize.h]});return url;},getFullRequestString:function(newParams,altUrl){var url=(altUrl==null)?this.url:altUrl;var allParams=OpenLayers.Util.extend({},this.params);allParams=OpenLayers.Util.extend(allParams,newParams);var paramsString=OpenLayers.Util.getParameterString(allParams);if(url instanceof Array){url=this.selectUrl(paramsString,url);}
60758 var urlParams=OpenLayers.Util.upperCaseObject(OpenLayers.Util.getParameters(url));for(var key in allParams){if(key.toUpperCase()in urlParams){delete allParams[key];}}
60759 paramsString=OpenLayers.Util.getParameterString(allParams);var requestString=url;paramsString=paramsString.replace(/,/g,"+");if(paramsString!=""){var lastServerChar=url.charAt(url.length-1);if((lastServerChar=="&")||(lastServerChar=="?")){requestString+=paramsString;}else{if(url.indexOf('?')==-1){requestString+='?'+paramsString;}else{requestString+='&'+paramsString;}}}
60760 return requestString;},CLASS_NAME:"OpenLayers.Layer.MapServer"});OpenLayers.Layer.TMS=OpenLayers.Class(OpenLayers.Layer.Grid,{serviceVersion:"1.0.0",isBaseLayer:true,tileOrigin:null,serverResolutions:null,zoomOffset:0,initialize:function(name,url,options){var newArguments=[];newArguments.push(name,url,{},options);OpenLayers.Layer.Grid.prototype.initialize.apply(this,newArguments);},destroy:function(){OpenLayers.Layer.Grid.prototype.destroy.apply(this,arguments);},clone:function(obj){if(obj==null){obj=new OpenLayers.Layer.TMS(this.name,this.url,this.getOptions());}
60761 obj=OpenLayers.Layer.Grid.prototype.clone.apply(this,[obj]);return obj;},getURL:function(bounds){bounds=this.adjustBounds(bounds);var res=this.map.getResolution();var x=Math.round((bounds.left-this.tileOrigin.lon)/(res*this.tileSize.w));var y=Math.round((bounds.bottom-this.tileOrigin.lat)/(res*this.tileSize.h));var z=this.serverResolutions!=null?OpenLayers.Util.indexOf(this.serverResolutions,res):this.map.getZoom()+this.zoomOffset;var path=this.serviceVersion+"/"+this.layername+"/"+z+"/"+x+"/"+y+"."+this.type;var url=this.url;if(url instanceof Array){url=this.selectUrl(path,url);}
60762 return url+path;},addTile:function(bounds,position){return new OpenLayers.Tile.Image(this,position,bounds,null,this.tileSize);},setMap:function(map){OpenLayers.Layer.Grid.prototype.setMap.apply(this,arguments);if(!this.tileOrigin){this.tileOrigin=new OpenLayers.LonLat(this.map.maxExtent.left,this.map.maxExtent.bottom);}},CLASS_NAME:"OpenLayers.Layer.TMS"});OpenLayers.Layer.TileCache=OpenLayers.Class(OpenLayers.Layer.Grid,{isBaseLayer:true,format:'image/png',serverResolutions:null,initialize:function(name,url,layername,options){this.layername=layername;OpenLayers.Layer.Grid.prototype.initialize.apply(this,[name,url,{},options]);this.extension=this.format.split('/')[1].toLowerCase();this.extension=(this.extension=='jpg')?'jpeg':this.extension;},clone:function(obj){if(obj==null){obj=new OpenLayers.Layer.TileCache(this.name,this.url,this.layername,this.getOptions());}
60763 obj=OpenLayers.Layer.Grid.prototype.clone.apply(this,[obj]);return obj;},getURL:function(bounds){var res=this.map.getResolution();var bbox=this.maxExtent;var size=this.tileSize;var tileX=Math.round((bounds.left-bbox.left)/(res*size.w));var tileY=Math.round((bounds.bottom-bbox.bottom)/(res*size.h));var tileZ=this.serverResolutions!=null?OpenLayers.Util.indexOf(this.serverResolutions,res):this.map.getZoom();function zeroPad(number,length){number=String(number);var zeros=[];for(var i=0;i<length;++i){zeros.push('0');}
60764 return zeros.join('').substring(0,length-number.length)+number;}
60765 var components=[this.layername,zeroPad(tileZ,2),zeroPad(parseInt(tileX/1000000),3),zeroPad((parseInt(tileX/1000)%1000),3),zeroPad((parseInt(tileX)%1000),3),zeroPad(parseInt(tileY/1000000),3),zeroPad((parseInt(tileY/1000)%1000),3),zeroPad((parseInt(tileY)%1000),3)+'.'+this.extension];var path=components.join('/');var url=this.url;if(url instanceof Array){url=this.selectUrl(path,url);}
60766 url=(url.charAt(url.length-1)=='/')?url:url+'/';return url+path;},addTile:function(bounds,position){var url=this.getURL(bounds);return new OpenLayers.Tile.Image(this,position,bounds,url,this.tileSize);},CLASS_NAME:"OpenLayers.Layer.TileCache"});OpenLayers.Layer.WMS=OpenLayers.Class(OpenLayers.Layer.Grid,{DEFAULT_PARAMS:{service:"WMS",version:"1.1.1",request:"GetMap",styles:"",exceptions:"application/vnd.ogc.se_inimage",format:"image/jpeg"},reproject:false,isBaseLayer:true,encodeBBOX:false,noMagic:false,yx:{'EPSG:4326':true},initialize:function(name,url,params,options){var newArguments=[];params=OpenLayers.Util.upperCaseObject(params);if(parseFloat(params.VERSION)>=1.3&&!params.EXCEPTIONS){params.EXCEPTIONS="INIMAGE";}
60767 newArguments.push(name,url,params,options);OpenLayers.Layer.Grid.prototype.initialize.apply(this,newArguments);OpenLayers.Util.applyDefaults(this.params,OpenLayers.Util.upperCaseObject(this.DEFAULT_PARAMS));if(!this.noMagic&&this.params.TRANSPARENT&&this.params.TRANSPARENT.toString().toLowerCase()=="true"){if((options==null)||(!options.isBaseLayer)){this.isBaseLayer=false;}
60768 if(this.params.FORMAT=="image/jpeg"){this.params.FORMAT=OpenLayers.Util.alphaHack()?"image/gif":"image/png";}}},destroy:function(){OpenLayers.Layer.Grid.prototype.destroy.apply(this,arguments);},clone:function(obj){if(obj==null){obj=new OpenLayers.Layer.WMS(this.name,this.url,this.params,this.getOptions());}
60769 obj=OpenLayers.Layer.Grid.prototype.clone.apply(this,[obj]);return obj;},reverseAxisOrder:function(){return(parseFloat(this.params.VERSION)>=1.3&&!!this.yx[this.map.getProjectionObject().getCode()]);},getURL:function(bounds){bounds=this.adjustBounds(bounds);var imageSize=this.getImageSize();var newParams={};var reverseAxisOrder=this.reverseAxisOrder();newParams.BBOX=this.encodeBBOX?bounds.toBBOX(null,reverseAxisOrder):bounds.toArray(reverseAxisOrder);newParams.WIDTH=imageSize.w;newParams.HEIGHT=imageSize.h;var requestString=this.getFullRequestString(newParams);return requestString;},addTile:function(bounds,position){return new OpenLayers.Tile.Image(this,position,bounds,null,this.tileSize);},mergeNewParams:function(newParams){var upperParams=OpenLayers.Util.upperCaseObject(newParams);var newArguments=[upperParams];return OpenLayers.Layer.Grid.prototype.mergeNewParams.apply(this,newArguments);},getFullRequestString:function(newParams,altUrl){var projectionCode=this.map.getProjection();var value=(projectionCode=="none")?null:projectionCode
60770 if(parseFloat(this.params.VERSION)>=1.3){this.params.CRS=value;}else{this.params.SRS=value;}
60771 return OpenLayers.Layer.Grid.prototype.getFullRequestString.apply(this,arguments);},CLASS_NAME:"OpenLayers.Layer.WMS"});OpenLayers.Layer.WMTS=OpenLayers.Class(OpenLayers.Layer.Grid,{isBaseLayer:true,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,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(config){var required={url:true,layer:true,style:true,matrixSet:true};for(var prop in required){if(!(prop in config)){throw new Error("Missing property '"+prop+"' in layer configuration.");}}
60772 config.params=OpenLayers.Util.upperCaseObject(config.params);var args=[config.name,config.url,config.params,config];OpenLayers.Layer.Grid.prototype.initialize.apply(this,args);if(!this.formatSuffix){this.formatSuffix=this.formatSuffixMap[this.format]||this.format.split("/").pop();}
60773 if(this.matrixIds){var len=this.matrixIds.length;if(len&&typeof this.matrixIds[0]==="string"){var ids=this.matrixIds;this.matrixIds=new Array(len);for(var i=0;i<len;++i){this.matrixIds[i]={identifier:ids[i]};}}}},setMap:function(){OpenLayers.Layer.Grid.prototype.setMap.apply(this,arguments);this.updateMatrixProperties();},updateMatrixProperties:function(){this.matrix=this.getMatrix();if(this.matrix){if(this.matrix.topLeftCorner){this.tileOrigin=this.matrix.topLeftCorner;}
60774 if(this.matrix.tileWidth&&this.matrix.tileHeight){this.tileSize=new OpenLayers.Size(this.matrix.tileWidth,this.matrix.tileHeight);}
60775 if(!this.tileOrigin){this.tileOrigin=new OpenLayers.LonLat(this.maxExtent.left,this.maxExtent.top);}
60776 if(!this.tileFullExtent){this.tileFullExtent=this.maxExtent;}}},moveTo:function(bounds,zoomChanged,dragging){if(zoomChanged||!this.matrix){this.updateMatrixProperties();}
60777 return OpenLayers.Layer.Grid.prototype.moveTo.apply(this,arguments);},clone:function(obj){if(obj==null){obj=new OpenLayers.Layer.WMTS(this.options);}
60778 obj=OpenLayers.Layer.Grid.prototype.clone.apply(this,[obj]);return obj;},getMatrix:function(){var matrix;if(!this.matrixIds||this.matrixIds.length===0){matrix={identifier:this.map.getZoom()+this.zoomOffset};}else{if("scaleDenominator"in this.matrixIds[0]){var denom=OpenLayers.METERS_PER_INCH*OpenLayers.INCHES_PER_UNIT[this.units]*this.map.getResolution()/0.28E-3;var diff=Number.POSITIVE_INFINITY;var delta;for(var i=0,ii=this.matrixIds.length;i<ii;++i){delta=Math.abs(1-(this.matrixIds[i].scaleDenominator/denom));if(delta<diff){diff=delta;matrix=this.matrixIds[i];}}}else{matrix=this.matrixIds[this.map.getZoom()+this.zoomOffset];}}
60779 return matrix;},getTileInfo:function(loc){var res=this.map.getResolution();var fx=(loc.lon-this.tileOrigin.lon)/(res*this.tileSize.w);var fy=(this.tileOrigin.lat-loc.lat)/(res*this.tileSize.h);var col=Math.floor(fx);var row=Math.floor(fy);return{col:col,row:row,i:Math.floor((fx-col)*this.tileSize.w),j:Math.floor((fy-row)*this.tileSize.h)};},getURL:function(bounds){bounds=this.adjustBounds(bounds);var url="";if(!this.tileFullExtent||this.tileFullExtent.intersectsBounds(bounds)){var center=bounds.getCenterLonLat();var info=this.getTileInfo(center);var matrixId=this.matrix.identifier;if(this.requestEncoding.toUpperCase()==="REST"){var path=this.version+"/"+this.layer+"/"+this.style+"/";if(this.dimensions){for(var i=0;i<this.dimensions.length;i++){if(this.params[this.dimensions[i]]){path=path+this.params[this.dimensions[i]]+"/";}}}
60780 path=path+this.matrixSet+"/"+this.matrix.identifier+"/"+info.row+"/"+info.col+"."+this.formatSuffix;if(this.url instanceof Array){url=this.selectUrl(path,this.url);}else{url=this.url;}
60781 if(!url.match(/\/$/)){url=url+"/";}
60782 url=url+path;}else if(this.requestEncoding.toUpperCase()==="KVP"){var params={SERVICE:"WMTS",REQUEST:"GetTile",VERSION:this.version,LAYER:this.layer,STYLE:this.style,TILEMATRIXSET:this.matrixSet,TILEMATRIX:this.matrix.identifier,TILEROW:info.row,TILECOL:info.col,FORMAT:this.format};url=OpenLayers.Layer.Grid.prototype.getFullRequestString.apply(this,[params]);}}
60783 return url;},mergeNewParams:function(newParams){if(this.requestEncoding.toUpperCase()==="KVP"){return OpenLayers.Layer.Grid.prototype.mergeNewParams.apply(this,[OpenLayers.Util.upperCaseObject(newParams)]);}},addTile:function(bounds,position){return new OpenLayers.Tile.Image(this,position,bounds,null,this.tileSize);},CLASS_NAME:"OpenLayers.Layer.WMTS"});OpenLayers.Layer.WorldWind=OpenLayers.Class(OpenLayers.Layer.Grid,{DEFAULT_PARAMS:{},isBaseLayer:true,lzd:null,zoomLevels:null,initialize:function(name,url,lzd,zoomLevels,params,options){this.lzd=lzd;this.zoomLevels=zoomLevels;var newArguments=[];newArguments.push(name,url,params,options);OpenLayers.Layer.Grid.prototype.initialize.apply(this,newArguments);this.params=OpenLayers.Util.applyDefaults(this.params,this.DEFAULT_PARAMS);},addTile:function(bounds,position){return new OpenLayers.Tile.Image(this,position,bounds,null,this.tileSize);},getZoom:function(){var zoom=this.map.getZoom();var extent=this.map.getMaxExtent();zoom=zoom-Math.log(this.maxResolution/(this.lzd/512))/Math.log(2);return zoom;},getURL:function(bounds){bounds=this.adjustBounds(bounds);var zoom=this.getZoom();var extent=this.map.getMaxExtent();var deg=this.lzd/Math.pow(2,this.getZoom());var x=Math.floor((bounds.left-extent.left)/deg);var y=Math.floor((bounds.bottom-extent.bottom)/deg);if(this.map.getResolution()<=(this.lzd/512)&&this.getZoom()<=this.zoomLevels){return this.getFullRequestString({L:zoom,X:x,Y:y});}else{return OpenLayers.Util.getImagesLocation()+"blank.gif";}},CLASS_NAME:"OpenLayers.Layer.WorldWind"});OpenLayers.Layer.XYZ=OpenLayers.Class(OpenLayers.Layer.Grid,{isBaseLayer:true,sphericalMercator:false,zoomOffset:0,initialize:function(name,url,options){if(options&&options.sphericalMercator||this.sphericalMercator){options=OpenLayers.Util.extend({maxExtent:new OpenLayers.Bounds(-128*156543.0339,-128*156543.0339,128*156543.0339,128*156543.0339),maxResolution:156543.0339,numZoomLevels:19,units:"m",projection:"EPSG:900913"},options);}
60784 url=url||this.url;name=name||this.name;var newArguments=[name,url,{},options];OpenLayers.Layer.Grid.prototype.initialize.apply(this,newArguments);},clone:function(obj){if(obj==null){obj=new OpenLayers.Layer.XYZ(this.name,this.url,this.getOptions());}
60785 obj=OpenLayers.Layer.Grid.prototype.clone.apply(this,[obj]);return obj;},getURL:function(bounds){var res=this.map.getResolution();var x=Math.round((bounds.left-this.maxExtent.left)/(res*this.tileSize.w));var y=Math.round((this.maxExtent.top-bounds.top)/(res*this.tileSize.h));var z=this.map.getZoom()+this.zoomOffset;var url=this.url;var s=''+x+y+z;if(url instanceof Array)
60786 {url=this.selectUrl(s,url);}
60787 var path=OpenLayers.String.format(url,{'x':x,'y':y,'z':z});return path;},addTile:function(bounds,position){return new OpenLayers.Tile.Image(this,position,bounds,null,this.tileSize);},setMap:function(map){OpenLayers.Layer.Grid.prototype.setMap.apply(this,arguments);if(!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",attribution:"Data CC-By-SA by <a href='http://openstreetmap.org/'>OpenStreetMap</a>",sphericalMercator:true,url:'http://tile.openstreetmap.org/${z}/${x}/${y}.png',clone:function(obj){if(obj==null){obj=new OpenLayers.Layer.OSM(this.name,this.url,this.getOptions());}
60788 obj=OpenLayers.Layer.XYZ.prototype.clone.apply(this,[obj]);return obj;},CLASS_NAME:"OpenLayers.Layer.OSM"});OpenLayers.Layer.Zoomify=OpenLayers.Class(OpenLayers.Layer.Grid,{url:null,size:null,isBaseLayer:true,standardTileSize:256,numberOfTiers:0,tileCountUpToTier:new Array(),tierSizeInTiles:new Array(),tierImageSize:new Array(),initialize:function(name,url,size,options){this.initializeZoomify(size);var newArguments=[];newArguments.push(name,url,size,{},options);OpenLayers.Layer.Grid.prototype.initialize.apply(this,newArguments);},initializeZoomify:function(size){var imageSize=size.clone()
60789 var tiles=new OpenLayers.Size(Math.ceil(imageSize.w/this.standardTileSize),Math.ceil(imageSize.h/this.standardTileSize));this.tierSizeInTiles.push(tiles);this.tierImageSize.push(imageSize);while(imageSize.w>this.standardTileSize||imageSize.h>this.standardTileSize){imageSize=new OpenLayers.Size(Math.floor(imageSize.w/2),Math.floor(imageSize.h/2));tiles=new OpenLayers.Size(Math.ceil(imageSize.w/this.standardTileSize),Math.ceil(imageSize.h/this.standardTileSize));this.tierSizeInTiles.push(tiles);this.tierImageSize.push(imageSize);}
60790 this.tierSizeInTiles.reverse();this.tierImageSize.reverse();this.numberOfTiers=this.tierSizeInTiles.length;this.tileCountUpToTier[0]=0;for(var i=1;i<this.numberOfTiers;i++){this.tileCountUpToTier.push(this.tierSizeInTiles[i-1].w*this.tierSizeInTiles[i-1].h+
60791 this.tileCountUpToTier[i-1]);}},destroy:function(){OpenLayers.Layer.Grid.prototype.destroy.apply(this,arguments);this.tileCountUpToTier.length=0
60792 this.tierSizeInTiles.length=0
60793 this.tierImageSize.length=0},clone:function(obj){if(obj==null){obj=new OpenLayers.Layer.Zoomify(this.name,this.url,this.size,this.options);}
60794 obj=OpenLayers.Layer.Grid.prototype.clone.apply(this,[obj]);return obj;},getURL:function(bounds){bounds=this.adjustBounds(bounds);var res=this.map.getResolution();var x=Math.round((bounds.left-this.tileOrigin.lon)/(res*this.tileSize.w));var y=Math.round((this.tileOrigin.lat-bounds.top)/(res*this.tileSize.h));var z=this.map.getZoom();var tileIndex=x+y*this.tierSizeInTiles[z].w+this.tileCountUpToTier[z];var path="TileGroup"+Math.floor((tileIndex)/256)+"/"+z+"-"+x+"-"+y+".jpg";var url=this.url;if(url instanceof Array){url=this.selectUrl(path,url);}
60795 return url+path;},getImageSize:function(){if(arguments.length>0){bounds=this.adjustBounds(arguments[0]);var res=this.map.getResolution();var x=Math.round((bounds.left-this.tileOrigin.lon)/(res*this.tileSize.w));var y=Math.round((this.tileOrigin.lat-bounds.top)/(res*this.tileSize.h));var z=this.map.getZoom();var w=this.standardTileSize;var h=this.standardTileSize;if(x==this.tierSizeInTiles[z].w-1){var w=this.tierImageSize[z].w%this.standardTileSize;};if(y==this.tierSizeInTiles[z].h-1){var h=this.tierImageSize[z].h%this.standardTileSize;};return(new OpenLayers.Size(w,h));}else{return this.tileSize;}},addTile:function(bounds,position){return new OpenLayers.Tile.Image(this,position,bounds,null,this.tileSize);},setMap:function(map){OpenLayers.Layer.Grid.prototype.setMap.apply(this,arguments);this.tileOrigin=new OpenLayers.LonLat(this.map.maxExtent.left,this.map.maxExtent.top);},calculateGridLayout:function(bounds,extent,resolution){var tilelon=resolution*this.tileSize.w;var tilelat=resolution*this.tileSize.h;var offsetlon=bounds.left-extent.left;var tilecol=Math.floor(offsetlon/tilelon)-this.buffer;var tilecolremain=offsetlon/tilelon-tilecol;var tileoffsetx=-tilecolremain*this.tileSize.w;var tileoffsetlon=extent.left+tilecol*tilelon;var offsetlat=extent.top-bounds.top+tilelat;var tilerow=Math.floor(offsetlat/tilelat)-this.buffer;var tilerowremain=tilerow-offsetlat/tilelat;var tileoffsety=tilerowremain*this.tileSize.h;var tileoffsetlat=extent.top-tilelat*tilerow;return{tilelon:tilelon,tilelat:tilelat,tileoffsetlon:tileoffsetlon,tileoffsetlat:tileoffsetlat,tileoffsetx:tileoffsetx,tileoffsety:tileoffsety};},CLASS_NAME:"OpenLayers.Layer.Zoomify"});OpenLayers.Protocol.SQL.Gears=OpenLayers.Class(OpenLayers.Protocol.SQL,{FID_PREFIX:'__gears_fid__',NULL_GEOMETRY:'__gears_null_geometry__',NULL_FEATURE_STATE:'__gears_null_feature_state__',jsonParser:null,wktParser:null,fidRegExp:null,saveFeatureState:true,typeOfFid:"string",db:null,initialize:function(options){if(!this.supported()){return;}
60796 OpenLayers.Protocol.SQL.prototype.initialize.apply(this,[options]);this.jsonParser=new OpenLayers.Format.JSON();this.wktParser=new OpenLayers.Format.WKT();this.fidRegExp=new RegExp('^'+this.FID_PREFIX);this.initializeDatabase();},initializeDatabase:function(){this.db=google.gears.factory.create('beta.database');this.db.open(this.databaseName);this.db.execute("CREATE TABLE IF NOT EXISTS "+this.tableName+" (fid TEXT UNIQUE, geometry TEXT, properties TEXT,"+"  state TEXT)");},destroy:function(){this.db.close();this.db=null;this.jsonParser=null;this.wktParser=null;OpenLayers.Protocol.SQL.prototype.destroy.apply(this);},supported:function(){return!!(window.google&&google.gears);},read:function(options){OpenLayers.Protocol.prototype.read.apply(this,arguments);options=OpenLayers.Util.applyDefaults(options,this.options);var feature,features=[];var rs=this.db.execute("SELECT * FROM "+this.tableName);while(rs.isValidRow()){feature=this.unfreezeFeature(rs);if(this.evaluateFilter(feature,options.filter)){if(!options.noFeatureStateReset){feature.state=null;}
60797 features.push(feature);}
60798 rs.next();}
60799 rs.close();var resp=new OpenLayers.Protocol.Response({code:OpenLayers.Protocol.Response.SUCCESS,requestType:"read",features:features});if(options&&options.callback){options.callback.call(options.scope,resp);}
60800 return resp;},unfreezeFeature:function(row){var feature;var wkt=row.fieldByName('geometry');if(wkt==this.NULL_GEOMETRY){feature=new OpenLayers.Feature.Vector();}else{feature=this.wktParser.read(wkt);}
60801 feature.attributes=this.jsonParser.read(row.fieldByName('properties'));feature.fid=this.extractFidFromField(row.fieldByName('fid'));var state=row.fieldByName('state');if(state==this.NULL_FEATURE_STATE){state=null;}
60802 feature.state=state;return feature;},extractFidFromField:function(field){if(!field.match(this.fidRegExp)&&this.typeOfFid=="number"){field=parseFloat(field);}
60803 return field;},create:function(features,options){options=OpenLayers.Util.applyDefaults(options,this.options);var resp=this.createOrUpdate(features);resp.requestType="create";if(options&&options.callback){options.callback.call(options.scope,resp);}
60804 return resp;},update:function(features,options){options=OpenLayers.Util.applyDefaults(options,this.options);var resp=this.createOrUpdate(features);resp.requestType="update";if(options&&options.callback){options.callback.call(options.scope,resp);}
60805 return resp;},createOrUpdate:function(features){if(!(features instanceof Array)){features=[features];}
60806 var i,len=features.length,feature;var insertedFeatures=new Array(len);for(i=0;i<len;i++){feature=features[i];var params=this.freezeFeature(feature);this.db.execute("REPLACE INTO "+this.tableName+" (fid, geometry, properties, state)"+" VALUES (?, ?, ?, ?)",params);var clone=feature.clone();clone.fid=this.extractFidFromField(params[0]);insertedFeatures[i]=clone;}
60807 return new OpenLayers.Protocol.Response({code:OpenLayers.Protocol.Response.SUCCESS,features:insertedFeatures,reqFeatures:features});},freezeFeature:function(feature){feature.fid=feature.fid!=null?""+feature.fid:OpenLayers.Util.createUniqueID(this.FID_PREFIX);var geometry=feature.geometry!=null?feature.geometry.toString():this.NULL_GEOMETRY;var properties=this.jsonParser.write(feature.attributes);var state=this.getFeatureStateForFreeze(feature);return[feature.fid,geometry,properties,state];},getFeatureStateForFreeze:function(feature){var state;if(!this.saveFeatureState){state=this.NULL_FEATURE_STATE;}else if(this.createdOffline(feature)){state=OpenLayers.State.INSERT;}else{state=feature.state;}
60808 return state;},"delete":function(features,options){if(!(features instanceof Array)){features=[features];}
60809 options=OpenLayers.Util.applyDefaults(options,this.options);var i,len,feature;for(i=0,len=features.length;i<len;i++){feature=features[i];if(this.saveFeatureState&&!this.createdOffline(feature)){var toDelete=feature.clone();toDelete.fid=feature.fid;if(toDelete.geometry){toDelete.geometry.destroy();toDelete.geometry=null;}
60810 toDelete.state=feature.state;this.createOrUpdate(toDelete);}else{this.db.execute("DELETE FROM "+this.tableName+" WHERE fid = ?",[feature.fid]);}}
60811 var resp=new OpenLayers.Protocol.Response({code:OpenLayers.Protocol.Response.SUCCESS,requestType:"delete",reqFeatures:features});if(options&&options.callback){options.callback.call(options.scope,resp);}
60812 return resp;},createdOffline:function(feature){return(typeof feature.fid=="string"&&!!(feature.fid.match(this.fidRegExp)));},commit:function(features,options){var opt,resp=[],nRequests=0,nResponses=0;function callback(resp){if(++nResponses<nRequests){resp.last=false;}
60813 this.callUserCallback(options,resp);}
60814 var feature,toCreate=[],toUpdate=[],toDelete=[];for(var i=features.length-1;i>=0;i--){feature=features[i];switch(feature.state){case OpenLayers.State.INSERT:toCreate.push(feature);break;case OpenLayers.State.UPDATE:toUpdate.push(feature);break;case OpenLayers.State.DELETE:toDelete.push(feature);break;}}
60815 if(toCreate.length>0){nRequests++;opt=OpenLayers.Util.applyDefaults({"callback":callback,"scope":this},options.create);resp.push(this.create(toCreate,opt));}
60816 if(toUpdate.length>0){nRequests++;opt=OpenLayers.Util.applyDefaults({"callback":callback,"scope":this},options.update);resp.push(this.update(toUpdate,opt));}
60817 if(toDelete.length>0){nRequests++;opt=OpenLayers.Util.applyDefaults({"callback":callback,"scope":this},options["delete"]);resp.push(this["delete"](toDelete,opt));}
60818 return resp;},clear:function(){this.db.execute("DELETE FROM "+this.tableName);},callUserCallback:function(options,resp){var opt=options[resp.requestType];if(opt&&opt.callback){opt.callback.call(opt.scope,resp);}
60819 if(resp.last&&options.callback){options.callback.call(options.scope);}},CLASS_NAME:"OpenLayers.Protocol.SQL.Gears"});OpenLayers.Rule=OpenLayers.Class({id:null,name:null,title:null,description:null,context:null,filter:null,elseFilter:false,symbolizer:null,symbolizers:null,minScaleDenominator:null,maxScaleDenominator:null,initialize:function(options){this.symbolizer={};OpenLayers.Util.extend(this,options);if(this.symbolizers){delete this.symbolizer;}
60820 this.id=OpenLayers.Util.createUniqueID(this.CLASS_NAME+"_");},destroy:function(){for(var i in this.symbolizer){this.symbolizer[i]=null;}
60821 this.symbolizer=null;delete this.symbolizers;},evaluate:function(feature){var context=this.getContext(feature);var applies=true;if(this.minScaleDenominator||this.maxScaleDenominator){var scale=feature.layer.map.getScale();}
60822 if(this.minScaleDenominator){applies=scale>=OpenLayers.Style.createLiteral(this.minScaleDenominator,context);}
60823 if(applies&&this.maxScaleDenominator){applies=scale<OpenLayers.Style.createLiteral(this.maxScaleDenominator,context);}
60824 if(applies&&this.filter){if(this.filter.CLASS_NAME=="OpenLayers.Filter.FeatureId"){applies=this.filter.evaluate(feature);}else{applies=this.filter.evaluate(context);}}
60825 return applies;},getContext:function(feature){var context=this.context;if(!context){context=feature.attributes||feature.data;}
60826 if(typeof this.context=="function"){context=this.context(feature);}
60827 return context;},clone:function(){var options=OpenLayers.Util.extend({},this);if(this.symbolizers){var len=this.symbolizers.length;options.symbolizers=new Array(len);for(var i=0;i<len;++i){options.symbolizers[i]=this.symbolizers[i].clone();}}else{options.symbolizer={};var value,type;for(var key in this.symbolizer){value=this.symbolizer[key];type=typeof value;if(type==="object"){options.symbolizer[key]=OpenLayers.Util.extend({},value);}else if(type==="string"){options.symbolizer[key]=value;}}}
60828 options.filter=this.filter&&this.filter.clone();options.context=this.context&&OpenLayers.Util.extend({},this.context);return new OpenLayers.Rule(options);},CLASS_NAME:"OpenLayers.Rule"});OpenLayers.StyleMap=OpenLayers.Class({styles:null,extendDefault:true,initialize:function(style,options){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(style instanceof OpenLayers.Style){this.styles["default"]=style;this.styles["select"]=style;this.styles["temporary"]=style;this.styles["delete"]=style;}else if(typeof style=="object"){for(var key in style){if(style[key]instanceof OpenLayers.Style){this.styles[key]=style[key];}else if(typeof style[key]=="object"){this.styles[key]=new OpenLayers.Style(style[key]);}else{this.styles["default"]=new OpenLayers.Style(style);this.styles["select"]=new OpenLayers.Style(style);this.styles["temporary"]=new OpenLayers.Style(style);this.styles["delete"]=new OpenLayers.Style(style);break;}}}
60829 OpenLayers.Util.extend(this,options);},destroy:function(){for(var key in this.styles){this.styles[key].destroy();}
60830 this.styles=null;},createSymbolizer:function(feature,intent){if(!feature){feature=new OpenLayers.Feature.Vector();}
60831 if(!this.styles[intent]){intent="default";}
60832 feature.renderIntent=intent;var defaultSymbolizer={};if(this.extendDefault&&intent!="default"){defaultSymbolizer=this.styles["default"].createSymbolizer(feature);}
60833 return OpenLayers.Util.extend(defaultSymbolizer,this.styles[intent].createSymbolizer(feature));},addUniqueValueRules:function(renderIntent,property,symbolizers,context){var rules=[];for(var value in symbolizers){rules.push(new OpenLayers.Rule({symbolizer:symbolizers[value],context:context,filter:new OpenLayers.Filter.Comparison({type:OpenLayers.Filter.Comparison.EQUAL_TO,property:property,value:value})}));}
60834 this.styles[renderIntent].addRules(rules);},CLASS_NAME:"OpenLayers.StyleMap"});OpenLayers.Control.NavToolbar=OpenLayers.Class(OpenLayers.Control.Panel,{initialize:function(options){OpenLayers.Control.Panel.prototype.initialize.apply(this,[options]);this.addControls([new OpenLayers.Control.Navigation(),new OpenLayers.Control.ZoomBox()]);},draw:function(){var div=OpenLayers.Control.Panel.prototype.draw.apply(this,arguments);this.activateControl(this.controls[0]);return div;},CLASS_NAME:"OpenLayers.Control.NavToolbar"});OpenLayers.Filter.Comparison=OpenLayers.Class(OpenLayers.Filter,{type:null,property:null,value:null,matchCase:true,lowerBoundary:null,upperBoundary:null,initialize:function(options){OpenLayers.Filter.prototype.initialize.apply(this,[options]);},evaluate:function(context){if(context instanceof OpenLayers.Feature.Vector){context=context.attributes;}
60835 var result=false;var got=context[this.property];switch(this.type){case OpenLayers.Filter.Comparison.EQUAL_TO:var exp=this.value;if(!this.matchCase&&typeof got=="string"&&typeof exp=="string"){result=(got.toUpperCase()==exp.toUpperCase());}else{result=(got==exp);}
60836 break;case OpenLayers.Filter.Comparison.NOT_EQUAL_TO:var exp=this.value;if(!this.matchCase&&typeof got=="string"&&typeof exp=="string"){result=(got.toUpperCase()!=exp.toUpperCase());}else{result=(got!=exp);}
60837 break;case OpenLayers.Filter.Comparison.LESS_THAN:result=got<this.value;break;case OpenLayers.Filter.Comparison.GREATER_THAN:result=got>this.value;break;case OpenLayers.Filter.Comparison.LESS_THAN_OR_EQUAL_TO:result=got<=this.value;break;case OpenLayers.Filter.Comparison.GREATER_THAN_OR_EQUAL_TO:result=got>=this.value;break;case OpenLayers.Filter.Comparison.BETWEEN:result=(got>=this.lowerBoundary)&&(got<=this.upperBoundary);break;case OpenLayers.Filter.Comparison.LIKE:var regexp=new RegExp(this.value,"gi");result=regexp.test(got);break;}
60838 return result;},value2regex:function(wildCard,singleChar,escapeChar){if(wildCard=="."){var msg="'.' is an unsupported wildCard character for "+"OpenLayers.Filter.Comparison";OpenLayers.Console.error(msg);return null;}
60839 wildCard=wildCard?wildCard:"*";singleChar=singleChar?singleChar:".";escapeChar=escapeChar?escapeChar:"!";this.value=this.value.replace(new RegExp("\\"+escapeChar+"(.|$)","g"),"\\$1");this.value=this.value.replace(new RegExp("\\"+singleChar,"g"),".");this.value=this.value.replace(new RegExp("\\"+wildCard,"g"),".*");this.value=this.value.replace(new RegExp("\\\\.\\*","g"),"\\"+wildCard);this.value=this.value.replace(new RegExp("\\\\\\.","g"),"\\"+singleChar);return this.value;},regex2value:function(){var value=this.value;value=value.replace(/!/g,"!!");value=value.replace(/(\\)?\\\./g,function($0,$1){return $1?$0:"!.";});value=value.replace(/(\\)?\\\*/g,function($0,$1){return $1?$0:"!*";});value=value.replace(/\\\\/g,"\\");value=value.replace(/\.\*/g,"*");return value;},clone:function(){return OpenLayers.Util.extend(new OpenLayers.Filter.Comparison(),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.FeatureId=OpenLayers.Class(OpenLayers.Filter,{fids:null,initialize:function(options){this.fids=[];OpenLayers.Filter.prototype.initialize.apply(this,[options]);},evaluate:function(feature){for(var i=0,len=this.fids.length;i<len;i++){var fid=feature.fid||feature.id;if(fid==this.fids[i]){return true;}}
60840 return false;},clone:function(){var filter=new OpenLayers.Filter.FeatureId();OpenLayers.Util.extend(filter,this);filter.fids=this.fids.slice();return filter;},CLASS_NAME:"OpenLayers.Filter.FeatureId"});OpenLayers.Filter.Logical=OpenLayers.Class(OpenLayers.Filter,{filters:null,type:null,initialize:function(options){this.filters=[];OpenLayers.Filter.prototype.initialize.apply(this,[options]);},destroy:function(){this.filters=null;OpenLayers.Filter.prototype.destroy.apply(this);},evaluate:function(context){switch(this.type){case OpenLayers.Filter.Logical.AND:for(var i=0,len=this.filters.length;i<len;i++){if(this.filters[i].evaluate(context)==false){return false;}}
60841 return true;case OpenLayers.Filter.Logical.OR:for(var i=0,len=this.filters.length;i<len;i++){if(this.filters[i].evaluate(context)==true){return true;}}
60842 return false;case OpenLayers.Filter.Logical.NOT:return(!this.filters[0].evaluate(context));}},clone:function(){var filters=[];for(var i=0,len=this.filters.length;i<len;++i){filters.push(this.filters[i].clone());}
60843 return new OpenLayers.Filter.Logical({type:this.type,filters:filters});},CLASS_NAME:"OpenLayers.Filter.Logical"});OpenLayers.Filter.Logical.AND="&&";OpenLayers.Filter.Logical.OR="||";OpenLayers.Filter.Logical.NOT="!";OpenLayers.Filter.Spatial=OpenLayers.Class(OpenLayers.Filter,{type:null,property:null,value:null,distance:null,distanceUnits:null,initialize:function(options){OpenLayers.Filter.prototype.initialize.apply(this,[options]);},evaluate:function(feature){var intersect=false;switch(this.type){case OpenLayers.Filter.Spatial.BBOX:case OpenLayers.Filter.Spatial.INTERSECTS:if(feature.geometry){var geom=this.value;if(this.value.CLASS_NAME=="OpenLayers.Bounds"){geom=this.value.toGeometry();}
60844 if(feature.geometry.intersects(geom)){intersect=true;}}
60845 break;default:OpenLayers.Console.error(OpenLayers.i18n("filterEvaluateNotImplemented"));break;}
60846 return intersect;},clone:function(){var options=OpenLayers.Util.applyDefaults({value:this.value&&this.value.clone&&this.value.clone()},this);return new OpenLayers.Filter.Spatial(options);},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.Geometry.Collection=OpenLayers.Class(OpenLayers.Geometry,{components:null,componentTypes:null,initialize:function(components){OpenLayers.Geometry.prototype.initialize.apply(this,arguments);this.components=[];if(components!=null){this.addComponents(components);}},destroy:function(){this.components.length=0;this.components=null;OpenLayers.Geometry.prototype.destroy.apply(this,arguments);},clone:function(){var geometry=eval("new "+this.CLASS_NAME+"()");for(var i=0,len=this.components.length;i<len;i++){geometry.addComponent(this.components[i].clone());}
60847 OpenLayers.Util.applyDefaults(geometry,this);return geometry;},getComponentsString:function(){var strings=[];for(var i=0,len=this.components.length;i<len;i++){strings.push(this.components[i].toShortString());}
60848 return strings.join(",");},calculateBounds:function(){this.bounds=null;if(this.components&&this.components.length>0){this.setBounds(this.components[0].getBounds());for(var i=1,len=this.components.length;i<len;i++){this.extendBounds(this.components[i].getBounds());}}},addComponents:function(components){if(!(components instanceof Array)){components=[components];}
60849 for(var i=0,len=components.length;i<len;i++){this.addComponent(components[i]);}},addComponent:function(component,index){var added=false;if(component){if(this.componentTypes==null||(OpenLayers.Util.indexOf(this.componentTypes,component.CLASS_NAME)>-1)){if(index!=null&&(index<this.components.length)){var components1=this.components.slice(0,index);var components2=this.components.slice(index,this.components.length);components1.push(component);this.components=components1.concat(components2);}else{this.components.push(component);}
60850 component.parent=this;this.clearBounds();added=true;}}
60851 return added;},removeComponents:function(components){if(!(components instanceof Array)){components=[components];}
60852 for(var i=components.length-1;i>=0;--i){this.removeComponent(components[i]);}},removeComponent:function(component){OpenLayers.Util.removeItem(this.components,component);this.clearBounds();},getLength:function(){var length=0.0;for(var i=0,len=this.components.length;i<len;i++){length+=this.components[i].getLength();}
60853 return length;},getArea:function(){var area=0.0;for(var i=0,len=this.components.length;i<len;i++){area+=this.components[i].getArea();}
60854 return area;},getGeodesicArea:function(projection){var area=0.0;for(var i=0,len=this.components.length;i<len;i++){area+=this.components[i].getGeodesicArea(projection);}
60855 return area;},getCentroid:function(weighted){if(!weighted){return this.components.length&&this.components[0].getCentroid();}
60856 var len=this.components.length;if(!len){return false;}
60857 var areas=[];var centroids=[];var areaSum=0;var minArea=Number.MAX_VALUE;var component;for(var i=0;i<len;++i){component=this.components[i];var area=component.getArea();var centroid=component.getCentroid(true);if(isNaN(area)||isNaN(centroid.x)||isNaN(centroid.y)){continue;}
60858 areas.push(area);areaSum+=area;minArea=(area<minArea&&area>0)?area:minArea;centroids.push(centroid);}
60859 len=areas.length;if(areaSum===0){for(var i=0;i<len;++i){areas[i]=1;}
60860 areaSum=areas.length;}else{for(var i=0;i<len;++i){areas[i]/=minArea;}
60861 areaSum/=minArea;}
60862 var xSum=0,ySum=0,centroid,area;for(var i=0;i<len;++i){centroid=centroids[i];area=areas[i];xSum+=centroid.x*area;ySum+=centroid.y*area;}
60863 return new OpenLayers.Geometry.Point(xSum/areaSum,ySum/areaSum);},getGeodesicLength:function(projection){var length=0.0;for(var i=0,len=this.components.length;i<len;i++){length+=this.components[i].getGeodesicLength(projection);}
60864 return length;},move:function(x,y){for(var i=0,len=this.components.length;i<len;i++){this.components[i].move(x,y);}},rotate:function(angle,origin){for(var i=0,len=this.components.length;i<len;++i){this.components[i].rotate(angle,origin);}},resize:function(scale,origin,ratio){for(var i=0;i<this.components.length;++i){this.components[i].resize(scale,origin,ratio);}
60865 return this;},distanceTo:function(geometry,options){var edge=!(options&&options.edge===false);var details=edge&&options&&options.details;var result,best,distance;var min=Number.POSITIVE_INFINITY;for(var i=0,len=this.components.length;i<len;++i){result=this.components[i].distanceTo(geometry,options);distance=details?result.distance:result;if(distance<min){min=distance;best=result;if(min==0){break;}}}
60866 return best;},equals:function(geometry){var equivalent=true;if(!geometry||!geometry.CLASS_NAME||(this.CLASS_NAME!=geometry.CLASS_NAME)){equivalent=false;}else if(!(geometry.components instanceof Array)||(geometry.components.length!=this.components.length)){equivalent=false;}else{for(var i=0,len=this.components.length;i<len;++i){if(!this.components[i].equals(geometry.components[i])){equivalent=false;break;}}}
60867 return equivalent;},transform:function(source,dest){if(source&&dest){for(var i=0,len=this.components.length;i<len;i++){var component=this.components[i];component.transform(source,dest);}
60868 this.bounds=null;}
60869 return this;},intersects:function(geometry){var intersect=false;for(var i=0,len=this.components.length;i<len;++i){intersect=geometry.intersects(this.components[i]);if(intersect){break;}}
60870 return intersect;},getVertices:function(nodes){var vertices=[];for(var i=0,len=this.components.length;i<len;++i){Array.prototype.push.apply(vertices,this.components[i].getVertices(nodes));}
60871 return vertices;},CLASS_NAME:"OpenLayers.Geometry.Collection"});OpenLayers.Geometry.Point=OpenLayers.Class(OpenLayers.Geometry,{x:null,y:null,initialize:function(x,y){OpenLayers.Geometry.prototype.initialize.apply(this,arguments);this.x=parseFloat(x);this.y=parseFloat(y);},clone:function(obj){if(obj==null){obj=new OpenLayers.Geometry.Point(this.x,this.y);}
60872 OpenLayers.Util.applyDefaults(obj,this);return obj;},calculateBounds:function(){this.bounds=new OpenLayers.Bounds(this.x,this.y,this.x,this.y);},distanceTo:function(geometry,options){var edge=!(options&&options.edge===false);var details=edge&&options&&options.details;var distance,x0,y0,x1,y1,result;if(geometry instanceof OpenLayers.Geometry.Point){x0=this.x;y0=this.y;x1=geometry.x;y1=geometry.y;distance=Math.sqrt(Math.pow(x0-x1,2)+Math.pow(y0-y1,2));result=!details?distance:{x0:x0,y0:y0,x1:x1,y1:y1,distance:distance};}else{result=geometry.distanceTo(this,options);if(details){result={x0:result.x1,y0:result.y1,x1:result.x0,y1:result.y0,distance:result.distance};}}
60873 return result;},equals:function(geom){var equals=false;if(geom!=null){equals=((this.x==geom.x&&this.y==geom.y)||(isNaN(this.x)&&isNaN(this.y)&&isNaN(geom.x)&&isNaN(geom.y)));}
60874 return equals;},toShortString:function(){return(this.x+", "+this.y);},move:function(x,y){this.x=this.x+x;this.y=this.y+y;this.clearBounds();},rotate:function(angle,origin){angle*=Math.PI/180;var radius=this.distanceTo(origin);var theta=angle+Math.atan2(this.y-origin.y,this.x-origin.x);this.x=origin.x+(radius*Math.cos(theta));this.y=origin.y+(radius*Math.sin(theta));this.clearBounds();},getCentroid:function(){return new OpenLayers.Geometry.Point(this.x,this.y);},resize:function(scale,origin,ratio){ratio=(ratio==undefined)?1:ratio;this.x=origin.x+(scale*ratio*(this.x-origin.x));this.y=origin.y+(scale*(this.y-origin.y));this.clearBounds();return this;},intersects:function(geometry){var intersect=false;if(geometry.CLASS_NAME=="OpenLayers.Geometry.Point"){intersect=this.equals(geometry);}else{intersect=geometry.intersects(this);}
60875 return intersect;},transform:function(source,dest){if((source&&dest)){OpenLayers.Projection.transform(this,source,dest);this.bounds=null;}
60876 return this;},getVertices:function(nodes){return[this];},CLASS_NAME:"OpenLayers.Geometry.Point"});OpenLayers.Geometry.Rectangle=OpenLayers.Class(OpenLayers.Geometry,{x:null,y:null,width:null,height:null,initialize:function(x,y,width,height){OpenLayers.Geometry.prototype.initialize.apply(this,arguments);this.x=x;this.y=y;this.width=width;this.height=height;},calculateBounds:function(){this.bounds=new OpenLayers.Bounds(this.x,this.y,this.x+this.width,this.y+this.height);},getLength:function(){var length=(2*this.width)+(2*this.height);return length;},getArea:function(){var area=this.width*this.height;return area;},CLASS_NAME:"OpenLayers.Geometry.Rectangle"});OpenLayers.Geometry.Surface=OpenLayers.Class(OpenLayers.Geometry,{initialize:function(){OpenLayers.Geometry.prototype.initialize.apply(this,arguments);},CLASS_NAME:"OpenLayers.Geometry.Surface"});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(name,url,params,options){OpenLayers.Layer.KaMap.prototype.initialize.apply(this,arguments);this.extension=this.IMAGE_EXTENSIONS[this.params.i.toLowerCase()||DEFAULT_FORMAT];},getURL:function(bounds){bounds=this.adjustBounds(bounds);var mapRes=this.map.getResolution();var scale=Math.round((this.map.getScale()*10000))/10000;var pX=Math.round(bounds.left/mapRes);var pY=-Math.round(bounds.top/mapRes);var metaX=Math.floor(pX/this.tileSize.w/this.params.metaTileSize.w)*this.tileSize.w*this.params.metaTileSize.w;var metaY=Math.floor(pY/this.tileSize.h/this.params.metaTileSize.h)*this.tileSize.h*this.params.metaTileSize.h;var url=this.url;if(url instanceof Array){url=this.selectUrl(paramsString,url);}
60877 var components=[url,"/",this.params.map,"/",scale,"/",this.params.g.replace(/\s/g,'_'),"/def/t",metaY,"/l",metaX,"/t",pY,"l",pX,".",this.extension];return components.join("");},CLASS_NAME:"OpenLayers.Layer.KaMapCache"});OpenLayers.Layer.MapServer.Untiled=OpenLayers.Class(OpenLayers.Layer.MapServer,{singleTile:true,initialize:function(name,url,params,options){OpenLayers.Layer.MapServer.prototype.initialize.apply(this,arguments);var msg="The OpenLayers.Layer.MapServer.Untiled class is deprecated and "+"will be removed in 3.0. Instead, you should use the "+"normal OpenLayers.Layer.MapServer class, passing it the option "+"'singleTile' as true.";OpenLayers.Console.warn(msg);},clone:function(obj){if(obj==null){obj=new OpenLayers.Layer.MapServer.Untiled(this.name,this.url,this.params,this.getOptions());}
60878 obj=OpenLayers.Layer.MapServer.prototype.clone.apply(this,[obj]);return obj;},CLASS_NAME:"OpenLayers.Layer.MapServer.Untiled"});OpenLayers.Layer.Vector=OpenLayers.Class(OpenLayers.Layer,{EVENT_TYPES:["beforefeatureadded","beforefeaturesadded","featureadded","featuresadded","beforefeatureremoved","beforefeaturesremoved","featureremoved","featuresremoved","beforefeatureselected","featureselected","featureunselected","beforefeaturemodified","featuremodified","afterfeaturemodified","vertexmodified","sketchstarted","sketchmodified","sketchcomplete","refresh"],isBaseLayer:false,isFixed:false,isVector:true,features:null,filter:null,selectedFeatures:null,unrenderedFeatures:null,reportError:true,style:null,styleMap:null,strategies:null,protocol:null,renderers:['SVG','VML','Canvas'],renderer:null,rendererOptions:null,geometryType:null,drawn:false,initialize:function(name,options){this.EVENT_TYPES=OpenLayers.Layer.Vector.prototype.EVENT_TYPES.concat(OpenLayers.Layer.prototype.EVENT_TYPES);OpenLayers.Layer.prototype.initialize.apply(this,arguments);if(!this.renderer||!this.renderer.supported()){this.assignRenderer();}
60879 if(!this.renderer||!this.renderer.supported()){this.renderer=null;this.displayError();}
60880 if(!this.styleMap){this.styleMap=new OpenLayers.StyleMap();}
60881 this.features=[];this.selectedFeatures=[];this.unrenderedFeatures={};if(this.strategies){for(var i=0,len=this.strategies.length;i<len;i++){this.strategies[i].setLayer(this);}}},destroy:function(){if(this.strategies){var strategy,i,len;for(i=0,len=this.strategies.length;i<len;i++){strategy=this.strategies[i];if(strategy.autoDestroy){strategy.destroy();}}
60882 this.strategies=null;}
60883 if(this.protocol){if(this.protocol.autoDestroy){this.protocol.destroy();}
60884 this.protocol=null;}
60885 this.destroyFeatures();this.features=null;this.selectedFeatures=null;this.unrenderedFeatures=null;if(this.renderer){this.renderer.destroy();}
60886 this.renderer=null;this.geometryType=null;this.drawn=null;OpenLayers.Layer.prototype.destroy.apply(this,arguments);},clone:function(obj){if(obj==null){obj=new OpenLayers.Layer.Vector(this.name,this.getOptions());}
60887 obj=OpenLayers.Layer.prototype.clone.apply(this,[obj]);var features=this.features;var len=features.length;var clonedFeatures=new Array(len);for(var i=0;i<len;++i){clonedFeatures[i]=features[i].clone();}
60888 obj.features=clonedFeatures;return obj;},refresh:function(obj){if(this.calculateInRange()&&this.visibility){this.events.triggerEvent("refresh",obj);}},assignRenderer:function(){for(var i=0,len=this.renderers.length;i<len;i++){var rendererClass=this.renderers[i];var renderer=(typeof rendererClass=="function")?rendererClass:OpenLayers.Renderer[rendererClass];if(renderer&&renderer.prototype.supported()){this.renderer=new renderer(this.div,this.rendererOptions);break;}}},displayError:function(){if(this.reportError){OpenLayers.Console.userError(OpenLayers.i18n("browserNotSupported",{'renderers':this.renderers.join("\n")}));}},setMap:function(map){OpenLayers.Layer.prototype.setMap.apply(this,arguments);if(!this.renderer){this.map.removeLayer(this);}else{this.renderer.map=this.map;this.renderer.setSize(this.map.getSize());}},afterAdd:function(){if(this.strategies){var strategy,i,len;for(i=0,len=this.strategies.length;i<len;i++){strategy=this.strategies[i];if(strategy.autoActivate){strategy.activate();}}}},removeMap:function(map){this.drawn=false;if(this.strategies){var strategy,i,len;for(i=0,len=this.strategies.length;i<len;i++){strategy=this.strategies[i];if(strategy.autoActivate){strategy.deactivate();}}}},onMapResize:function(){OpenLayers.Layer.prototype.onMapResize.apply(this,arguments);this.renderer.setSize(this.map.getSize());},moveTo:function(bounds,zoomChanged,dragging){OpenLayers.Layer.prototype.moveTo.apply(this,arguments);var coordSysUnchanged=true;if(!dragging){this.renderer.root.style.visibility="hidden";this.div.style.left=-parseInt(this.map.layerContainerDiv.style.left)+"px";this.div.style.top=-parseInt(this.map.layerContainerDiv.style.top)+"px";var extent=this.map.getExtent();coordSysUnchanged=this.renderer.setExtent(extent,zoomChanged);this.renderer.root.style.visibility="visible";if(navigator.userAgent.toLowerCase().indexOf("gecko")!=-1){this.div.scrollLeft=this.div.scrollLeft;}
60889 if(!zoomChanged&&coordSysUnchanged){for(var i in this.unrenderedFeatures){var feature=this.unrenderedFeatures[i];this.drawFeature(feature);}}}
60890 if(!this.drawn||zoomChanged||!coordSysUnchanged){this.drawn=true;var feature;for(var i=0,len=this.features.length;i<len;i++){this.renderer.locked=(i!==(len-1));feature=this.features[i];this.drawFeature(feature);}}},display:function(display){OpenLayers.Layer.prototype.display.apply(this,arguments);var currentDisplay=this.div.style.display;if(currentDisplay!=this.renderer.root.style.display){this.renderer.root.style.display=currentDisplay;}},addFeatures:function(features,options){if(!(features instanceof Array)){features=[features];}
60891 var notify=!options||!options.silent;if(notify){var event={features:features};var ret=this.events.triggerEvent("beforefeaturesadded",event);if(ret===false){return;}
60892 features=event.features;}
60893 var featuresAdded=[];for(var i=0,len=features.length;i<len;i++){if(i!=(features.length-1)){this.renderer.locked=true;}else{this.renderer.locked=false;}
60894 var feature=features[i];if(this.geometryType&&!(feature.geometry instanceof this.geometryType)){var throwStr=OpenLayers.i18n('componentShouldBe',{'geomType':this.geometryType.prototype.CLASS_NAME});throw throwStr;}
60895 feature.layer=this;if(!feature.style&&this.style){feature.style=OpenLayers.Util.extend({},this.style);}
60896 if(notify){if(this.events.triggerEvent("beforefeatureadded",{feature:feature})===false){continue;};this.preFeatureInsert(feature);}
60897 featuresAdded.push(feature);this.features.push(feature);this.drawFeature(feature);if(notify){this.events.triggerEvent("featureadded",{feature:feature});this.onFeatureInsert(feature);}}
60898 if(notify){this.events.triggerEvent("featuresadded",{features:featuresAdded});}},removeFeatures:function(features,options){if(!features||features.length===0){return;}
60899 if(features===this.features){return this.removeAllFeatures(options);}
60900 if(!(features instanceof Array)){features=[features];}
60901 if(features===this.selectedFeatures){features=features.slice();}
60902 var notify=!options||!options.silent;if(notify){this.events.triggerEvent("beforefeaturesremoved",{features:features});}
60903 for(var i=features.length-1;i>=0;i--){if(i!=0&&features[i-1].geometry){this.renderer.locked=true;}else{this.renderer.locked=false;}
60904 var feature=features[i];delete this.unrenderedFeatures[feature.id];if(notify){this.events.triggerEvent("beforefeatureremoved",{feature:feature});}
60905 this.features=OpenLayers.Util.removeItem(this.features,feature);feature.layer=null;if(feature.geometry){this.renderer.eraseFeatures(feature);}
60906 if(OpenLayers.Util.indexOf(this.selectedFeatures,feature)!=-1){OpenLayers.Util.removeItem(this.selectedFeatures,feature);}
60907 if(notify){this.events.triggerEvent("featureremoved",{feature:feature});}}
60908 if(notify){this.events.triggerEvent("featuresremoved",{features:features});}},removeAllFeatures:function(options){var notify=!options||!options.silent;var features=this.features;if(notify){this.events.triggerEvent("beforefeaturesremoved",{features:features});}
60909 var feature;for(var i=features.length-1;i>=0;i--){feature=features[i];if(notify){this.events.triggerEvent("beforefeatureremoved",{feature:feature});}
60910 feature.layer=null;if(notify){this.events.triggerEvent("featureremoved",{feature:feature});}}
60911 this.renderer.clear();this.features=[];this.unrenderedFeatures={};this.selectedFeatures=[];if(notify){this.events.triggerEvent("featuresremoved",{features:features});}},destroyFeatures:function(features,options){var all=(features==undefined);if(all){features=this.features;}
60912 if(features){this.removeFeatures(features,options);for(var i=features.length-1;i>=0;i--){features[i].destroy();}}},drawFeature:function(feature,style){if(!this.drawn){return}
60913 if(typeof style!="object"){if(!style&&feature.state===OpenLayers.State.DELETE){style="delete";}
60914 var renderIntent=style||feature.renderIntent;style=feature.style||this.style;if(!style){style=this.styleMap.createSymbolizer(feature,renderIntent);}}
60915 if(!this.renderer.drawFeature(feature,style)){this.unrenderedFeatures[feature.id]=feature;}else{delete this.unrenderedFeatures[feature.id];};},eraseFeatures:function(features){this.renderer.eraseFeatures(features);},getFeatureFromEvent:function(evt){if(!this.renderer){OpenLayers.Console.error(OpenLayers.i18n("getFeatureError"));return null;}
60916 var featureId=this.renderer.getFeatureIdFromEvent(evt);return this.getFeatureById(featureId);},getFeatureBy:function(property,value){var feature=null;for(var i=0,len=this.features.length;i<len;++i){if(this.features[i][property]==value){feature=this.features[i];break;}}
60917 return feature;},getFeatureById:function(featureId){return this.getFeatureBy('id',featureId);},getFeatureByFid:function(featureFid){return this.getFeatureBy('fid',featureFid);},onFeatureInsert:function(feature){},preFeatureInsert:function(feature){},getDataExtent:function(){var maxExtent=null;var features=this.features;if(features&&(features.length>0)){maxExtent=new OpenLayers.Bounds();var geometry=null;for(var i=0,len=features.length;i<len;i++){geometry=features[i].geometry;if(geometry){maxExtent.extend(geometry.getBounds());}}}
60918 return maxExtent;},CLASS_NAME:"OpenLayers.Layer.Vector"});OpenLayers.Layer.WMS.Post=OpenLayers.Class(OpenLayers.Layer.WMS,{tileClass:null,unsupportedBrowsers:["mozilla","firefox","opera"],SUPPORTED_TRANSITIONS:[],initialize:function(name,url,params,options){var newArguments=[];newArguments.push(name,url,params,options);OpenLayers.Layer.WMS.prototype.initialize.apply(this,newArguments);this.tileClass=OpenLayers.Util.indexOf(this.unsupportedBrowsers,OpenLayers.Util.getBrowserName())!=-1?OpenLayers.Tile.Image:OpenLayers.Tile.Image.IFrame;},addTile:function(bounds,position){return new this.tileClass(this,position,bounds,null,this.tileSize);},CLASS_NAME:'OpenLayers.Layer.WMS.Post'});OpenLayers.Layer.WMS.Untiled=OpenLayers.Class(OpenLayers.Layer.WMS,{singleTile:true,initialize:function(name,url,params,options){OpenLayers.Layer.WMS.prototype.initialize.apply(this,arguments);var msg="The OpenLayers.Layer.WMS.Untiled class is deprecated and "+"will be removed in 3.0. Instead, you should use the "+"normal OpenLayers.Layer.WMS class, passing it the option "+"'singleTile' as true.";OpenLayers.Console.warn(msg);},clone:function(obj){if(obj==null){obj=new OpenLayers.Layer.WMS.Untiled(this.name,this.url,this.params,this.getOptions());}
60919 obj=OpenLayers.Layer.WMS.prototype.clone.apply(this,[obj]);return obj;},CLASS_NAME:"OpenLayers.Layer.WMS.Untiled"});OpenLayers.Strategy.Filter=OpenLayers.Class(OpenLayers.Strategy,{filter:null,cache:null,caching:false,initialize:function(options){OpenLayers.Strategy.prototype.initialize.apply(this,[options]);if(!this.filter||!(this.filter instanceof OpenLayers.Filter)){throw new Error("Filter strategy must be constructed with a filter");}},activate:function(){var activated=OpenLayers.Strategy.prototype.activate.apply(this,arguments);if(activated){this.cache=[];this.layer.events.on({"beforefeaturesadded":this.handleAdd,"beforefeaturesremoved":this.handleRemove,scope:this});}
60920 return activated;},deactivate:function(){this.cache=null;if(this.layer&&this.layer.events){this.layer.events.un({"beforefeaturesadded":this.handleAdd,"beforefeaturesremoved":this.handleRemove,scope:this});}
60921 return OpenLayers.Strategy.prototype.deactivate.apply(this,arguments);},handleAdd:function(event){if(!this.caching){var features=event.features;event.features=[];var feature;for(var i=0,ii=features.length;i<ii;++i){feature=features[i];if(this.filter.evaluate(feature)){event.features.push(feature);}else{this.cache.push(feature);}}}},handleRemove:function(event){if(!this.caching){this.cache=[];}},setFilter:function(filter){this.filter=filter;var previousCache=this.cache;this.cache=[];this.handleAdd({features:this.layer.features});if(this.cache.length>0){this.caching=true;this.layer.removeFeatures(this.cache.slice(),{silent:true});this.caching=false;}
60922 if(previousCache.length>0){var event={features:previousCache};this.handleAdd(event);this.caching=true;this.layer.addFeatures(event.features,{silent:true});this.caching=false;}},CLASS_NAME:"OpenLayers.Strategy.Filter"});OpenLayers.Style2=OpenLayers.Class({id:null,name:null,title:null,description:null,layerName:null,isDefault:false,rules:null,initialize:function(config){OpenLayers.Util.extend(this,config);this.id=OpenLayers.Util.createUniqueID(this.CLASS_NAME+"_");},destroy:function(){for(var i=0,len=this.rules.length;i<len;i++){this.rules[i].destroy();}
60923 delete this.rules;},clone:function(){var config=OpenLayers.Util.extend({},this);if(this.rules){config.rules=[];for(var i=0,len=this.rules.length;i<len;++i){config.rules.push(this.rules[i].clone());}}
60924 return new OpenLayers.Style2(config);},CLASS_NAME:"OpenLayers.Style2"});OpenLayers.Control.GetFeature=OpenLayers.Class(OpenLayers.Control,{protocol:null,multipleKey:null,toggleKey:null,modifiers:null,multiple:false,click:true,single:true,clickout:true,toggle:false,clickTolerance:5,hover:false,box:false,maxFeatures:10,features:null,hoverFeature:null,handlerOptions:null,handlers:null,hoverResponse:null,filterType:OpenLayers.Filter.Spatial.BBOX,EVENT_TYPES:["featureselected","featuresselected","featureunselected","clickout","beforefeatureselected","beforefeaturesselected","hoverfeature","outfeature"],initialize:function(options){this.EVENT_TYPES=OpenLayers.Control.GetFeature.prototype.EVENT_TYPES.concat(OpenLayers.Control.prototype.EVENT_TYPES);options.handlerOptions=options.handlerOptions||{};OpenLayers.Control.prototype.initialize.apply(this,[options]);this.features={};this.handlers={};if(this.click){this.handlers.click=new OpenLayers.Handler.Click(this,{click:this.selectClick},this.handlerOptions.click||{});}
60925 if(this.box){this.handlers.box=new OpenLayers.Handler.Box(this,{done:this.selectBox},OpenLayers.Util.extend(this.handlerOptions.box,{boxDivClassName:"olHandlerBoxSelectFeature"}));}
60926 if(this.hover){this.handlers.hover=new OpenLayers.Handler.Hover(this,{'move':this.cancelHover,'pause':this.selectHover},OpenLayers.Util.extend(this.handlerOptions.hover,{'delay':250}));}},activate:function(){if(!this.active){for(var i in this.handlers){this.handlers[i].activate();}}
60927 return OpenLayers.Control.prototype.activate.apply(this,arguments);},deactivate:function(){if(this.active){for(var i in this.handlers){this.handlers[i].deactivate();}}
60928 return OpenLayers.Control.prototype.deactivate.apply(this,arguments);},selectClick:function(evt){var bounds=this.pixelToBounds(evt.xy);this.setModifiers(evt);this.request(bounds,{single:this.single});},selectBox:function(position){var bounds;if(position instanceof OpenLayers.Bounds){var minXY=this.map.getLonLatFromPixel(new OpenLayers.Pixel(position.left,position.bottom));var maxXY=this.map.getLonLatFromPixel(new OpenLayers.Pixel(position.right,position.top));bounds=new OpenLayers.Bounds(minXY.lon,minXY.lat,maxXY.lon,maxXY.lat);}else{if(this.click){return;}
60929 bounds=this.pixelToBounds(position);}
60930 this.setModifiers(this.handlers.box.dragHandler.evt);this.request(bounds);},selectHover:function(evt){var bounds=this.pixelToBounds(evt.xy);this.request(bounds,{single:true,hover:true});},cancelHover:function(){if(this.hoverResponse){this.protocol.abort(this.hoverResponse);this.hoverResponse=null;OpenLayers.Element.removeClass(this.map.viewPortDiv,"olCursorWait");}},request:function(bounds,options){options=options||{};var filter=new OpenLayers.Filter.Spatial({type:this.filterType,value:bounds});OpenLayers.Element.addClass(this.map.viewPortDiv,"olCursorWait");var response=this.protocol.read({maxFeatures:options.single==true?this.maxFeatures:undefined,filter:filter,callback:function(result){if(result.success()){if(result.features.length){if(options.single==true){this.selectBestFeature(result.features,bounds.getCenterLonLat(),options);}else{this.select(result.features);}}else if(options.hover){this.hoverSelect();}else{this.events.triggerEvent("clickout");if(this.clickout){this.unselectAll();}}}
60931 OpenLayers.Element.removeClass(this.map.viewPortDiv,"olCursorWait");},scope:this});if(options.hover==true){this.hoverResponse=response;}},selectBestFeature:function(features,clickPosition,options){options=options||{};if(features.length){var point=new OpenLayers.Geometry.Point(clickPosition.lon,clickPosition.lat);var feature,resultFeature,dist;var minDist=Number.MAX_VALUE;for(var i=0;i<features.length;++i){feature=features[i];if(feature.geometry){dist=point.distanceTo(feature.geometry,{edge:false});if(dist<minDist){minDist=dist;resultFeature=feature;if(minDist==0){break;}}}}
60932 if(options.hover==true){this.hoverSelect(resultFeature);}else{this.select(resultFeature||features);}}},setModifiers:function(evt){this.modifiers={multiple:this.multiple||(this.multipleKey&&evt[this.multipleKey]),toggle:this.toggle||(this.toggleKey&&evt[this.toggleKey])};},select:function(features){if(!this.modifiers.multiple&&!this.modifiers.toggle){this.unselectAll();}
60933 if(!(features instanceof Array)){features=[features];}
60934 var cont=this.events.triggerEvent("beforefeaturesselected",{features:features});if(cont!==false){var selectedFeatures=[];var feature;for(var i=0,len=features.length;i<len;++i){feature=features[i];if(this.features[feature.fid||feature.id]){if(this.modifiers.toggle){this.unselect(this.features[feature.fid||feature.id]);}}else{cont=this.events.triggerEvent("beforefeatureselected",{feature:feature});if(cont!==false){this.features[feature.fid||feature.id]=feature;selectedFeatures.push(feature);this.events.triggerEvent("featureselected",{feature:feature});}}}
60935 this.events.triggerEvent("featuresselected",{features:selectedFeatures});}},hoverSelect:function(feature){var fid=feature?feature.fid||feature.id:null;var hfid=this.hoverFeature?this.hoverFeature.fid||this.hoverFeature.id:null;if(hfid&&hfid!=fid){this.events.triggerEvent("outfeature",{feature:this.hoverFeature});this.hoverFeature=null;}
60936 if(fid&&fid!=hfid){this.events.triggerEvent("hoverfeature",{feature:feature});this.hoverFeature=feature;}},unselect:function(feature){delete this.features[feature.fid||feature.id];this.events.triggerEvent("featureunselected",{feature:feature});},unselectAll:function(){for(var fid in this.features){this.unselect(this.features[fid]);}},setMap:function(map){for(var i in this.handlers){this.handlers[i].setMap(map);}
60937 OpenLayers.Control.prototype.setMap.apply(this,arguments);},pixelToBounds:function(pixel){var llPx=pixel.add(-this.clickTolerance/2,this.clickTolerance/2);var urPx=pixel.add(this.clickTolerance/2,-this.clickTolerance/2);var ll=this.map.getLonLatFromPixel(llPx);var ur=this.map.getLonLatFromPixel(urPx);return new OpenLayers.Bounds(ll.lon,ll.lat,ur.lon,ur.lat);},CLASS_NAME:"OpenLayers.Control.GetFeature"});OpenLayers.Control.Snapping=OpenLayers.Class(OpenLayers.Control,{EVENT_TYPES:["beforesnap","snap","unsnap"],DEFAULTS:{tolerance:10,node:true,edge:true,vertex:true},greedy:true,precedence:["node","vertex","edge"],resolution:null,geoToleranceCache:null,layer:null,feature:null,point:null,initialize:function(options){Array.prototype.push.apply(this.EVENT_TYPES,OpenLayers.Control.prototype.EVENT_TYPES);OpenLayers.Control.prototype.initialize.apply(this,[options]);this.options=options||{};if(this.options.layer){this.setLayer(this.options.layer);}
60938 var defaults=OpenLayers.Util.extend({},this.options.defaults);this.defaults=OpenLayers.Util.applyDefaults(defaults,this.DEFAULTS);this.setTargets(this.options.targets);if(this.targets.length===0&&this.layer){this.addTargetLayer(this.layer);}
60939 this.geoToleranceCache={};},setLayer:function(layer){if(this.active){this.deactivate();this.layer=layer;this.activate();}else{this.layer=layer;}},setTargets:function(targets){this.targets=[];if(targets&&targets.length){var target;for(var i=0,len=targets.length;i<len;++i){target=targets[i];if(target instanceof OpenLayers.Layer.Vector){this.addTargetLayer(target);}else{this.addTarget(target);}}}},addTargetLayer:function(layer){this.addTarget({layer:layer});},addTarget:function(target){target=OpenLayers.Util.applyDefaults(target,this.defaults);target.nodeTolerance=target.nodeTolerance||target.tolerance;target.vertexTolerance=target.vertexTolerance||target.tolerance;target.edgeTolerance=target.edgeTolerance||target.tolerance;this.targets.push(target);},removeTargetLayer:function(layer){var target;for(var i=this.targets.length-1;i>=0;--i){target=this.targets[i];if(target.layer===layer){this.removeTarget(target);}}},removeTarget:function(target){return OpenLayers.Util.removeItem(this.targets,target);},activate:function(){var activated=OpenLayers.Control.prototype.activate.call(this);if(activated){if(this.layer&&this.layer.events){this.layer.events.on({sketchstarted:this.onSketchModified,sketchmodified:this.onSketchModified,vertexmodified:this.onVertexModified,scope:this});}}
60940 return activated;},deactivate:function(){var deactivated=OpenLayers.Control.prototype.deactivate.call(this);if(deactivated){if(this.layer&&this.layer.events){this.layer.events.un({sketchstarted:this.onSketchModified,sketchmodified:this.onSketchModified,vertexmodified:this.onVertexModified,scope:this});}}
60941 this.feature=null;this.point=null;return deactivated;},onSketchModified:function(event){this.feature=event.feature;this.considerSnapping(event.vertex,event.vertex);},onVertexModified:function(event){this.feature=event.feature;var loc=this.layer.map.getLonLatFromViewPortPx(event.pixel);this.considerSnapping(event.vertex,new OpenLayers.Geometry.Point(loc.lon,loc.lat));},considerSnapping:function(point,loc){var best={rank:Number.POSITIVE_INFINITY,dist:Number.POSITIVE_INFINITY,x:null,y:null};var snapped=false;var result,target;for(var i=0,len=this.targets.length;i<len;++i){target=this.targets[i];result=this.testTarget(target,loc);if(result){if(this.greedy){best=result;best.target=target;snapped=true;break;}else{if((result.rank<best.rank)||(result.rank===best.rank&&result.dist<best.dist)){best=result;best.target=target;snapped=true;}}}}
60942 if(snapped){var proceed=this.events.triggerEvent("beforesnap",{point:point,x:best.x,y:best.y,distance:best.dist,layer:best.target.layer,snapType:this.precedence[best.rank]});if(proceed!==false){point.x=best.x;point.y=best.y;this.point=point;this.events.triggerEvent("snap",{point:point,snapType:this.precedence[best.rank],layer:best.target.layer,distance:best.dist});}else{snapped=false;}}
60943 if(this.point&&!snapped){point.x=loc.x;point.y=loc.y;this.point=null;this.events.triggerEvent("unsnap",{point:point});}},testTarget:function(target,loc){var tolerance={node:this.getGeoTolerance(target.nodeTolerance),vertex:this.getGeoTolerance(target.vertexTolerance),edge:this.getGeoTolerance(target.edgeTolerance)};var maxTolerance=Math.max(tolerance.node,tolerance.vertex,tolerance.edge);var result={rank:Number.POSITIVE_INFINITY,dist:Number.POSITIVE_INFINITY};var eligible=false;var features=target.layer.features;var feature,type,vertices,vertex,closest,dist,found;var numTypes=this.precedence.length;var ll=new OpenLayers.LonLat(loc.x,loc.y);for(var i=0,len=features.length;i<len;++i){feature=features[i];if(feature!==this.feature&&!feature._sketch&&feature.state!==OpenLayers.State.DELETE&&(!target.filter||target.filter.evaluate(feature.attributes))){if(feature.atPoint(ll,maxTolerance,maxTolerance)){for(var j=0,stop=Math.min(result.rank+1,numTypes);j<stop;++j){type=this.precedence[j];if(target[type]){if(type==="edge"){closest=feature.geometry.distanceTo(loc,{details:true});dist=closest.distance;if(dist<=tolerance[type]&&dist<result.dist){result={rank:j,dist:dist,x:closest.x0,y:closest.y0};eligible=true;break;}}else{vertices=feature.geometry.getVertices(type==="node");found=false;for(var k=0,klen=vertices.length;k<klen;++k){vertex=vertices[k];dist=vertex.distanceTo(loc);if(dist<=tolerance[type]&&(j<result.rank||(j===result.rank&&dist<result.dist))){result={rank:j,dist:dist,x:vertex.x,y:vertex.y};eligible=true;found=true;}}
60944 if(found){break;}}}}}}}
60945 return eligible?result:null;},getGeoTolerance:function(tolerance){var resolution=this.layer.map.getResolution();if(resolution!==this.resolution){this.resolution=resolution;this.geoToleranceCache={};}
60946 var geoTolerance=this.geoToleranceCache[tolerance];if(geoTolerance===undefined){geoTolerance=tolerance*resolution;this.geoToleranceCache[tolerance]=geoTolerance;}
60947 return geoTolerance;},destroy:function(){if(this.active){this.deactivate();}
60948 delete this.layer;delete this.targets;OpenLayers.Control.prototype.destroy.call(this);},CLASS_NAME:"OpenLayers.Control.Snapping"});OpenLayers.Format.Filter=OpenLayers.Class(OpenLayers.Format.XML,{defaultVersion:"1.0.0",version:null,parser:null,initialize:function(options){OpenLayers.Format.XML.prototype.initialize.apply(this,[options]);},write:function(filter,options){var version=(options&&options.version)||this.version||this.defaultVersion;if(!this.parser||this.parser.VERSION!=version){var format=OpenLayers.Format.Filter["v"+version.replace(/\./g,"_")];if(!format){throw"Can't find a Filter parser for version "+
60949 version;}
60950 this.parser=new format(this.options);}
60951 return this.parser.write(filter);},read:function(data){if(typeof data=="string"){data=OpenLayers.Format.XML.prototype.read.apply(this,[data]);}
60952 var version=this.version;if(!version){version=this.defaultVersion;}
60953 if(!this.parser||this.parser.VERSION!=version){var format=OpenLayers.Format.Filter["v"+version.replace(/\./g,"_")];if(!format){throw"Can't find a Filter parser for version "+
60954 version;}
60955 this.parser=new format(this.options);}
60956 var filter=this.parser.read(data);return filter;},CLASS_NAME:"OpenLayers.Format.Filter"});OpenLayers.Format.SLD=OpenLayers.Class(OpenLayers.Format.XML,{defaultVersion:"1.0.0",version:null,namedLayersAsArray:false,parser:null,initialize:function(options){OpenLayers.Format.XML.prototype.initialize.apply(this,[options]);},write:function(sld,options){var version=(options&&options.version)||this.version||this.defaultVersion;if(!this.parser||this.parser.VERSION!=version){var format=OpenLayers.Format.SLD["v"+version.replace(/\./g,"_")];if(!format){throw"Can't find a SLD parser for version "+
60957 version;}
60958 this.parser=new format(this.options);}
60959 var root=this.parser.write(sld);return OpenLayers.Format.XML.prototype.write.apply(this,[root]);},read:function(data,options){if(typeof data=="string"){data=OpenLayers.Format.XML.prototype.read.apply(this,[data]);}
60960 var root=data.documentElement;var version=this.version;if(!version){version=root.getAttribute("version");if(!version){version=this.defaultVersion;}}
60961 if(!this.parser||this.parser.VERSION!=version){var format=OpenLayers.Format.SLD["v"+version.replace(/\./g,"_")];if(!format){throw"Can't find a SLD parser for version "+
60962 version;}
60963 this.parser=new format(this.options);}
60964 var sld=this.parser.read(data,options);return sld;},CLASS_NAME:"OpenLayers.Format.SLD"});OpenLayers.Format.Text=OpenLayers.Class(OpenLayers.Format,{defaultStyle:null,extractStyles:true,initialize:function(options){options=options||{};if(options.extractStyles!==false){options.defaultStyle={'externalGraphic':OpenLayers.Util.getImagesLocation()+"marker.png",'graphicWidth':21,'graphicHeight':25,'graphicXOffset':-10.5,'graphicYOffset':-12.5};}
60965 OpenLayers.Format.prototype.initialize.apply(this,[options]);},read:function(text){var lines=text.split('\n');var columns;var features=[];for(var lcv=0;lcv<(lines.length-1);lcv++){var currLine=lines[lcv].replace(/^\s*/,'').replace(/\s*$/,'');if(currLine.charAt(0)!='#'){if(!columns){columns=currLine.split('\t');}else{var vals=currLine.split('\t');var geometry=new OpenLayers.Geometry.Point(0,0);var attributes={};var style=this.defaultStyle?OpenLayers.Util.applyDefaults({},this.defaultStyle):null;var icon,iconSize,iconOffset,overflow;var set=false;for(var valIndex=0;valIndex<vals.length;valIndex++){if(vals[valIndex]){if(columns[valIndex]=='point'){var coords=vals[valIndex].split(',');geometry.y=parseFloat(coords[0]);geometry.x=parseFloat(coords[1]);set=true;}else if(columns[valIndex]=='lat'){geometry.y=parseFloat(vals[valIndex]);set=true;}else if(columns[valIndex]=='lon'){geometry.x=parseFloat(vals[valIndex]);set=true;}else if(columns[valIndex]=='title')
60966 attributes['title']=vals[valIndex];else if(columns[valIndex]=='image'||columns[valIndex]=='icon'&&style){style['externalGraphic']=vals[valIndex];}else if(columns[valIndex]=='iconSize'&&style){var size=vals[valIndex].split(',');style['graphicWidth']=parseFloat(size[0]);style['graphicHeight']=parseFloat(size[1]);}else if(columns[valIndex]=='iconOffset'&&style){var offset=vals[valIndex].split(',');style['graphicXOffset']=parseFloat(offset[0]);style['graphicYOffset']=parseFloat(offset[1]);}else if(columns[valIndex]=='description'){attributes['description']=vals[valIndex];}else if(columns[valIndex]=='overflow'){attributes['overflow']=vals[valIndex];}else{attributes[columns[valIndex]]=vals[valIndex];}}}
60967 if(set){if(this.internalProjection&&this.externalProjection){geometry.transform(this.externalProjection,this.internalProjection);}
60968 var feature=new OpenLayers.Feature.Vector(geometry,attributes,style);features.push(feature);}}}}
60969 return features;},CLASS_NAME:"OpenLayers.Format.Text"});OpenLayers.Geometry.MultiPoint=OpenLayers.Class(OpenLayers.Geometry.Collection,{componentTypes:["OpenLayers.Geometry.Point"],initialize:function(components){OpenLayers.Geometry.Collection.prototype.initialize.apply(this,arguments);},addPoint:function(point,index){this.addComponent(point,index);},removePoint:function(point){this.removeComponent(point);},CLASS_NAME:"OpenLayers.Geometry.MultiPoint"});OpenLayers.Handler.Point=OpenLayers.Class(OpenLayers.Handler,{point:null,layer:null,multi:false,drawing:false,mouseDown:false,lastDown:null,lastUp:null,persist:false,layerOptions:null,initialize:function(control,callbacks,options){if(!(options&&options.layerOptions&&options.layerOptions.styleMap)){this.style=OpenLayers.Util.extend(OpenLayers.Feature.Vector.style['default'],{});}
60970 OpenLayers.Handler.prototype.initialize.apply(this,arguments);},activate:function(){if(!OpenLayers.Handler.prototype.activate.apply(this,arguments)){return false;}
60971 var options=OpenLayers.Util.extend({displayInLayerSwitcher:false,calculateInRange:OpenLayers.Function.True},this.layerOptions);this.layer=new OpenLayers.Layer.Vector(this.CLASS_NAME,options);this.map.addLayer(this.layer);return true;},createFeature:function(pixel){var lonlat=this.map.getLonLatFromPixel(pixel);this.point=new OpenLayers.Feature.Vector(new OpenLayers.Geometry.Point(lonlat.lon,lonlat.lat));this.callback("create",[this.point.geometry,this.point]);this.point.geometry.clearBounds();this.layer.addFeatures([this.point],{silent:true});},deactivate:function(){if(!OpenLayers.Handler.prototype.deactivate.apply(this,arguments)){return false;}
60972 if(this.drawing){this.cancel();}
60973 this.destroyFeature();if(this.layer.map!=null){this.layer.destroy(false);}
60974 this.layer=null;return true;},destroyFeature:function(){if(this.layer){this.layer.destroyFeatures();}
60975 this.point=null;},finalize:function(cancel){var key=cancel?"cancel":"done";this.drawing=false;this.mouseDown=false;this.lastDown=null;this.lastUp=null;this.callback(key,[this.geometryClone()]);if(cancel||!this.persist){this.destroyFeature();}},cancel:function(){this.finalize(true);},click:function(evt){OpenLayers.Event.stop(evt);return false;},dblclick:function(evt){OpenLayers.Event.stop(evt);return false;},modifyFeature:function(pixel){var lonlat=this.map.getLonLatFromPixel(pixel);this.point.geometry.x=lonlat.lon;this.point.geometry.y=lonlat.lat;this.callback("modify",[this.point.geometry,this.point]);this.point.geometry.clearBounds();this.drawFeature();},drawFeature:function(){this.layer.drawFeature(this.point,this.style);},getGeometry:function(){var geometry=this.point&&this.point.geometry;if(geometry&&this.multi){geometry=new OpenLayers.Geometry.MultiPoint([geometry]);}
60976 return geometry;},geometryClone:function(){var geom=this.getGeometry();return geom&&geom.clone();},mousedown:function(evt){if(!this.checkModifiers(evt)){return true;}
60977 if(this.lastDown&&this.lastDown.equals(evt.xy)){return true;}
60978 this.drawing=true;if(this.lastDown==null){if(this.persist){this.destroyFeature();}
60979 this.createFeature(evt.xy);}else{this.modifyFeature(evt.xy);}
60980 this.lastDown=evt.xy;return false;},mousemove:function(evt){if(this.drawing){this.modifyFeature(evt.xy);}
60981 return true;},mouseup:function(evt){if(this.drawing){this.finalize();return false;}else{return true;}},CLASS_NAME:"OpenLayers.Handler.Point"});OpenLayers.Layer.GML=OpenLayers.Class(OpenLayers.Layer.Vector,{loaded:false,format:null,formatOptions:null,initialize:function(name,url,options){var newArguments=[];newArguments.push(name,options);OpenLayers.Layer.Vector.prototype.initialize.apply(this,newArguments);this.url=url;},setVisibility:function(visibility,noEvent){OpenLayers.Layer.Vector.prototype.setVisibility.apply(this,arguments);if(this.visibility&&!this.loaded){this.loadGML();}},moveTo:function(bounds,zoomChanged,minor){OpenLayers.Layer.Vector.prototype.moveTo.apply(this,arguments);if(this.visibility&&!this.loaded){this.loadGML();}},loadGML:function(){if(!this.loaded){this.events.triggerEvent("loadstart");OpenLayers.Request.GET({url:this.url,success:this.requestSuccess,failure:this.requestFailure,scope:this});this.loaded=true;}},setUrl:function(url){this.url=url;this.destroyFeatures();this.loaded=false;this.loadGML();},requestSuccess:function(request){var doc=request.responseXML;if(!doc||!doc.documentElement){doc=request.responseText;}
60982 var options={};OpenLayers.Util.extend(options,this.formatOptions);if(this.map&&!this.projection.equals(this.map.getProjectionObject())){options.externalProjection=this.projection;options.internalProjection=this.map.getProjectionObject();}
60983 var gml=this.format?new this.format(options):new OpenLayers.Format.GML(options);this.addFeatures(gml.read(doc));this.events.triggerEvent("loadend");},requestFailure:function(request){OpenLayers.Console.userError(OpenLayers.i18n("errorLoadingGML",{'url':this.url}));this.events.triggerEvent("loadend");},CLASS_NAME:"OpenLayers.Layer.GML"});OpenLayers.Layer.PointTrack=OpenLayers.Class(OpenLayers.Layer.Vector,{dataFrom:null,initialize:function(name,options){OpenLayers.Layer.Vector.prototype.initialize.apply(this,arguments);},addNodes:function(pointFeatures){if(pointFeatures.length<2){OpenLayers.Console.error("At least two point features have to be added to create"+"a line from");return;}
60984 var lines=new Array(pointFeatures.length-1);var pointFeature,startPoint,endPoint;for(var i=0,len=pointFeatures.length;i<len;i++){pointFeature=pointFeatures[i];endPoint=pointFeature.geometry;if(!endPoint){var lonlat=pointFeature.lonlat;endPoint=new OpenLayers.Geometry.Point(lonlat.lon,lonlat.lat);}else if(endPoint.CLASS_NAME!="OpenLayers.Geometry.Point"){OpenLayers.Console.error("Only features with point geometries are supported.");return;}
60985 if(i>0){var attributes=(this.dataFrom!=null)?(pointFeatures[i+this.dataFrom].data||pointFeatures[i+this.dataFrom].attributes):null;var line=new OpenLayers.Geometry.LineString([startPoint,endPoint]);lines[i-1]=new OpenLayers.Feature.Vector(line,attributes);}
60986 startPoint=endPoint;}
60987 this.addFeatures(lines);},CLASS_NAME:"OpenLayers.Layer.PointTrack"});OpenLayers.Layer.PointTrack.dataFrom={'SOURCE_NODE':-1,'TARGET_NODE':0};OpenLayers.Layer.Vector.RootContainer=OpenLayers.Class(OpenLayers.Layer.Vector,{displayInLayerSwitcher:false,layers:null,initialize:function(name,options){OpenLayers.Layer.Vector.prototype.initialize.apply(this,arguments);},display:function(){},getFeatureFromEvent:function(evt){var layers=this.layers;var feature;for(var i=0;i<layers.length;i++){feature=layers[i].getFeatureFromEvent(evt);if(feature){return feature;}}},setMap:function(map){OpenLayers.Layer.Vector.prototype.setMap.apply(this,arguments);this.collectRoots();map.events.register("changelayer",this,this.handleChangeLayer);},removeMap:function(map){map.events.unregister("changelayer",this,this.handleChangeLayer);this.resetRoots();OpenLayers.Layer.Vector.prototype.removeMap.apply(this,arguments);},collectRoots:function(){var layer;for(var i=0;i<this.map.layers.length;++i){layer=this.map.layers[i];if(OpenLayers.Util.indexOf(this.layers,layer)!=-1){layer.renderer.moveRoot(this.renderer);}}},resetRoots:function(){var layer;for(var i=0;i<this.layers.length;++i){layer=this.layers[i];if(this.renderer&&layer.renderer.getRenderLayerId()==this.id){this.renderer.moveRoot(layer.renderer);}}},handleChangeLayer:function(evt){var layer=evt.layer;if(evt.property=="order"&&OpenLayers.Util.indexOf(this.layers,layer)!=-1){this.resetRoots();this.collectRoots();}},CLASS_NAME:"OpenLayers.Layer.Vector.RootContainer"});OpenLayers.Layer.WFS=OpenLayers.Class(OpenLayers.Layer.Vector,OpenLayers.Layer.Markers,{isBaseLayer:false,tile:null,ratio:2,DEFAULT_PARAMS:{service:"WFS",version:"1.0.0",request:"GetFeature"},featureClass:null,format:null,formatObject:null,formatOptions:null,vectorMode:true,encodeBBOX:false,extractAttributes:false,initialize:function(name,url,params,options){if(options==undefined){options={};}
60988 if(options.featureClass||!OpenLayers.Layer.Vector||!OpenLayers.Feature.Vector){this.vectorMode=false;}
60989 params=OpenLayers.Util.upperCaseObject(params);OpenLayers.Util.extend(options,{'reportError':false});var newArguments=[];newArguments.push(name,options);OpenLayers.Layer.Vector.prototype.initialize.apply(this,newArguments);if(!this.renderer||!this.vectorMode){this.vectorMode=false;if(!options.featureClass){options.featureClass=OpenLayers.Feature.WFS;}
60990 OpenLayers.Layer.Markers.prototype.initialize.apply(this,newArguments);}
60991 if(this.params&&this.params.typename&&!this.options.typename){this.options.typename=this.params.typename;}
60992 if(!this.options.geometry_column){this.options.geometry_column="the_geom";}
60993 this.params=OpenLayers.Util.applyDefaults(params,OpenLayers.Util.upperCaseObject(this.DEFAULT_PARAMS));this.url=url;},destroy:function(){if(this.vectorMode){OpenLayers.Layer.Vector.prototype.destroy.apply(this,arguments);}else{OpenLayers.Layer.Markers.prototype.destroy.apply(this,arguments);}
60994 if(this.tile){this.tile.destroy();}
60995 this.tile=null;this.ratio=null;this.featureClass=null;this.format=null;if(this.formatObject&&this.formatObject.destroy){this.formatObject.destroy();}
60996 this.formatObject=null;this.formatOptions=null;this.vectorMode=null;this.encodeBBOX=null;this.extractAttributes=null;},setMap:function(map){if(this.vectorMode){OpenLayers.Layer.Vector.prototype.setMap.apply(this,arguments);var options={'extractAttributes':this.extractAttributes};OpenLayers.Util.extend(options,this.formatOptions);if(this.map&&!this.projection.equals(this.map.getProjectionObject())){options.externalProjection=this.projection;options.internalProjection=this.map.getProjectionObject();}
60997 this.formatObject=this.format?new this.format(options):new OpenLayers.Format.GML(options);}else{OpenLayers.Layer.Markers.prototype.setMap.apply(this,arguments);}},moveTo:function(bounds,zoomChanged,dragging){if(this.vectorMode){OpenLayers.Layer.Vector.prototype.moveTo.apply(this,arguments);}else{OpenLayers.Layer.Markers.prototype.moveTo.apply(this,arguments);}
60998 if(dragging){return false;}
60999 if(zoomChanged){if(this.vectorMode){this.renderer.clear();}}
61000 if(this.options.minZoomLevel){OpenLayers.Console.warn(OpenLayers.i18n('minZoomLevelError'));if(this.map.getZoom()<this.options.minZoomLevel){return null;}}
61001 if(bounds==null){bounds=this.map.getExtent();}
61002 var firstRendering=(this.tile==null);var outOfBounds=(!firstRendering&&!this.tile.bounds.containsBounds(bounds));if(zoomChanged||firstRendering||(!dragging&&outOfBounds)){var center=bounds.getCenterLonLat();var tileWidth=bounds.getWidth()*this.ratio;var tileHeight=bounds.getHeight()*this.ratio;var tileBounds=new OpenLayers.Bounds(center.lon-(tileWidth/2),center.lat-(tileHeight/2),center.lon+(tileWidth/2),center.lat+(tileHeight/2));var tileSize=this.map.getSize();tileSize.w=tileSize.w*this.ratio;tileSize.h=tileSize.h*this.ratio;var ul=new OpenLayers.LonLat(tileBounds.left,tileBounds.top);var pos=this.map.getLayerPxFromLonLat(ul);var url=this.getFullRequestString();var params=null;var filter=this.params.filter||this.params.FILTER;if(filter){params={FILTER:filter};}
61003 else{params={BBOX:this.encodeBBOX?tileBounds.toBBOX():tileBounds.toArray()};}
61004 if(this.map&&!this.projection.equals(this.map.getProjectionObject())){var projectedBounds=tileBounds.clone();projectedBounds.transform(this.map.getProjectionObject(),this.projection);if(!filter){params.BBOX=this.encodeBBOX?projectedBounds.toBBOX():projectedBounds.toArray();}}
61005 url+="&"+OpenLayers.Util.getParameterString(params);if(!this.tile){this.tile=new OpenLayers.Tile.WFS(this,pos,tileBounds,url,tileSize);this.addTileMonitoringHooks(this.tile);this.tile.draw();}else{if(this.vectorMode){this.destroyFeatures();this.renderer.clear();}else{this.clearMarkers();}
61006 this.removeTileMonitoringHooks(this.tile);this.tile.destroy();this.tile=null;this.tile=new OpenLayers.Tile.WFS(this,pos,tileBounds,url,tileSize);this.addTileMonitoringHooks(this.tile);this.tile.draw();}}},addTileMonitoringHooks:function(tile){tile.onLoadStart=function(){if(this==this.layer.tile){this.layer.events.triggerEvent("loadstart");}};tile.events.register("loadstart",tile,tile.onLoadStart);tile.onLoadEnd=function(){if(this==this.layer.tile){this.layer.events.triggerEvent("tileloaded");this.layer.events.triggerEvent("loadend");}};tile.events.register("loadend",tile,tile.onLoadEnd);tile.events.register("unload",tile,tile.onLoadEnd);},removeTileMonitoringHooks:function(tile){tile.unload();tile.events.un({"loadstart":tile.onLoadStart,"loadend":tile.onLoadEnd,"unload":tile.onLoadEnd,scope:tile});},onMapResize:function(){if(this.vectorMode){OpenLayers.Layer.Vector.prototype.onMapResize.apply(this,arguments);}else{OpenLayers.Layer.Markers.prototype.onMapResize.apply(this,arguments);}},display:function(){if(this.vectorMode){OpenLayers.Layer.Vector.prototype.display.apply(this,arguments);}else{OpenLayers.Layer.Markers.prototype.display.apply(this,arguments);}},mergeNewParams:function(newParams){var upperParams=OpenLayers.Util.upperCaseObject(newParams);var newArguments=[upperParams];return OpenLayers.Layer.HTTPRequest.prototype.mergeNewParams.apply(this,newArguments);},clone:function(obj){if(obj==null){obj=new OpenLayers.Layer.WFS(this.name,this.url,this.params,this.getOptions());}
61007 if(this.vectorMode){obj=OpenLayers.Layer.Vector.prototype.clone.apply(this,[obj]);}else{obj=OpenLayers.Layer.Markers.prototype.clone.apply(this,[obj]);}
61008 return obj;},getFullRequestString:function(newParams,altUrl){var projectionCode=this.projection.getCode()||this.map.getProjection();this.params.SRS=(projectionCode=="none")?null:projectionCode;return OpenLayers.Layer.Grid.prototype.getFullRequestString.apply(this,arguments);},commit:function(){if(!this.writer){var options={};if(this.map&&!this.projection.equals(this.map.getProjectionObject())){options.externalProjection=this.projection;options.internalProjection=this.map.getProjectionObject();}
61009 this.writer=new OpenLayers.Format.WFS(options,this);}
61010 var data=this.writer.write(this.features);OpenLayers.Request.POST({url:this.url,data:data,success:this.commitSuccess,failure:this.commitFailure,scope:this});},commitSuccess:function(request){var response=request.responseText;if(response.indexOf('SUCCESS')!=-1){this.commitReport(OpenLayers.i18n("commitSuccess",{'response':response}));for(var i=0;i<this.features.length;i++){this.features[i].state=null;}}else if(response.indexOf('FAILED')!=-1||response.indexOf('Exception')!=-1){this.commitReport(OpenLayers.i18n("commitFailed",{'response':response}));}},commitFailure:function(request){},commitReport:function(string,response){OpenLayers.Console.userError(string);},refresh:function(){if(this.tile){if(this.vectorMode){this.renderer.clear();this.features.length=0;}else{this.clearMarkers();this.markers.length=0;}
61011 this.tile.draw();}},getDataExtent:function(){var extent;if(this.vectorMode){extent=OpenLayers.Layer.Vector.prototype.getDataExtent.apply(this);}else{extent=OpenLayers.Layer.Markers.prototype.getDataExtent.apply(this);}
61012 return extent;},setOpacity:function(opacity){if(this.vectorMode){OpenLayers.Layer.Vector.prototype.setOpacity.apply(this,[opacity]);}else{OpenLayers.Layer.Markers.prototype.setOpacity.apply(this,[opacity]);}},CLASS_NAME:"OpenLayers.Layer.WFS"});OpenLayers.Protocol.HTTP=OpenLayers.Class(OpenLayers.Protocol,{url:null,headers:null,params:null,callback:null,scope:null,readWithPOST:false,wildcarded:false,initialize:function(options){options=options||{};this.params={};this.headers={};OpenLayers.Protocol.prototype.initialize.apply(this,arguments);},destroy:function(){this.params=null;this.headers=null;OpenLayers.Protocol.prototype.destroy.apply(this);},read:function(options){OpenLayers.Protocol.prototype.read.apply(this,arguments);options=OpenLayers.Util.applyDefaults(options,this.options);options.params=OpenLayers.Util.applyDefaults(options.params,this.options.params);if(options.filter){options.params=this.filterToParams(options.filter,options.params);}
61013 var readWithPOST=(options.readWithPOST!==undefined)?options.readWithPOST:this.readWithPOST;var resp=new OpenLayers.Protocol.Response({requestType:"read"});if(readWithPOST){resp.priv=OpenLayers.Request.POST({url:options.url,callback:this.createCallback(this.handleRead,resp,options),data:OpenLayers.Util.getParameterString(options.params),headers:{"Content-Type":"application/x-www-form-urlencoded"}});}else{resp.priv=OpenLayers.Request.GET({url:options.url,callback:this.createCallback(this.handleRead,resp,options),params:options.params,headers:options.headers});}
61014 return resp;},handleRead:function(resp,options){this.handleResponse(resp,options);},filterToParams:function(filter,params){params=params||{};var className=filter.CLASS_NAME;var filterType=className.substring(className.lastIndexOf(".")+1);switch(filterType){case"Spatial":switch(filter.type){case OpenLayers.Filter.Spatial.BBOX:params.bbox=filter.value.toArray();break;case OpenLayers.Filter.Spatial.DWITHIN:params.tolerance=filter.distance;case OpenLayers.Filter.Spatial.WITHIN:params.lon=filter.value.x;params.lat=filter.value.y;break;default:OpenLayers.Console.warn("Unknown spatial filter type "+filter.type);}
61015 break;case"Comparison":var op=OpenLayers.Protocol.HTTP.COMP_TYPE_TO_OP_STR[filter.type];if(op!==undefined){var value=filter.value;if(filter.type==OpenLayers.Filter.Comparison.LIKE){value=this.regex2value(value);if(this.wildcarded){value="%"+value+"%";}}
61016 params[filter.property+"__"+op]=value;params.queryable=params.queryable||[];params.queryable.push(filter.property);}else{OpenLayers.Console.warn("Unknown comparison filter type "+filter.type);}
61017 break;case"Logical":if(filter.type===OpenLayers.Filter.Logical.AND){for(var i=0,len=filter.filters.length;i<len;i++){params=this.filterToParams(filter.filters[i],params);}}else{OpenLayers.Console.warn("Unsupported logical filter type "+filter.type);}
61018 break;default:OpenLayers.Console.warn("Unknown filter type "+filterType);}
61019 return params;},regex2value:function(value){value=value.replace(/%/g,"\\%");value=value.replace(/\\\\\.(\*)?/g,function($0,$1){return $1?$0:"\\\\_";});value=value.replace(/\\\\\.\*/g,"\\\\%");value=value.replace(/(\\)?\.(\*)?/g,function($0,$1,$2){return $1||$2?$0:"_";});value=value.replace(/(\\)?\.\*/g,function($0,$1){return $1?$0:"%";});value=value.replace(/\\\./g,".");value=value.replace(/(\\)?\\\*/g,function($0,$1){return $1?$0:"*";});return value;},create:function(features,options){options=OpenLayers.Util.applyDefaults(options,this.options);var resp=new OpenLayers.Protocol.Response({reqFeatures:features,requestType:"create"});resp.priv=OpenLayers.Request.POST({url:options.url,callback:this.createCallback(this.handleCreate,resp,options),headers:options.headers,data:this.format.write(features)});return resp;},handleCreate:function(resp,options){this.handleResponse(resp,options);},update:function(feature,options){options=options||{};var url=options.url||feature.url||this.options.url+"/"+feature.fid;options=OpenLayers.Util.applyDefaults(options,this.options);var resp=new OpenLayers.Protocol.Response({reqFeatures:feature,requestType:"update"});resp.priv=OpenLayers.Request.PUT({url:url,callback:this.createCallback(this.handleUpdate,resp,options),headers:options.headers,data:this.format.write(feature)});return resp;},handleUpdate:function(resp,options){this.handleResponse(resp,options);},"delete":function(feature,options){options=options||{};var url=options.url||feature.url||this.options.url+"/"+feature.fid;options=OpenLayers.Util.applyDefaults(options,this.options);var resp=new OpenLayers.Protocol.Response({reqFeatures:feature,requestType:"delete"});resp.priv=OpenLayers.Request.DELETE({url:url,callback:this.createCallback(this.handleDelete,resp,options),headers:options.headers});return resp;},handleDelete:function(resp,options){this.handleResponse(resp,options);},handleResponse:function(resp,options){var request=resp.priv;if(options.callback){if(request.status>=200&&request.status<300){if(resp.requestType!="delete"){resp.features=this.parseFeatures(request);}
61020 resp.code=OpenLayers.Protocol.Response.SUCCESS;}else{resp.code=OpenLayers.Protocol.Response.FAILURE;}
61021 options.callback.call(options.scope,resp);}},parseFeatures:function(request){var doc=request.responseXML;if(!doc||!doc.documentElement){doc=request.responseText;}
61022 if(!doc||doc.length<=0){return null;}
61023 return this.format.read(doc);},commit:function(features,options){options=OpenLayers.Util.applyDefaults(options,this.options);var resp=[],nResponses=0;var types={};types[OpenLayers.State.INSERT]=[];types[OpenLayers.State.UPDATE]=[];types[OpenLayers.State.DELETE]=[];var feature,list,requestFeatures=[];for(var i=0,len=features.length;i<len;++i){feature=features[i];list=types[feature.state];if(list){list.push(feature);requestFeatures.push(feature);}}
61024 var nRequests=(types[OpenLayers.State.INSERT].length>0?1:0)+
61025 types[OpenLayers.State.UPDATE].length+
61026 types[OpenLayers.State.DELETE].length;var success=true;var finalResponse=new OpenLayers.Protocol.Response({reqFeatures:requestFeatures});function insertCallback(response){var len=response.features?response.features.length:0;var fids=new Array(len);for(var i=0;i<len;++i){fids[i]=response.features[i].fid;}
61027 finalResponse.insertIds=fids;callback.apply(this,[response]);}
61028 function callback(response){this.callUserCallback(response,options);success=success&&response.success();nResponses++;if(nResponses>=nRequests){if(options.callback){finalResponse.code=success?OpenLayers.Protocol.Response.SUCCESS:OpenLayers.Protocol.Response.FAILURE;options.callback.apply(options.scope,[finalResponse]);}}}
61029 var queue=types[OpenLayers.State.INSERT];if(queue.length>0){resp.push(this.create(queue,OpenLayers.Util.applyDefaults({callback:insertCallback,scope:this},options.create)));}
61030 queue=types[OpenLayers.State.UPDATE];for(var i=queue.length-1;i>=0;--i){resp.push(this.update(queue[i],OpenLayers.Util.applyDefaults({callback:callback,scope:this},options.update)));}
61031 queue=types[OpenLayers.State.DELETE];for(var i=queue.length-1;i>=0;--i){resp.push(this["delete"](queue[i],OpenLayers.Util.applyDefaults({callback:callback,scope:this},options["delete"])));}
61032 return resp;},abort:function(response){if(response){response.priv.abort();}},callUserCallback:function(resp,options){var opt=options[resp.requestType];if(opt&&opt.callback){opt.callback.call(opt.scope,resp);}},CLASS_NAME:"OpenLayers.Protocol.HTTP"});(function(){var o=OpenLayers.Protocol.HTTP.COMP_TYPE_TO_OP_STR={};o[OpenLayers.Filter.Comparison.EQUAL_TO]="eq";o[OpenLayers.Filter.Comparison.NOT_EQUAL_TO]="ne";o[OpenLayers.Filter.Comparison.LESS_THAN]="lt";o[OpenLayers.Filter.Comparison.LESS_THAN_OR_EQUAL_TO]="lte";o[OpenLayers.Filter.Comparison.GREATER_THAN]="gt";o[OpenLayers.Filter.Comparison.GREATER_THAN_OR_EQUAL_TO]="gte";o[OpenLayers.Filter.Comparison.LIKE]="ilike";})();OpenLayers.Strategy.BBOX=OpenLayers.Class(OpenLayers.Strategy,{bounds:null,resolution:null,ratio:2,resFactor:null,response:null,initialize:function(options){OpenLayers.Strategy.prototype.initialize.apply(this,[options]);},activate:function(){var activated=OpenLayers.Strategy.prototype.activate.call(this);if(activated){this.layer.events.on({"moveend":this.update,scope:this});this.layer.events.on({"refresh":this.update,scope:this});}
61033 return activated;},deactivate:function(){var deactivated=OpenLayers.Strategy.prototype.deactivate.call(this);if(deactivated){this.layer.events.un({"moveend":this.update,scope:this});this.layer.events.un({"refresh":this.update,scope:this});}
61034 return deactivated;},update:function(options){var mapBounds=this.getMapBounds();if((options&&options.force)||this.invalidBounds(mapBounds)){this.calculateBounds(mapBounds);this.resolution=this.layer.map.getResolution();this.triggerRead();}},getMapBounds:function(){var bounds=this.layer.map.getExtent();if(!this.layer.projection.equals(this.layer.map.getProjectionObject())){bounds=bounds.clone().transform(this.layer.map.getProjectionObject(),this.layer.projection);}
61035 return bounds;},invalidBounds:function(mapBounds){if(!mapBounds){mapBounds=this.getMapBounds();}
61036 var invalid=!this.bounds||!this.bounds.containsBounds(mapBounds);if(!invalid&&this.resFactor){var ratio=this.resolution/this.layer.map.getResolution();invalid=(ratio>=this.resFactor||ratio<=(1/this.resFactor));}
61037 return invalid;},calculateBounds:function(mapBounds){if(!mapBounds){mapBounds=this.getMapBounds();}
61038 var center=mapBounds.getCenterLonLat();var dataWidth=mapBounds.getWidth()*this.ratio;var dataHeight=mapBounds.getHeight()*this.ratio;this.bounds=new OpenLayers.Bounds(center.lon-(dataWidth/2),center.lat-(dataHeight/2),center.lon+(dataWidth/2),center.lat+(dataHeight/2));},triggerRead:function(){if(this.response){this.layer.protocol.abort(this.response);this.layer.events.triggerEvent("loadend");}
61039 this.layer.events.triggerEvent("loadstart");this.response=this.layer.protocol.read({filter:this.createFilter(),callback:this.merge,scope:this});},createFilter:function(){var filter=new OpenLayers.Filter.Spatial({type:OpenLayers.Filter.Spatial.BBOX,value:this.bounds,projection:this.layer.projection});if(this.layer.filter){filter=new OpenLayers.Filter.Logical({type:OpenLayers.Filter.Logical.AND,filters:[this.layer.filter,filter]});}
61040 return filter;},merge:function(resp){this.layer.destroyFeatures();var features=resp.features;if(features&&features.length>0){var remote=this.layer.projection;var local=this.layer.map.getProjectionObject();if(!local.equals(remote)){var geom;for(var i=0,len=features.length;i<len;++i){geom=features[i].geometry;if(geom){geom.transform(remote,local);}}}
61041 this.layer.addFeatures(features);}
61042 this.response=null;this.layer.events.triggerEvent("loadend");},CLASS_NAME:"OpenLayers.Strategy.BBOX"});OpenLayers.Control.SelectFeature=OpenLayers.Class(OpenLayers.Control,{EVENT_TYPES:["beforefeaturehighlighted","featurehighlighted","featureunhighlighted"],multipleKey:null,toggleKey:null,multiple:false,clickout:true,toggle:false,hover:false,highlightOnly:false,box:false,onBeforeSelect:function(){},onSelect:function(){},onUnselect:function(){},scope:null,geometryTypes:null,layer:null,layers:null,callbacks:null,selectStyle:null,renderIntent:"select",handlers:null,initialize:function(layers,options){this.EVENT_TYPES=OpenLayers.Control.SelectFeature.prototype.EVENT_TYPES.concat(OpenLayers.Control.prototype.EVENT_TYPES);OpenLayers.Control.prototype.initialize.apply(this,[options]);if(this.scope===null){this.scope=this;}
61043 this.initLayer(layers);var callbacks={click:this.clickFeature,clickout:this.clickoutFeature};if(this.hover){callbacks.over=this.overFeature;callbacks.out=this.outFeature;}
61044 this.callbacks=OpenLayers.Util.extend(callbacks,this.callbacks);this.handlers={feature:new OpenLayers.Handler.Feature(this,this.layer,this.callbacks,{geometryTypes:this.geometryTypes})};if(this.box){this.handlers.box=new OpenLayers.Handler.Box(this,{done:this.selectBox},{boxDivClassName:"olHandlerBoxSelectFeature"});}},initLayer:function(layers){if(layers instanceof Array){this.layers=layers;this.layer=new OpenLayers.Layer.Vector.RootContainer(this.id+"_container",{layers:layers});}else{this.layer=layers;}},destroy:function(){if(this.active&&this.layers){this.map.removeLayer(this.layer);}
61045 OpenLayers.Control.prototype.destroy.apply(this,arguments);if(this.layers){this.layer.destroy();}},activate:function(){if(!this.active){if(this.layers){this.map.addLayer(this.layer);}
61046 this.handlers.feature.activate();if(this.box&&this.handlers.box){this.handlers.box.activate();}}
61047 return OpenLayers.Control.prototype.activate.apply(this,arguments);},deactivate:function(){if(this.active){this.handlers.feature.deactivate();if(this.handlers.box){this.handlers.box.deactivate();}
61048 if(this.layers){this.map.removeLayer(this.layer);}}
61049 return OpenLayers.Control.prototype.deactivate.apply(this,arguments);},unselectAll:function(options){var layers=this.layers||[this.layer];var layer,feature;for(var l=0;l<layers.length;++l){layer=layers[l];for(var i=layer.selectedFeatures.length-1;i>=0;--i){feature=layer.selectedFeatures[i];if(!options||options.except!=feature){this.unselect(feature);}}}},clickFeature:function(feature){if(!this.hover){var selected=(OpenLayers.Util.indexOf(feature.layer.selectedFeatures,feature)>-1);if(selected){if(this.toggleSelect()){this.unselect(feature);}else if(!this.multipleSelect()){this.unselectAll({except:feature});}}else{if(!this.multipleSelect()){this.unselectAll({except:feature});}
61050 this.select(feature);}}},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(feature){if(!this.hover&&this.clickout){this.unselectAll();}},overFeature:function(feature){var layer=feature.layer;if(this.hover){if(this.highlightOnly){this.highlight(feature);}else if(OpenLayers.Util.indexOf(layer.selectedFeatures,feature)==-1){this.select(feature);}}},outFeature:function(feature){if(this.hover){if(this.highlightOnly){if(feature._lastHighlighter==this.id){if(feature._prevHighlighter&&feature._prevHighlighter!=this.id){delete feature._lastHighlighter;var control=this.map.getControl(feature._prevHighlighter);if(control){control.highlight(feature);}}else{this.unhighlight(feature);}}}else{this.unselect(feature);}}},highlight:function(feature){var layer=feature.layer;var cont=this.events.triggerEvent("beforefeaturehighlighted",{feature:feature});if(cont!==false){feature._prevHighlighter=feature._lastHighlighter;feature._lastHighlighter=this.id;var style=this.selectStyle||this.renderIntent;layer.drawFeature(feature,style);this.events.triggerEvent("featurehighlighted",{feature:feature});}},unhighlight:function(feature){var layer=feature.layer;feature._lastHighlighter=feature._prevHighlighter;delete feature._prevHighlighter;layer.drawFeature(feature,feature.style||feature.layer.style||"default");this.events.triggerEvent("featureunhighlighted",{feature:feature});},select:function(feature){var cont=this.onBeforeSelect.call(this.scope,feature);var layer=feature.layer;if(cont!==false){cont=layer.events.triggerEvent("beforefeatureselected",{feature:feature});if(cont!==false){layer.selectedFeatures.push(feature);this.highlight(feature);if(!this.handlers.feature.lastFeature){this.handlers.feature.lastFeature=layer.selectedFeatures[0];}
61051 layer.events.triggerEvent("featureselected",{feature:feature});this.onSelect.call(this.scope,feature);}}},unselect:function(feature){var layer=feature.layer;this.unhighlight(feature);OpenLayers.Util.removeItem(layer.selectedFeatures,feature);layer.events.triggerEvent("featureunselected",{feature:feature});this.onUnselect.call(this.scope,feature);},selectBox:function(position){if(position instanceof OpenLayers.Bounds){var minXY=this.map.getLonLatFromPixel(new OpenLayers.Pixel(position.left,position.bottom));var maxXY=this.map.getLonLatFromPixel(new OpenLayers.Pixel(position.right,position.top));var bounds=new OpenLayers.Bounds(minXY.lon,minXY.lat,maxXY.lon,maxXY.lat);if(!this.multipleSelect()){this.unselectAll();}
61052 var prevMultiple=this.multiple;this.multiple=true;var layers=this.layers||[this.layer];var layer;for(var l=0;l<layers.length;++l){layer=layers[l];for(var i=0,len=layer.features.length;i<len;++i){var feature=layer.features[i];if(!feature.getVisibility()){continue;}
61053 if(this.geometryTypes==null||OpenLayers.Util.indexOf(this.geometryTypes,feature.geometry.CLASS_NAME)>-1){if(bounds.toGeometry().intersects(feature.geometry)){if(OpenLayers.Util.indexOf(layer.selectedFeatures,feature)==-1){this.select(feature);}}}}}
61054 this.multiple=prevMultiple;}},setMap:function(map){this.handlers.feature.setMap(map);if(this.box){this.handlers.box.setMap(map);}
61055 OpenLayers.Control.prototype.setMap.apply(this,arguments);},setLayer:function(layers){var isActive=this.active;this.unselectAll();this.deactivate();if(this.layers){this.layer.destroy();this.layers=null;}
61056 this.initLayer(layers);this.handlers.feature.layer=this.layer;if(isActive){this.activate();}},CLASS_NAME:"OpenLayers.Control.SelectFeature"});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(options){OpenLayers.Format.XML.prototype.initialize.apply(this,[options]);},read:function(data){var obj={};this.readers.ogc["Filter"].apply(this,[data,obj]);return obj.filter;},readers:{"ogc":{"Filter":function(node,parent){var obj={fids:[],filters:[]};this.readChildNodes(node,obj);if(obj.fids.length>0){parent.filter=new OpenLayers.Filter.FeatureId({fids:obj.fids});}else if(obj.filters.length>0){parent.filter=obj.filters[0];}},"FeatureId":function(node,obj){var fid=node.getAttribute("fid");if(fid){obj.fids.push(fid);}},"And":function(node,obj){var filter=new OpenLayers.Filter.Logical({type:OpenLayers.Filter.Logical.AND});this.readChildNodes(node,filter);obj.filters.push(filter);},"Or":function(node,obj){var filter=new OpenLayers.Filter.Logical({type:OpenLayers.Filter.Logical.OR});this.readChildNodes(node,filter);obj.filters.push(filter);},"Not":function(node,obj){var filter=new OpenLayers.Filter.Logical({type:OpenLayers.Filter.Logical.NOT});this.readChildNodes(node,filter);obj.filters.push(filter);},"PropertyIsLessThan":function(node,obj){var filter=new OpenLayers.Filter.Comparison({type:OpenLayers.Filter.Comparison.LESS_THAN});this.readChildNodes(node,filter);obj.filters.push(filter);},"PropertyIsGreaterThan":function(node,obj){var filter=new OpenLayers.Filter.Comparison({type:OpenLayers.Filter.Comparison.GREATER_THAN});this.readChildNodes(node,filter);obj.filters.push(filter);},"PropertyIsLessThanOrEqualTo":function(node,obj){var filter=new OpenLayers.Filter.Comparison({type:OpenLayers.Filter.Comparison.LESS_THAN_OR_EQUAL_TO});this.readChildNodes(node,filter);obj.filters.push(filter);},"PropertyIsGreaterThanOrEqualTo":function(node,obj){var filter=new OpenLayers.Filter.Comparison({type:OpenLayers.Filter.Comparison.GREATER_THAN_OR_EQUAL_TO});this.readChildNodes(node,filter);obj.filters.push(filter);},"PropertyIsBetween":function(node,obj){var filter=new OpenLayers.Filter.Comparison({type:OpenLayers.Filter.Comparison.BETWEEN});this.readChildNodes(node,filter);obj.filters.push(filter);},"Literal":function(node,obj){obj.value=OpenLayers.String.numericIf(this.getChildValue(node));},"PropertyName":function(node,filter){filter.property=this.getChildValue(node);},"LowerBoundary":function(node,filter){filter.lowerBoundary=OpenLayers.String.numericIf(this.readOgcExpression(node));},"UpperBoundary":function(node,filter){filter.upperBoundary=OpenLayers.String.numericIf(this.readOgcExpression(node));},"Intersects":function(node,obj){this.readSpatial(node,obj,OpenLayers.Filter.Spatial.INTERSECTS);},"Within":function(node,obj){this.readSpatial(node,obj,OpenLayers.Filter.Spatial.WITHIN);},"Contains":function(node,obj){this.readSpatial(node,obj,OpenLayers.Filter.Spatial.CONTAINS);},"DWithin":function(node,obj){this.readSpatial(node,obj,OpenLayers.Filter.Spatial.DWITHIN);},"Distance":function(node,obj){obj.distance=parseInt(this.getChildValue(node));obj.distanceUnits=node.getAttribute("units");}}},readSpatial:function(node,obj,type){var filter=new OpenLayers.Filter.Spatial({type:type});this.readChildNodes(node,filter);filter.value=filter.components[0];delete filter.components;obj.filters.push(filter);},readOgcExpression:function(node){var obj={};this.readChildNodes(node,obj);var value=obj.value;if(value===undefined){value=this.getChildValue(node);}
61057 return value;},write:function(filter){return this.writers.ogc["Filter"].apply(this,[filter]);},writers:{"ogc":{"Filter":function(filter){var node=this.createElementNSPlus("ogc:Filter");var sub=filter.CLASS_NAME.split(".").pop();if(sub=="FeatureId"){for(var i=0;i<filter.fids.length;++i){this.writeNode("FeatureId",filter.fids[i],node);}}else{this.writeNode(this.getFilterType(filter),filter,node);}
61058 return node;},"FeatureId":function(fid){return this.createElementNSPlus("ogc:FeatureId",{attributes:{fid:fid}});},"And":function(filter){var node=this.createElementNSPlus("ogc:And");var childFilter;for(var i=0;i<filter.filters.length;++i){childFilter=filter.filters[i];this.writeNode(this.getFilterType(childFilter),childFilter,node);}
61059 return node;},"Or":function(filter){var node=this.createElementNSPlus("ogc:Or");var childFilter;for(var i=0;i<filter.filters.length;++i){childFilter=filter.filters[i];this.writeNode(this.getFilterType(childFilter),childFilter,node);}
61060 return node;},"Not":function(filter){var node=this.createElementNSPlus("ogc:Not");var childFilter=filter.filters[0];this.writeNode(this.getFilterType(childFilter),childFilter,node);return node;},"PropertyIsLessThan":function(filter){var node=this.createElementNSPlus("ogc:PropertyIsLessThan");this.writeNode("PropertyName",filter,node);this.writeNode("Literal",filter.value,node);return node;},"PropertyIsGreaterThan":function(filter){var node=this.createElementNSPlus("ogc:PropertyIsGreaterThan");this.writeNode("PropertyName",filter,node);this.writeNode("Literal",filter.value,node);return node;},"PropertyIsLessThanOrEqualTo":function(filter){var node=this.createElementNSPlus("ogc:PropertyIsLessThanOrEqualTo");this.writeNode("PropertyName",filter,node);this.writeNode("Literal",filter.value,node);return node;},"PropertyIsGreaterThanOrEqualTo":function(filter){var node=this.createElementNSPlus("ogc:PropertyIsGreaterThanOrEqualTo");this.writeNode("PropertyName",filter,node);this.writeNode("Literal",filter.value,node);return node;},"PropertyIsBetween":function(filter){var node=this.createElementNSPlus("ogc:PropertyIsBetween");this.writeNode("PropertyName",filter,node);this.writeNode("LowerBoundary",filter,node);this.writeNode("UpperBoundary",filter,node);return node;},"PropertyName":function(filter){return this.createElementNSPlus("ogc:PropertyName",{value:filter.property});},"Literal":function(value){return this.createElementNSPlus("ogc:Literal",{value:value});},"LowerBoundary":function(filter){var node=this.createElementNSPlus("ogc:LowerBoundary");this.writeNode("Literal",filter.lowerBoundary,node);return node;},"UpperBoundary":function(filter){var node=this.createElementNSPlus("ogc:UpperBoundary");this.writeNode("Literal",filter.upperBoundary,node);return node;},"INTERSECTS":function(filter){return this.writeSpatial(filter,"Intersects");},"WITHIN":function(filter){return this.writeSpatial(filter,"Within");},"CONTAINS":function(filter){return this.writeSpatial(filter,"Contains");},"DWITHIN":function(filter){var node=this.writeSpatial(filter,"DWithin");this.writeNode("Distance",filter,node);return node;},"Distance":function(filter){return this.createElementNSPlus("ogc:Distance",{attributes:{units:filter.distanceUnits},value:filter.distance});}}},getFilterType:function(filter){var filterType=this.filterMap[filter.type];if(!filterType){throw"Filter writing not supported for rule type: "+filter.type;}
61061 return filterType;},filterMap:{"&&":"And","||":"Or","!":"Not","==":"PropertyIsEqualTo","!=":"PropertyIsNotEqualTo","<":"PropertyIsLessThan",">":"PropertyIsGreaterThan","<=":"PropertyIsLessThanOrEqualTo",">=":"PropertyIsGreaterThanOrEqualTo","..":"PropertyIsBetween","~":"PropertyIsLike","BBOX":"BBOX","DWITHIN":"DWITHIN","WITHIN":"WITHIN","CONTAINS":"CONTAINS","INTERSECTS":"INTERSECTS"},CLASS_NAME:"OpenLayers.Format.Filter.v1"});OpenLayers.Geometry.Curve=OpenLayers.Class(OpenLayers.Geometry.MultiPoint,{componentTypes:["OpenLayers.Geometry.Point"],initialize:function(points){OpenLayers.Geometry.MultiPoint.prototype.initialize.apply(this,arguments);},getLength:function(){var length=0.0;if(this.components&&(this.components.length>1)){for(var i=1,len=this.components.length;i<len;i++){length+=this.components[i-1].distanceTo(this.components[i]);}}
61062 return length;},getGeodesicLength:function(projection){var geom=this;if(projection){var gg=new OpenLayers.Projection("EPSG:4326");if(!gg.equals(projection)){geom=this.clone().transform(projection,gg);}}
61063 var length=0.0;if(geom.components&&(geom.components.length>1)){var p1,p2;for(var i=1,len=geom.components.length;i<len;i++){p1=geom.components[i-1];p2=geom.components[i];length+=OpenLayers.Util.distVincenty({lon:p1.x,lat:p1.y},{lon:p2.x,lat:p2.y});}}
61064 return length*1000;},CLASS_NAME:"OpenLayers.Geometry.Curve"});OpenLayers.Layer.Text=OpenLayers.Class(OpenLayers.Layer.Markers,{location:null,features:null,formatOptions:null,selectedFeature:null,initialize:function(name,options){OpenLayers.Layer.Markers.prototype.initialize.apply(this,arguments);this.features=new Array();},destroy:function(){OpenLayers.Layer.Markers.prototype.destroy.apply(this,arguments);this.clearFeatures();this.features=null;},loadText:function(){if(!this.loaded){if(this.location!=null){var onFail=function(e){this.events.triggerEvent("loadend");};this.events.triggerEvent("loadstart");OpenLayers.Request.GET({url:this.location,success:this.parseData,failure:onFail,scope:this});this.loaded=true;}}},moveTo:function(bounds,zoomChanged,minor){OpenLayers.Layer.Markers.prototype.moveTo.apply(this,arguments);if(this.visibility&&!this.loaded){this.loadText();}},parseData:function(ajaxRequest){var text=ajaxRequest.responseText;var options={};OpenLayers.Util.extend(options,this.formatOptions);if(this.map&&!this.projection.equals(this.map.getProjectionObject())){options.externalProjection=this.projection;options.internalProjection=this.map.getProjectionObject();}
61065 var parser=new OpenLayers.Format.Text(options);var features=parser.read(text);for(var i=0,len=features.length;i<len;i++){var data={};var feature=features[i];var location;var iconSize,iconOffset;location=new OpenLayers.LonLat(feature.geometry.x,feature.geometry.y);if(feature.style.graphicWidth&&feature.style.graphicHeight){iconSize=new OpenLayers.Size(feature.style.graphicWidth,feature.style.graphicHeight);}
61066 if(feature.style.graphicXOffset!==undefined&&feature.style.graphicYOffset!==undefined){iconOffset=new OpenLayers.Pixel(feature.style.graphicXOffset,feature.style.graphicYOffset);}
61067 if(feature.style.externalGraphic!=null){data.icon=new OpenLayers.Icon(feature.style.externalGraphic,iconSize,iconOffset);}else{data.icon=OpenLayers.Marker.defaultIcon();if(iconSize!=null){data.icon.setSize(iconSize);}}
61068 if((feature.attributes.title!=null)&&(feature.attributes.description!=null)){data['popupContentHTML']='<h2>'+feature.attributes.title+'</h2>'+'<p>'+feature.attributes.description+'</p>';}
61069 data['overflow']=feature.attributes.overflow||"auto";var markerFeature=new OpenLayers.Feature(this,location,data);this.features.push(markerFeature);var marker=markerFeature.createMarker();if((feature.attributes.title!=null)&&(feature.attributes.description!=null)){marker.events.register('click',markerFeature,this.markerClick);}
61070 this.addMarker(marker);}
61071 this.events.triggerEvent("loadend");},markerClick:function(evt){var sameMarkerClicked=(this==this.layer.selectedFeature);this.layer.selectedFeature=(!sameMarkerClicked)?this:null;for(var i=0,len=this.layer.map.popups.length;i<len;i++){this.layer.map.removePopup(this.layer.map.popups[i]);}
61072 if(!sameMarkerClicked){this.layer.map.addPopup(this.createPopup());}
61073 OpenLayers.Event.stop(evt);},clearFeatures:function(){if(this.features!=null){while(this.features.length>0){var feature=this.features[0];OpenLayers.Util.removeItem(this.features,feature);feature.destroy();}}},CLASS_NAME:"OpenLayers.Layer.Text"});OpenLayers.Control.ModifyFeature=OpenLayers.Class(OpenLayers.Control,{geometryTypes:null,clickout:true,toggle:true,standalone:false,layer:null,feature:null,vertices:null,virtualVertices:null,selectControl:null,dragControl:null,handlers:null,deleteCodes:null,virtualStyle:null,mode:null,modified:false,radiusHandle:null,dragHandle:null,onModificationStart:function(){},onModification:function(){},onModificationEnd:function(){},initialize:function(layer,options){this.layer=layer;this.vertices=[];this.virtualVertices=[];this.virtualStyle=OpenLayers.Util.extend({},this.layer.style||this.layer.styleMap.createSymbolizer());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,[options]);if(!(this.deleteCodes instanceof Array)){this.deleteCodes=[this.deleteCodes];}
61074 var control=this;var selectOptions={geometryTypes:this.geometryTypes,clickout:this.clickout,toggle:this.toggle,onBeforeSelect:this.beforeSelectFeature,onSelect:this.selectFeature,onUnselect:this.unselectFeature,scope:this};if(this.standalone===false){this.selectControl=new OpenLayers.Control.SelectFeature(layer,selectOptions);}
61075 var dragOptions={geometryTypes:["OpenLayers.Geometry.Point"],snappingOptions:this.snappingOptions,onStart:function(feature,pixel){control.dragStart.apply(control,[feature,pixel]);},onDrag:function(feature,pixel){control.dragVertex.apply(control,[feature,pixel]);},onComplete:function(feature){control.dragComplete.apply(control,[feature]);},featureCallbacks:{over:function(feature){if(control.standalone!==true||feature._sketch||control.feature===feature){control.dragControl.overFeature.apply(control.dragControl,[feature]);}}}};this.dragControl=new OpenLayers.Control.DragFeature(layer,dragOptions);var keyboardOptions={keydown:this.handleKeypress};this.handlers={keyboard:new OpenLayers.Handler.Keyboard(this,keyboardOptions)};},destroy:function(){this.layer=null;this.standalone||this.selectControl.destroy();this.dragControl.destroy();OpenLayers.Control.prototype.destroy.apply(this,[]);},activate:function(){return((this.standalone||this.selectControl.activate())&&this.handlers.keyboard.activate()&&OpenLayers.Control.prototype.activate.apply(this,arguments));},deactivate:function(){var deactivated=false;if(OpenLayers.Control.prototype.deactivate.apply(this,arguments)){this.layer.removeFeatures(this.vertices,{silent:true});this.layer.removeFeatures(this.virtualVertices,{silent:true});this.vertices=[];this.dragControl.deactivate();var feature=this.feature;var valid=feature&&feature.geometry&&feature.layer;if(this.standalone===false){if(valid){this.selectControl.unselect.apply(this.selectControl,[feature]);}
61076 this.selectControl.deactivate();}else{if(valid){this.unselectFeature(feature);}}
61077 this.handlers.keyboard.deactivate();deactivated=true;}
61078 return deactivated;},beforeSelectFeature:function(feature){return this.layer.events.triggerEvent("beforefeaturemodified",{feature:feature});},selectFeature:function(feature){this.feature=feature;this.modified=false;this.resetVertices();this.dragControl.activate();this.onModificationStart(this.feature);},unselectFeature:function(feature){this.layer.removeFeatures(this.vertices,{silent:true});this.vertices=[];this.layer.destroyFeatures(this.virtualVertices,{silent:true});this.virtualVertices=[];if(this.dragHandle){this.layer.destroyFeatures([this.dragHandle],{silent:true});delete this.dragHandle;}
61079 if(this.radiusHandle){this.layer.destroyFeatures([this.radiusHandle],{silent:true});delete this.radiusHandle;}
61080 this.feature=null;this.dragControl.deactivate();this.onModificationEnd(feature);this.layer.events.triggerEvent("afterfeaturemodified",{feature:feature,modified:this.modified});this.modified=false;},dragStart:function(feature,pixel){if(feature!=this.feature&&!feature.geometry.parent&&feature!=this.dragHandle&&feature!=this.radiusHandle){if(this.standalone===false&&this.feature){this.selectControl.clickFeature.apply(this.selectControl,[this.feature]);}
61081 if(this.geometryTypes==null||OpenLayers.Util.indexOf(this.geometryTypes,feature.geometry.CLASS_NAME)!=-1){this.standalone||this.selectControl.clickFeature.apply(this.selectControl,[feature]);this.dragControl.overFeature.apply(this.dragControl,[feature]);this.dragControl.lastPixel=pixel;this.dragControl.handlers.drag.started=true;this.dragControl.handlers.drag.start=pixel;this.dragControl.handlers.drag.last=pixel;}}},dragVertex:function(vertex,pixel){this.modified=true;if(this.feature.geometry.CLASS_NAME=="OpenLayers.Geometry.Point"){if(this.feature!=vertex){this.feature=vertex;}
61082 this.layer.events.triggerEvent("vertexmodified",{vertex:vertex.geometry,feature:this.feature,pixel:pixel});}else{if(vertex._index){vertex.geometry.parent.addComponent(vertex.geometry,vertex._index);delete vertex._index;OpenLayers.Util.removeItem(this.virtualVertices,vertex);this.vertices.push(vertex);}else if(vertex==this.dragHandle){this.layer.removeFeatures(this.vertices,{silent:true});this.vertices=[];if(this.radiusHandle){this.layer.destroyFeatures([this.radiusHandle],{silent:true});this.radiusHandle=null;}}else if(vertex!==this.radiusHandle){this.layer.events.triggerEvent("vertexmodified",{vertex:vertex.geometry,feature:this.feature,pixel:pixel});}
61083 if(this.virtualVertices.length>0){this.layer.destroyFeatures(this.virtualVertices,{silent:true});this.virtualVertices=[];}
61084 this.layer.drawFeature(this.feature,this.standalone?undefined:this.selectControl.renderIntent);}
61085 this.layer.drawFeature(vertex);},dragComplete:function(vertex){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&&this.feature.state!=OpenLayers.State.DELETE){this.feature.state=OpenLayers.State.UPDATE;}},resetVertices:function(){if(this.dragControl.feature){this.dragControl.outFeature(this.dragControl.feature);}
61086 if(this.vertices.length>0){this.layer.removeFeatures(this.vertices,{silent:true});this.vertices=[];}
61087 if(this.virtualVertices.length>0){this.layer.removeFeatures(this.virtualVertices,{silent:true});this.virtualVertices=[];}
61088 if(this.dragHandle){this.layer.destroyFeatures([this.dragHandle],{silent:true});this.dragHandle=null;}
61089 if(this.radiusHandle){this.layer.destroyFeatures([this.radiusHandle],{silent:true});this.radiusHandle=null;}
61090 if(this.feature&&this.feature.geometry.CLASS_NAME!="OpenLayers.Geometry.Point"){if((this.mode&OpenLayers.Control.ModifyFeature.DRAG)){this.collectDragHandle();}
61091 if((this.mode&(OpenLayers.Control.ModifyFeature.ROTATE|OpenLayers.Control.ModifyFeature.RESIZE))){this.collectRadiusHandle();}
61092 if(this.mode&OpenLayers.Control.ModifyFeature.RESHAPE){if(!(this.mode&OpenLayers.Control.ModifyFeature.RESIZE)){this.collectVertices();}}}},handleKeypress:function(evt){var code=evt.keyCode;if(this.feature&&OpenLayers.Util.indexOf(this.deleteCodes,code)!=-1){var vertex=this.dragControl.feature;if(vertex&&OpenLayers.Util.indexOf(this.vertices,vertex)!=-1&&!this.dragControl.handlers.drag.dragging&&vertex.geometry.parent){vertex.geometry.parent.removeComponent(vertex.geometry);this.layer.drawFeature(this.feature,this.standalone?undefined:this.selectControl.renderIntent);this.resetVertices();this.setFeatureState();this.onModification(this.feature);this.layer.events.triggerEvent("featuremodified",{feature:this.feature});}}},collectVertices:function(){this.vertices=[];this.virtualVertices=[];var control=this;function collectComponentVertices(geometry){var i,vertex,component,len;if(geometry.CLASS_NAME=="OpenLayers.Geometry.Point"){vertex=new OpenLayers.Feature.Vector(geometry);vertex._sketch=true;control.vertices.push(vertex);}else{var numVert=geometry.components.length;if(geometry.CLASS_NAME=="OpenLayers.Geometry.LinearRing"){numVert-=1;}
61093 for(i=0;i<numVert;++i){component=geometry.components[i];if(component.CLASS_NAME=="OpenLayers.Geometry.Point"){vertex=new OpenLayers.Feature.Vector(component);vertex._sketch=true;control.vertices.push(vertex);}else{collectComponentVertices(component);}}
61094 if(geometry.CLASS_NAME!="OpenLayers.Geometry.MultiPoint"){for(i=0,len=geometry.components.length;i<len-1;++i){var prevVertex=geometry.components[i];var nextVertex=geometry.components[i+1];if(prevVertex.CLASS_NAME=="OpenLayers.Geometry.Point"&&nextVertex.CLASS_NAME=="OpenLayers.Geometry.Point"){var x=(prevVertex.x+nextVertex.x)/2;var y=(prevVertex.y+nextVertex.y)/2;var point=new OpenLayers.Feature.Vector(new OpenLayers.Geometry.Point(x,y),null,control.virtualStyle);point.geometry.parent=geometry;point._index=i+1;point._sketch=true;control.virtualVertices.push(point);}}}}}
61095 collectComponentVertices.call(this,this.feature.geometry);this.layer.addFeatures(this.virtualVertices,{silent:true});this.layer.addFeatures(this.vertices,{silent:true});},collectDragHandle:function(){var geometry=this.feature.geometry;var center=geometry.getBounds().getCenterLonLat();var originGeometry=new OpenLayers.Geometry.Point(center.lon,center.lat);var origin=new OpenLayers.Feature.Vector(originGeometry);originGeometry.move=function(x,y){OpenLayers.Geometry.Point.prototype.move.call(this,x,y);geometry.move(x,y);};origin._sketch=true;this.dragHandle=origin;this.layer.addFeatures([this.dragHandle],{silent:true});},collectRadiusHandle:function(){var geometry=this.feature.geometry;var bounds=geometry.getBounds();var center=bounds.getCenterLonLat();var originGeometry=new OpenLayers.Geometry.Point(center.lon,center.lat);var radiusGeometry=new OpenLayers.Geometry.Point(bounds.right,bounds.bottom);var radius=new OpenLayers.Feature.Vector(radiusGeometry);var resize=(this.mode&OpenLayers.Control.ModifyFeature.RESIZE);var reshape=(this.mode&OpenLayers.Control.ModifyFeature.RESHAPE);var rotate=(this.mode&OpenLayers.Control.ModifyFeature.ROTATE);radiusGeometry.move=function(x,y){OpenLayers.Geometry.Point.prototype.move.call(this,x,y);var dx1=this.x-originGeometry.x;var dy1=this.y-originGeometry.y;var dx0=dx1-x;var dy0=dy1-y;if(rotate){var a0=Math.atan2(dy0,dx0);var a1=Math.atan2(dy1,dx1);var angle=a1-a0;angle*=180/Math.PI;geometry.rotate(angle,originGeometry);}
61096 if(resize){var scale,ratio;if(reshape){scale=dy1/dy0;ratio=(dx1/dx0)/scale;}else{var l0=Math.sqrt((dx0*dx0)+(dy0*dy0));var l1=Math.sqrt((dx1*dx1)+(dy1*dy1));scale=l1/l0;}
61097 geometry.resize(scale,originGeometry,ratio);}};radius._sketch=true;this.radiusHandle=radius;this.layer.addFeatures([this.radiusHandle],{silent:true});},setMap:function(map){this.standalone||this.selectControl.setMap(map);this.dragControl.setMap(map);OpenLayers.Control.prototype.setMap.apply(this,arguments);},CLASS_NAME:"OpenLayers.Control.ModifyFeature"});OpenLayers.Control.ModifyFeature.RESHAPE=1;OpenLayers.Control.ModifyFeature.RESIZE=2;OpenLayers.Control.ModifyFeature.ROTATE=4;OpenLayers.Control.ModifyFeature.DRAG=8;OpenLayers.Geometry.LineString=OpenLayers.Class(OpenLayers.Geometry.Curve,{initialize:function(points){OpenLayers.Geometry.Curve.prototype.initialize.apply(this,arguments);},removeComponent:function(point){if(this.components&&(this.components.length>2)){OpenLayers.Geometry.Collection.prototype.removeComponent.apply(this,arguments);}},intersects:function(geometry){var intersect=false;var type=geometry.CLASS_NAME;if(type=="OpenLayers.Geometry.LineString"||type=="OpenLayers.Geometry.LinearRing"||type=="OpenLayers.Geometry.Point"){var segs1=this.getSortedSegments();var segs2;if(type=="OpenLayers.Geometry.Point"){segs2=[{x1:geometry.x,y1:geometry.y,x2:geometry.x,y2:geometry.y}];}else{segs2=geometry.getSortedSegments();}
61098 var seg1,seg1x1,seg1x2,seg1y1,seg1y2,seg2,seg2y1,seg2y2;outer:for(var i=0,len=segs1.length;i<len;++i){seg1=segs1[i];seg1x1=seg1.x1;seg1x2=seg1.x2;seg1y1=seg1.y1;seg1y2=seg1.y2;inner:for(var j=0,jlen=segs2.length;j<jlen;++j){seg2=segs2[j];if(seg2.x1>seg1x2){break;}
61099 if(seg2.x2<seg1x1){continue;}
61100 seg2y1=seg2.y1;seg2y2=seg2.y2;if(Math.min(seg2y1,seg2y2)>Math.max(seg1y1,seg1y2)){continue;}
61101 if(Math.max(seg2y1,seg2y2)<Math.min(seg1y1,seg1y2)){continue;}
61102 if(OpenLayers.Geometry.segmentsIntersect(seg1,seg2)){intersect=true;break outer;}}}}else{intersect=geometry.intersects(this);}
61103 return intersect;},getSortedSegments:function(){var numSeg=this.components.length-1;var segments=new Array(numSeg),point1,point2;for(var i=0;i<numSeg;++i){point1=this.components[i];point2=this.components[i+1];if(point1.x<point2.x){segments[i]={x1:point1.x,y1:point1.y,x2:point2.x,y2:point2.y};}else{segments[i]={x1:point2.x,y1:point2.y,x2:point1.x,y2:point1.y};}}
61104 function byX1(seg1,seg2){return seg1.x1-seg2.x1;}
61105 return segments.sort(byX1);},splitWithSegment:function(seg,options){var edge=!(options&&options.edge===false);var tolerance=options&&options.tolerance;var lines=[];var verts=this.getVertices();var points=[];var intersections=[];var split=false;var vert1,vert2,point;var node,vertex,target;var interOptions={point:true,tolerance:tolerance};var result=null;for(var i=0,stop=verts.length-2;i<=stop;++i){vert1=verts[i];points.push(vert1.clone());vert2=verts[i+1];target={x1:vert1.x,y1:vert1.y,x2:vert2.x,y2:vert2.y};point=OpenLayers.Geometry.segmentsIntersect(seg,target,interOptions);if(point instanceof OpenLayers.Geometry.Point){if((point.x===seg.x1&&point.y===seg.y1)||(point.x===seg.x2&&point.y===seg.y2)||point.equals(vert1)||point.equals(vert2)){vertex=true;}else{vertex=false;}
61106 if(vertex||edge){if(!point.equals(intersections[intersections.length-1])){intersections.push(point.clone());}
61107 if(i===0){if(point.equals(vert1)){continue;}}
61108 if(point.equals(vert2)){continue;}
61109 split=true;if(!point.equals(vert1)){points.push(point);}
61110 lines.push(new OpenLayers.Geometry.LineString(points));points=[point.clone()];}}}
61111 if(split){points.push(vert2.clone());lines.push(new OpenLayers.Geometry.LineString(points));}
61112 if(intersections.length>0){var xDir=seg.x1<seg.x2?1:-1;var yDir=seg.y1<seg.y2?1:-1;result={lines:lines,points:intersections.sort(function(p1,p2){return(xDir*p1.x-xDir*p2.x)||(yDir*p1.y-yDir*p2.y);})};}
61113 return result;},split:function(target,options){var results=null;var mutual=options&&options.mutual;var sourceSplit,targetSplit,sourceParts,targetParts;if(target instanceof OpenLayers.Geometry.LineString){var verts=this.getVertices();var vert1,vert2,seg,splits,lines,point;var points=[];sourceParts=[];for(var i=0,stop=verts.length-2;i<=stop;++i){vert1=verts[i];vert2=verts[i+1];seg={x1:vert1.x,y1:vert1.y,x2:vert2.x,y2:vert2.y};targetParts=targetParts||[target];if(mutual){points.push(vert1.clone());}
61114 for(var j=0;j<targetParts.length;++j){splits=targetParts[j].splitWithSegment(seg,options);if(splits){lines=splits.lines;if(lines.length>0){lines.unshift(j,1);Array.prototype.splice.apply(targetParts,lines);j+=lines.length-2;}
61115 if(mutual){for(var k=0,len=splits.points.length;k<len;++k){point=splits.points[k];if(!point.equals(vert1)){points.push(point);sourceParts.push(new OpenLayers.Geometry.LineString(points));if(point.equals(vert2)){points=[];}else{points=[point.clone()];}}}}}}}
61116 if(mutual&&sourceParts.length>0&&points.length>0){points.push(vert2.clone());sourceParts.push(new OpenLayers.Geometry.LineString(points));}}else{results=target.splitWith(this,options);}
61117 if(targetParts&&targetParts.length>1){targetSplit=true;}else{targetParts=[];}
61118 if(sourceParts&&sourceParts.length>1){sourceSplit=true;}else{sourceParts=[];}
61119 if(targetSplit||sourceSplit){if(mutual){results=[sourceParts,targetParts];}else{results=targetParts;}}
61120 return results;},splitWith:function(geometry,options){return geometry.split(this,options);},getVertices:function(nodes){var vertices;if(nodes===true){vertices=[this.components[0],this.components[this.components.length-1]];}else if(nodes===false){vertices=this.components.slice(1,this.components.length-1);}else{vertices=this.components.slice();}
61121 return vertices;},distanceTo:function(geometry,options){var edge=!(options&&options.edge===false);var details=edge&&options&&options.details;var result,best={};var min=Number.POSITIVE_INFINITY;if(geometry instanceof OpenLayers.Geometry.Point){var segs=this.getSortedSegments();var x=geometry.x;var y=geometry.y;var seg;for(var i=0,len=segs.length;i<len;++i){seg=segs[i];result=OpenLayers.Geometry.distanceToSegment(geometry,seg);if(result.distance<min){min=result.distance;best=result;if(min===0){break;}}else{if(seg.x2>x&&((y>seg.y1&&y<seg.y2)||(y<seg.y1&&y>seg.y2))){break;}}}
61122 if(details){best={distance:best.distance,x0:best.x,y0:best.y,x1:x,y1:y};}else{best=best.distance;}}else if(geometry instanceof OpenLayers.Geometry.LineString){var segs0=this.getSortedSegments();var segs1=geometry.getSortedSegments();var seg0,seg1,intersection,x0,y0;var len1=segs1.length;var interOptions={point:true};outer:for(var i=0,len=segs0.length;i<len;++i){seg0=segs0[i];x0=seg0.x1;y0=seg0.y1;for(var j=0;j<len1;++j){seg1=segs1[j];intersection=OpenLayers.Geometry.segmentsIntersect(seg0,seg1,interOptions);if(intersection){min=0;best={distance:0,x0:intersection.x,y0:intersection.y,x1:intersection.x,y1:intersection.y};break outer;}else{result=OpenLayers.Geometry.distanceToSegment({x:x0,y:y0},seg1);if(result.distance<min){min=result.distance;best={distance:min,x0:x0,y0:y0,x1:result.x,y1:result.y};}}}}
61123 if(!details){best=best.distance;}
61124 if(min!==0){if(seg0){result=geometry.distanceTo(new OpenLayers.Geometry.Point(seg0.x2,seg0.y2),options);var dist=details?result.distance:result;if(dist<min){if(details){best={distance:min,x0:result.x1,y0:result.y1,x1:result.x0,y1:result.y0};}else{best=dist;}}}}}else{best=geometry.distanceTo(this,options);if(details){best={distance:best.distance,x0:best.x1,y0:best.y1,x1:best.x0,y1:best.y0};}}
61125 return best;},CLASS_NAME:"OpenLayers.Geometry.LineString"});OpenLayers.Control.TransformFeature=OpenLayers.Class(OpenLayers.Control,{EVENT_TYPES:["beforesetfeature","setfeature","beforetransform","transform","transformcomplete"],geometryTypes:null,layer:null,preserveAspectRatio:false,rotate:true,feature:null,renderIntent:"temporary",rotationHandleSymbolizer:null,box:null,center:null,scale:1,ratio:1,rotation:0,handles:null,rotationHandles:null,dragControl:null,initialize:function(layer,options){this.EVENT_TYPES=OpenLayers.Control.TransformFeature.prototype.EVENT_TYPES.concat(OpenLayers.Control.prototype.EVENT_TYPES);OpenLayers.Control.prototype.initialize.apply(this,[options]);this.layer=layer;if(!this.rotationHandleSymbolizer){this.rotationHandleSymbolizer={stroke:false,pointRadius:10,fillOpacity:0,cursor:"pointer"};}
61126 this.createBox();this.createControl();},activate:function(){var activated=false;if(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);activated=true;}
61127 return activated;},deactivate:function(){var deactivated=false;if(OpenLayers.Control.prototype.deactivate.apply(this,arguments)){this.layer.removeFeatures(this.handles);this.rotate&&this.layer.removeFeatures(this.rotationHandles);this.layer.removeFeatures([this.box]);this.dragControl.deactivate();deactivated=true;}
61128 return deactivated;},setMap:function(map){this.dragControl.setMap(map);OpenLayers.Control.prototype.setMap.apply(this,arguments);},setFeature:function(feature,initialParams){initialParams=OpenLayers.Util.applyDefaults(initialParams,{rotation:0,scale:1,ratio:1});var evt={feature:feature};var oldRotation=this.rotation;var oldCenter=this.center;OpenLayers.Util.extend(this,initialParams);if(this.events.triggerEvent("beforesetfeature",evt)===false){return;}
61129 this.feature=feature;this.activate();this._setfeature=true;var featureBounds=this.feature.geometry.getBounds();this.box.move(featureBounds.getCenterLonLat());this.box.geometry.rotate(-oldRotation,oldCenter);this._angle=0;var ll;if(this.rotation){var geom=feature.geometry.clone();geom.rotate(-this.rotation,this.center);var box=new OpenLayers.Feature.Vector(geom.getBounds().toGeometry());box.geometry.rotate(this.rotation,this.center);this.box.geometry.rotate(this.rotation,this.center);this.box.move(box.geometry.getBounds().getCenterLonLat());var llGeom=box.geometry.components[0].components[0];ll=llGeom.getBounds().getCenterLonLat();}else{ll=new OpenLayers.LonLat(featureBounds.left,featureBounds.bottom);}
61130 this.handles[0].move(ll);delete this._setfeature;this.events.triggerEvent("setfeature",evt);},createBox:function(){var control=this;this.center=new OpenLayers.Geometry.Point(0,0);var 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,1),new OpenLayers.Geometry.Point(-1,0),new OpenLayers.Geometry.Point(-1,-1)]),null,typeof this.renderIntent=="string"?null:this.renderIntent);box.geometry.move=function(x,y){control._moving=true;OpenLayers.Geometry.LineString.prototype.move.apply(this,arguments);control.center.move(x,y);delete control._moving;};var vertexMoveFn=function(x,y){OpenLayers.Geometry.Point.prototype.move.apply(this,arguments);this._rotationHandle&&this._rotationHandle.geometry.move(x,y);this._handle.geometry.move(x,y);};var vertexResizeFn=function(scale,center,ratio){OpenLayers.Geometry.Point.prototype.resize.apply(this,arguments);this._rotationHandle&&this._rotationHandle.geometry.resize(scale,center,ratio);this._handle.geometry.resize(scale,center,ratio);};var vertexRotateFn=function(angle,center){OpenLayers.Geometry.Point.prototype.rotate.apply(this,arguments);this._rotationHandle&&this._rotationHandle.geometry.rotate(angle,center);this._handle.geometry.rotate(angle,center);};var handleMoveFn=function(x,y){var oldX=this.x,oldY=this.y;OpenLayers.Geometry.Point.prototype.move.call(this,x,y);if(control._moving){return;}
61131 var evt=control.dragControl.handlers.drag.evt;var preserveAspectRatio=!control._setfeature&&control.preserveAspectRatio;var reshape=!preserveAspectRatio&&!(evt&&evt.shiftKey);var oldGeom=new OpenLayers.Geometry.Point(oldX,oldY);var centerGeometry=control.center;this.rotate(-control.rotation,centerGeometry);oldGeom.rotate(-control.rotation,centerGeometry);var dx1=this.x-centerGeometry.x;var dy1=this.y-centerGeometry.y;var dx0=dx1-(this.x-oldGeom.x);var dy0=dy1-(this.y-oldGeom.y);this.x=oldX;this.y=oldY;var scale,ratio=1;if(reshape){scale=Math.abs(dy0)<0.00001?1:dy1/dy0;ratio=(Math.abs(dx0)<0.00001?1:(dx1/dx0))/scale;}else{var l0=Math.sqrt((dx0*dx0)+(dy0*dy0));var l1=Math.sqrt((dx1*dx1)+(dy1*dy1));scale=l1/l0;}
61132 control._moving=true;control.box.geometry.rotate(-control.rotation,centerGeometry);delete control._moving;control.box.geometry.resize(scale,centerGeometry,ratio);control.box.geometry.rotate(control.rotation,centerGeometry);control.transformFeature({scale:scale,ratio:ratio});};var rotationHandleMoveFn=function(x,y){var oldX=this.x,oldY=this.y;OpenLayers.Geometry.Point.prototype.move.call(this,x,y);if(control._moving){return;}
61133 var evt=control.dragControl.handlers.drag.evt;var constrain=(evt&&evt.shiftKey)?45:1;var centerGeometry=control.center;var dx1=this.x-centerGeometry.x;var dy1=this.y-centerGeometry.y;var dx0=dx1-x;var dy0=dy1-y;this.x=oldX;this.y=oldY;var a0=Math.atan2(dy0,dx0);var a1=Math.atan2(dy1,dx1);var angle=a1-a0;angle*=180/Math.PI;control._angle=(control._angle+angle)%360;var diff=control.rotation%constrain;if(Math.abs(control._angle)>=constrain||diff!==0){angle=Math.round(control._angle/constrain)*constrain-
61134 diff;control._angle=0;control.box.geometry.rotate(angle,centerGeometry);control.transformFeature({rotation:angle});}};var handles=new Array(8);var rotationHandles=new Array(4);var geom,handle,rotationHandle;for(var i=0;i<8;++i){geom=box.geometry.components[i];handle=new OpenLayers.Feature.Vector(geom.clone(),null,typeof this.renderIntent=="string"?null:this.renderIntent);if(i%2==0){rotationHandle=new OpenLayers.Feature.Vector(geom.clone(),null,typeof this.rotationHandleSymbolizer=="string"?null:this.rotationHandleSymbolizer);rotationHandle.geometry.move=rotationHandleMoveFn;geom._rotationHandle=rotationHandle;rotationHandles[i/2]=rotationHandle;}
61135 geom.move=vertexMoveFn;geom.resize=vertexResizeFn;geom.rotate=vertexRotateFn;handle.geometry.move=handleMoveFn;geom._handle=handle;handles[i]=handle;}
61136 this.box=box;this.rotationHandles=rotationHandles;this.handles=handles;},createControl:function(){var control=this;this.dragControl=new OpenLayers.Control.DragFeature(this.layer,{documentDrag:true,moveFeature:function(pixel){if(this.feature===control.feature){this.feature=control.box;}
61137 OpenLayers.Control.DragFeature.prototype.moveFeature.apply(this,arguments);},onDrag:function(feature,pixel){if(feature===control.box){control.transformFeature({center:control.center});control.drawHandles();}},onStart:function(feature,pixel){var eligible=!control.geometryTypes||OpenLayers.Util.indexOf(control.geometryTypes,feature.geometry.CLASS_NAME)!==-1;var i=OpenLayers.Util.indexOf(control.handles,feature);i+=OpenLayers.Util.indexOf(control.rotationHandles,feature);if(feature!==control.feature&&feature!==control.box&&i==-2&&eligible){control.setFeature(feature);}},onComplete:function(feature,pixel){control.events.triggerEvent("transformcomplete",{feature:control.feature});}});},drawHandles:function(){var layer=this.layer;for(var i=0;i<8;++i){if(this.rotate&&i%2===0){layer.drawFeature(this.rotationHandles[i/2],this.rotationHandleSymbolizer);}
61138 layer.drawFeature(this.handles[i],this.renderIntent);}},transformFeature:function(mods){if(!this._setfeature){this.scale*=(mods.scale||1);this.ratio*=(mods.ratio||1);var oldRotation=this.rotation;this.rotation=(this.rotation+(mods.rotation||0))%360;if(this.events.triggerEvent("beforetransform",mods)!==false){var feature=this.feature;var geom=feature.geometry;var center=this.center;geom.rotate(-oldRotation,center);if(mods.scale||mods.ratio){geom.resize(mods.scale,center,mods.ratio);}else if(mods.center){feature.move(mods.center.getBounds().getCenterLonLat());}
61139 geom.rotate(this.rotation,center);this.layer.drawFeature(feature);feature.toState(OpenLayers.State.UPDATE);this.events.triggerEvent("transform",mods);}}
61140 this.layer.drawFeature(this.box,this.renderIntent);this.drawHandles();},destroy:function(){var geom;for(var i=0;i<8;++i){geom=this.box.geometry.components[i];geom._handle.destroy();geom._handle=null;geom._rotationHandle&&geom._rotationHandle.destroy();geom._rotationHandle=null;}
61141 this.box.destroy();this.box=null;this.layer=null;this.dragControl.destroy();OpenLayers.Control.prototype.destroy.apply(this,arguments);},CLASS_NAME:"OpenLayers.Control.TransformFeature"});OpenLayers.Format.GPX=OpenLayers.Class(OpenLayers.Format.XML,{extractWaypoints:true,extractTracks:true,extractRoutes:true,extractAttributes:true,initialize:function(options){this.externalProjection=new OpenLayers.Projection("EPSG:4326");OpenLayers.Format.XML.prototype.initialize.apply(this,[options]);},read:function(doc){if(typeof doc=="string"){doc=OpenLayers.Format.XML.prototype.read.apply(this,[doc]);}
61142 var features=[];if(this.extractTracks){var tracks=doc.getElementsByTagName("trk");for(var i=0,len=tracks.length;i<len;i++){var attrs={};if(this.extractAttributes){attrs=this.parseAttributes(tracks[i]);}
61143 var segs=this.getElementsByTagNameNS(tracks[i],tracks[i].namespaceURI,"trkseg");for(var j=0,seglen=segs.length;j<seglen;j++){var track=this.extractSegment(segs[j],"trkpt");features.push(new OpenLayers.Feature.Vector(track,attrs));}}}
61144 if(this.extractRoutes){var routes=doc.getElementsByTagName("rte");for(var k=0,klen=routes.length;k<klen;k++){var attrs={};if(this.extractAttributes){attrs=this.parseAttributes(routes[k]);}
61145 var route=this.extractSegment(routes[k],"rtept");features.push(new OpenLayers.Feature.Vector(route,attrs));}}
61146 if(this.extractWaypoints){var waypoints=doc.getElementsByTagName("wpt");for(var l=0,len=waypoints.length;l<len;l++){var attrs={};if(this.extractAttributes){attrs=this.parseAttributes(waypoints[l]);}
61147 var wpt=new OpenLayers.Geometry.Point(waypoints[l].getAttribute("lon"),waypoints[l].getAttribute("lat"));features.push(new OpenLayers.Feature.Vector(wpt,attrs));}}
61148 if(this.internalProjection&&this.externalProjection){for(var g=0,featLength=features.length;g<featLength;g++){features[g].geometry.transform(this.externalProjection,this.internalProjection);}}
61149 return features;},extractSegment:function(segment,segmentType){var points=this.getElementsByTagNameNS(segment,segment.namespaceURI,segmentType);var point_features=[];for(var i=0,len=points.length;i<len;i++){point_features.push(new OpenLayers.Geometry.Point(points[i].getAttribute("lon"),points[i].getAttribute("lat")));}
61150 return new OpenLayers.Geometry.LineString(point_features);},parseAttributes:function(node){var attributes={};var attrNode=node.firstChild;while(attrNode){if(attrNode.nodeType==1){var value=attrNode.firstChild;if(value.nodeType==3||value.nodeType==4){name=(attrNode.prefix)?attrNode.nodeName.split(":")[1]:attrNode.nodeName;if(name!="trkseg"&&name!="rtept"){attributes[name]=value.nodeValue;}}}
61151 attrNode=attrNode.nextSibling;}
61152 return attributes;},CLASS_NAME:"OpenLayers.Format.GPX"});OpenLayers.Geometry.LinearRing=OpenLayers.Class(OpenLayers.Geometry.LineString,{componentTypes:["OpenLayers.Geometry.Point"],initialize:function(points){OpenLayers.Geometry.LineString.prototype.initialize.apply(this,arguments);},addComponent:function(point,index){var added=false;var lastPoint=this.components.pop();if(index!=null||!point.equals(lastPoint)){added=OpenLayers.Geometry.Collection.prototype.addComponent.apply(this,arguments);}
61153 var firstPoint=this.components[0];OpenLayers.Geometry.Collection.prototype.addComponent.apply(this,[firstPoint]);return added;},removeComponent:function(point){if(this.components.length>4){this.components.pop();OpenLayers.Geometry.Collection.prototype.removeComponent.apply(this,arguments);var firstPoint=this.components[0];OpenLayers.Geometry.Collection.prototype.addComponent.apply(this,[firstPoint]);}},move:function(x,y){for(var i=0,len=this.components.length;i<len-1;i++){this.components[i].move(x,y);}},rotate:function(angle,origin){for(var i=0,len=this.components.length;i<len-1;++i){this.components[i].rotate(angle,origin);}},resize:function(scale,origin,ratio){for(var i=0,len=this.components.length;i<len-1;++i){this.components[i].resize(scale,origin,ratio);}
61154 return this;},transform:function(source,dest){if(source&&dest){for(var i=0,len=this.components.length;i<len-1;i++){var component=this.components[i];component.transform(source,dest);}
61155 this.bounds=null;}
61156 return this;},getCentroid:function(){if(this.components&&(this.components.length>2)){var sumX=0.0;var sumY=0.0;for(var i=0;i<this.components.length-1;i++){var b=this.components[i];var c=this.components[i+1];sumX+=(b.x+c.x)*(b.x*c.y-c.x*b.y);sumY+=(b.y+c.y)*(b.x*c.y-c.x*b.y);}
61157 var area=-1*this.getArea();var x=sumX/(6*area);var y=sumY/(6*area);return new OpenLayers.Geometry.Point(x,y);}else{return null;}},getArea:function(){var area=0.0;if(this.components&&(this.components.length>2)){var sum=0.0;for(var i=0,len=this.components.length;i<len-1;i++){var b=this.components[i];var c=this.components[i+1];sum+=(b.x+c.x)*(c.y-b.y);}
61158 area=-sum/2.0;}
61159 return area;},getGeodesicArea:function(projection){var ring=this;if(projection){var gg=new OpenLayers.Projection("EPSG:4326");if(!gg.equals(projection)){ring=this.clone().transform(projection,gg);}}
61160 var area=0.0;var len=ring.components&&ring.components.length;if(len>2){var p1,p2;for(var i=0;i<len-1;i++){p1=ring.components[i];p2=ring.components[i+1];area+=OpenLayers.Util.rad(p2.x-p1.x)*(2+Math.sin(OpenLayers.Util.rad(p1.y))+
61161 Math.sin(OpenLayers.Util.rad(p2.y)));}
61162 area=area*6378137.0*6378137.0/2.0;}
61163 return area;},containsPoint:function(point){var approx=OpenLayers.Number.limitSigDigs;var digs=14;var px=approx(point.x,digs);var py=approx(point.y,digs);function getX(y,x1,y1,x2,y2){return(((x1-x2)*y)+((x2*y1)-(x1*y2)))/(y1-y2);}
61164 var numSeg=this.components.length-1;var start,end,x1,y1,x2,y2,cx,cy;var crosses=0;for(var i=0;i<numSeg;++i){start=this.components[i];x1=approx(start.x,digs);y1=approx(start.y,digs);end=this.components[i+1];x2=approx(end.x,digs);y2=approx(end.y,digs);if(y1==y2){if(py==y1){if(x1<=x2&&(px>=x1&&px<=x2)||x1>=x2&&(px<=x1&&px>=x2)){crosses=-1;break;}}
61165 continue;}
61166 cx=approx(getX(py,x1,y1,x2,y2),digs);if(cx==px){if(y1<y2&&(py>=y1&&py<=y2)||y1>y2&&(py<=y1&&py>=y2)){crosses=-1;break;}}
61167 if(cx<=px){continue;}
61168 if(x1!=x2&&(cx<Math.min(x1,x2)||cx>Math.max(x1,x2))){continue;}
61169 if(y1<y2&&(py>=y1&&py<y2)||y1>y2&&(py<y1&&py>=y2)){++crosses;}}
61170 var contained=(crosses==-1)?1:!!(crosses&1);return contained;},intersects:function(geometry){var intersect=false;if(geometry.CLASS_NAME=="OpenLayers.Geometry.Point"){intersect=this.containsPoint(geometry);}else if(geometry.CLASS_NAME=="OpenLayers.Geometry.LineString"){intersect=geometry.intersects(this);}else if(geometry.CLASS_NAME=="OpenLayers.Geometry.LinearRing"){intersect=OpenLayers.Geometry.LineString.prototype.intersects.apply(this,[geometry]);}else{for(var i=0,len=geometry.components.length;i<len;++i){intersect=geometry.components[i].intersects(this);if(intersect){break;}}}
61171 return intersect;},getVertices:function(nodes){return(nodes===true)?[]:this.components.slice(0,this.components.length-1);},CLASS_NAME:"OpenLayers.Geometry.LinearRing"});OpenLayers.Geometry.MultiLineString=OpenLayers.Class(OpenLayers.Geometry.Collection,{componentTypes:["OpenLayers.Geometry.LineString"],initialize:function(components){OpenLayers.Geometry.Collection.prototype.initialize.apply(this,arguments);},split:function(geometry,options){var results=null;var mutual=options&&options.mutual;var splits,sourceLine,sourceLines,sourceSplit,targetSplit;var sourceParts=[];var targetParts=[geometry];for(var i=0,len=this.components.length;i<len;++i){sourceLine=this.components[i];sourceSplit=false;for(var j=0;j<targetParts.length;++j){splits=sourceLine.split(targetParts[j],options);if(splits){if(mutual){sourceLines=splits[0];for(var k=0,klen=sourceLines.length;k<klen;++k){if(k===0&&sourceParts.length){sourceParts[sourceParts.length-1].addComponent(sourceLines[k]);}else{sourceParts.push(new OpenLayers.Geometry.MultiLineString([sourceLines[k]]));}}
61172 sourceSplit=true;splits=splits[1];}
61173 if(splits.length){splits.unshift(j,1);Array.prototype.splice.apply(targetParts,splits);break;}}}
61174 if(!sourceSplit){if(sourceParts.length){sourceParts[sourceParts.length-1].addComponent(sourceLine.clone());}else{sourceParts=[new OpenLayers.Geometry.MultiLineString(sourceLine.clone())];}}}
61175 if(sourceParts&&sourceParts.length>1){sourceSplit=true;}else{sourceParts=[];}
61176 if(targetParts&&targetParts.length>1){targetSplit=true;}else{targetParts=[];}
61177 if(sourceSplit||targetSplit){if(mutual){results=[sourceParts,targetParts];}else{results=targetParts;}}
61178 return results;},splitWith:function(geometry,options){var results=null;var mutual=options&&options.mutual;var splits,targetLine,sourceLines,sourceSplit,targetSplit,sourceParts,targetParts;if(geometry instanceof OpenLayers.Geometry.LineString){targetParts=[];sourceParts=[geometry];for(var i=0,len=this.components.length;i<len;++i){targetSplit=false;targetLine=this.components[i];for(var j=0;j<sourceParts.length;++j){splits=sourceParts[j].split(targetLine,options);if(splits){if(mutual){sourceLines=splits[0];if(sourceLines.length){sourceLines.unshift(j,1);Array.prototype.splice.apply(sourceParts,sourceLines);j+=sourceLines.length-2;}
61179 splits=splits[1];if(splits.length===0){splits=[targetLine.clone()];}}
61180 for(var k=0,klen=splits.length;k<klen;++k){if(k===0&&targetParts.length){targetParts[targetParts.length-1].addComponent(splits[k]);}else{targetParts.push(new OpenLayers.Geometry.MultiLineString([splits[k]]));}}
61181 targetSplit=true;}}
61182 if(!targetSplit){if(targetParts.length){targetParts[targetParts.length-1].addComponent(targetLine.clone());}else{targetParts=[new OpenLayers.Geometry.MultiLineString([targetLine.clone()])];}}}}else{results=geometry.split(this);}
61183 if(sourceParts&&sourceParts.length>1){sourceSplit=true;}else{sourceParts=[];}
61184 if(targetParts&&targetParts.length>1){targetSplit=true;}else{targetParts=[];}
61185 if(sourceSplit||targetSplit){if(mutual){results=[sourceParts,targetParts];}else{results=targetParts;}}
61186 return results;},CLASS_NAME:"OpenLayers.Geometry.MultiLineString"});OpenLayers.Handler.Path=OpenLayers.Class(OpenLayers.Handler.Point,{line:null,freehand:false,freehandToggle:'shiftKey',initialize:function(control,callbacks,options){OpenLayers.Handler.Point.prototype.initialize.apply(this,arguments);},createFeature:function(pixel){var lonlat=this.control.map.getLonLatFromPixel(pixel);this.point=new OpenLayers.Feature.Vector(new OpenLayers.Geometry.Point(lonlat.lon,lonlat.lat));this.line=new OpenLayers.Feature.Vector(new OpenLayers.Geometry.LineString([this.point.geometry]));this.callback("create",[this.point.geometry,this.getSketch()]);this.point.geometry.clearBounds();this.layer.addFeatures([this.line,this.point],{silent:true});},destroyFeature:function(){OpenLayers.Handler.Point.prototype.destroyFeature.apply(this);this.line=null;},removePoint:function(){if(this.point){this.layer.removeFeatures([this.point]);}},addPoint:function(pixel){this.layer.removeFeatures([this.point]);var lonlat=this.control.map.getLonLatFromPixel(pixel);this.point=new OpenLayers.Feature.Vector(new OpenLayers.Geometry.Point(lonlat.lon,lonlat.lat));this.line.geometry.addComponent(this.point.geometry,this.line.geometry.components.length);this.callback("point",[this.point.geometry,this.getGeometry()]);this.callback("modify",[this.point.geometry,this.getSketch()]);this.drawFeature();},freehandMode:function(evt){return(this.freehandToggle&&evt[this.freehandToggle])?!this.freehand:this.freehand;},modifyFeature:function(pixel){var lonlat=this.control.map.getLonLatFromPixel(pixel);this.point.geometry.x=lonlat.lon;this.point.geometry.y=lonlat.lat;this.callback("modify",[this.point.geometry,this.getSketch()]);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 geometry=this.line&&this.line.geometry;if(geometry&&this.multi){geometry=new OpenLayers.Geometry.MultiLineString([geometry]);}
61187 return geometry;},mousedown:function(evt){if(this.lastDown&&this.lastDown.equals(evt.xy)){return false;}
61188 if(this.lastDown==null){if(this.persist){this.destroyFeature();}
61189 this.createFeature(evt.xy);}else if((this.lastUp==null)||!this.lastUp.equals(evt.xy)){this.addPoint(evt.xy);}
61190 this.mouseDown=true;this.lastDown=evt.xy;this.drawing=true;return false;},mousemove:function(evt){if(this.drawing){if(this.mouseDown&&this.freehandMode(evt)){this.addPoint(evt.xy);}else{this.modifyFeature(evt.xy);}}
61191 return true;},mouseup:function(evt){this.mouseDown=false;if(this.drawing){if(this.freehandMode(evt)){this.removePoint();this.finalize();}else{if(this.lastUp==null){this.addPoint(evt.xy);}
61192 this.lastUp=evt.xy;}
61193 return false;}
61194 return true;},dblclick:function(evt){if(!this.freehandMode(evt)){var index=this.line.geometry.components.length-1;this.line.geometry.removeComponent(this.line.geometry.components[index]);this.removePoint();this.finalize();}
61195 return false;},CLASS_NAME:"OpenLayers.Handler.Path"});OpenLayers.Control.Split=OpenLayers.Class(OpenLayers.Control,{EVENT_TYPES:["beforesplit","split","aftersplit"],layer:null,source:null,sourceOptions:null,tolerance:null,edge:true,deferDelete:false,mutual:true,targetFilter:null,sourceFilter:null,handler:null,initialize:function(options){Array.prototype.push.apply(this.EVENT_TYPES,OpenLayers.Control.prototype.EVENT_TYPES);OpenLayers.Control.prototype.initialize.apply(this,[options]);this.options=options||{};if(this.options.source){this.setSource(this.options.source);}},setSource:function(layer){if(this.active){this.deactivate();if(this.handler){this.handler.destroy();delete this.handler;}
61196 this.source=layer;this.activate();}else{this.source=layer;}},activate:function(){var activated=OpenLayers.Control.prototype.activate.call(this);if(activated){if(!this.source){if(!this.handler){this.handler=new OpenLayers.Handler.Path(this,{done:function(geometry){this.onSketchComplete({feature:new OpenLayers.Feature.Vector(geometry)});}},{layerOptions:this.sourceOptions});}
61197 this.handler.activate();}else if(this.source.events){this.source.events.on({sketchcomplete:this.onSketchComplete,afterfeaturemodified:this.afterFeatureModified,scope:this});}}
61198 return activated;},deactivate:function(){var deactivated=OpenLayers.Control.prototype.deactivate.call(this);if(deactivated){if(this.source&&this.source.events){this.layer.events.un({sketchcomplete:this.onSketchComplete,afterfeaturemodified:this.afterFeatureModified,scope:this});}}
61199 return deactivated;},onSketchComplete:function(event){this.feature=null;return!this.considerSplit(event.feature);},afterFeatureModified:function(event){if(event.modified){var feature=event.feature;if(feature.geometry instanceof OpenLayers.Geometry.LineString||feature.geometry instanceof OpenLayers.Geometry.MultiLineString){this.feature=event.feature;this.considerSplit(event.feature);}}},removeByGeometry:function(features,geometry){for(var i=0,len=features.length;i<len;++i){if(features[i].geometry===geometry){features.splice(i,1);break;}}},isEligible:function(target){return(target.state!==OpenLayers.State.DELETE)&&(target.geometry instanceof OpenLayers.Geometry.LineString||target.geometry instanceof OpenLayers.Geometry.MultiLineString)&&(this.feature!==target)&&(!this.targetFilter||this.targetFilter.evaluate(target.attributes));},considerSplit:function(feature){var sourceSplit=false;var targetSplit=false;if(!this.sourceFilter||this.sourceFilter.evaluate(feature.attributes)){var features=this.layer&&this.layer.features||[];var target,results,proceed;var additions=[],removals=[];var mutual=(this.layer===this.source)&&this.mutual;var options={edge:this.edge,tolerance:this.tolerance,mutual:mutual};var sourceParts=[feature.geometry];var targetFeature,targetParts;var source,parts;for(var i=0,len=features.length;i<len;++i){targetFeature=features[i];if(this.isEligible(targetFeature)){targetParts=[targetFeature.geometry];for(var j=0;j<sourceParts.length;++j){source=sourceParts[j];for(var k=0;k<targetParts.length;++k){target=targetParts[k];if(source.getBounds().intersectsBounds(target.getBounds())){results=source.split(target,options);if(results){proceed=this.events.triggerEvent("beforesplit",{source:feature,target:targetFeature});if(proceed!==false){if(mutual){parts=results[0];if(parts.length>1){parts.unshift(j,1);Array.prototype.splice.apply(sourceParts,parts);j+=parts.length-3;}
61200 results=results[1];}
61201 if(results.length>1){results.unshift(k,1);Array.prototype.splice.apply(targetParts,results);k+=results.length-3;}}}}}}
61202 if(targetParts&&targetParts.length>1){this.geomsToFeatures(targetFeature,targetParts);this.events.triggerEvent("split",{original:targetFeature,features:targetParts});Array.prototype.push.apply(additions,targetParts);removals.push(targetFeature);targetSplit=true;}}}
61203 if(sourceParts&&sourceParts.length>1){this.geomsToFeatures(feature,sourceParts);this.events.triggerEvent("split",{original:feature,features:sourceParts});Array.prototype.push.apply(additions,sourceParts);removals.push(feature);sourceSplit=true;}
61204 if(sourceSplit||targetSplit){if(this.deferDelete){var feat,destroys=[];for(var i=0,len=removals.length;i<len;++i){feat=removals[i];if(feat.state===OpenLayers.State.INSERT){destroys.push(feat);}else{feat.state=OpenLayers.State.DELETE;this.layer.drawFeature(feat);}}
61205 this.layer.destroyFeatures(destroys,{silent:true});for(var i=0,len=additions.length;i<len;++i){additions[i].state=OpenLayers.State.INSERT;}}else{this.layer.destroyFeatures(removals,{silent:true});}
61206 this.layer.addFeatures(additions,{silent:true});this.events.triggerEvent("aftersplit",{source:feature,features:additions});}}
61207 return sourceSplit;},geomsToFeatures:function(feature,geoms){var clone=feature.clone();delete clone.geometry;var newFeature;for(var i=0,len=geoms.length;i<len;++i){newFeature=clone.clone();newFeature.geometry=geoms[i];newFeature.state=OpenLayers.State.INSERT;geoms[i]=newFeature;}},destroy:function(){if(this.active){this.deactivate();}
61208 OpenLayers.Control.prototype.destroy.call(this);},CLASS_NAME:"OpenLayers.Control.Split"});OpenLayers.Geometry.Polygon=OpenLayers.Class(OpenLayers.Geometry.Collection,{componentTypes:["OpenLayers.Geometry.LinearRing"],initialize:function(components){OpenLayers.Geometry.Collection.prototype.initialize.apply(this,arguments);},getArea:function(){var area=0.0;if(this.components&&(this.components.length>0)){area+=Math.abs(this.components[0].getArea());for(var i=1,len=this.components.length;i<len;i++){area-=Math.abs(this.components[i].getArea());}}
61209 return area;},getGeodesicArea:function(projection){var area=0.0;if(this.components&&(this.components.length>0)){area+=Math.abs(this.components[0].getGeodesicArea(projection));for(var i=1,len=this.components.length;i<len;i++){area-=Math.abs(this.components[i].getGeodesicArea(projection));}}
61210 return area;},containsPoint:function(point){var numRings=this.components.length;var contained=false;if(numRings>0){contained=this.components[0].containsPoint(point);if(contained!==1){if(contained&&numRings>1){var hole;for(var i=1;i<numRings;++i){hole=this.components[i].containsPoint(point);if(hole){if(hole===1){contained=1;}else{contained=false;}
61211 break;}}}}}
61212 return contained;},intersects:function(geometry){var intersect=false;var i,len;if(geometry.CLASS_NAME=="OpenLayers.Geometry.Point"){intersect=this.containsPoint(geometry);}else if(geometry.CLASS_NAME=="OpenLayers.Geometry.LineString"||geometry.CLASS_NAME=="OpenLayers.Geometry.LinearRing"){for(i=0,len=this.components.length;i<len;++i){intersect=geometry.intersects(this.components[i]);if(intersect){break;}}
61213 if(!intersect){for(i=0,len=geometry.components.length;i<len;++i){intersect=this.containsPoint(geometry.components[i]);if(intersect){break;}}}}else{for(i=0,len=geometry.components.length;i<len;++i){intersect=this.intersects(geometry.components[i]);if(intersect){break;}}}
61214 if(!intersect&&geometry.CLASS_NAME=="OpenLayers.Geometry.Polygon"){var ring=this.components[0];for(i=0,len=ring.components.length;i<len;++i){intersect=geometry.containsPoint(ring.components[i]);if(intersect){break;}}}
61215 return intersect;},distanceTo:function(geometry,options){var edge=!(options&&options.edge===false);var result;if(!edge&&this.intersects(geometry)){result=0;}else{result=OpenLayers.Geometry.Collection.prototype.distanceTo.apply(this,[geometry,options]);}
61216 return result;},CLASS_NAME:"OpenLayers.Geometry.Polygon"});OpenLayers.Geometry.Polygon.createRegularPolygon=function(origin,radius,sides,rotation){var angle=Math.PI*((1/sides)-(1/2));if(rotation){angle+=(rotation/180)*Math.PI;}
61217 var rotatedAngle,x,y;var points=[];for(var i=0;i<sides;++i){rotatedAngle=angle+(i*2*Math.PI/sides);x=origin.x+(radius*Math.cos(rotatedAngle));y=origin.y+(radius*Math.sin(rotatedAngle));points.push(new OpenLayers.Geometry.Point(x,y));}
61218 var ring=new OpenLayers.Geometry.LinearRing(points);return new OpenLayers.Geometry.Polygon([ring]);};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:false,initialize:function(options){OpenLayers.Format.XML.prototype.initialize.apply(this,[options]);},createGeometryFromItem:function(item){var point=this.getElementsByTagNameNS(item,this.georssns,"point");var lat=this.getElementsByTagNameNS(item,this.geons,'lat');var lon=this.getElementsByTagNameNS(item,this.geons,'long');var line=this.getElementsByTagNameNS(item,this.georssns,"line");var polygon=this.getElementsByTagNameNS(item,this.georssns,"polygon");var where=this.getElementsByTagNameNS(item,this.georssns,"where");var box=this.getElementsByTagNameNS(item,this.georssns,"box");if(point.length>0||(lat.length>0&&lon.length>0)){var location;if(point.length>0){location=OpenLayers.String.trim(point[0].firstChild.nodeValue).split(/\s+/);if(location.length!=2){location=OpenLayers.String.trim(point[0].firstChild.nodeValue).split(/\s*,\s*/);}}else{location=[parseFloat(lat[0].firstChild.nodeValue),parseFloat(lon[0].firstChild.nodeValue)];}
61219 var geometry=new OpenLayers.Geometry.Point(parseFloat(location[1]),parseFloat(location[0]));}else if(line.length>0){var coords=OpenLayers.String.trim(this.concatChildValues(line[0])).split(/\s+/);var components=[];var point;for(var i=0,len=coords.length;i<len;i+=2){point=new OpenLayers.Geometry.Point(parseFloat(coords[i+1]),parseFloat(coords[i]));components.push(point);}
61220 geometry=new OpenLayers.Geometry.LineString(components);}else if(polygon.length>0){var coords=OpenLayers.String.trim(this.concatChildValues(polygon[0])).split(/\s+/);var components=[];var point;for(var i=0,len=coords.length;i<len;i+=2){point=new OpenLayers.Geometry.Point(parseFloat(coords[i+1]),parseFloat(coords[i]));components.push(point);}
61221 geometry=new OpenLayers.Geometry.Polygon([new OpenLayers.Geometry.LinearRing(components)]);}else if(where.length>0){if(!this.gmlParser){this.gmlParser=new OpenLayers.Format.GML({'xy':this.xy});}
61222 var feature=this.gmlParser.parseFeature(where[0]);geometry=feature.geometry;}else if(box.length>0){var coords=OpenLayers.String.trim(box[0].firstChild.nodeValue).split(/\s+/);var components=[];var point;if(coords.length>3){point=new OpenLayers.Geometry.Point(parseFloat(coords[1]),parseFloat(coords[0]));components.push(point);point=new OpenLayers.Geometry.Point(parseFloat(coords[1]),parseFloat(coords[2]));components.push(point);point=new OpenLayers.Geometry.Point(parseFloat(coords[3]),parseFloat(coords[2]));components.push(point);point=new OpenLayers.Geometry.Point(parseFloat(coords[3]),parseFloat(coords[0]));components.push(point);point=new OpenLayers.Geometry.Point(parseFloat(coords[1]),parseFloat(coords[0]));components.push(point);}
61223 geometry=new OpenLayers.Geometry.Polygon([new OpenLayers.Geometry.LinearRing(components)]);}
61224 if(geometry&&this.internalProjection&&this.externalProjection){geometry.transform(this.externalProjection,this.internalProjection);}
61225 return geometry;},createFeatureFromItem:function(item){var geometry=this.createGeometryFromItem(item);var title=this.getChildValue(item,"*","title",this.featureTitle);var description=this.getChildValue(item,"*","description",this.getChildValue(item,"*","content",this.getChildValue(item,"*","summary",this.featureDescription)));var link=this.getChildValue(item,"*","link");if(!link){try{link=this.getElementsByTagNameNS(item,"*","link")[0].getAttribute("href");}catch(e){link=null;}}
61226 var id=this.getChildValue(item,"*","id",null);var data={"title":title,"description":description,"link":link};var feature=new OpenLayers.Feature.Vector(geometry,data);feature.fid=id;return feature;},getChildValue:function(node,nsuri,name,def){var value;var eles=this.getElementsByTagNameNS(node,nsuri,name);if(eles&&eles[0]&&eles[0].firstChild&&eles[0].firstChild.nodeValue){value=eles[0].firstChild.nodeValue;}else{value=(def==undefined)?"":def;}
61227 return value;},read:function(doc){if(typeof doc=="string"){doc=OpenLayers.Format.XML.prototype.read.apply(this,[doc]);}
61228 var itemlist=null;itemlist=this.getElementsByTagNameNS(doc,'*','item');if(itemlist.length==0){itemlist=this.getElementsByTagNameNS(doc,'*','entry');}
61229 var numItems=itemlist.length;var features=new Array(numItems);for(var i=0;i<numItems;i++){features[i]=this.createFeatureFromItem(itemlist[i]);}
61230 return features;},write:function(features){var georss;if(features instanceof Array){georss=this.createElementNS(this.rssns,"rss");for(var i=0,len=features.length;i<len;i++){georss.appendChild(this.createFeatureXML(features[i]));}}else{georss=this.createFeatureXML(features);}
61231 return OpenLayers.Format.XML.prototype.write.apply(this,[georss]);},createFeatureXML:function(feature){var geometryNode=this.buildGeometryNode(feature.geometry);var featureNode=this.createElementNS(this.rssns,"item");var titleNode=this.createElementNS(this.rssns,"title");titleNode.appendChild(this.createTextNode(feature.attributes.title?feature.attributes.title:""));var descNode=this.createElementNS(this.rssns,"description");descNode.appendChild(this.createTextNode(feature.attributes.description?feature.attributes.description:""));featureNode.appendChild(titleNode);featureNode.appendChild(descNode);if(feature.attributes.link){var linkNode=this.createElementNS(this.rssns,"link");linkNode.appendChild(this.createTextNode(feature.attributes.link));featureNode.appendChild(linkNode);}
61232 for(var attr in feature.attributes){if(attr=="link"||attr=="title"||attr=="description"){continue;}
61233 var attrText=this.createTextNode(feature.attributes[attr]);var nodename=attr;if(attr.search(":")!=-1){nodename=attr.split(":")[1];}
61234 var attrContainer=this.createElementNS(this.featureNS,"feature:"+nodename);attrContainer.appendChild(attrText);featureNode.appendChild(attrContainer);}
61235 featureNode.appendChild(geometryNode);return featureNode;},buildGeometryNode:function(geometry){if(this.internalProjection&&this.externalProjection){geometry=geometry.clone();geometry.transform(this.internalProjection,this.externalProjection);}
61236 var node;if(geometry.CLASS_NAME=="OpenLayers.Geometry.Polygon"){node=this.createElementNS(this.georssns,'georss:polygon');node.appendChild(this.buildCoordinatesNode(geometry.components[0]));}
61237 else if(geometry.CLASS_NAME=="OpenLayers.Geometry.LineString"){node=this.createElementNS(this.georssns,'georss:line');node.appendChild(this.buildCoordinatesNode(geometry));}
61238 else if(geometry.CLASS_NAME=="OpenLayers.Geometry.Point"){node=this.createElementNS(this.georssns,'georss:point');node.appendChild(this.buildCoordinatesNode(geometry));}else{throw"Couldn't parse "+geometry.CLASS_NAME;}
61239 return node;},buildCoordinatesNode:function(geometry){var points=null;if(geometry.components){points=geometry.components;}
61240 var path;if(points){var numPoints=points.length;var parts=new Array(numPoints);for(var i=0;i<numPoints;i++){parts[i]=points[i].y+" "+points[i].x;}
61241 path=parts.join(" ");}else{path=geometry.y+" "+geometry.x;}
61242 return this.createTextNode(path);},CLASS_NAME:"OpenLayers.Format.GeoRSS"});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:true,extractStyles:false,extractTracks:false,trackAttributes:null,internalns:null,features:null,styles:null,styleBaseUrl:"",fetched:null,maxDepth:0,initialize:function(options){this.regExes={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,[options]);},read:function(data){this.features=[];this.styles={};this.fetched={};var options={depth:0,styleBaseUrl:this.styleBaseUrl};return this.parseData(data,options);},parseData:function(data,options){if(typeof data=="string"){data=OpenLayers.Format.XML.prototype.read.apply(this,[data]);}
61243 var types=["Link","NetworkLink","Style","StyleMap","Placemark"];for(var i=0,len=types.length;i<len;++i){var type=types[i];var nodes=this.getElementsByTagNameNS(data,"*",type);if(nodes.length==0){continue;}
61244 switch(type.toLowerCase()){case"link":case"networklink":this.parseLinks(nodes,options);break;case"style":if(this.extractStyles){this.parseStyles(nodes,options);}
61245 break;case"stylemap":if(this.extractStyles){this.parseStyleMaps(nodes,options);}
61246 break;case"placemark":this.parseFeatures(nodes,options);break;}}
61247 return this.features;},parseLinks:function(nodes,options){if(options.depth>=this.maxDepth){return false;}
61248 var newOptions=OpenLayers.Util.extend({},options);newOptions.depth++;for(var i=0,len=nodes.length;i<len;i++){var href=this.parseProperty(nodes[i],"*","href");if(href&&!this.fetched[href]){this.fetched[href]=true;var data=this.fetchLink(href);if(data){this.parseData(data,newOptions);}}}},fetchLink:function(href){var request=OpenLayers.Request.GET({url:href,async:false});if(request){return request.responseText;}},parseStyles:function(nodes,options){for(var i=0,len=nodes.length;i<len;i++){var style=this.parseStyle(nodes[i]);if(style){var styleName=(options.styleBaseUrl||"")+"#"+style.id;this.styles[styleName]=style;}}},parseKmlColor:function(kmlColor){var color=null;if(kmlColor){var matches=kmlColor.match(this.regExes.kmlColor);if(matches){color={color:'#'+matches[4]+matches[3]+matches[2],opacity:parseInt(matches[1],16)/255};}}
61249 return color;},parseStyle:function(node){var style={};var types=["LineStyle","PolyStyle","IconStyle","BalloonStyle","LabelStyle"];var type,nodeList,geometry,parser;for(var i=0,len=types.length;i<len;++i){type=types[i];styleTypeNode=this.getElementsByTagNameNS(node,"*",type)[0];if(!styleTypeNode){continue;}
61250 switch(type.toLowerCase()){case"linestyle":var kmlColor=this.parseProperty(styleTypeNode,"*","color");var color=this.parseKmlColor(kmlColor);if(color){style["strokeColor"]=color.color;style["strokeOpacity"]=color.opacity;}
61251 var width=this.parseProperty(styleTypeNode,"*","width");if(width){style["strokeWidth"]=width;}
61252 break;case"polystyle":var kmlColor=this.parseProperty(styleTypeNode,"*","color");var color=this.parseKmlColor(kmlColor);if(color){style["fillOpacity"]=color.opacity;style["fillColor"]=color.color;}
61253 var fill=this.parseProperty(styleTypeNode,"*","fill");if(fill=="0"){style["fillColor"]="none";}
61254 var outline=this.parseProperty(styleTypeNode,"*","outline");if(outline=="0"){style["strokeWidth"]="0";}
61255 break;case"iconstyle":var scale=parseFloat(this.parseProperty(styleTypeNode,"*","scale")||1);var width=32*scale;var height=32*scale;var iconNode=this.getElementsByTagNameNS(styleTypeNode,"*","Icon")[0];if(iconNode){var href=this.parseProperty(iconNode,"*","href");if(href){var w=this.parseProperty(iconNode,"*","w");var h=this.parseProperty(iconNode,"*","h");var google="http://maps.google.com/mapfiles/kml";if(OpenLayers.String.startsWith(href,google)&&!w&&!h){w=64;h=64;scale=scale/2;}
61256 w=w||h;h=h||w;if(w){width=parseInt(w)*scale;}
61257 if(h){height=parseInt(h)*scale;}
61258 var matches=href.match(this.regExes.kmlIconPalette);if(matches){var palette=matches[1];var file_extension=matches[2];var x=this.parseProperty(iconNode,"*","x");var y=this.parseProperty(iconNode,"*","y");var posX=x?x/32:0;var posY=y?(7-y/32):7;var pos=posY*8+posX;href="http://maps.google.com/mapfiles/kml/pal"
61259 +palette+"/icon"+pos+file_extension;}
61260 style["graphicOpacity"]=1;style["externalGraphic"]=href;}}
61261 var hotSpotNode=this.getElementsByTagNameNS(styleTypeNode,"*","hotSpot")[0];if(hotSpotNode){var x=parseFloat(hotSpotNode.getAttribute("x"));var y=parseFloat(hotSpotNode.getAttribute("y"));var xUnits=hotSpotNode.getAttribute("xunits");if(xUnits=="pixels"){style["graphicXOffset"]=-x*scale;}
61262 else if(xUnits=="insetPixels"){style["graphicXOffset"]=-width+(x*scale);}
61263 else if(xUnits=="fraction"){style["graphicXOffset"]=-width*x;}
61264 var yUnits=hotSpotNode.getAttribute("yunits");if(yUnits=="pixels"){style["graphicYOffset"]=-height+(y*scale)+1;}
61265 else if(yUnits=="insetPixels"){style["graphicYOffset"]=-(y*scale)+1;}
61266 else if(yUnits=="fraction"){style["graphicYOffset"]=-height*(1-y)+1;}}
61267 style["graphicWidth"]=width;style["graphicHeight"]=height;break;case"balloonstyle":var balloonStyle=OpenLayers.Util.getXmlNodeValue(styleTypeNode);if(balloonStyle){style["balloonStyle"]=balloonStyle.replace(this.regExes.straightBracket,"${$1}");}
61268 break;case"labelstyle":var kmlColor=this.parseProperty(styleTypeNode,"*","color");var color=this.parseKmlColor(kmlColor);if(color){style["fontColor"]=color.color;style["fontOpacity"]=color.opacity;}
61269 break;default:}}
61270 if(!style["strokeColor"]&&style["fillColor"]){style["strokeColor"]=style["fillColor"];}
61271 var id=node.getAttribute("id");if(id&&style){style.id=id;}
61272 return style;},parseStyleMaps:function(nodes,options){for(var i=0,len=nodes.length;i<len;i++){var node=nodes[i];var pairs=this.getElementsByTagNameNS(node,"*","Pair");var id=node.getAttribute("id");for(var j=0,jlen=pairs.length;j<jlen;j++){var pair=pairs[j];var key=this.parseProperty(pair,"*","key");var styleUrl=this.parseProperty(pair,"*","styleUrl");if(styleUrl&&key=="normal"){this.styles[(options.styleBaseUrl||"")+"#"+id]=this.styles[(options.styleBaseUrl||"")+styleUrl];}
61273 if(styleUrl&&key=="highlight"){}}}},parseFeatures:function(nodes,options){var features=[];for(var i=0,len=nodes.length;i<len;i++){var featureNode=nodes[i];var feature=this.parseFeature.apply(this,[featureNode]);if(feature){if(this.extractStyles&&feature.attributes&&feature.attributes.styleUrl){feature.style=this.getStyle(feature.attributes.styleUrl,options);}
61274 if(this.extractStyles){var inlineStyleNode=this.getElementsByTagNameNS(featureNode,"*","Style")[0];if(inlineStyleNode){var inlineStyle=this.parseStyle(inlineStyleNode);if(inlineStyle){feature.style=OpenLayers.Util.extend(feature.style,inlineStyle);}}}
61275 if(this.extractTracks){var tracks=this.getElementsByTagNameNS(featureNode,this.namespaces.gx,"Track");if(tracks&&tracks.length>0){var track=tracks[0];var container={features:[],feature:feature};this.readNode(track,container);if(container.features.length>0){features.push.apply(features,container.features);}}}else{features.push(feature);}}else{throw"Bad Placemark: "+i;}}
61276 this.features=this.features.concat(features);},readers:{"kml":{"when":function(node,container){container.whens.push(OpenLayers.Date.parse(this.getChildValue(node)));},"_trackPointAttribute":function(node,container){var name=node.nodeName.split(":").pop();container.attributes[name].push(this.getChildValue(node));}},"gx":{"Track":function(node,container){var obj={whens:[],points:[],angles:[]};if(this.trackAttributes){var name;obj.attributes={};for(var i=0,ii=this.trackAttributes.length;i<ii;++i){name=this.trackAttributes[i];obj.attributes[name]=[];if(!(name in this.readers.kml)){this.readers.kml[name]=this.readers.kml._trackPointAttribute;}}}
61277 this.readChildNodes(node,obj);if(obj.whens.length!==obj.points.length){throw new Error("gx:Track with unequal number of when ("+obj.whens.length+") and gx:coord ("+obj.points.length+") elements.");}
61278 var hasAngles=obj.angles.length>0;if(hasAngles&&obj.whens.length!==obj.angles.length){throw new Error("gx:Track with unequal number of when ("+obj.whens.length+") and gx:angles ("+obj.angles.length+") elements.");}
61279 var feature,point,angles;for(var i=0,ii=obj.whens.length;i<ii;++i){feature=container.feature.clone();feature.fid=container.feature.fid||container.feature.id;point=obj.points[i];feature.geometry=point;if("z"in point){feature.attributes.altitude=point.z;}
61280 if(this.internalProjection&&this.externalProjection){feature.geometry.transform(this.externalProjection,this.internalProjection);}
61281 if(this.trackAttributes){for(var j=0,jj=this.trackAttributes.length;j<jj;++j){feature.attributes[name]=obj.attributes[this.trackAttributes[j]][i];}}
61282 feature.attributes.when=obj.whens[i];feature.attributes.trackId=container.feature.id;if(hasAngles){angles=obj.angles[i];feature.attributes.heading=parseFloat(angles[0]);feature.attributes.tilt=parseFloat(angles[1]);feature.attributes.roll=parseFloat(angles[2]);}
61283 container.features.push(feature);}},"coord":function(node,container){var str=this.getChildValue(node);var coords=str.replace(this.regExes.trimSpace,"").split(/\s+/);var point=new OpenLayers.Geometry.Point(coords[0],coords[1]);if(coords.length>2){point.z=parseFloat(coords[2]);}
61284 container.points.push(point);},"angles":function(node,container){var str=this.getChildValue(node);var parts=str.replace(this.regExes.trimSpace,"").split(/\s+/);container.angles.push(parts);}}},parseFeature:function(node){var order=["MultiGeometry","Polygon","LineString","Point"];var type,nodeList,geometry,parser;for(var i=0,len=order.length;i<len;++i){type=order[i];this.internalns=node.namespaceURI?node.namespaceURI:this.kmlns;nodeList=this.getElementsByTagNameNS(node,this.internalns,type);if(nodeList.length>0){var parser=this.parseGeometry[type.toLowerCase()];if(parser){geometry=parser.apply(this,[nodeList[0]]);if(this.internalProjection&&this.externalProjection){geometry.transform(this.externalProjection,this.internalProjection);}}else{OpenLayers.Console.error(OpenLayers.i18n("unsupportedGeometryType",{'geomType':type}));}
61285 break;}}
61286 var attributes;if(this.extractAttributes){attributes=this.parseAttributes(node);}
61287 var feature=new OpenLayers.Feature.Vector(geometry,attributes);var fid=node.getAttribute("id")||node.getAttribute("name");if(fid!=null){feature.fid=fid;}
61288 return feature;},getStyle:function(styleUrl,options){var styleBaseUrl=OpenLayers.Util.removeTail(styleUrl);var newOptions=OpenLayers.Util.extend({},options);newOptions.depth++;newOptions.styleBaseUrl=styleBaseUrl;if(!this.styles[styleUrl]&&!OpenLayers.String.startsWith(styleUrl,"#")&&newOptions.depth<=this.maxDepth&&!this.fetched[styleBaseUrl]){var data=this.fetchLink(styleBaseUrl);if(data){this.parseData(data,newOptions);}}
61289 var style=OpenLayers.Util.extend({},this.styles[styleUrl]);return style;},parseGeometry:{point:function(node){var nodeList=this.getElementsByTagNameNS(node,this.internalns,"coordinates");var coords=[];if(nodeList.length>0){var coordString=nodeList[0].firstChild.nodeValue;coordString=coordString.replace(this.regExes.removeSpace,"");coords=coordString.split(",");}
61290 var point=null;if(coords.length>1){if(coords.length==2){coords[2]=null;}
61291 point=new OpenLayers.Geometry.Point(coords[0],coords[1],coords[2]);}else{throw"Bad coordinate string: "+coordString;}
61292 return point;},linestring:function(node,ring){var nodeList=this.getElementsByTagNameNS(node,this.internalns,"coordinates");var line=null;if(nodeList.length>0){var coordString=this.getChildValue(nodeList[0]);coordString=coordString.replace(this.regExes.trimSpace,"");coordString=coordString.replace(this.regExes.trimComma,",");var pointList=coordString.split(this.regExes.splitSpace);var numPoints=pointList.length;var points=new Array(numPoints);var coords,numCoords;for(var i=0;i<numPoints;++i){coords=pointList[i].split(",");numCoords=coords.length;if(numCoords>1){if(coords.length==2){coords[2]=null;}
61293 points[i]=new OpenLayers.Geometry.Point(coords[0],coords[1],coords[2]);}else{throw"Bad LineString point coordinates: "+
61294 pointList[i];}}
61295 if(numPoints){if(ring){line=new OpenLayers.Geometry.LinearRing(points);}else{line=new OpenLayers.Geometry.LineString(points);}}else{throw"Bad LineString coordinates: "+coordString;}}
61296 return line;},polygon:function(node){var nodeList=this.getElementsByTagNameNS(node,this.internalns,"LinearRing");var numRings=nodeList.length;var components=new Array(numRings);if(numRings>0){var ring;for(var i=0,len=nodeList.length;i<len;++i){ring=this.parseGeometry.linestring.apply(this,[nodeList[i],true]);if(ring){components[i]=ring;}else{throw"Bad LinearRing geometry: "+i;}}}
61297 return new OpenLayers.Geometry.Polygon(components);},multigeometry:function(node){var child,parser;var parts=[];var children=node.childNodes;for(var i=0,len=children.length;i<len;++i){child=children[i];if(child.nodeType==1){var type=(child.prefix)?child.nodeName.split(":")[1]:child.nodeName;var parser=this.parseGeometry[type.toLowerCase()];if(parser){parts.push(parser.apply(this,[child]));}}}
61298 return new OpenLayers.Geometry.Collection(parts);}},parseAttributes:function(node){var attributes={};var edNodes=node.getElementsByTagName("ExtendedData");if(edNodes.length){attributes=this.parseExtendedData(edNodes[0]);}
61299 var child,grandchildren,grandchild;var children=node.childNodes;for(var i=0,len=children.length;i<len;++i){child=children[i];if(child.nodeType==1){grandchildren=child.childNodes;if(grandchildren.length>=1&&grandchildren.length<=3){var grandchild;switch(grandchildren.length){case 1:grandchild=grandchildren[0];break;case 2:var c1=grandchildren[0];var c2=grandchildren[1];grandchild=(c1.nodeType==3||c1.nodeType==4)?c1:c2;break;case 3:default:grandchild=grandchildren[1];break;}
61300 if(grandchild.nodeType==3||grandchild.nodeType==4){var name=(child.prefix)?child.nodeName.split(":")[1]:child.nodeName;var value=OpenLayers.Util.getXmlNodeValue(grandchild);if(value){value=value.replace(this.regExes.trimSpace,"");attributes[name]=value;}}}}}
61301 return attributes;},parseExtendedData:function(node){var attributes={};var i,len,data,key;var dataNodes=node.getElementsByTagName("Data");for(i=0,len=dataNodes.length;i<len;i++){data=dataNodes[i];key=data.getAttribute("name");var ed={};var valueNode=data.getElementsByTagName("value");if(valueNode.length){ed['value']=this.getChildValue(valueNode[0]);}
61302 var nameNode=data.getElementsByTagName("displayName");if(nameNode.length){ed['displayName']=this.getChildValue(nameNode[0]);}
61303 attributes[key]=ed;}
61304 var simpleDataNodes=node.getElementsByTagName("SimpleData");for(i=0,len=simpleDataNodes.length;i<len;i++){var ed={};data=simpleDataNodes[i];key=data.getAttribute("name");ed['value']=this.getChildValue(data);ed['displayName']=key;attributes[key]=ed;}
61305 return attributes;},parseProperty:function(xmlNode,namespace,tagName){var value;var nodeList=this.getElementsByTagNameNS(xmlNode,namespace,tagName);try{value=OpenLayers.Util.getXmlNodeValue(nodeList[0]);}catch(e){value=null;}
61306 return value;},write:function(features){if(!(features instanceof Array)){features=[features];}
61307 var kml=this.createElementNS(this.kmlns,"kml");var folder=this.createFolderXML();for(var i=0,len=features.length;i<len;++i){folder.appendChild(this.createPlacemarkXML(features[i]));}
61308 kml.appendChild(folder);return OpenLayers.Format.XML.prototype.write.apply(this,[kml]);},createFolderXML:function(){var folder=this.createElementNS(this.kmlns,"Folder");if(this.foldersName){var folderName=this.createElementNS(this.kmlns,"name");var folderNameText=this.createTextNode(this.foldersName);folderName.appendChild(folderNameText);folder.appendChild(folderName);}
61309 if(this.foldersDesc){var folderDesc=this.createElementNS(this.kmlns,"description");var folderDescText=this.createTextNode(this.foldersDesc);folderDesc.appendChild(folderDescText);folder.appendChild(folderDesc);}
61310 return folder;},createPlacemarkXML:function(feature){var placemarkName=this.createElementNS(this.kmlns,"name");var name=feature.style&&feature.style.label?feature.style.label:feature.attributes.name||feature.id;placemarkName.appendChild(this.createTextNode(name));var placemarkDesc=this.createElementNS(this.kmlns,"description");var desc=feature.attributes.description||this.placemarksDesc;placemarkDesc.appendChild(this.createTextNode(desc));var placemarkNode=this.createElementNS(this.kmlns,"Placemark");if(feature.fid!=null){placemarkNode.setAttribute("id",feature.fid);}
61311 placemarkNode.appendChild(placemarkName);placemarkNode.appendChild(placemarkDesc);var geometryNode=this.buildGeometryNode(feature.geometry);placemarkNode.appendChild(geometryNode);return placemarkNode;},buildGeometryNode:function(geometry){if(this.internalProjection&&this.externalProjection){geometry=geometry.clone();geometry.transform(this.internalProjection,this.externalProjection);}
61312 var className=geometry.CLASS_NAME;var type=className.substring(className.lastIndexOf(".")+1);var builder=this.buildGeometry[type.toLowerCase()];var node=null;if(builder){node=builder.apply(this,[geometry]);}
61313 return node;},buildGeometry:{point:function(geometry){var kml=this.createElementNS(this.kmlns,"Point");kml.appendChild(this.buildCoordinatesNode(geometry));return kml;},multipoint:function(geometry){return this.buildGeometry.collection.apply(this,[geometry]);},linestring:function(geometry){var kml=this.createElementNS(this.kmlns,"LineString");kml.appendChild(this.buildCoordinatesNode(geometry));return kml;},multilinestring:function(geometry){return this.buildGeometry.collection.apply(this,[geometry]);},linearring:function(geometry){var kml=this.createElementNS(this.kmlns,"LinearRing");kml.appendChild(this.buildCoordinatesNode(geometry));return kml;},polygon:function(geometry){var kml=this.createElementNS(this.kmlns,"Polygon");var rings=geometry.components;var ringMember,ringGeom,type;for(var i=0,len=rings.length;i<len;++i){type=(i==0)?"outerBoundaryIs":"innerBoundaryIs";ringMember=this.createElementNS(this.kmlns,type);ringGeom=this.buildGeometry.linearring.apply(this,[rings[i]]);ringMember.appendChild(ringGeom);kml.appendChild(ringMember);}
61314 return kml;},multipolygon:function(geometry){return this.buildGeometry.collection.apply(this,[geometry]);},collection:function(geometry){var kml=this.createElementNS(this.kmlns,"MultiGeometry");var child;for(var i=0,len=geometry.components.length;i<len;++i){child=this.buildGeometryNode.apply(this,[geometry.components[i]]);if(child){kml.appendChild(child);}}
61315 return kml;}},buildCoordinatesNode:function(geometry){var coordinatesNode=this.createElementNS(this.kmlns,"coordinates");var path;var points=geometry.components;if(points){var point;var numPoints=points.length;var parts=new Array(numPoints);for(var i=0;i<numPoints;++i){point=points[i];parts[i]=point.x+","+point.y;}
61316 path=parts.join(" ");}else{path=geometry.x+","+geometry.y;}
61317 var txtNode=this.createTextNode(path);coordinatesNode.appendChild(txtNode);return coordinatesNode;},CLASS_NAME:"OpenLayers.Format.KML"});OpenLayers.Format.OSM=OpenLayers.Class(OpenLayers.Format.XML,{checkTags:false,interestingTagsExclude:null,areaTags:null,initialize:function(options){var layer_defaults={'interestingTagsExclude':['source','source_ref','source:ref','history','attribution','created_by'],'areaTags':['area','building','leisure','tourism','ruins','historic','landuse','military','natural','sport']};layer_defaults=OpenLayers.Util.extend(layer_defaults,options);var interesting={};for(var i=0;i<layer_defaults.interestingTagsExclude.length;i++){interesting[layer_defaults.interestingTagsExclude[i]]=true;}
61318 layer_defaults.interestingTagsExclude=interesting;var area={};for(var i=0;i<layer_defaults.areaTags.length;i++){area[layer_defaults.areaTags[i]]=true;}
61319 layer_defaults.areaTags=area;this.externalProjection=new OpenLayers.Projection("EPSG:4326");OpenLayers.Format.XML.prototype.initialize.apply(this,[layer_defaults]);},read:function(doc){if(typeof doc=="string"){doc=OpenLayers.Format.XML.prototype.read.apply(this,[doc]);}
61320 var nodes=this.getNodes(doc);var ways=this.getWays(doc);var feat_list=new Array(ways.length);for(var i=0;i<ways.length;i++){var point_list=new Array(ways[i].nodes.length);var poly=this.isWayArea(ways[i])?1:0;for(var j=0;j<ways[i].nodes.length;j++){var node=nodes[ways[i].nodes[j]];var point=new OpenLayers.Geometry.Point(node.lon,node.lat);point.osm_id=parseInt(ways[i].nodes[j]);point_list[j]=point;node.used=true;}
61321 var geometry=null;if(poly){geometry=new OpenLayers.Geometry.Polygon(new OpenLayers.Geometry.LinearRing(point_list));}else{geometry=new OpenLayers.Geometry.LineString(point_list);}
61322 if(this.internalProjection&&this.externalProjection){geometry.transform(this.externalProjection,this.internalProjection);}
61323 var feat=new OpenLayers.Feature.Vector(geometry,ways[i].tags);feat.osm_id=parseInt(ways[i].id);feat.fid="way."+feat.osm_id;feat_list[i]=feat;}
61324 for(var node_id in nodes){var node=nodes[node_id];if(!node.used||this.checkTags){var tags=null;if(this.checkTags){var result=this.getTags(node.node,true);if(node.used&&!result[1]){continue;}
61325 tags=result[0];}else{tags=this.getTags(node.node);}
61326 var feat=new OpenLayers.Feature.Vector(new OpenLayers.Geometry.Point(node['lon'],node['lat']),tags);if(this.internalProjection&&this.externalProjection){feat.geometry.transform(this.externalProjection,this.internalProjection);}
61327 feat.osm_id=parseInt(node_id);feat.fid="node."+feat.osm_id;feat_list.push(feat);}
61328 node.node=null;}
61329 return feat_list;},getNodes:function(doc){var node_list=doc.getElementsByTagName("node");var nodes={};for(var i=0;i<node_list.length;i++){var node=node_list[i];var id=node.getAttribute("id");nodes[id]={'lat':node.getAttribute("lat"),'lon':node.getAttribute("lon"),'node':node};}
61330 return nodes;},getWays:function(doc){var way_list=doc.getElementsByTagName("way");var return_ways=[];for(var i=0;i<way_list.length;i++){var way=way_list[i];var way_object={id:way.getAttribute("id")};way_object.tags=this.getTags(way);var node_list=way.getElementsByTagName("nd");way_object.nodes=new Array(node_list.length);for(var j=0;j<node_list.length;j++){way_object.nodes[j]=node_list[j].getAttribute("ref");}
61331 return_ways.push(way_object);}
61332 return return_ways;},getTags:function(dom_node,interesting_tags){var tag_list=dom_node.getElementsByTagName("tag");var tags={};var interesting=false;for(var j=0;j<tag_list.length;j++){var key=tag_list[j].getAttribute("k");tags[key]=tag_list[j].getAttribute("v");if(interesting_tags){if(!this.interestingTagsExclude[key]){interesting=true;}}}
61333 return interesting_tags?[tags,interesting]:tags;},isWayArea:function(way){var poly_shaped=false;var poly_tags=false;if(way.nodes[0]==way.nodes[way.nodes.length-1]){poly_shaped=true;}
61334 if(this.checkTags){for(var key in way.tags){if(this.areaTags[key]){poly_tags=true;break;}}}
61335 return poly_shaped&&(this.checkTags?poly_tags:true);},write:function(features){if(!(features instanceof Array)){features=[features];}
61336 this.osm_id=1;this.created_nodes={};var root_node=this.createElementNS(null,"osm");root_node.setAttribute("version","0.5");root_node.setAttribute("generator","OpenLayers "+OpenLayers.VERSION_NUMBER);for(var i=features.length-1;i>=0;i--){var nodes=this.createFeatureNodes(features[i]);for(var j=0;j<nodes.length;j++){root_node.appendChild(nodes[j]);}}
61337 return OpenLayers.Format.XML.prototype.write.apply(this,[root_node]);},createFeatureNodes:function(feature){var nodes=[];var className=feature.geometry.CLASS_NAME;var type=className.substring(className.lastIndexOf(".")+1);type=type.toLowerCase();var builder=this.createXML[type];if(builder){nodes=builder.apply(this,[feature]);}
61338 return nodes;},createXML:{'point':function(point){var id=null;var geometry=point.geometry?point.geometry:point;var already_exists=false;if(point.osm_id){id=point.osm_id;if(this.created_nodes[id]){already_exists=true;}}else{id=-this.osm_id;this.osm_id++;}
61339 if(already_exists){node=this.created_nodes[id];}else{var node=this.createElementNS(null,"node");}
61340 this.created_nodes[id]=node;node.setAttribute("id",id);node.setAttribute("lon",geometry.x);node.setAttribute("lat",geometry.y);if(point.attributes){this.serializeTags(point,node);}
61341 this.setState(point,node);return already_exists?[]:[node];},linestring:function(feature){var nodes=[];var geometry=feature.geometry;if(feature.osm_id){id=feature.osm_id;}else{id=-this.osm_id;this.osm_id++;}
61342 var way=this.createElementNS(null,"way");way.setAttribute("id",id);for(var i=0;i<geometry.components.length;i++){var node=this.createXML['point'].apply(this,[geometry.components[i]]);if(node.length){node=node[0];var node_ref=node.getAttribute("id");nodes.push(node);}else{node_ref=geometry.components[i].osm_id;node=this.created_nodes[node_ref];}
61343 this.setState(feature,node);var nd_dom=this.createElementNS(null,"nd");nd_dom.setAttribute("ref",node_ref);way.appendChild(nd_dom);}
61344 this.serializeTags(feature,way);nodes.push(way);return nodes;},polygon:function(feature){var attrs=OpenLayers.Util.extend({'area':'yes'},feature.attributes);var feat=new OpenLayers.Feature.Vector(feature.geometry.components[0],attrs);feat.osm_id=feature.osm_id;return this.createXML['linestring'].apply(this,[feat]);}},serializeTags:function(feature,node){for(var key in feature.attributes){var tag=this.createElementNS(null,"tag");tag.setAttribute("k",key);tag.setAttribute("v",feature.attributes[key]);node.appendChild(tag);}},setState:function(feature,node){if(feature.state){var state=null;switch(feature.state){case OpenLayers.State.UPDATE:state="modify";case OpenLayers.State.DELETE:state="delete";}
61345 if(state){node.setAttribute("action",state);}}},CLASS_NAME:"OpenLayers.Format.OSM"});OpenLayers.Geometry.MultiPolygon=OpenLayers.Class(OpenLayers.Geometry.Collection,{componentTypes:["OpenLayers.Geometry.Polygon"],initialize:function(components){OpenLayers.Geometry.Collection.prototype.initialize.apply(this,arguments);},CLASS_NAME:"OpenLayers.Geometry.MultiPolygon"});OpenLayers.Handler.Polygon=OpenLayers.Class(OpenLayers.Handler.Path,{polygon:null,initialize:function(control,callbacks,options){OpenLayers.Handler.Path.prototype.initialize.apply(this,arguments);},createFeature:function(pixel){var lonlat=this.control.map.getLonLatFromPixel(pixel);this.point=new OpenLayers.Feature.Vector(new OpenLayers.Geometry.Point(lonlat.lon,lonlat.lat));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,this.getSketch()]);this.point.geometry.clearBounds();this.layer.addFeatures([this.polygon,this.point],{silent:true});},destroyFeature:function(){OpenLayers.Handler.Path.prototype.destroyFeature.apply(this);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 geometry=this.polygon&&this.polygon.geometry;if(geometry&&this.multi){geometry=new OpenLayers.Geometry.MultiPolygon([geometry]);}
61346 return geometry;},dblclick:function(evt){if(!this.freehandMode(evt)){var index=this.line.geometry.components.length-2;this.line.geometry.removeComponent(this.line.geometry.components[index]);this.removePoint();this.finalize();}
61347 return false;},CLASS_NAME:"OpenLayers.Handler.Polygon"});OpenLayers.Control.EditingToolbar=OpenLayers.Class(OpenLayers.Control.Panel,{initialize:function(layer,options){OpenLayers.Control.Panel.prototype.initialize.apply(this,[options]);this.addControls([new OpenLayers.Control.Navigation()]);var controls=[new OpenLayers.Control.DrawFeature(layer,OpenLayers.Handler.Point,{'displayClass':'olControlDrawFeaturePoint'}),new OpenLayers.Control.DrawFeature(layer,OpenLayers.Handler.Path,{'displayClass':'olControlDrawFeaturePath'}),new OpenLayers.Control.DrawFeature(layer,OpenLayers.Handler.Polygon,{'displayClass':'olControlDrawFeaturePolygon'})];this.addControls(controls);},draw:function(){var div=OpenLayers.Control.Panel.prototype.draw.apply(this,arguments);this.activateControl(this.controls[0]);return div;},CLASS_NAME:"OpenLayers.Control.EditingToolbar"});OpenLayers.Control.SLDSelect=OpenLayers.Class(OpenLayers.Control,{EVENT_TYPES:["selected"],clearOnDeactivate:false,layers:null,callbacks:null,selectionSymbolizer:{'Polygon':{fillColor:'#FF0000',stroke:false},'Line':{strokeColor:'#FF0000',strokeWidth:2},'Point':{graphicName:'square',fillColor:'#FF0000',pointRadius:5}},layerOptions:null,handlerOptions:null,sketchStyle:null,wfsCache:{},layerCache:{},initialize:function(handler,options){this.EVENT_TYPES=OpenLayers.Control.SLDSelect.prototype.EVENT_TYPES.concat(OpenLayers.Control.prototype.EVENT_TYPES);OpenLayers.Control.prototype.initialize.apply(this,[options]);this.callbacks=OpenLayers.Util.extend({done:this.select,click:this.select},this.callbacks);this.handlerOptions=this.handlerOptions||{};this.layerOptions=OpenLayers.Util.applyDefaults(this.layerOptions,{displayInLayerSwitcher:false});if(this.sketchStyle){this.handlerOptions.layerOptions=OpenLayers.Util.applyDefaults(this.handlerOptions.layerOptions,{styleMap:new OpenLayers.StyleMap({"default":this.sketchStyle})});}
61348 this.handler=new handler(this,this.callbacks,this.handlerOptions);},destroy:function(){for(var key in this.layerCache){delete this.layerCache[key];}
61349 for(var key in this.wfsCache){delete this.wfsCache[key];}
61350 OpenLayers.Control.prototype.destroy.apply(this,arguments);},coupleLayerVisiblity:function(evt){this.setVisibility(evt.object.getVisibility());},createSelectionLayer:function(source){var selectionLayer;if(!this.layerCache[source.id]){selectionLayer=new OpenLayers.Layer.WMS.Post(source.name,source.url,source.params,OpenLayers.Util.applyDefaults(this.layerOptions,source.getOptions()));this.layerCache[source.id]=selectionLayer;if(this.layerOptions.displayInLayerSwitcher===false){source.events.on({"visibilitychanged":this.coupleLayerVisiblity,scope:selectionLayer});}
61351 this.map.addLayer(selectionLayer);}else{selectionLayer=this.layerCache[source.id];}
61352 return selectionLayer;},createSLD:function(layer,filters,geometryAttributes){var sld={version:"1.0.0",namedLayers:{}};var layerNames=[layer.params.LAYERS].join(",").split(",");for(var i=0,len=layerNames.length;i<len;i++){var name=layerNames[i];sld.namedLayers[name]={name:name,userStyles:[]};var symbolizer=this.selectionSymbolizer;var geometryAttribute=geometryAttributes[i];if(geometryAttribute.type.indexOf('Polygon')>=0){symbolizer={Polygon:this.selectionSymbolizer['Polygon']};}else if(geometryAttribute.type.indexOf('LineString')>=0){symbolizer={Line:this.selectionSymbolizer['Line']};}else if(geometryAttribute.type.indexOf('Point')>=0){symbolizer={Point:this.selectionSymbolizer['Point']};}
61353 var filter=filters[i];sld.namedLayers[name].userStyles.push({name:'default',rules:[new OpenLayers.Rule({symbolizer:symbolizer,filter:filter,maxScaleDenominator:layer.options.minScale})]});}
61354 return new OpenLayers.Format.SLD().write(sld);},parseDescribeLayer:function(request){var format=new OpenLayers.Format.WMSDescribeLayer();var doc=request.responseXML;if(!doc||!doc.documentElement){doc=request.responseText;}
61355 var describeLayer=format.read(doc);var typeNames=[];var url=null;for(var i=0,len=describeLayer.length;i<len;i++){if(describeLayer[i].owsType=="WFS"){typeNames.push(describeLayer[i].typeName);url=describeLayer[i].owsURL;}}
61356 var options={url:url,params:{SERVICE:"WFS",TYPENAME:typeNames.toString(),REQUEST:"DescribeFeatureType",VERSION:"1.0.0"},callback:function(request){var format=new OpenLayers.Format.WFSDescribeFeatureType();var doc=request.responseXML;if(!doc||!doc.documentElement){doc=request.responseText;}
61357 var describeFeatureType=format.read(doc);this.control.wfsCache[this.layer.id]=describeFeatureType;this.control._queue&&this.control.applySelection();},scope:this};OpenLayers.Request.GET(options);},getGeometryAttributes:function(layer){var result=[];var cache=this.wfsCache[layer.id];for(var i=0,len=cache.featureTypes.length;i<len;i++){var typeName=cache.featureTypes[i];var properties=typeName.properties;for(var j=0,lenj=properties.length;j<lenj;j++){var property=properties[j];var type=property.type;if((type.indexOf('LineString')>=0)||(type.indexOf('GeometryAssociationType')>=0)||(type.indexOf('GeometryPropertyType')>=0)||(type.indexOf('Point')>=0)||(type.indexOf('Polygon')>=0)){result.push(property);}}}
61358 return result;},activate:function(){var activated=OpenLayers.Control.prototype.activate.call(this);if(activated){for(var i=0,len=this.layers.length;i<len;i++){var layer=this.layers[i];if(layer&&!this.wfsCache[layer.id]){var options={url:layer.url,params:{SERVICE:"WMS",VERSION:layer.params.VERSION,LAYERS:layer.params.LAYERS,REQUEST:"DescribeLayer"},callback:this.parseDescribeLayer,scope:{layer:layer,control:this}};OpenLayers.Request.GET(options);}}}
61359 return activated;},deactivate:function(){var deactivated=OpenLayers.Control.prototype.deactivate.call(this);if(deactivated){for(var i=0,len=this.layers.length;i<len;i++){var layer=this.layers[i];if(layer&&this.clearOnDeactivate===true){var layerCache=this.layerCache;var selectionLayer=layerCache[layer.id];if(selectionLayer){layer.events.un({"visibilitychanged":this.coupleLayerVisiblity,scope:selectionLayer});selectionLayer.destroy();delete layerCache[layer.id];}}}}
61360 return deactivated;},setLayers:function(layers){if(this.active){this.deactivate();this.layers=layers;this.activate();}else{this.layers=layers;}},createFilter:function(geometryAttribute,geometry){var filter=null;if(this.handler instanceof OpenLayers.Handler.RegularPolygon){if(this.handler.irregular===true){filter=new OpenLayers.Filter.Spatial({type:OpenLayers.Filter.Spatial.BBOX,property:geometryAttribute.name,value:geometry.getBounds()});}else{filter=new OpenLayers.Filter.Spatial({type:OpenLayers.Filter.Spatial.INTERSECTS,property:geometryAttribute.name,value:geometry});}}else if(this.handler instanceof OpenLayers.Handler.Polygon){filter=new OpenLayers.Filter.Spatial({type:OpenLayers.Filter.Spatial.INTERSECTS,property:geometryAttribute.name,value:geometry});}else if(this.handler instanceof OpenLayers.Handler.Path){if(geometryAttribute.type.indexOf('Point')>=0){filter=new OpenLayers.Filter.Spatial({type:OpenLayers.Filter.Spatial.DWITHIN,property:geometryAttribute.name,distance:this.map.getExtent().getWidth()*0.01,distanceUnits:this.map.getUnits(),value:geometry});}else{filter=new OpenLayers.Filter.Spatial({type:OpenLayers.Filter.Spatial.INTERSECTS,property:geometryAttribute.name,value:geometry});}}else if(this.handler instanceof OpenLayers.Handler.Click){if(geometryAttribute.type.indexOf('Polygon')>=0){filter=new OpenLayers.Filter.Spatial({type:OpenLayers.Filter.Spatial.INTERSECTS,property:geometryAttribute.name,value:geometry});}else{filter=new OpenLayers.Filter.Spatial({type:OpenLayers.Filter.Spatial.DWITHIN,property:geometryAttribute.name,distance:this.map.getExtent().getWidth()*0.01,distanceUnits:this.map.getUnits(),value:geometry});}}
61361 return filter;},select:function(geometry){this._queue=function(){for(var i=0,len=this.layers.length;i<len;i++){var layer=this.layers[i];var geometryAttributes=this.getGeometryAttributes(layer);var filters=[];for(var j=0,lenj=geometryAttributes.length;j<lenj;j++){var geometryAttribute=geometryAttributes[j];if(geometryAttribute!==null){if(!(geometry instanceof OpenLayers.Geometry)){var point=this.map.getLonLatFromPixel(geometry.xy);geometry=new OpenLayers.Geometry.Point(point.lon,point.lat);}
61362 var filter=this.createFilter(geometryAttribute,geometry);if(filter!==null){filters.push(filter);}}}
61363 var selectionLayer=this.createSelectionLayer(layer);var sld=this.createSLD(layer,filters,geometryAttributes);this.events.triggerEvent("selected",{layer:layer,filters:filters});selectionLayer.mergeNewParams({SLD_BODY:sld});delete this._queue;}};this.applySelection();},applySelection:function(){var canApply=true;for(var i=0,len=this.layers.length;i<len;i++){if(!this.wfsCache[this.layers[i].id]){canApply=false;break;}}
61364 canApply&&this._queue.call(this);},CLASS_NAME:"OpenLayers.Control.SLDSelect"});OpenLayers.Format.ArcXML=OpenLayers.Class(OpenLayers.Format.XML,{fontStyleKeys:['antialiasing','blockout','font','fontcolor','fontsize','fontstyle','glowing','interval','outline','printmode','shadow','transparency'],request:null,response:null,initialize:function(options){this.request=new OpenLayers.Format.ArcXML.Request();this.response=new OpenLayers.Format.ArcXML.Response();if(options){if(options.requesttype=="feature"){this.request.get_image=null;var qry=this.request.get_feature.query;this.addCoordSys(qry.featurecoordsys,options.featureCoordSys);this.addCoordSys(qry.filtercoordsys,options.filterCoordSys);if(options.polygon){qry.isspatial=true;qry.spatialfilter.polygon=options.polygon;}else if(options.envelope){qry.isspatial=true;qry.spatialfilter.envelope={minx:0,miny:0,maxx:0,maxy:0};this.parseEnvelope(qry.spatialfilter.envelope,options.envelope);}}else if(options.requesttype=="image"){this.request.get_feature=null;var props=this.request.get_image.properties;this.parseEnvelope(props.envelope,options.envelope);this.addLayers(props.layerlist,options.layers);this.addImageSize(props.imagesize,options.tileSize);this.addCoordSys(props.featurecoordsys,options.featureCoordSys);this.addCoordSys(props.filtercoordsys,options.filterCoordSys);}else{this.request=null;}}
61365 OpenLayers.Format.XML.prototype.initialize.apply(this,[options]);},parseEnvelope:function(env,arr){if(arr&&arr.length==4){env.minx=arr[0];env.miny=arr[1];env.maxx=arr[2];env.maxy=arr[3];}},addLayers:function(ll,lyrs){for(var lind=0,len=lyrs.length;lind<len;lind++){ll.push(lyrs[lind]);}},addImageSize:function(imsize,olsize){if(olsize!==null){imsize.width=olsize.w;imsize.height=olsize.h;imsize.printwidth=olsize.w;imsize.printheight=olsize.h;}},addCoordSys:function(featOrFilt,fsys){if(typeof fsys=="string"){featOrFilt.id=parseInt(fsys);featOrFilt.string=fsys;}
61366 else if(typeof fsys=="object"&&fsys.proj!==null){featOrFilt.id=fsys.proj.srsProjNumber;featOrFilt.string=fsys.proj.srsCode;}else{featOrFilt=fsys;}},iserror:function(data){var ret=null;if(!data){ret=(this.response.error!=='');}else{data=OpenLayers.Format.XML.prototype.read.apply(this,[data]);var errorNodes=data.documentElement.getElementsByTagName("ERROR");ret=(errorNodes!==null&&errorNodes.length>0);}
61367 return ret;},read:function(data){if(typeof data=="string"){data=OpenLayers.Format.XML.prototype.read.apply(this,[data]);}
61368 var arcNode=null;if(data&&data.documentElement){if(data.documentElement.nodeName=="ARCXML"){arcNode=data.documentElement;}else{arcNode=data.documentElement.getElementsByTagName("ARCXML")[0];}}
61369 if(!arcNode||arcNode.firstChild.nodeName==='parsererror'){var error,source;try{error=data.firstChild.nodeValue;source=data.firstChild.childNodes[1].firstChild.nodeValue;}catch(err){}
61370 throw{message:"Error parsing the ArcXML request",error:error,source:source};}
61371 var response=this.parseResponse(arcNode);return response;},write:function(request){if(!request){request=this.request;}
61372 var root=this.createElementNS("","ARCXML");root.setAttribute("version","1.1");var reqElem=this.createElementNS("","REQUEST");if(request.get_image!=null){var getElem=this.createElementNS("","GET_IMAGE");reqElem.appendChild(getElem);var propElem=this.createElementNS("","PROPERTIES");getElem.appendChild(propElem);var props=request.get_image.properties;if(props.featurecoordsys!=null){var feat=this.createElementNS("","FEATURECOORDSYS");propElem.appendChild(feat);if(props.featurecoordsys.id===0){feat.setAttribute("string",props.featurecoordsys['string']);}
61373 else{feat.setAttribute("id",props.featurecoordsys.id);}}
61374 if(props.filtercoordsys!=null){var filt=this.createElementNS("","FILTERCOORDSYS");propElem.appendChild(filt);if(props.filtercoordsys.id===0){filt.setAttribute("string",props.filtercoordsys.string);}
61375 else{filt.setAttribute("id",props.filtercoordsys.id);}}
61376 if(props.envelope!=null){var env=this.createElementNS("","ENVELOPE");propElem.appendChild(env);env.setAttribute("minx",props.envelope.minx);env.setAttribute("miny",props.envelope.miny);env.setAttribute("maxx",props.envelope.maxx);env.setAttribute("maxy",props.envelope.maxy);}
61377 var imagesz=this.createElementNS("","IMAGESIZE");propElem.appendChild(imagesz);imagesz.setAttribute("height",props.imagesize.height);imagesz.setAttribute("width",props.imagesize.width);if(props.imagesize.height!=props.imagesize.printheight||props.imagesize.width!=props.imagesize.printwidth){imagesz.setAttribute("printheight",props.imagesize.printheight);imagesz.setArrtibute("printwidth",props.imagesize.printwidth);}
61378 if(props.background!=null){var backgrnd=this.createElementNS("","BACKGROUND");propElem.appendChild(backgrnd);backgrnd.setAttribute("color",props.background.color.r+","+
61379 props.background.color.g+","+
61380 props.background.color.b);if(props.background.transcolor!==null){backgrnd.setAttribute("transcolor",props.background.transcolor.r+","+
61381 props.background.transcolor.g+","+
61382 props.background.transcolor.b);}}
61383 if(props.layerlist!=null&&props.layerlist.length>0){var layerlst=this.createElementNS("","LAYERLIST");propElem.appendChild(layerlst);for(var ld=0;ld<props.layerlist.length;ld++){var ldef=this.createElementNS("","LAYERDEF");layerlst.appendChild(ldef);ldef.setAttribute("id",props.layerlist[ld].id);ldef.setAttribute("visible",props.layerlist[ld].visible);if(typeof props.layerlist[ld].query=="object"){var query=props.layerlist[ld].query;if(query.where.length<0){continue;}
61384 var queryElem=null;if(typeof query.spatialfilter=="boolean"&&query.spatialfilter){queryElem=this.createElementNS("","SPATIALQUERY");}
61385 else{queryElem=this.createElementNS("","QUERY");}
61386 queryElem.setAttribute("where",query.where);if(typeof query.accuracy=="number"&&query.accuracy>0){queryElem.setAttribute("accuracy",query.accuracy);}
61387 if(typeof query.featurelimit=="number"&&query.featurelimit<2000){queryElem.setAttribute("featurelimit",query.featurelimit);}
61388 if(typeof query.subfields=="string"&&query.subfields!="#ALL#"){queryElem.setAttribute("subfields",query.subfields);}
61389 if(typeof query.joinexpression=="string"&&query.joinexpression.length>0){queryElem.setAttribute("joinexpression",query.joinexpression);}
61390 if(typeof query.jointables=="string"&&query.jointables.length>0){queryElem.setAttribute("jointables",query.jointables);}
61391 ldef.appendChild(queryElem);}
61392 if(typeof props.layerlist[ld].renderer=="object"){this.addRenderer(ldef,props.layerlist[ld].renderer);}}}}else if(request.get_feature!=null){var getElem=this.createElementNS("","GET_FEATURES");getElem.setAttribute("outputmode","newxml");getElem.setAttribute("checkesc","true");if(request.get_feature.geometry){getElem.setAttribute("geometry",request.get_feature.geometry);}
61393 else{getElem.setAttribute("geometry","false");}
61394 if(request.get_feature.compact){getElem.setAttribute("compact",request.get_feature.compact);}
61395 if(request.get_feature.featurelimit=="number"){getElem.setAttribute("featurelimit",request.get_feature.featurelimit);}
61396 getElem.setAttribute("globalenvelope","true");reqElem.appendChild(getElem);if(request.get_feature.layer!=null&&request.get_feature.layer.length>0){var lyrElem=this.createElementNS("","LAYER");lyrElem.setAttribute("id",request.get_feature.layer);getElem.appendChild(lyrElem);}
61397 var fquery=request.get_feature.query;if(fquery!=null){var qElem=null;if(fquery.isspatial){qElem=this.createElementNS("","SPATIALQUERY");}else{qElem=this.createElementNS("","QUERY");}
61398 getElem.appendChild(qElem);if(typeof fquery.accuracy=="number"){qElem.setAttribute("accuracy",fquery.accuracy);}
61399 if(fquery.featurecoordsys!=null){var fcsElem1=this.createElementNS("","FEATURECOORDSYS");if(fquery.featurecoordsys.id==0){fcsElem1.setAttribute("string",fquery.featurecoordsys.string);}else{fcsElem1.setAttribute("id",fquery.featurecoordsys.id);}
61400 qElem.appendChild(fcsElem1);}
61401 if(fquery.filtercoordsys!=null){var fcsElem2=this.createElementNS("","FILTERCOORDSYS");if(fquery.filtercoordsys.id===0){fcsElem2.setAttribute("string",fquery.filtercoordsys.string);}else{fcsElem2.setAttribute("id",fquery.filtercoordsys.id);}
61402 qElem.appendChild(fcsElem2);}
61403 if(fquery.buffer>0){var bufElem=this.createElementNS("","BUFFER");bufElem.setAttribute("distance",fquery.buffer);qElem.appendChild(bufElem);}
61404 if(fquery.isspatial){var spfElem=this.createElementNS("","SPATIALFILTER");spfElem.setAttribute("relation",fquery.spatialfilter.relation);qElem.appendChild(spfElem);if(fquery.spatialfilter.envelope){var envElem=this.createElementNS("","ENVELOPE");envElem.setAttribute("minx",fquery.spatialfilter.envelope.minx);envElem.setAttribute("miny",fquery.spatialfilter.envelope.miny);envElem.setAttribute("maxx",fquery.spatialfilter.envelope.maxx);envElem.setAttribute("maxy",fquery.spatialfilter.envelope.maxy);spfElem.appendChild(envElem);}else if(typeof fquery.spatialfilter.polygon=="object"){spfElem.appendChild(this.writePolygonGeometry(fquery.spatialfilter.polygon));}}
61405 if(fquery.where!=null&&fquery.where.length>0){qElem.setAttribute("where",fquery.where);}}}
61406 root.appendChild(reqElem);return OpenLayers.Format.XML.prototype.write.apply(this,[root]);},addGroupRenderer:function(ldef,toprenderer){var topRelem=this.createElementNS("","GROUPRENDERER");ldef.appendChild(topRelem);for(var rind=0;rind<toprenderer.length;rind++){var renderer=toprenderer[rind];this.addRenderer(topRelem,renderer);}},addRenderer:function(topRelem,renderer){if(renderer instanceof Array){this.addGroupRenderer(topRelem,renderer);}else{var renderElem=this.createElementNS("",renderer.type.toUpperCase()+"RENDERER");topRelem.appendChild(renderElem);if(renderElem.tagName=="VALUEMAPRENDERER"){this.addValueMapRenderer(renderElem,renderer);}else if(renderElem.tagName=="VALUEMAPLABELRENDERER"){this.addValueMapLabelRenderer(renderElem,renderer);}else if(renderElem.tagName=="SIMPLELABELRENDERER"){this.addSimpleLabelRenderer(renderElem,renderer);}else if(renderElem.tagName=="SCALEDEPENDENTRENDERER"){this.addScaleDependentRenderer(renderElem,renderer);}}},addScaleDependentRenderer:function(renderElem,renderer){if(typeof renderer.lower=="string"||typeof renderer.lower=="number"){renderElem.setAttribute("lower",renderer.lower);}
61407 if(typeof renderer.upper=="string"||typeof renderer.upper=="number"){renderElem.setAttribute("upper",renderer.upper);}
61408 this.addRenderer(renderElem,renderer.renderer);},addValueMapLabelRenderer:function(renderElem,renderer){renderElem.setAttribute("lookupfield",renderer.lookupfield);renderElem.setAttribute("labelfield",renderer.labelfield);if(typeof renderer.exacts=="object"){for(var ext=0,extlen=renderer.exacts.length;ext<extlen;ext++){var exact=renderer.exacts[ext];var eelem=this.createElementNS("","EXACT");if(typeof exact.value=="string"){eelem.setAttribute("value",exact.value);}
61409 if(typeof exact.label=="string"){eelem.setAttribute("label",exact.label);}
61410 if(typeof exact.method=="string"){eelem.setAttribute("method",exact.method);}
61411 renderElem.appendChild(eelem);if(typeof exact.symbol=="object"){var selem=null;if(exact.symbol.type=="text"){selem=this.createElementNS("","TEXTSYMBOL");}
61412 if(selem!=null){var keys=this.fontStyleKeys;for(var i=0,len=keys.length;i<len;i++){var key=keys[i];if(exact.symbol[key]){selem.setAttribute(key,exact.symbol[key]);}}
61413 eelem.appendChild(selem);}}}}},addValueMapRenderer:function(renderElem,renderer){renderElem.setAttribute("lookupfield",renderer.lookupfield);if(typeof renderer.ranges=="object"){for(var rng=0,rnglen=renderer.ranges.length;rng<rnglen;rng++){var range=renderer.ranges[rng];var relem=this.createElementNS("","RANGE");relem.setAttribute("lower",range.lower);relem.setAttribute("upper",range.upper);renderElem.appendChild(relem);if(typeof range.symbol=="object"){var selem=null;if(range.symbol.type=="simplepolygon"){selem=this.createElementNS("","SIMPLEPOLYGONSYMBOL");}
61414 if(selem!=null){if(typeof range.symbol.boundarycolor=="string"){selem.setAttribute("boundarycolor",range.symbol.boundarycolor);}
61415 if(typeof range.symbol.fillcolor=="string"){selem.setAttribute("fillcolor",range.symbol.fillcolor);}
61416 if(typeof range.symbol.filltransparency=="number"){selem.setAttribute("filltransparency",range.symbol.filltransparency);}
61417 relem.appendChild(selem);}}}}else if(typeof renderer.exacts=="object"){for(var ext=0,extlen=renderer.exacts.length;ext<extlen;ext++){var exact=renderer.exacts[ext];var eelem=this.createElementNS("","EXACT");if(typeof exact.value=="string"){eelem.setAttribute("value",exact.value);}
61418 if(typeof exact.label=="string"){eelem.setAttribute("label",exact.label);}
61419 if(typeof exact.method=="string"){eelem.setAttribute("method",exact.method);}
61420 renderElem.appendChild(eelem);if(typeof exact.symbol=="object"){var selem=null;if(exact.symbol.type=="simplemarker"){selem=this.createElementNS("","SIMPLEMARKERSYMBOL");}
61421 if(selem!=null){if(typeof exact.symbol.antialiasing=="string"){selem.setAttribute("antialiasing",exact.symbol.antialiasing);}
61422 if(typeof exact.symbol.color=="string"){selem.setAttribute("color",exact.symbol.color);}
61423 if(typeof exact.symbol.outline=="string"){selem.setAttribute("outline",exact.symbol.outline);}
61424 if(typeof exact.symbol.overlap=="string"){selem.setAttribute("overlap",exact.symbol.overlap);}
61425 if(typeof exact.symbol.shadow=="string"){selem.setAttribute("shadow",exact.symbol.shadow);}
61426 if(typeof exact.symbol.transparency=="number"){selem.setAttribute("transparency",exact.symbol.transparency);}
61427 if(typeof exact.symbol.usecentroid=="string"){selem.setAttribute("usecentroid",exact.symbol.usecentroid);}
61428 if(typeof exact.symbol.width=="number"){selem.setAttribute("width",exact.symbol.width);}
61429 eelem.appendChild(selem);}}}}},addSimpleLabelRenderer:function(renderElem,renderer){renderElem.setAttribute("field",renderer.field);var keys=['featureweight','howmanylabels','labelbufferratio','labelpriorities','labelweight','linelabelposition','rotationalangles'];for(var i=0,len=keys.length;i<len;i++){var key=keys[i];if(renderer[key]){renderElem.setAttribute(key,renderer[key]);}}
61430 if(renderer.symbol.type=="text"){var symbol=renderer.symbol;var selem=this.createElementNS("","TEXTSYMBOL");renderElem.appendChild(selem);var keys=this.fontStyleKeys;for(var i=0,len=keys.length;i<len;i++){var key=keys[i];if(symbol[key]){selem.setAttribute(key,renderer[key]);}}}},writePolygonGeometry:function(polygon){if(!(polygon instanceof OpenLayers.Geometry.Polygon)){throw{message:'Cannot write polygon geometry to ArcXML with an '+
61431 polygon.CLASS_NAME+' object.',geometry:polygon};}
61432 var polyElem=this.createElementNS("","POLYGON");for(var ln=0,lnlen=polygon.components.length;ln<lnlen;ln++){var ring=polygon.components[ln];var ringElem=this.createElementNS("","RING");for(var rn=0,rnlen=ring.components.length;rn<rnlen;rn++){var point=ring.components[rn];var pointElem=this.createElementNS("","POINT");pointElem.setAttribute("x",point.x);pointElem.setAttribute("y",point.y);ringElem.appendChild(pointElem);}
61433 polyElem.appendChild(ringElem);}
61434 return polyElem;},parseResponse:function(data){if(typeof data=="string"){var newData=new OpenLayers.Format.XML();data=newData.read(data);}
61435 var response=new OpenLayers.Format.ArcXML.Response();var errorNode=data.getElementsByTagName("ERROR");if(errorNode!=null&&errorNode.length>0){response.error=this.getChildValue(errorNode,"Unknown error.");}else{var responseNode=data.getElementsByTagName("RESPONSE");if(responseNode==null||responseNode.length==0){response.error="No RESPONSE tag found in ArcXML response.";return response;}
61436 var rtype=responseNode[0].firstChild.nodeName;if(rtype=="#text"){rtype=responseNode[0].firstChild.nextSibling.nodeName;}
61437 if(rtype=="IMAGE"){var envelopeNode=data.getElementsByTagName("ENVELOPE");var outputNode=data.getElementsByTagName("OUTPUT");if(envelopeNode==null||envelopeNode.length==0){response.error="No ENVELOPE tag found in ArcXML response.";}else if(outputNode==null||outputNode.length==0){response.error="No OUTPUT tag found in ArcXML response.";}else{var envAttr=this.parseAttributes(envelopeNode[0]);var outputAttr=this.parseAttributes(outputNode[0]);if(typeof outputAttr.type=="string"){response.image={envelope:envAttr,output:{type:outputAttr.type,data:this.getChildValue(outputNode[0])}};}else{response.image={envelope:envAttr,output:outputAttr};}}}else if(rtype=="FEATURES"){var features=responseNode[0].getElementsByTagName("FEATURES");var featureCount=features[0].getElementsByTagName("FEATURECOUNT");response.features.featurecount=featureCount[0].getAttribute("count");if(response.features.featurecount>0){var envelope=features[0].getElementsByTagName("ENVELOPE");response.features.envelope=this.parseAttributes(envelope[0],typeof(0));var featureList=features[0].getElementsByTagName("FEATURE");for(var fn=0;fn<featureList.length;fn++){var feature=new OpenLayers.Feature.Vector();var fields=featureList[fn].getElementsByTagName("FIELD");for(var fdn=0;fdn<fields.length;fdn++){var fieldName=fields[fdn].getAttribute("name");var fieldValue=fields[fdn].getAttribute("value");feature.attributes[fieldName]=fieldValue;}
61438 var geom=featureList[fn].getElementsByTagName("POLYGON");if(geom.length>0){var ring=geom[0].getElementsByTagName("RING");var polys=[];for(var rn=0;rn<ring.length;rn++){var linearRings=[];linearRings.push(this.parsePointGeometry(ring[rn]));var holes=ring[rn].getElementsByTagName("HOLE");for(var hn=0;hn<holes.length;hn++){linearRings.push(this.parsePointGeometry(holes[hn]));}
61439 holes=null;polys.push(new OpenLayers.Geometry.Polygon(linearRings));linearRings=null;}
61440 ring=null;if(polys.length==1){feature.geometry=polys[0];}else
61441 {feature.geometry=new OpenLayers.Geometry.MultiPolygon(polys);}}
61442 response.features.feature.push(feature);}}}else{response.error="Unidentified response type.";}}
61443 return response;},parseAttributes:function(node,type){var attributes={};for(var attr=0;attr<node.attributes.length;attr++){if(type=="number"){attributes[node.attributes[attr].nodeName]=parseFloat(node.attributes[attr].nodeValue);}else{attributes[node.attributes[attr].nodeName]=node.attributes[attr].nodeValue;}}
61444 return attributes;},parsePointGeometry:function(node){var ringPoints=[];var coords=node.getElementsByTagName("COORDS");if(coords.length>0){var coordArr=this.getChildValue(coords[0]);coordArr=coordArr.split(/;/);for(var cn=0;cn<coordArr.length;cn++){var coordItems=coordArr[cn].split(/ /);ringPoints.push(new OpenLayers.Geometry.Point(parseFloat(coordItems[0]),parseFloat(coordItems[1])));}
61445 coords=null;}else{var point=node.getElementsByTagName("POINT");if(point.length>0){for(var pn=0;pn<point.length;pn++){ringPoints.push(new OpenLayers.Geometry.Point(parseFloat(point[pn].getAttribute("x")),parseFloat(point[pn].getAttribute("y"))));}}
61446 point=null;}
61447 return new OpenLayers.Geometry.LinearRing(ringPoints);},CLASS_NAME:"OpenLayers.Format.ArcXML"});OpenLayers.Format.ArcXML.Request=OpenLayers.Class({initialize:function(params){var defaults={get_image:{properties:{background:null,draw:true,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:false},layerlist:[],output:{baseurl:"",legendbaseurl:"",legendname:"",legendpath:"",legendurl:"",name:"",path:"",type:"jpg",url:""}}},get_feature:{layer:"",query:{isspatial:false,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:[]};return OpenLayers.Util.extend(this,defaults);},CLASS_NAME:"OpenLayers.Format.ArcXML.Request"});OpenLayers.Format.ArcXML.Response=OpenLayers.Class({initialize:function(params){var defaults={image:{envelope:null,output:''},features:{featurecount:0,envelope:null,feature:[]},error:''};return OpenLayers.Util.extend(this,defaults);},CLASS_NAME:"OpenLayers.Format.ArcXML.Response"});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:true,xy:true,initialize:function(options){this.regExes={trimSpace:(/^\s*|\s*$/g),removeSpace:(/\s*/g),splitSpace:(/\s+/),trimComma:(/\s*,\s*/g)};OpenLayers.Format.XML.prototype.initialize.apply(this,[options]);},read:function(data){if(typeof data=="string"){data=OpenLayers.Format.XML.prototype.read.apply(this,[data]);}
61448 var featureNodes=this.getElementsByTagNameNS(data.documentElement,this.gmlns,this.featureName);var features=[];for(var i=0;i<featureNodes.length;i++){var feature=this.parseFeature(featureNodes[i]);if(feature){features.push(feature);}}
61449 return features;},parseFeature:function(node){var order=["MultiPolygon","Polygon","MultiLineString","LineString","MultiPoint","Point","Envelope"];var type,nodeList,geometry,parser;for(var i=0;i<order.length;++i){type=order[i];nodeList=this.getElementsByTagNameNS(node,this.gmlns,type);if(nodeList.length>0){parser=this.parseGeometry[type.toLowerCase()];if(parser){geometry=parser.apply(this,[nodeList[0]]);if(this.internalProjection&&this.externalProjection){geometry.transform(this.externalProjection,this.internalProjection);}}else{OpenLayers.Console.error(OpenLayers.i18n("unsupportedGeometryType",{'geomType':type}));}
61450 break;}}
61451 var bounds;var boxNodes=this.getElementsByTagNameNS(node,this.gmlns,"Box");for(i=0;i<boxNodes.length;++i){var boxNode=boxNodes[i];var box=this.parseGeometry["box"].apply(this,[boxNode]);var parentNode=boxNode.parentNode;var parentName=parentNode.localName||parentNode.nodeName.split(":").pop();if(parentName==="boundedBy"){bounds=box;}else{geometry=box.toGeometry();}}
61452 var attributes;if(this.extractAttributes){attributes=this.parseAttributes(node);}
61453 var feature=new OpenLayers.Feature.Vector(geometry,attributes);feature.bounds=bounds;feature.gml={featureType:node.firstChild.nodeName.split(":")[1],featureNS:node.firstChild.namespaceURI,featureNSPrefix:node.firstChild.prefix};var childNode=node.firstChild;var fid;while(childNode){if(childNode.nodeType==1){fid=childNode.getAttribute("fid")||childNode.getAttribute("id");if(fid){break;}}
61454 childNode=childNode.nextSibling;}
61455 feature.fid=fid;return feature;},parseGeometry:{point:function(node){var nodeList,coordString;var coords=[];var nodeList=this.getElementsByTagNameNS(node,this.gmlns,"pos");if(nodeList.length>0){coordString=nodeList[0].firstChild.nodeValue;coordString=coordString.replace(this.regExes.trimSpace,"");coords=coordString.split(this.regExes.splitSpace);}
61456 if(coords.length==0){nodeList=this.getElementsByTagNameNS(node,this.gmlns,"coordinates");if(nodeList.length>0){coordString=nodeList[0].firstChild.nodeValue;coordString=coordString.replace(this.regExes.removeSpace,"");coords=coordString.split(",");}}
61457 if(coords.length==0){nodeList=this.getElementsByTagNameNS(node,this.gmlns,"coord");if(nodeList.length>0){var xList=this.getElementsByTagNameNS(nodeList[0],this.gmlns,"X");var yList=this.getElementsByTagNameNS(nodeList[0],this.gmlns,"Y");if(xList.length>0&&yList.length>0){coords=[xList[0].firstChild.nodeValue,yList[0].firstChild.nodeValue];}}}
61458 if(coords.length==2){coords[2]=null;}
61459 if(this.xy){return new OpenLayers.Geometry.Point(coords[0],coords[1],coords[2]);}
61460 else{return new OpenLayers.Geometry.Point(coords[1],coords[0],coords[2]);}},multipoint:function(node){var nodeList=this.getElementsByTagNameNS(node,this.gmlns,"Point");var components=[];if(nodeList.length>0){var point;for(var i=0;i<nodeList.length;++i){point=this.parseGeometry.point.apply(this,[nodeList[i]]);if(point){components.push(point);}}}
61461 return new OpenLayers.Geometry.MultiPoint(components);},linestring:function(node,ring){var nodeList,coordString;var coords=[];var points=[];nodeList=this.getElementsByTagNameNS(node,this.gmlns,"posList");if(nodeList.length>0){coordString=this.getChildValue(nodeList[0]);coordString=coordString.replace(this.regExes.trimSpace,"");coords=coordString.split(this.regExes.splitSpace);var dim=parseInt(nodeList[0].getAttribute("dimension"));var j,x,y,z;for(var i=0;i<coords.length/dim;++i){j=i*dim;x=coords[j];y=coords[j+1];z=(dim==2)?null:coords[j+2];if(this.xy){points.push(new OpenLayers.Geometry.Point(x,y,z));}else{points.push(new OpenLayers.Geometry.Point(y,x,z));}}}
61462 if(coords.length==0){nodeList=this.getElementsByTagNameNS(node,this.gmlns,"coordinates");if(nodeList.length>0){coordString=this.getChildValue(nodeList[0]);coordString=coordString.replace(this.regExes.trimSpace,"");coordString=coordString.replace(this.regExes.trimComma,",");var pointList=coordString.split(this.regExes.splitSpace);for(var i=0;i<pointList.length;++i){coords=pointList[i].split(",");if(coords.length==2){coords[2]=null;}
61463 if(this.xy){points.push(new OpenLayers.Geometry.Point(coords[0],coords[1],coords[2]));}else{points.push(new OpenLayers.Geometry.Point(coords[1],coords[0],coords[2]));}}}}
61464 var line=null;if(points.length!=0){if(ring){line=new OpenLayers.Geometry.LinearRing(points);}else{line=new OpenLayers.Geometry.LineString(points);}}
61465 return line;},multilinestring:function(node){var nodeList=this.getElementsByTagNameNS(node,this.gmlns,"LineString");var components=[];if(nodeList.length>0){var line;for(var i=0;i<nodeList.length;++i){line=this.parseGeometry.linestring.apply(this,[nodeList[i]]);if(line){components.push(line);}}}
61466 return new OpenLayers.Geometry.MultiLineString(components);},polygon:function(node){var nodeList=this.getElementsByTagNameNS(node,this.gmlns,"LinearRing");var components=[];if(nodeList.length>0){var ring;for(var i=0;i<nodeList.length;++i){ring=this.parseGeometry.linestring.apply(this,[nodeList[i],true]);if(ring){components.push(ring);}}}
61467 return new OpenLayers.Geometry.Polygon(components);},multipolygon:function(node){var nodeList=this.getElementsByTagNameNS(node,this.gmlns,"Polygon");var components=[];if(nodeList.length>0){var polygon;for(var i=0;i<nodeList.length;++i){polygon=this.parseGeometry.polygon.apply(this,[nodeList[i]]);if(polygon){components.push(polygon);}}}
61468 return new OpenLayers.Geometry.MultiPolygon(components);},envelope:function(node){var components=[];var coordString;var envelope;var lpoint=this.getElementsByTagNameNS(node,this.gmlns,"lowerCorner");if(lpoint.length>0){var coords=[];if(lpoint.length>0){coordString=lpoint[0].firstChild.nodeValue;coordString=coordString.replace(this.regExes.trimSpace,"");coords=coordString.split(this.regExes.splitSpace);}
61469 if(coords.length==2){coords[2]=null;}
61470 if(this.xy){var lowerPoint=new OpenLayers.Geometry.Point(coords[0],coords[1],coords[2]);}else{var lowerPoint=new OpenLayers.Geometry.Point(coords[1],coords[0],coords[2]);}}
61471 var upoint=this.getElementsByTagNameNS(node,this.gmlns,"upperCorner");if(upoint.length>0){var coords=[];if(upoint.length>0){coordString=upoint[0].firstChild.nodeValue;coordString=coordString.replace(this.regExes.trimSpace,"");coords=coordString.split(this.regExes.splitSpace);}
61472 if(coords.length==2){coords[2]=null;}
61473 if(this.xy){var upperPoint=new OpenLayers.Geometry.Point(coords[0],coords[1],coords[2]);}else{var upperPoint=new OpenLayers.Geometry.Point(coords[1],coords[0],coords[2]);}}
61474 if(lowerPoint&&upperPoint){components.push(new OpenLayers.Geometry.Point(lowerPoint.x,lowerPoint.y));components.push(new OpenLayers.Geometry.Point(upperPoint.x,lowerPoint.y));components.push(new OpenLayers.Geometry.Point(upperPoint.x,upperPoint.y));components.push(new OpenLayers.Geometry.Point(lowerPoint.x,upperPoint.y));components.push(new OpenLayers.Geometry.Point(lowerPoint.x,lowerPoint.y));var ring=new OpenLayers.Geometry.LinearRing(components);envelope=new OpenLayers.Geometry.Polygon([ring]);}
61475 return envelope;},box:function(node){var nodeList=this.getElementsByTagNameNS(node,this.gmlns,"coordinates");var coordString;var coords,beginPoint=null,endPoint=null;if(nodeList.length>0){coordString=nodeList[0].firstChild.nodeValue;coords=coordString.split(" ");if(coords.length==2){beginPoint=coords[0].split(",");endPoint=coords[1].split(",");}}
61476 if(beginPoint!==null&&endPoint!==null){return new OpenLayers.Bounds(parseFloat(beginPoint[0]),parseFloat(beginPoint[1]),parseFloat(endPoint[0]),parseFloat(endPoint[1]));}}},parseAttributes:function(node){var attributes={};var childNode=node.firstChild;var children,i,child,grandchildren,grandchild,name,value;while(childNode){if(childNode.nodeType==1){children=childNode.childNodes;for(i=0;i<children.length;++i){child=children[i];if(child.nodeType==1){grandchildren=child.childNodes;if(grandchildren.length==1){grandchild=grandchildren[0];if(grandchild.nodeType==3||grandchild.nodeType==4){name=(child.prefix)?child.nodeName.split(":")[1]:child.nodeName;value=grandchild.nodeValue.replace(this.regExes.trimSpace,"");attributes[name]=value;}}else{attributes[child.nodeName.split(":").pop()]=null;}}}
61477 break;}
61478 childNode=childNode.nextSibling;}
61479 return attributes;},write:function(features){if(!(features instanceof Array)){features=[features];}
61480 var gml=this.createElementNS("http://www.opengis.net/wfs","wfs:"+this.collectionName);for(var i=0;i<features.length;i++){gml.appendChild(this.createFeatureXML(features[i]));}
61481 return OpenLayers.Format.XML.prototype.write.apply(this,[gml]);},createFeatureXML:function(feature){var geometry=feature.geometry;var geometryNode=this.buildGeometryNode(geometry);var geomContainer=this.createElementNS(this.featureNS,this.featurePrefix+":"+
61482 this.geometryName);geomContainer.appendChild(geometryNode);var featureNode=this.createElementNS(this.gmlns,"gml:"+this.featureName);var featureContainer=this.createElementNS(this.featureNS,this.featurePrefix+":"+
61483 this.layerName);var fid=feature.fid||feature.id;featureContainer.setAttribute("fid",fid);featureContainer.appendChild(geomContainer);for(var attr in feature.attributes){var attrText=this.createTextNode(feature.attributes[attr]);var nodename=attr.substring(attr.lastIndexOf(":")+1);var attrContainer=this.createElementNS(this.featureNS,this.featurePrefix+":"+
61484 nodename);attrContainer.appendChild(attrText);featureContainer.appendChild(attrContainer);}
61485 featureNode.appendChild(featureContainer);return featureNode;},buildGeometryNode:function(geometry){if(this.externalProjection&&this.internalProjection){geometry=geometry.clone();geometry.transform(this.internalProjection,this.externalProjection);}
61486 var className=geometry.CLASS_NAME;var type=className.substring(className.lastIndexOf(".")+1);var builder=this.buildGeometry[type.toLowerCase()];return builder.apply(this,[geometry]);},buildGeometry:{point:function(geometry){var gml=this.createElementNS(this.gmlns,"gml:Point");gml.appendChild(this.buildCoordinatesNode(geometry));return gml;},multipoint:function(geometry){var gml=this.createElementNS(this.gmlns,"gml:MultiPoint");var points=geometry.components;var pointMember,pointGeom;for(var i=0;i<points.length;i++){pointMember=this.createElementNS(this.gmlns,"gml:pointMember");pointGeom=this.buildGeometry.point.apply(this,[points[i]]);pointMember.appendChild(pointGeom);gml.appendChild(pointMember);}
61487 return gml;},linestring:function(geometry){var gml=this.createElementNS(this.gmlns,"gml:LineString");gml.appendChild(this.buildCoordinatesNode(geometry));return gml;},multilinestring:function(geometry){var gml=this.createElementNS(this.gmlns,"gml:MultiLineString");var lines=geometry.components;var lineMember,lineGeom;for(var i=0;i<lines.length;++i){lineMember=this.createElementNS(this.gmlns,"gml:lineStringMember");lineGeom=this.buildGeometry.linestring.apply(this,[lines[i]]);lineMember.appendChild(lineGeom);gml.appendChild(lineMember);}
61488 return gml;},linearring:function(geometry){var gml=this.createElementNS(this.gmlns,"gml:LinearRing");gml.appendChild(this.buildCoordinatesNode(geometry));return gml;},polygon:function(geometry){var gml=this.createElementNS(this.gmlns,"gml:Polygon");var rings=geometry.components;var ringMember,ringGeom,type;for(var i=0;i<rings.length;++i){type=(i==0)?"outerBoundaryIs":"innerBoundaryIs";ringMember=this.createElementNS(this.gmlns,"gml:"+type);ringGeom=this.buildGeometry.linearring.apply(this,[rings[i]]);ringMember.appendChild(ringGeom);gml.appendChild(ringMember);}
61489 return gml;},multipolygon:function(geometry){var gml=this.createElementNS(this.gmlns,"gml:MultiPolygon");var polys=geometry.components;var polyMember,polyGeom;for(var i=0;i<polys.length;++i){polyMember=this.createElementNS(this.gmlns,"gml:polygonMember");polyGeom=this.buildGeometry.polygon.apply(this,[polys[i]]);polyMember.appendChild(polyGeom);gml.appendChild(polyMember);}
61490 return gml;},bounds:function(bounds){var gml=this.createElementNS(this.gmlns,"gml:Box");gml.appendChild(this.buildCoordinatesNode(bounds));return gml;}},buildCoordinatesNode:function(geometry){var coordinatesNode=this.createElementNS(this.gmlns,"gml:coordinates");coordinatesNode.setAttribute("decimal",".");coordinatesNode.setAttribute("cs",",");coordinatesNode.setAttribute("ts"," ");var parts=[];if(geometry instanceof OpenLayers.Bounds){parts.push(geometry.left+","+geometry.bottom);parts.push(geometry.right+","+geometry.top);}else{var points=(geometry.components)?geometry.components:[geometry];for(var i=0;i<points.length;i++){parts.push(points[i].x+","+points[i].y);}}
61491 var txtNode=this.createTextNode(parts.join(" "));coordinatesNode.appendChild(txtNode);return coordinatesNode;},CLASS_NAME:"OpenLayers.Format.GML"});OpenLayers.Format.GeoJSON=OpenLayers.Class(OpenLayers.Format.JSON,{ignoreExtraDims:false,initialize:function(options){OpenLayers.Format.JSON.prototype.initialize.apply(this,[options]);},read:function(json,type,filter){type=(type)?type:"FeatureCollection";var results=null;var obj=null;if(typeof json=="string"){obj=OpenLayers.Format.JSON.prototype.read.apply(this,[json,filter]);}else{obj=json;}
61492 if(!obj){OpenLayers.Console.error("Bad JSON: "+json);}else if(typeof(obj.type)!="string"){OpenLayers.Console.error("Bad GeoJSON - no type: "+json);}else if(this.isValidType(obj,type)){switch(type){case"Geometry":try{results=this.parseGeometry(obj);}catch(err){OpenLayers.Console.error(err);}
61493 break;case"Feature":try{results=this.parseFeature(obj);results.type="Feature";}catch(err){OpenLayers.Console.error(err);}
61494 break;case"FeatureCollection":results=[];switch(obj.type){case"Feature":try{results.push(this.parseFeature(obj));}catch(err){results=null;OpenLayers.Console.error(err);}
61495 break;case"FeatureCollection":for(var i=0,len=obj.features.length;i<len;++i){try{results.push(this.parseFeature(obj.features[i]));}catch(err){results=null;OpenLayers.Console.error(err);}}
61496 break;default:try{var geom=this.parseGeometry(obj);results.push(new OpenLayers.Feature.Vector(geom));}catch(err){results=null;OpenLayers.Console.error(err);}}
61497 break;}}
61498 return results;},isValidType:function(obj,type){var valid=false;switch(type){case"Geometry":if(OpenLayers.Util.indexOf(["Point","MultiPoint","LineString","MultiLineString","Polygon","MultiPolygon","Box","GeometryCollection"],obj.type)==-1){OpenLayers.Console.error("Unsupported geometry type: "+
61499 obj.type);}else{valid=true;}
61500 break;case"FeatureCollection":valid=true;break;default:if(obj.type==type){valid=true;}else{OpenLayers.Console.error("Cannot convert types from "+
61501 obj.type+" to "+type);}}
61502 return valid;},parseFeature:function(obj){var feature,geometry,attributes,bbox;attributes=(obj.properties)?obj.properties:{};bbox=(obj.geometry&&obj.geometry.bbox)||obj.bbox;try{geometry=this.parseGeometry(obj.geometry);}catch(err){throw err;}
61503 feature=new OpenLayers.Feature.Vector(geometry,attributes);if(bbox){feature.bounds=OpenLayers.Bounds.fromArray(bbox);}
61504 if(obj.id){feature.fid=obj.id;}
61505 return feature;},parseGeometry:function(obj){if(obj==null){return null;}
61506 var geometry,collection=false;if(obj.type=="GeometryCollection"){if(!(obj.geometries instanceof Array)){throw"GeometryCollection must have geometries array: "+obj;}
61507 var numGeom=obj.geometries.length;var components=new Array(numGeom);for(var i=0;i<numGeom;++i){components[i]=this.parseGeometry.apply(this,[obj.geometries[i]]);}
61508 geometry=new OpenLayers.Geometry.Collection(components);collection=true;}else{if(!(obj.coordinates instanceof Array)){throw"Geometry must have coordinates array: "+obj;}
61509 if(!this.parseCoords[obj.type.toLowerCase()]){throw"Unsupported geometry type: "+obj.type;}
61510 try{geometry=this.parseCoords[obj.type.toLowerCase()].apply(this,[obj.coordinates]);}catch(err){throw err;}}
61511 if(this.internalProjection&&this.externalProjection&&!collection){geometry.transform(this.externalProjection,this.internalProjection);}
61512 return geometry;},parseCoords:{"point":function(array){if(this.ignoreExtraDims==false&&array.length!=2){throw"Only 2D points are supported: "+array;}
61513 return new OpenLayers.Geometry.Point(array[0],array[1]);},"multipoint":function(array){var points=[];var p=null;for(var i=0,len=array.length;i<len;++i){try{p=this.parseCoords["point"].apply(this,[array[i]]);}catch(err){throw err;}
61514 points.push(p);}
61515 return new OpenLayers.Geometry.MultiPoint(points);},"linestring":function(array){var points=[];var p=null;for(var i=0,len=array.length;i<len;++i){try{p=this.parseCoords["point"].apply(this,[array[i]]);}catch(err){throw err;}
61516 points.push(p);}
61517 return new OpenLayers.Geometry.LineString(points);},"multilinestring":function(array){var lines=[];var l=null;for(var i=0,len=array.length;i<len;++i){try{l=this.parseCoords["linestring"].apply(this,[array[i]]);}catch(err){throw err;}
61518 lines.push(l);}
61519 return new OpenLayers.Geometry.MultiLineString(lines);},"polygon":function(array){var rings=[];var r,l;for(var i=0,len=array.length;i<len;++i){try{l=this.parseCoords["linestring"].apply(this,[array[i]]);}catch(err){throw err;}
61520 r=new OpenLayers.Geometry.LinearRing(l.components);rings.push(r);}
61521 return new OpenLayers.Geometry.Polygon(rings);},"multipolygon":function(array){var polys=[];var p=null;for(var i=0,len=array.length;i<len;++i){try{p=this.parseCoords["polygon"].apply(this,[array[i]]);}catch(err){throw err;}
61522 polys.push(p);}
61523 return new OpenLayers.Geometry.MultiPolygon(polys);},"box":function(array){if(array.length!=2){throw"GeoJSON box coordinates must have 2 elements";}
61524 return new OpenLayers.Geometry.Polygon([new OpenLayers.Geometry.LinearRing([new OpenLayers.Geometry.Point(array[0][0],array[0][1]),new OpenLayers.Geometry.Point(array[1][0],array[0][1]),new OpenLayers.Geometry.Point(array[1][0],array[1][1]),new OpenLayers.Geometry.Point(array[0][0],array[1][1]),new OpenLayers.Geometry.Point(array[0][0],array[0][1])])]);}},write:function(obj,pretty){var geojson={"type":null};if(obj instanceof Array){geojson.type="FeatureCollection";var numFeatures=obj.length;geojson.features=new Array(numFeatures);for(var i=0;i<numFeatures;++i){var element=obj[i];if(!element instanceof OpenLayers.Feature.Vector){var msg="FeatureCollection only supports collections "+"of features: "+element;throw msg;}
61525 geojson.features[i]=this.extract.feature.apply(this,[element]);}}else if(obj.CLASS_NAME.indexOf("OpenLayers.Geometry")==0){geojson=this.extract.geometry.apply(this,[obj]);}else if(obj instanceof OpenLayers.Feature.Vector){geojson=this.extract.feature.apply(this,[obj]);if(obj.layer&&obj.layer.projection){geojson.crs=this.createCRSObject(obj);}}
61526 return OpenLayers.Format.JSON.prototype.write.apply(this,[geojson,pretty]);},createCRSObject:function(object){var proj=object.layer.projection.toString();var crs={};if(proj.match(/epsg:/i)){var code=parseInt(proj.substring(proj.indexOf(":")+1));if(code==4326){crs={"type":"OGC","properties":{"urn":"urn:ogc:def:crs:OGC:1.3:CRS84"}};}else{crs={"type":"EPSG","properties":{"code":code}};}}
61527 return crs;},extract:{'feature':function(feature){var geom=this.extract.geometry.apply(this,[feature.geometry]);return{"type":"Feature","id":feature.fid==null?feature.id:feature.fid,"properties":feature.attributes,"geometry":geom};},'geometry':function(geometry){if(geometry==null){return null;}
61528 if(this.internalProjection&&this.externalProjection){geometry=geometry.clone();geometry.transform(this.internalProjection,this.externalProjection);}
61529 var geometryType=geometry.CLASS_NAME.split('.')[2];var data=this.extract[geometryType.toLowerCase()].apply(this,[geometry]);var json;if(geometryType=="Collection"){json={"type":"GeometryCollection","geometries":data};}else{json={"type":geometryType,"coordinates":data};}
61530 return json;},'point':function(point){return[point.x,point.y];},'multipoint':function(multipoint){var array=[];for(var i=0,len=multipoint.components.length;i<len;++i){array.push(this.extract.point.apply(this,[multipoint.components[i]]));}
61531 return array;},'linestring':function(linestring){var array=[];for(var i=0,len=linestring.components.length;i<len;++i){array.push(this.extract.point.apply(this,[linestring.components[i]]));}
61532 return array;},'multilinestring':function(multilinestring){var array=[];for(var i=0,len=multilinestring.components.length;i<len;++i){array.push(this.extract.linestring.apply(this,[multilinestring.components[i]]));}
61533 return array;},'polygon':function(polygon){var array=[];for(var i=0,len=polygon.components.length;i<len;++i){array.push(this.extract.linestring.apply(this,[polygon.components[i]]));}
61534 return array;},'multipolygon':function(multipolygon){var array=[];for(var i=0,len=multipolygon.components.length;i<len;++i){array.push(this.extract.polygon.apply(this,[multipolygon.components[i]]));}
61535 return array;},'collection':function(collection){var len=collection.components.length;var array=new Array(len);for(var i=0;i<len;++i){array[i]=this.extract.geometry.apply(this,[collection.components[i]]);}
61536 return array;}},CLASS_NAME:"OpenLayers.Format.GeoJSON"});OpenLayers.Format.ArcXML.Features=OpenLayers.Class(OpenLayers.Format.XML,{initialize:function(options){OpenLayers.Format.XML.prototype.initialize.apply(this,[options]);},read:function(data){var axl=new OpenLayers.Format.ArcXML();var parsed=axl.read(data);return parsed.features.feature;}});if(!OpenLayers.Format.GML){OpenLayers.Format.GML={};}
61537 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:true,srsName:null,xy:true,geometryTypes:null,singleFeatureType:null,regExes:{trimSpace:(/^\s*|\s*$/g),removeSpace:(/\s*/g),splitSpace:(/\s+/),trimComma:(/\s*,\s*/g)},initialize:function(options){OpenLayers.Format.XML.prototype.initialize.apply(this,[options]);this.setGeometryTypes();if(options&&options.featureNS){this.setNamespace("feature",options.featureNS);}
61538 this.singleFeatureType=!options||(typeof options.featureType==="string");},read:function(data){if(typeof data=="string"){data=OpenLayers.Format.XML.prototype.read.apply(this,[data]);}
61539 if(data&&data.nodeType==9){data=data.documentElement;}
61540 var features=[];this.readNode(data,{features:features});if(features.length==0){var elements=this.getElementsByTagNameNS(data,this.namespaces.gml,"featureMember");if(elements.length){for(var i=0,len=elements.length;i<len;++i){this.readNode(elements[i],{features:features});}}else{var elements=this.getElementsByTagNameNS(data,this.namespaces.gml,"featureMembers");if(elements.length){this.readNode(elements[0],{features:features});}}}
61541 return features;},readers:{"gml":{"featureMember":function(node,obj){this.readChildNodes(node,obj);},"featureMembers":function(node,obj){this.readChildNodes(node,obj);},"name":function(node,obj){obj.name=this.getChildValue(node);},"boundedBy":function(node,obj){var container={};this.readChildNodes(node,container);if(container.components&&container.components.length>0){obj.bounds=container.components[0];}},"Point":function(node,container){var obj={points:[]};this.readChildNodes(node,obj);if(!container.components){container.components=[];}
61542 container.components.push(obj.points[0]);},"coordinates":function(node,obj){var str=this.getChildValue(node).replace(this.regExes.trimSpace,"");str=str.replace(this.regExes.trimComma,",");var pointList=str.split(this.regExes.splitSpace);var coords;var numPoints=pointList.length;var points=new Array(numPoints);for(var i=0;i<numPoints;++i){coords=pointList[i].split(",");if(this.xy){points[i]=new OpenLayers.Geometry.Point(coords[0],coords[1],coords[2]);}else{points[i]=new OpenLayers.Geometry.Point(coords[1],coords[0],coords[2]);}}
61543 obj.points=points;},"coord":function(node,obj){var coord={};this.readChildNodes(node,coord);if(!obj.points){obj.points=[];}
61544 obj.points.push(new OpenLayers.Geometry.Point(coord.x,coord.y,coord.z));},"X":function(node,coord){coord.x=this.getChildValue(node);},"Y":function(node,coord){coord.y=this.getChildValue(node);},"Z":function(node,coord){coord.z=this.getChildValue(node);},"MultiPoint":function(node,container){var obj={components:[]};this.readChildNodes(node,obj);container.components=[new OpenLayers.Geometry.MultiPoint(obj.components)];},"pointMember":function(node,obj){this.readChildNodes(node,obj);},"LineString":function(node,container){var obj={};this.readChildNodes(node,obj);if(!container.components){container.components=[];}
61545 container.components.push(new OpenLayers.Geometry.LineString(obj.points));},"MultiLineString":function(node,container){var obj={components:[]};this.readChildNodes(node,obj);container.components=[new OpenLayers.Geometry.MultiLineString(obj.components)];},"lineStringMember":function(node,obj){this.readChildNodes(node,obj);},"Polygon":function(node,container){var obj={outer:null,inner:[]};this.readChildNodes(node,obj);obj.inner.unshift(obj.outer);if(!container.components){container.components=[];}
61546 container.components.push(new OpenLayers.Geometry.Polygon(obj.inner));},"LinearRing":function(node,obj){var container={};this.readChildNodes(node,container);obj.components=[new OpenLayers.Geometry.LinearRing(container.points)];},"MultiPolygon":function(node,container){var obj={components:[]};this.readChildNodes(node,obj);container.components=[new OpenLayers.Geometry.MultiPolygon(obj.components)];},"polygonMember":function(node,obj){this.readChildNodes(node,obj);},"GeometryCollection":function(node,container){var obj={components:[]};this.readChildNodes(node,obj);container.components=[new OpenLayers.Geometry.Collection(obj.components)];},"geometryMember":function(node,obj){this.readChildNodes(node,obj);}},"feature":{"*":function(node,obj){var name;var local=node.localName||node.nodeName.split(":").pop();if(obj.features){if(!this.singleFeatureType&&(OpenLayers.Util.indexOf(this.featureType,local)!==-1)){name="_typeName";}else if(local===this.featureType){name="_typeName";}}else{if(node.childNodes.length==0||(node.childNodes.length==1&&node.firstChild.nodeType==3)){if(this.extractAttributes){name="_attribute";}}else{name="_geometry";}}
61547 if(name){this.readers.feature[name].apply(this,[node,obj]);}},"_typeName":function(node,obj){var container={components:[],attributes:{}};this.readChildNodes(node,container);if(container.name){container.attributes.name=container.name;}
61548 var feature=new OpenLayers.Feature.Vector(container.components[0],container.attributes);if(!this.singleFeatureType){feature.type=node.nodeName.split(":").pop();feature.namespace=node.namespaceURI;}
61549 var fid=node.getAttribute("fid")||this.getAttributeNS(node,this.namespaces["gml"],"id");if(fid){feature.fid=fid;}
61550 if(this.internalProjection&&this.externalProjection&&feature.geometry){feature.geometry.transform(this.externalProjection,this.internalProjection);}
61551 if(container.bounds){feature.bounds=container.bounds;}
61552 obj.features.push(feature);},"_geometry":function(node,obj){this.readChildNodes(node,obj);},"_attribute":function(node,obj){var local=node.localName||node.nodeName.split(":").pop();var value=this.getChildValue(node);obj.attributes[local]=value;}},"wfs":{"FeatureCollection":function(node,obj){this.readChildNodes(node,obj);}}},write:function(features){var name;if(features instanceof Array){name="featureMembers";}else{name="featureMember";}
61553 var root=this.writeNode("gml:"+name,features);this.setAttributeNS(root,this.namespaces["xsi"],"xsi:schemaLocation",this.schemaLocation);return OpenLayers.Format.XML.prototype.write.apply(this,[root]);},writers:{"gml":{"featureMember":function(feature){var node=this.createElementNSPlus("gml:featureMember");this.writeNode("feature:_typeName",feature,node);return node;},"MultiPoint":function(geometry){var node=this.createElementNSPlus("gml:MultiPoint");for(var i=0;i<geometry.components.length;++i){this.writeNode("pointMember",geometry.components[i],node);}
61554 return node;},"pointMember":function(geometry){var node=this.createElementNSPlus("gml:pointMember");this.writeNode("Point",geometry,node);return node;},"MultiLineString":function(geometry){var node=this.createElementNSPlus("gml:MultiLineString");for(var i=0;i<geometry.components.length;++i){this.writeNode("lineStringMember",geometry.components[i],node);}
61555 return node;},"lineStringMember":function(geometry){var node=this.createElementNSPlus("gml:lineStringMember");this.writeNode("LineString",geometry,node);return node;},"MultiPolygon":function(geometry){var node=this.createElementNSPlus("gml:MultiPolygon");for(var i=0;i<geometry.components.length;++i){this.writeNode("polygonMember",geometry.components[i],node);}
61556 return node;},"polygonMember":function(geometry){var node=this.createElementNSPlus("gml:polygonMember");this.writeNode("Polygon",geometry,node);return node;},"GeometryCollection":function(geometry){var node=this.createElementNSPlus("gml:GeometryCollection");for(var i=0,len=geometry.components.length;i<len;++i){this.writeNode("geometryMember",geometry.components[i],node);}
61557 return node;},"geometryMember":function(geometry){var node=this.createElementNSPlus("gml:geometryMember");var child=this.writeNode("feature:_geometry",geometry);node.appendChild(child.firstChild);return node;}},"feature":{"_typeName":function(feature){var node=this.createElementNSPlus("feature:"+this.featureType,{attributes:{fid:feature.fid}});if(feature.geometry){this.writeNode("feature:_geometry",feature.geometry,node);}
61558 for(var name in feature.attributes){var value=feature.attributes[name];if(value!=null){this.writeNode("feature:_attribute",{name:name,value:value},node);}}
61559 return node;},"_geometry":function(geometry){if(this.externalProjection&&this.internalProjection){geometry=geometry.clone().transform(this.internalProjection,this.externalProjection);}
61560 var node=this.createElementNSPlus("feature:"+this.geometryName);var type=this.geometryTypes[geometry.CLASS_NAME];var child=this.writeNode("gml:"+type,geometry,node);if(this.srsName){child.setAttribute("srsName",this.srsName);}
61561 return node;},"_attribute":function(obj){return this.createElementNSPlus("feature:"+obj.name,{value:obj.value});}},"wfs":{"FeatureCollection":function(features){var node=this.createElementNSPlus("wfs:FeatureCollection");for(var i=0,len=features.length;i<len;++i){this.writeNode("gml:featureMember",features[i],node);}
61562 return node;}}},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.WFS=OpenLayers.Class(OpenLayers.Format.GML,{layer:null,wfsns:"http://www.opengis.net/wfs",ogcns:"http://www.opengis.net/ogc",initialize:function(options,layer){OpenLayers.Format.GML.prototype.initialize.apply(this,[options]);this.layer=layer;if(this.layer.featureNS){this.featureNS=this.layer.featureNS;}
61563 if(this.layer.options.geometry_column){this.geometryName=this.layer.options.geometry_column;}
61564 if(this.layer.options.typename){this.featureName=this.layer.options.typename;}},write:function(features){var transaction=this.createElementNS(this.wfsns,'wfs:Transaction');transaction.setAttribute("version","1.0.0");transaction.setAttribute("service","WFS");for(var i=0;i<features.length;i++){switch(features[i].state){case OpenLayers.State.INSERT:transaction.appendChild(this.insert(features[i]));break;case OpenLayers.State.UPDATE:transaction.appendChild(this.update(features[i]));break;case OpenLayers.State.DELETE:transaction.appendChild(this.remove(features[i]));break;}}
61565 return OpenLayers.Format.XML.prototype.write.apply(this,[transaction]);},createFeatureXML:function(feature){var geometryNode=this.buildGeometryNode(feature.geometry);var geomContainer=this.createElementNS(this.featureNS,"feature:"+this.geometryName);geomContainer.appendChild(geometryNode);var featureContainer=this.createElementNS(this.featureNS,"feature:"+this.featureName);featureContainer.appendChild(geomContainer);for(var attr in feature.attributes){var attrText=this.createTextNode(feature.attributes[attr]);var nodename=attr;if(attr.search(":")!=-1){nodename=attr.split(":")[1];}
61566 var attrContainer=this.createElementNS(this.featureNS,"feature:"+nodename);attrContainer.appendChild(attrText);featureContainer.appendChild(attrContainer);}
61567 return featureContainer;},insert:function(feature){var insertNode=this.createElementNS(this.wfsns,'wfs:Insert');insertNode.appendChild(this.createFeatureXML(feature));return insertNode;},update:function(feature){if(!feature.fid){OpenLayers.Console.userError(OpenLayers.i18n("noFID"));}
61568 var updateNode=this.createElementNS(this.wfsns,'wfs:Update');updateNode.setAttribute("typeName",this.featurePrefix+':'+this.featureName);updateNode.setAttribute("xmlns:"+this.featurePrefix,this.featureNS);var propertyNode=this.createElementNS(this.wfsns,'wfs:Property');var nameNode=this.createElementNS(this.wfsns,'wfs:Name');var txtNode=this.createTextNode(this.geometryName);nameNode.appendChild(txtNode);propertyNode.appendChild(nameNode);var valueNode=this.createElementNS(this.wfsns,'wfs:Value');var geometryNode=this.buildGeometryNode(feature.geometry);if(feature.layer){geometryNode.setAttribute("srsName",feature.layer.projection.getCode());}
61569 valueNode.appendChild(geometryNode);propertyNode.appendChild(valueNode);updateNode.appendChild(propertyNode);for(var propName in feature.attributes){propertyNode=this.createElementNS(this.wfsns,'wfs:Property');nameNode=this.createElementNS(this.wfsns,'wfs:Name');nameNode.appendChild(this.createTextNode(propName));propertyNode.appendChild(nameNode);valueNode=this.createElementNS(this.wfsns,'wfs:Value');valueNode.appendChild(this.createTextNode(feature.attributes[propName]));propertyNode.appendChild(valueNode);updateNode.appendChild(propertyNode);}
61570 var filterNode=this.createElementNS(this.ogcns,'ogc:Filter');var filterIdNode=this.createElementNS(this.ogcns,'ogc:FeatureId');filterIdNode.setAttribute("fid",feature.fid);filterNode.appendChild(filterIdNode);updateNode.appendChild(filterNode);return updateNode;},remove:function(feature){if(!feature.fid){OpenLayers.Console.userError(OpenLayers.i18n("noFID"));return false;}
61571 var deleteNode=this.createElementNS(this.wfsns,'wfs:Delete');deleteNode.setAttribute("typeName",this.featurePrefix+':'+this.featureName);deleteNode.setAttribute("xmlns:"+this.featurePrefix,this.featureNS);var filterNode=this.createElementNS(this.ogcns,'ogc:Filter');var filterIdNode=this.createElementNS(this.ogcns,'ogc:FeatureId');filterIdNode.setAttribute("fid",feature.fid);filterNode.appendChild(filterIdNode);deleteNode.appendChild(filterNode);return deleteNode;},destroy:function(){this.layer=null;},CLASS_NAME:"OpenLayers.Format.WFS"});OpenLayers.Layer.ArcIMS=OpenLayers.Class(OpenLayers.Layer.Grid,{DEFAULT_PARAMS:{ClientVersion:"9.2",ServiceName:''},tileSize:null,featureCoordSys:"4326",filterCoordSys:"4326",layers:null,async:true,name:"ArcIMS",isBaseLayer:true,DEFAULT_OPTIONS:{tileSize:new OpenLayers.Size(512,512),featureCoordSys:"4326",filterCoordSys:"4326",layers:null,isBaseLayer:true,async:true,name:"ArcIMS"},initialize:function(name,url,options){this.tileSize=new OpenLayers.Size(512,512);this.params=OpenLayers.Util.applyDefaults({ServiceName:options.serviceName},this.DEFAULT_PARAMS);this.options=OpenLayers.Util.applyDefaults(options,this.DEFAULT_OPTIONS);OpenLayers.Layer.Grid.prototype.initialize.apply(this,[name,url,this.params,options]);if(this.transparent){if(!this.isBaseLayer){this.isBaseLayer=false;}
61572 if(this.format=="image/jpeg"){this.format=OpenLayers.Util.alphaHack()?"image/gif":"image/png";}}
61573 if(this.options.layers===null){this.options.layers=[];}},destroy:function(){OpenLayers.Layer.Grid.prototype.destroy.apply(this,arguments);},getURL:function(bounds){var url="";bounds=this.adjustBounds(bounds);var axlReq=new OpenLayers.Format.ArcXML(OpenLayers.Util.extend(this.options,{requesttype:"image",envelope:bounds.toArray(),tileSize:this.tileSize}));var req=new OpenLayers.Request.POST({url:this.getFullRequestString(),data:axlReq.write(),async:false});if(req!=null){var doc=req.responseXML;if(!doc||!doc.documentElement){doc=req.responseText;}
61574 var axlResp=new OpenLayers.Format.ArcXML();var arcxml=axlResp.read(doc);url=this.getUrlOrImage(arcxml.image.output);}
61575 return url;},getURLasync:function(bounds,scope,prop,callback){bounds=this.adjustBounds(bounds);var axlReq=new OpenLayers.Format.ArcXML(OpenLayers.Util.extend(this.options,{requesttype:"image",envelope:bounds.toArray(),tileSize:this.tileSize}));OpenLayers.Request.POST({url:this.getFullRequestString(),async:true,data:axlReq.write(),callback:function(req){var doc=req.responseXML;if(!doc||!doc.documentElement){doc=req.responseText;}
61576 var axlResp=new OpenLayers.Format.ArcXML();var arcxml=axlResp.read(doc);scope[prop]=this.getUrlOrImage(arcxml.image.output);callback.apply(scope);},scope:this});},getUrlOrImage:function(output){var ret="";if(output.url){ret=output.url;}else if(output.data){ret="data:image/"+output.type+";base64,"+output.data;}
61577 return ret;},setLayerQuery:function(id,querydef){for(var lyr=0;lyr<this.options.layers.length;lyr++){if(id==this.options.layers[lyr].id){this.options.layers[lyr].query=querydef;return;}}
61578 this.options.layers.push({id:id,visible:true,query:querydef});},getFeatureInfo:function(geometry,layer,options){var buffer=options.buffer||1;var callback=options.callback||function(){};var scope=options.scope||window;var requestOptions={};OpenLayers.Util.extend(requestOptions,this.options);requestOptions.requesttype="feature";if(geometry instanceof OpenLayers.LonLat){requestOptions.polygon=null;requestOptions.envelope=[geometry.lon-buffer,geometry.lat-buffer,geometry.lon+buffer,geometry.lat+buffer];}else if(geometry instanceof OpenLayers.Geometry.Polygon){requestOptions.envelope=null;requestOptions.polygon=geometry;}
61579 var arcxml=new OpenLayers.Format.ArcXML(requestOptions);OpenLayers.Util.extend(arcxml.request.get_feature,options);arcxml.request.get_feature.layer=layer.id;if(typeof layer.query.accuracy=="number"){arcxml.request.get_feature.query.accuracy=layer.query.accuracy;}else{var mapCenter=this.map.getCenter();var viewPx=this.map.getViewPortPxFromLonLat(mapCenter);viewPx.x++;var mapOffCenter=this.map.getLonLatFromPixel(viewPx);arcxml.request.get_feature.query.accuracy=mapOffCenter.lon-mapCenter.lon;}
61580 arcxml.request.get_feature.query.where=layer.query.where;arcxml.request.get_feature.query.spatialfilter.relation="area_intersection";OpenLayers.Request.POST({url:this.getFullRequestString({'CustomService':'Query'}),data:arcxml.write(),callback:function(request){var response=arcxml.parseResponse(request.responseText);if(!arcxml.iserror()){callback.call(scope,response.features);}else{callback.call(scope,null);}}});},clone:function(obj){if(obj==null){obj=new OpenLayers.Layer.ArcIMS(this.name,this.url,this.getOptions());}
61581 obj=OpenLayers.Layer.Grid.prototype.clone.apply(this,[obj]);return obj;},addTile:function(bounds,position){return new OpenLayers.Tile.Image(this,position,bounds,null,this.tileSize);},CLASS_NAME:"OpenLayers.Layer.ArcIMS"});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(options){OpenLayers.Format.GML.Base.prototype.initialize.apply(this,[options]);},readers:{"gml":OpenLayers.Util.applyDefaults({"outerBoundaryIs":function(node,container){var obj={};this.readChildNodes(node,obj);container.outer=obj.components[0];},"innerBoundaryIs":function(node,container){var obj={};this.readChildNodes(node,obj);container.inner.push(obj.components[0]);},"Box":function(node,container){var obj={};this.readChildNodes(node,obj);if(!container.components){container.components=[];}
61582 var min=obj.points[0];var max=obj.points[1];container.components.push(new OpenLayers.Bounds(min.x,min.y,max.x,max.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(features){var name;if(features instanceof Array){name="wfs:FeatureCollection";}else{name="gml:featureMember";}
61583 var root=this.writeNode(name,features);this.setAttributeNS(root,this.namespaces["xsi"],"xsi:schemaLocation",this.schemaLocation);return OpenLayers.Format.XML.prototype.write.apply(this,[root]);},writers:{"gml":OpenLayers.Util.applyDefaults({"Point":function(geometry){var node=this.createElementNSPlus("gml:Point");this.writeNode("coordinates",[geometry],node);return node;},"coordinates":function(points){var numPoints=points.length;var parts=new Array(numPoints);var point;for(var i=0;i<numPoints;++i){point=points[i];if(this.xy){parts[i]=point.x+","+point.y;}else{parts[i]=point.y+","+point.x;}
61584 if(point.z!=undefined){parts[i]+=","+point.z;}}
61585 return this.createElementNSPlus("gml:coordinates",{attributes:{decimal:".",cs:",",ts:" "},value:(numPoints==1)?parts[0]:parts.join(" ")});},"LineString":function(geometry){var node=this.createElementNSPlus("gml:LineString");this.writeNode("coordinates",geometry.components,node);return node;},"Polygon":function(geometry){var node=this.createElementNSPlus("gml:Polygon");this.writeNode("outerBoundaryIs",geometry.components[0],node);for(var i=1;i<geometry.components.length;++i){this.writeNode("innerBoundaryIs",geometry.components[i],node);}
61586 return node;},"outerBoundaryIs":function(ring){var node=this.createElementNSPlus("gml:outerBoundaryIs");this.writeNode("LinearRing",ring,node);return node;},"innerBoundaryIs":function(ring){var node=this.createElementNSPlus("gml:innerBoundaryIs");this.writeNode("LinearRing",ring,node);return node;},"LinearRing":function(ring){var node=this.createElementNSPlus("gml:LinearRing");this.writeNode("coordinates",ring.components,node);return node;},"Box":function(bounds){var node=this.createElementNSPlus("gml:Box");this.writeNode("coordinates",[{x:bounds.left,y:bounds.bottom},{x:bounds.right,y:bounds.top}],node);if(this.srsName){node.setAttribute("srsName",this.srsName);}
61587 return node;}},OpenLayers.Format.GML.Base.prototype.writers["gml"]),"feature":OpenLayers.Format.GML.Base.prototype.writers["feature"],"wfs":OpenLayers.Format.GML.Base.prototype.writers["wfs"]},CLASS_NAME:"OpenLayers.Format.GML.v2"});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:false,multiCurve:true,surface:false,multiSurface:true,initialize:function(options){OpenLayers.Format.GML.Base.prototype.initialize.apply(this,[options]);},readers:{"gml":OpenLayers.Util.applyDefaults({"featureMembers":function(node,obj){this.readChildNodes(node,obj);},"Curve":function(node,container){var obj={points:[]};this.readChildNodes(node,obj);if(!container.components){container.components=[];}
61588 container.components.push(new OpenLayers.Geometry.LineString(obj.points));},"segments":function(node,obj){this.readChildNodes(node,obj);},"LineStringSegment":function(node,container){var obj={};this.readChildNodes(node,obj);if(obj.points){Array.prototype.push.apply(container.points,obj.points);}},"pos":function(node,obj){var str=this.getChildValue(node).replace(this.regExes.trimSpace,"");var coords=str.split(this.regExes.splitSpace);var point;if(this.xy){point=new OpenLayers.Geometry.Point(coords[0],coords[1],coords[2]);}else{point=new OpenLayers.Geometry.Point(coords[1],coords[0],coords[2]);}
61589 obj.points=[point];},"posList":function(node,obj){var str=this.getChildValue(node).replace(this.regExes.trimSpace,"");var coords=str.split(this.regExes.splitSpace);var dim=parseInt(node.getAttribute("dimension"))||2;var j,x,y,z;var numPoints=coords.length/dim;var points=new Array(numPoints);for(var i=0,len=coords.length;i<len;i+=dim){x=coords[i];y=coords[i+1];z=(dim==2)?undefined:coords[i+2];if(this.xy){points[i/dim]=new OpenLayers.Geometry.Point(x,y,z);}else{points[i/dim]=new OpenLayers.Geometry.Point(y,x,z);}}
61590 obj.points=points;},"Surface":function(node,obj){this.readChildNodes(node,obj);},"patches":function(node,obj){this.readChildNodes(node,obj);},"PolygonPatch":function(node,obj){this.readers.gml.Polygon.apply(this,[node,obj]);},"exterior":function(node,container){var obj={};this.readChildNodes(node,obj);container.outer=obj.components[0];},"interior":function(node,container){var obj={};this.readChildNodes(node,obj);container.inner.push(obj.components[0]);},"MultiCurve":function(node,container){var obj={components:[]};this.readChildNodes(node,obj);if(obj.components.length>0){container.components=[new OpenLayers.Geometry.MultiLineString(obj.components)];}},"curveMember":function(node,obj){this.readChildNodes(node,obj);},"MultiSurface":function(node,container){var obj={components:[]};this.readChildNodes(node,obj);if(obj.components.length>0){container.components=[new OpenLayers.Geometry.MultiPolygon(obj.components)];}},"surfaceMember":function(node,obj){this.readChildNodes(node,obj);},"surfaceMembers":function(node,obj){this.readChildNodes(node,obj);},"pointMembers":function(node,obj){this.readChildNodes(node,obj);},"lineStringMembers":function(node,obj){this.readChildNodes(node,obj);},"polygonMembers":function(node,obj){this.readChildNodes(node,obj);},"geometryMembers":function(node,obj){this.readChildNodes(node,obj);},"Envelope":function(node,container){var obj={points:new Array(2)};this.readChildNodes(node,obj);if(!container.components){container.components=[];}
61591 var min=obj.points[0];var max=obj.points[1];container.components.push(new OpenLayers.Bounds(min.x,min.y,max.x,max.y));},"lowerCorner":function(node,container){var obj={};this.readers.gml.pos.apply(this,[node,obj]);container.points[0]=obj.points[0];},"upperCorner":function(node,container){var obj={};this.readers.gml.pos.apply(this,[node,obj]);container.points[1]=obj.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(features){var name;if(features instanceof Array){name="featureMembers";}else{name="featureMember";}
61592 var root=this.writeNode("gml:"+name,features);this.setAttributeNS(root,this.namespaces["xsi"],"xsi:schemaLocation",this.schemaLocation);return OpenLayers.Format.XML.prototype.write.apply(this,[root]);},writers:{"gml":OpenLayers.Util.applyDefaults({"featureMembers":function(features){var node=this.createElementNSPlus("gml:featureMembers");for(var i=0,len=features.length;i<len;++i){this.writeNode("feature:_typeName",features[i],node);}
61593 return node;},"Point":function(geometry){var node=this.createElementNSPlus("gml:Point");this.writeNode("pos",geometry,node);return node;},"pos":function(point){var pos=(this.xy)?(point.x+" "+point.y):(point.y+" "+point.x);return this.createElementNSPlus("gml:pos",{value:pos});},"LineString":function(geometry){var node=this.createElementNSPlus("gml:LineString");this.writeNode("posList",geometry.components,node);return node;},"Curve":function(geometry){var node=this.createElementNSPlus("gml:Curve");this.writeNode("segments",geometry,node);return node;},"segments":function(geometry){var node=this.createElementNSPlus("gml:segments");this.writeNode("LineStringSegment",geometry,node);return node;},"LineStringSegment":function(geometry){var node=this.createElementNSPlus("gml:LineStringSegment");this.writeNode("posList",geometry.components,node);return node;},"posList":function(points){var len=points.length;var parts=new Array(len);var point;for(var i=0;i<len;++i){point=points[i];if(this.xy){parts[i]=point.x+" "+point.y;}else{parts[i]=point.y+" "+point.x;}}
61594 return this.createElementNSPlus("gml:posList",{value:parts.join(" ")});},"Surface":function(geometry){var node=this.createElementNSPlus("gml:Surface");this.writeNode("patches",geometry,node);return node;},"patches":function(geometry){var node=this.createElementNSPlus("gml:patches");this.writeNode("PolygonPatch",geometry,node);return node;},"PolygonPatch":function(geometry){var node=this.createElementNSPlus("gml:PolygonPatch",{attributes:{interpolation:"planar"}});this.writeNode("exterior",geometry.components[0],node);for(var i=1,len=geometry.components.length;i<len;++i){this.writeNode("interior",geometry.components[i],node);}
61595 return node;},"Polygon":function(geometry){var node=this.createElementNSPlus("gml:Polygon");this.writeNode("exterior",geometry.components[0],node);for(var i=1,len=geometry.components.length;i<len;++i){this.writeNode("interior",geometry.components[i],node);}
61596 return node;},"exterior":function(ring){var node=this.createElementNSPlus("gml:exterior");this.writeNode("LinearRing",ring,node);return node;},"interior":function(ring){var node=this.createElementNSPlus("gml:interior");this.writeNode("LinearRing",ring,node);return node;},"LinearRing":function(ring){var node=this.createElementNSPlus("gml:LinearRing");this.writeNode("posList",ring.components,node);return node;},"MultiCurve":function(geometry){var node=this.createElementNSPlus("gml:MultiCurve");for(var i=0,len=geometry.components.length;i<len;++i){this.writeNode("curveMember",geometry.components[i],node);}
61597 return node;},"curveMember":function(geometry){var node=this.createElementNSPlus("gml:curveMember");if(this.curve){this.writeNode("Curve",geometry,node);}else{this.writeNode("LineString",geometry,node);}
61598 return node;},"MultiSurface":function(geometry){var node=this.createElementNSPlus("gml:MultiSurface");for(var i=0,len=geometry.components.length;i<len;++i){this.writeNode("surfaceMember",geometry.components[i],node);}
61599 return node;},"surfaceMember":function(polygon){var node=this.createElementNSPlus("gml:surfaceMember");if(this.surface){this.writeNode("Surface",polygon,node);}else{this.writeNode("Polygon",polygon,node);}
61600 return node;},"Envelope":function(bounds){var node=this.createElementNSPlus("gml:Envelope");this.writeNode("lowerCorner",bounds,node);this.writeNode("upperCorner",bounds,node);if(this.srsName){node.setAttribute("srsName",this.srsName);}
61601 return node;},"lowerCorner":function(bounds){var pos=(this.xy)?(bounds.left+" "+bounds.bottom):(bounds.bottom+" "+bounds.left);return this.createElementNSPlus("gml:lowerCorner",{value:pos});},"upperCorner":function(bounds){var pos=(this.xy)?(bounds.right+" "+bounds.top):(bounds.top+" "+bounds.right);return this.createElementNSPlus("gml:upperCorner",{value:pos});}},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":(this.curve===true)?"Curve":"LineString","OpenLayers.Geometry.MultiLineString":(this.multiCurve===false)?"MultiLineString":"MultiCurve","OpenLayers.Geometry.Polygon":(this.surface===true)?"Surface":"Polygon","OpenLayers.Geometry.MultiPolygon":(this.multiSurface===false)?"MultiPolygon":"MultiSurface","OpenLayers.Geometry.Collection":"GeometryCollection"};},CLASS_NAME:"OpenLayers.Format.GML.v3"});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:false,initialize:function(options){OpenLayers.Format.XML.prototype.initialize.apply(this,[options]);},read:function(doc){if(typeof doc=="string"){doc=OpenLayers.Format.XML.prototype.read.apply(this,[doc]);}
61602 return this.parseFeatures(doc);},write:function(features){var doc;if(features instanceof Array){doc=this.createElementNSPlus("atom:feed");doc.appendChild(this.createElementNSPlus("atom:title",{value:this.feedTitle}));for(var i=0,ii=features.length;i<ii;i++){doc.appendChild(this.buildEntryNode(features[i]));}}
61603 else{doc=this.buildEntryNode(features);}
61604 return OpenLayers.Format.XML.prototype.write.apply(this,[doc]);},buildContentNode:function(content){var node=this.createElementNSPlus("atom:content",{attributes:{type:content.type||null}});if(content.src){node.setAttribute("src",content.src);}else{if(content.type=="text"||content.type==null){node.appendChild(this.createTextNode(content.value));}else if(content.type=="html"){if(typeof content.value!="string"){throw"HTML content must be in form of an escaped string";}
61605 node.appendChild(this.createTextNode(content.value));}else if(content.type=="xhtml"){node.appendChild(content.value);}else if(content.type=="xhtml"||content.type.match(/(\+|\/)xml$/)){node.appendChild(content.value);}
61606 else{node.appendChild(this.createTextNode(content.value));}}
61607 return node;},buildEntryNode:function(feature){var attrib=feature.attributes;var atomAttrib=attrib.atom||{};var entryNode=this.createElementNSPlus("atom:entry");if(atomAttrib.authors){var authors=atomAttrib.authors instanceof Array?atomAttrib.authors:[atomAttrib.authors];for(var i=0,ii=authors.length;i<ii;i++){entryNode.appendChild(this.buildPersonConstructNode("author",authors[i]));}}
61608 if(atomAttrib.categories){var categories=atomAttrib.categories instanceof Array?atomAttrib.categories:[atomAttrib.categories];var category;for(var i=0,ii=categories.length;i<ii;i++){category=categories[i];entryNode.appendChild(this.createElementNSPlus("atom:category",{attributes:{term:category.term,scheme:category.scheme||null,label:category.label||null}}));}}
61609 if(atomAttrib.content){entryNode.appendChild(this.buildContentNode(atomAttrib.content));}
61610 if(atomAttrib.contributors){var contributors=atomAttrib.contributors instanceof Array?atomAttrib.contributors:[atomAttrib.contributors];for(var i=0,ii=contributors.length;i<ii;i++){entryNode.appendChild(this.buildPersonConstructNode("contributor",contributors[i]));}}
61611 if(feature.fid){entryNode.appendChild(this.createElementNSPlus("atom:id",{value:feature.fid}));}
61612 if(atomAttrib.links){var links=atomAttrib.links instanceof Array?atomAttrib.links:[atomAttrib.links];var link;for(var i=0,ii=links.length;i<ii;i++){link=links[i];entryNode.appendChild(this.createElementNSPlus("atom:link",{attributes:{href:link.href,rel:link.rel||null,type:link.type||null,hreflang:link.hreflang||null,title:link.title||null,length:link.length||null}}));}}
61613 if(atomAttrib.published){entryNode.appendChild(this.createElementNSPlus("atom:published",{value:atomAttrib.published}));}
61614 if(atomAttrib.rights){entryNode.appendChild(this.createElementNSPlus("atom:rights",{value:atomAttrib.rights}));}
61615 if(atomAttrib.summary||attrib.description){entryNode.appendChild(this.createElementNSPlus("atom:summary",{value:atomAttrib.summary||attrib.description}));}
61616 entryNode.appendChild(this.createElementNSPlus("atom:title",{value:atomAttrib.title||attrib.title||this.defaultEntryTitle}));if(atomAttrib.updated){entryNode.appendChild(this.createElementNSPlus("atom:updated",{value:atomAttrib.updated}));}
61617 if(feature.geometry){var whereNode=this.createElementNSPlus("georss:where");whereNode.appendChild(this.buildGeometryNode(feature.geometry));entryNode.appendChild(whereNode);}
61618 return entryNode;},initGmlParser:function(){this.gmlParser=new OpenLayers.Format.GML.v3({xy:this.xy,featureNS:"http://example.com#feature",internalProjection:this.internalProjection,externalProjection:this.externalProjection});},buildGeometryNode:function(geometry){if(!this.gmlParser){this.initGmlParser();}
61619 var node=this.gmlParser.writeNode("feature:_geometry",geometry);return node.firstChild;},buildPersonConstructNode:function(name,value){var oNames=["uri","email"];var personNode=this.createElementNSPlus("atom:"+name);personNode.appendChild(this.createElementNSPlus("atom:name",{value:value.name}));for(var i=0,ii=oNames.length;i<ii;i++){if(value[oNames[i]]){personNode.appendChild(this.createElementNSPlus("atom:"+oNames[i],{value:value[oNames[i]]}));}}
61620 return personNode;},getFirstChildValue:function(node,nsuri,name,def){var value;var nodes=this.getElementsByTagNameNS(node,nsuri,name);if(nodes&&nodes.length>0){value=this.getChildValue(nodes[0],def);}else{value=def;}
61621 return value;},parseFeature:function(node){var atomAttrib={};var value=null;var nodes=null;var attval=null;var atomns=this.namespaces.atom;this.parsePersonConstructs(node,"author",atomAttrib);nodes=this.getElementsByTagNameNS(node,atomns,"category");if(nodes.length>0){atomAttrib.categories=[];}
61622 for(var i=0,ii=nodes.length;i<ii;i++){value={};value.term=nodes[i].getAttribute("term");attval=nodes[i].getAttribute("scheme");if(attval){value.scheme=attval;}
61623 attval=nodes[i].getAttribute("label");if(attval){value.label=attval;}
61624 atomAttrib.categories.push(value);}
61625 nodes=this.getElementsByTagNameNS(node,atomns,"content");if(nodes.length>0){value={};attval=nodes[0].getAttribute("type");if(attval){value.type=attval;}
61626 attval=nodes[0].getAttribute("src");if(attval){value.src=attval;}else{if(value.type=="text"||value.type=="html"||value.type==null){value.value=this.getFirstChildValue(node,atomns,"content",null);}else if(value.type=="xhtml"||value.type.match(/(\+|\/)xml$/)){value.value=this.getChildEl(nodes[0]);}else{value.value=this.getFirstChildValue(node,atomns,"content",null);}
61627 atomAttrib.content=value;}}
61628 this.parsePersonConstructs(node,"contributor",atomAttrib);atomAttrib.id=this.getFirstChildValue(node,atomns,"id",null);nodes=this.getElementsByTagNameNS(node,atomns,"link");if(nodes.length>0){atomAttrib.links=new Array(nodes.length);}
61629 var oAtts=["rel","type","hreflang","title","length"];for(var i=0,ii=nodes.length;i<ii;i++){value={};value.href=nodes[i].getAttribute("href");for(var j=0,jj=oAtts.length;j<jj;j++){attval=nodes[i].getAttribute(oAtts[j]);if(attval){value[oAtts[j]]=attval;}}
61630 atomAttrib.links[i]=value;}
61631 value=this.getFirstChildValue(node,atomns,"published",null);if(value){atomAttrib.published=value;}
61632 value=this.getFirstChildValue(node,atomns,"rights",null);if(value){atomAttrib.rights=value;}
61633 value=this.getFirstChildValue(node,atomns,"summary",null);if(value){atomAttrib.summary=value;}
61634 atomAttrib.title=this.getFirstChildValue(node,atomns,"title",null);atomAttrib.updated=this.getFirstChildValue(node,atomns,"updated",null);var featureAttrib={title:atomAttrib.title,description:atomAttrib.summary,atom:atomAttrib};var geometry=this.parseLocations(node)[0];var feature=new OpenLayers.Feature.Vector(geometry,featureAttrib);feature.fid=atomAttrib.id;return feature;},parseFeatures:function(node){var features=[];var entries=this.getElementsByTagNameNS(node,this.namespaces.atom,"entry");if(entries.length==0){entries=[node];}
61635 for(var i=0,ii=entries.length;i<ii;i++){features.push(this.parseFeature(entries[i]));}
61636 return features;},parseLocations:function(node){var georssns=this.namespaces.georss;var locations={components:[]};var where=this.getElementsByTagNameNS(node,georssns,"where");if(where&&where.length>0){if(!this.gmlParser){this.initGmlParser();}
61637 for(var i=0,ii=where.length;i<ii;i++){this.gmlParser.readChildNodes(where[i],locations);}}
61638 var components=locations.components;var point=this.getElementsByTagNameNS(node,georssns,"point");if(point&&point.length>0){for(var i=0,ii=point.length;i<ii;i++){var xy=OpenLayers.String.trim(point[i].firstChild.nodeValue).split(/\s+/);if(xy.length!=2){xy=OpenLayers.String.trim(point[i].firstChild.nodeValue).split(/\s*,\s*/);}
61639 components.push(new OpenLayers.Geometry.Point(parseFloat(xy[1]),parseFloat(xy[0])));}}
61640 var line=this.getElementsByTagNameNS(node,georssns,"line");if(line&&line.length>0){var coords;var p;var points;for(var i=0,ii=line.length;i<ii;i++){coords=OpenLayers.String.trim(line[i].firstChild.nodeValue).split(/\s+/);points=[];for(var j=0,jj=coords.length;j<jj;j+=2){p=new OpenLayers.Geometry.Point(parseFloat(coords[j+1]),parseFloat(coords[j]));points.push(p);}
61641 components.push(new OpenLayers.Geometry.LineString(points));}}
61642 var polygon=this.getElementsByTagNameNS(node,georssns,"polygon");if(polygon&&polygon.length>0){var coords;var p;var points;for(var i=0,ii=polygon.length;i<ii;i++){coords=OpenLayers.String.trim(polygon[i].firstChild.nodeValue).split(/\s+/);points=[];for(var j=0,jj=coords.length;j<jj;j+=2){p=new OpenLayers.Geometry.Point(parseFloat(coords[j+1]),parseFloat(coords[j]));points.push(p);}
61643 components.push(new OpenLayers.Geometry.Polygon([new OpenLayers.Geometry.LinearRing(components)]));}}
61644 if(this.internalProjection&&this.externalProjection){for(var i=0,ii=components.length;i<ii;i++){if(components[i]){components[i].transform(this.externalProjection,this.internalProjection);}}}
61645 return components;},parsePersonConstructs:function(node,name,data){var persons=[];var atomns=this.namespaces.atom;var nodes=this.getElementsByTagNameNS(node,atomns,name);var oAtts=["uri","email"];for(var i=0,ii=nodes.length;i<ii;i++){var value={};value.name=this.getFirstChildValue(nodes[i],atomns,"name",null);for(var j=0,jj=oAtts.length;j<jj;j++){var attval=this.getFirstChildValue(nodes[i],atomns,oAtts[j],null);if(attval){value[oAtts[j]]=attval;}}
61646 persons.push(value);}
61647 if(persons.length>0){data[name+"s"]=persons;}},CLASS_NAME:"OpenLayers.Format.Atom"});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(options){OpenLayers.Format.GML.v2.prototype.initialize.apply(this,[options]);},readers:{"ogc":OpenLayers.Util.applyDefaults({"PropertyIsEqualTo":function(node,obj){var filter=new OpenLayers.Filter.Comparison({type:OpenLayers.Filter.Comparison.EQUAL_TO});this.readChildNodes(node,filter);obj.filters.push(filter);},"PropertyIsNotEqualTo":function(node,obj){var filter=new OpenLayers.Filter.Comparison({type:OpenLayers.Filter.Comparison.NOT_EQUAL_TO});this.readChildNodes(node,filter);obj.filters.push(filter);},"PropertyIsLike":function(node,obj){var filter=new OpenLayers.Filter.Comparison({type:OpenLayers.Filter.Comparison.LIKE});this.readChildNodes(node,filter);var wildCard=node.getAttribute("wildCard");var singleChar=node.getAttribute("singleChar");var esc=node.getAttribute("escape");filter.value2regex(wildCard,singleChar,esc);obj.filters.push(filter);}},OpenLayers.Format.Filter.v1.prototype.readers["ogc"]),"gml":OpenLayers.Format.GML.v2.prototype.readers["gml"],"feature":OpenLayers.Format.GML.v2.prototype.readers["feature"]},writers:{"ogc":OpenLayers.Util.applyDefaults({"PropertyIsEqualTo":function(filter){var node=this.createElementNSPlus("ogc:PropertyIsEqualTo");this.writeNode("PropertyName",filter,node);this.writeNode("Literal",filter.value,node);return node;},"PropertyIsNotEqualTo":function(filter){var node=this.createElementNSPlus("ogc:PropertyIsNotEqualTo");this.writeNode("PropertyName",filter,node);this.writeNode("Literal",filter.value,node);return node;},"PropertyIsLike":function(filter){var node=this.createElementNSPlus("ogc:PropertyIsLike",{attributes:{wildCard:"*",singleChar:".",escape:"!"}});this.writeNode("PropertyName",filter,node);this.writeNode("Literal",filter.regex2value(),node);return node;},"BBOX":function(filter){var node=this.createElementNSPlus("ogc:BBOX");this.writeNode("PropertyName",filter,node);var box=this.writeNode("gml:Box",filter.value,node);if(filter.projection){box.setAttribute("srsName",filter.projection);}
61648 return node;}},OpenLayers.Format.Filter.v1.prototype.writers["ogc"]),"gml":OpenLayers.Format.GML.v2.prototype.writers["gml"],"feature":OpenLayers.Format.GML.v2.prototype.writers["feature"]},writeSpatial:function(filter,name){var node=this.createElementNSPlus("ogc:"+name);this.writeNode("PropertyName",filter,node);var child;if(filter.value instanceof OpenLayers.Geometry){child=this.writeNode("feature:_geometry",filter.value).firstChild;}else{child=this.writeNode("gml:Box",filter.value);}
61649 if(filter.projection){child.setAttribute("srsName",filter.projection);}
61650 node.appendChild(child);return node;},CLASS_NAME:"OpenLayers.Format.Filter.v1_0_0"});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(options){OpenLayers.Format.GML.v3.prototype.initialize.apply(this,[options]);},readers:{"ogc":OpenLayers.Util.applyDefaults({"PropertyIsEqualTo":function(node,obj){var matchCase=node.getAttribute("matchCase");var filter=new OpenLayers.Filter.Comparison({type:OpenLayers.Filter.Comparison.EQUAL_TO,matchCase:!(matchCase==="false"||matchCase==="0")});this.readChildNodes(node,filter);obj.filters.push(filter);},"PropertyIsNotEqualTo":function(node,obj){var matchCase=node.getAttribute("matchCase");var filter=new OpenLayers.Filter.Comparison({type:OpenLayers.Filter.Comparison.NOT_EQUAL_TO,matchCase:!(matchCase==="false"||matchCase==="0")});this.readChildNodes(node,filter);obj.filters.push(filter);},"PropertyIsLike":function(node,obj){var filter=new OpenLayers.Filter.Comparison({type:OpenLayers.Filter.Comparison.LIKE});this.readChildNodes(node,filter);var wildCard=node.getAttribute("wildCard");var singleChar=node.getAttribute("singleChar");var esc=node.getAttribute("escapeChar");filter.value2regex(wildCard,singleChar,esc);obj.filters.push(filter);}},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(filter){var node=this.createElementNSPlus("ogc:PropertyIsEqualTo",{attributes:{matchCase:filter.matchCase}});this.writeNode("PropertyName",filter,node);this.writeNode("Literal",filter.value,node);return node;},"PropertyIsNotEqualTo":function(filter){var node=this.createElementNSPlus("ogc:PropertyIsNotEqualTo",{attributes:{matchCase:filter.matchCase}});this.writeNode("PropertyName",filter,node);this.writeNode("Literal",filter.value,node);return node;},"PropertyIsLike":function(filter){var node=this.createElementNSPlus("ogc:PropertyIsLike",{attributes:{wildCard:"*",singleChar:".",escapeChar:"!"}});this.writeNode("PropertyName",filter,node);this.writeNode("Literal",filter.regex2value(),node);return node;},"BBOX":function(filter){var node=this.createElementNSPlus("ogc:BBOX");this.writeNode("PropertyName",filter,node);var box=this.writeNode("gml:Envelope",filter.value);if(filter.projection){box.setAttribute("srsName",filter.projection);}
61651 node.appendChild(box);return node;}},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(filter,name){var node=this.createElementNSPlus("ogc:"+name);this.writeNode("PropertyName",filter,node);var child;if(filter.value instanceof OpenLayers.Geometry){child=this.writeNode("feature:_geometry",filter.value).firstChild;}else{child=this.writeNode("gml:Envelope",filter.value);}
61652 if(filter.projection){child.setAttribute("srsName",filter.projection);}
61653 node.appendChild(child);return node;},CLASS_NAME:"OpenLayers.Format.Filter.v1_1_0"});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(options){OpenLayers.Format.XML.prototype.initialize.apply(this,[options]);this.options=options;},read:function(data){if(typeof data=="string"){data=OpenLayers.Format.XML.prototype.read.apply(this,[data]);}
61654 if(data&&data.nodeType==9){data=data.documentElement;}
61655 var capabilities={};this.readNode(data,capabilities);return capabilities;},readers:{"gml":OpenLayers.Util.applyDefaults({"name":function(node,obj){obj.name=this.getChildValue(node);},"TimePeriod":function(node,obj){obj.timePeriod={};this.readChildNodes(node,obj.timePeriod);},"beginPosition":function(node,timePeriod){timePeriod.beginPosition=this.getChildValue(node);},"endPosition":function(node,timePeriod){timePeriod.endPosition=this.getChildValue(node);}},OpenLayers.Format.GML.v3.prototype.readers["gml"]),"sos":{"Capabilities":function(node,obj){this.readChildNodes(node,obj);},"Contents":function(node,obj){obj.contents={};this.readChildNodes(node,obj.contents);},"ObservationOfferingList":function(node,contents){contents.offeringList={};this.readChildNodes(node,contents.offeringList);},"ObservationOffering":function(node,offeringList){var id=this.getAttributeNS(node,this.namespaces.gml,"id");offeringList[id]={procedures:[],observedProperties:[],featureOfInterestIds:[],responseFormats:[],resultModels:[],responseModes:[]};this.readChildNodes(node,offeringList[id]);},"time":function(node,offering){offering.time={};this.readChildNodes(node,offering.time);},"procedure":function(node,offering){offering.procedures.push(this.getAttributeNS(node,this.namespaces.xlink,"href"));},"observedProperty":function(node,offering){offering.observedProperties.push(this.getAttributeNS(node,this.namespaces.xlink,"href"));},"featureOfInterest":function(node,offering){offering.featureOfInterestIds.push(this.getAttributeNS(node,this.namespaces.xlink,"href"));},"responseFormat":function(node,offering){offering.responseFormats.push(this.getChildValue(node));},"resultModel":function(node,offering){offering.resultModels.push(this.getChildValue(node));},"responseMode":function(node,offering){offering.responseModes.push(this.getChildValue(node));;}},"ows":OpenLayers.Format.OWSCommon.v1_1_0.prototype.readers["ows"]},CLASS_NAME:"OpenLayers.Format.SOSCapabilities.v1_0_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)},initialize:function(options){OpenLayers.Format.XML.prototype.initialize.apply(this,[options]);},read:function(data){if(typeof data=="string"){data=OpenLayers.Format.XML.prototype.read.apply(this,[data]);}
61656 if(data&&data.nodeType==9){data=data.documentElement;}
61657 var info={features:[]};this.readNode(data,info);var features=[];for(var i=0,len=info.features.length;i<len;i++){var container=info.features[i];if(this.internalProjection&&this.externalProjection&&container.components[0]){container.components[0].transform(this.externalProjection,this.internalProjection);}
61658 var feature=new OpenLayers.Feature.Vector(container.components[0],container.attributes);features.push(feature);}
61659 return features;},readers:{"sa":{"SamplingPoint":function(node,obj){if(!obj.attributes){var feature={attributes:{}};obj.features.push(feature);obj=feature;}
61660 obj.attributes.id=this.getAttributeNS(node,this.namespaces.gml,"id");this.readChildNodes(node,obj);},"position":function(node,obj){this.readChildNodes(node,obj);}},"gml":OpenLayers.Util.applyDefaults({"FeatureCollection":function(node,obj){this.readChildNodes(node,obj);},"featureMember":function(node,obj){var feature={attributes:{}};obj.features.push(feature);this.readChildNodes(node,feature);},"name":function(node,obj){obj.attributes.name=this.getChildValue(node);},"pos":function(node,obj){if(!this.externalProjection){this.externalProjection=new OpenLayers.Projection(node.getAttribute("srsName"));}
61661 OpenLayers.Format.GML.v3.prototype.readers.gml.pos.apply(this,[node,obj]);}},OpenLayers.Format.GML.v3.prototype.readers.gml)},writers:{"sos":{"GetFeatureOfInterest":function(options){var node=this.createElementNSPlus("GetFeatureOfInterest",{attributes:{version:this.VERSION,service:'SOS',"xsi:schemaLocation":this.schemaLocation}});for(var i=0,len=options.fois.length;i<len;i++){this.writeNode("FeatureOfInterestId",{foi:options.fois[i]},node);}
61662 return node;},"FeatureOfInterestId":function(options){var node=this.createElementNSPlus("FeatureOfInterestId",{value:options.foi});return node;}}},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",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",defaultPrefix:"sos",initialize:function(options){OpenLayers.Format.XML.prototype.initialize.apply(this,[options]);},read:function(data){if(typeof data=="string"){data=OpenLayers.Format.XML.prototype.read.apply(this,[data]);}
61663 if(data&&data.nodeType==9){data=data.documentElement;}
61664 var info={measurements:[]};this.readNode(data,info);return info;},write:function(options){var node=this.writeNode("sos:GetObservation",options);node.setAttribute("xmlns:om",this.namespaces.om);this.setAttributeNS(node,this.namespaces.xsi,"xsi:schemaLocation",this.schemaLocation);return OpenLayers.Format.XML.prototype.write.apply(this,[node]);},readers:{"om":{"ObservationCollection":function(node,obj){obj.id=this.getAttributeNS(node,this.namespaces.gml,"id");this.readChildNodes(node,obj);},"member":function(node,observationCollection){this.readChildNodes(node,observationCollection);},"Measurement":function(node,observationCollection){var measurement={};observationCollection.measurements.push(measurement);this.readChildNodes(node,measurement);},"samplingTime":function(node,measurement){var samplingTime={};measurement.samplingTime=samplingTime;this.readChildNodes(node,samplingTime);},"observedProperty":function(node,measurement){measurement.observedProperty=this.getAttributeNS(node,this.namespaces.xlink,"href");this.readChildNodes(node,measurement);},"procedure":function(node,measurement){measurement.procedure=this.getAttributeNS(node,this.namespaces.xlink,"href");this.readChildNodes(node,measurement);},"result":function(node,measurement){var result={};measurement.result=result;if(this.getChildValue(node)!==''){result.value=this.getChildValue(node);result.uom=node.getAttribute("uom");}else{this.readChildNodes(node,result);}}},"gml":OpenLayers.Util.applyDefaults({"TimeInstant":function(node,samplingTime){var timeInstant={};samplingTime.timeInstant=timeInstant;this.readChildNodes(node,timeInstant);},"timePosition":function(node,timeInstant){timeInstant.timePosition=this.getChildValue(node);}},OpenLayers.Format.GML.v3.prototype.readers.gml)},writers:{"sos":{"GetObservation":function(options){var node=this.createElementNSPlus("GetObservation",{attributes:{version:this.VERSION,service:'SOS'}});this.writeNode("offering",options,node);this.writeNode("eventTime",options,node);this.writeNode("procedure",options,node);this.writeNode("observedProperty",options,node);this.writeNode("responseFormat",options,node);this.writeNode("resultModel",options,node);this.writeNode("responseMode",options,node);return node;},"responseFormat":function(options){return this.createElementNSPlus("responseFormat",{value:options.responseFormat});},"procedure":function(options){return this.createElementNSPlus("procedure",{value:options.procedure});},"offering":function(options){return this.createElementNSPlus("offering",{value:options.offering});},"observedProperty":function(options){return this.createElementNSPlus("observedProperty",{value:options.observedProperty});},"eventTime":function(options){var node=this.createElementNSPlus("eventTime");if(options.eventTime==='latest'){this.writeNode("ogc:TM_Equals",options,node);}
61665 return node;},"resultModel":function(options){return this.createElementNSPlus("resultModel",{value:options.resultModel});},"responseMode":function(options){return this.createElementNSPlus("responseMode",{value:options.responseMode});}},"ogc":{"TM_Equals":function(options){var node=this.createElementNSPlus("ogc:TM_Equals");this.writeNode("ogc:PropertyName",{property:"urn:ogc:data:time:iso8601"},node);if(options.eventTime==='latest'){this.writeNode("gml:TimeInstant",{value:'latest'},node);}
61666 return node;},"PropertyName":function(options){return this.createElementNSPlus("ogc:PropertyName",{value:options.property});}},"gml":{"TimeInstant":function(options){var node=this.createElementNSPlus("gml:TimeInstant");this.writeNode("gml:timePosition",options,node);return node;},"timePosition":function(options){var node=this.createElementNSPlus("gml:timePosition",{value:options.value});return node;}}},CLASS_NAME:"OpenLayers.Format.SOSGetObservation"});OpenLayers.Format.CSWGetRecords.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",dc:"http://purl.org/dc/elements/1.1/",dct:"http://purl.org/dc/terms/",ows:"http://www.opengis.net/ows"},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",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(options){OpenLayers.Format.XML.prototype.initialize.apply(this,[options]);},read:function(data){if(typeof data=="string"){data=OpenLayers.Format.XML.prototype.read.apply(this,[data]);}
61667 if(data&&data.nodeType==9){data=data.documentElement;}
61668 var obj={};this.readNode(data,obj);return obj;},readers:{"csw":{"GetRecordsResponse":function(node,obj){obj.records=[];this.readChildNodes(node,obj);var version=this.getAttributeNS(node,"",'version');if(version!=""){obj.version=version;}},"RequestId":function(node,obj){obj.RequestId=this.getChildValue(node);},"SearchStatus":function(node,obj){obj.SearchStatus={};var timestamp=this.getAttributeNS(node,"",'timestamp');if(timestamp!=""){obj.SearchStatus.timestamp=timestamp;}},"SearchResults":function(node,obj){this.readChildNodes(node,obj);var attrs=node.attributes;var SearchResults={};for(var i=0,len=attrs.length;i<len;++i){if((attrs[i].name=="numberOfRecordsMatched")||(attrs[i].name=="numberOfRecordsReturned")||(attrs[i].name=="nextRecord")){SearchResults[attrs[i].name]=parseInt(attrs[i].nodeValue);}else{SearchResults[attrs[i].name]=attrs[i].nodeValue;}}
61669 obj.SearchResults=SearchResults;},"SummaryRecord":function(node,obj){var record={type:"SummaryRecord"};this.readChildNodes(node,record);obj.records.push(record);},"BriefRecord":function(node,obj){var record={type:"BriefRecord"};this.readChildNodes(node,record);obj.records.push(record);},"DCMIRecord":function(node,obj){var record={type:"DCMIRecord"};this.readChildNodes(node,record);obj.records.push(record);},"Record":function(node,obj){var record={type:"Record"};this.readChildNodes(node,record);obj.records.push(record);}},"dc":{"*":function(node,obj){var name=node.localName||node.nodeName.split(":").pop();if(!(obj[name]instanceof Array)){obj[name]=new Array();}
61670 var dc_element={};var attrs=node.attributes;for(var i=0,len=attrs.length;i<len;++i){dc_element[attrs[i].name]=attrs[i].nodeValue;}
61671 dc_element.value=this.getChildValue(node);obj[name].push(dc_element);}},"dct":{"*":function(node,obj){var name=node.localName||node.nodeName.split(":").pop();if(!(obj[name]instanceof Array)){obj[name]=new Array();}
61672 obj[name].push(this.getChildValue(node));}},"ows":OpenLayers.Util.applyDefaults({"BoundingBox":function(node,obj){if(obj.bounds){obj.BoundingBox=[{crs:obj.projection,value:[obj.bounds.left,obj.bounds.bottom,obj.bounds.right,obj.bounds.top]}];delete obj.projection;delete obj.bounds;}
61673 OpenLayers.Format.OWSCommon.v1_0_0.prototype.readers["ows"]["BoundingBox"].apply(this,arguments);}},OpenLayers.Format.OWSCommon.v1_0_0.prototype.readers["ows"])},write:function(options){var node=this.writeNode("csw:GetRecords",options);return OpenLayers.Format.XML.prototype.write.apply(this,[node]);},writers:{"csw":{"GetRecords":function(options){if(!options){options={};}
61674 var node=this.createElementNSPlus("csw:GetRecords",{attributes:{service:"CSW",version:this.version,requestId:options.requestId||this.requestId,resultType:options.resultType||this.resultType,outputFormat:options.outputFormat||this.outputFormat,outputSchema:options.outputSchema||this.outputSchema,startPosition:options.startPosition||this.startPosition,maxRecords:options.maxRecords||this.maxRecords}});if(options.DistributedSearch||this.DistributedSearch){this.writeNode("csw:DistributedSearch",options.DistributedSearch||this.DistributedSearch,node);}
61675 var ResponseHandler=options.ResponseHandler||this.ResponseHandler;if(ResponseHandler instanceof Array&&ResponseHandler.length>0){for(var i=0,len=ResponseHandler.length;i<len;i++){this.writeNode("csw:ResponseHandler",ResponseHandler[i],node);}}
61676 this.writeNode("Query",options.Query||this.Query,node);return node;},"DistributedSearch":function(options){var node=this.createElementNSPlus("csw:DistributedSearch",{attributes:{hopCount:options.hopCount}});return node;},"ResponseHandler":function(options){var node=this.createElementNSPlus("csw:ResponseHandler",{value:options.value});return node;},"Query":function(options){if(!options){options={};}
61677 var node=this.createElementNSPlus("csw:Query",{attributes:{typeNames:options.typeNames||"csw:Record"}});var ElementName=options.ElementName;if(ElementName instanceof Array&&ElementName.length>0){for(var i=0,len=ElementName.length;i<len;i++){this.writeNode("csw:ElementName",ElementName[i],node);}}else{this.writeNode("csw:ElementSetName",options.ElementSetName||{value:'summary'},node);}
61678 if(options.Constraint){this.writeNode("csw:Constraint",options.Constraint,node);}
61679 return node;},"ElementName":function(options){var node=this.createElementNSPlus("csw:ElementName",{value:options.value});return node;},"ElementSetName":function(options){var node=this.createElementNSPlus("csw:ElementSetName",{attributes:{typeNames:options.typeNames},value:options.value});return node;},"Constraint":function(options){var node=this.createElementNSPlus("csw:Constraint",{attributes:{version:options.version}});if(options.Filter){var format=new OpenLayers.Format.Filter({version:options.version});node.appendChild(format.write(options.Filter));}else if(options.CqlText){var child=this.createElementNSPlus("CqlText",{value:options.CqlText.value});node.appendChild(child);}
61680 return node;}}},CLASS_NAME:"OpenLayers.Format.CSWGetRecords.v2_0_2"});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:false,featureTypeCounter:null,defaultSymbolizer:{fillColor:"#808080",fillOpacity:1,strokeColor:"#000000",strokeOpacity:1,strokeWidth:1,strokeDashstyle:"solid",pointRadius:3,graphicName:"square"},initialize:function(options){OpenLayers.Format.Filter.v1_0_0.prototype.initialize.apply(this,[options]);},read:function(data,options){options=OpenLayers.Util.applyDefaults(options,this.options);var sld={namedLayers:options.namedLayersAsArray===true?[]:{}};this.readChildNodes(data,sld);return sld;},readers:OpenLayers.Util.applyDefaults({"sld":{"StyledLayerDescriptor":function(node,sld){sld.version=node.getAttribute("version");this.readChildNodes(node,sld);},"Name":function(node,obj){obj.name=this.getChildValue(node);},"Title":function(node,obj){obj.title=this.getChildValue(node);},"Abstract":function(node,obj){obj.description=this.getChildValue(node);},"NamedLayer":function(node,sld){var layer={userStyles:[],namedStyles:[]};this.readChildNodes(node,layer);for(var i=0,len=layer.userStyles.length;i<len;++i){layer.userStyles[i].layerName=layer.name;}
61681 if(sld.namedLayers instanceof Array){sld.namedLayers.push(layer);}else{sld.namedLayers[layer.name]=layer;}},"NamedStyle":function(node,layer){layer.namedStyles.push(this.getChildName(node.firstChild));},"UserStyle":function(node,layer){var obj={defaultsPerSymbolizer:true,rules:[]};this.featureTypeCounter=-1;this.readChildNodes(node,obj);var style;if(this.multipleSymbolizers){delete obj.defaultsPerSymbolizer;style=new OpenLayers.Style2(obj);}else{style=new OpenLayers.Style(this.defaultSymbolizer,obj);}
61682 layer.userStyles.push(style);},"IsDefault":function(node,style){if(this.getChildValue(node)=="1"){style.isDefault=true;}},"FeatureTypeStyle":function(node,style){++this.featureTypeCounter;var obj={rules:this.multipleSymbolizers?style.rules:[]};this.readChildNodes(node,obj);if(!this.multipleSymbolizers){style.rules=obj.rules;}},"Rule":function(node,obj){var config;if(this.multipleSymbolizers){config={symbolizers:[]};}
61683 var rule=new OpenLayers.Rule(config);this.readChildNodes(node,rule);obj.rules.push(rule);},"ElseFilter":function(node,rule){rule.elseFilter=true;},"MinScaleDenominator":function(node,rule){rule.minScaleDenominator=parseFloat(this.getChildValue(node));},"MaxScaleDenominator":function(node,rule){rule.maxScaleDenominator=parseFloat(this.getChildValue(node));},"TextSymbolizer":function(node,rule){var config={};this.readChildNodes(node,config);if(this.multipleSymbolizers){config.zIndex=this.featureTypeCounter;rule.symbolizers.push(new OpenLayers.Symbolizer.Text(config));}else{rule.symbolizer["Text"]=OpenLayers.Util.applyDefaults(config,rule.symbolizer["Text"]);}},"Label":function(node,symbolizer){var obj={};this.readChildNodes(node,obj);if(obj.property){symbolizer.label="${"+obj.property+"}";}else{var value=this.readOgcExpression(node);if(value){symbolizer.label=value;}}},"Font":function(node,symbolizer){this.readChildNodes(node,symbolizer);},"Halo":function(node,symbolizer){var obj={};this.readChildNodes(node,obj);symbolizer.haloRadius=obj.haloRadius;symbolizer.haloColor=obj.fillColor;symbolizer.haloOpacity=obj.fillOpacity;},"Radius":function(node,symbolizer){var radius=this.readOgcExpression(node);if(radius!=null){symbolizer.haloRadius=radius;}},"RasterSymbolizer":function(node,rule){var config={};this.readChildNodes(node,config);if(this.multipleSymbolizers){config.zIndex=this.featureTypeCounter;rule.symbolizers.push(new OpenLayers.Symbolizer.Raster(config));}else{rule.symbolizer["Raster"]=OpenLayers.Util.applyDefaults(config,rule.symbolizer["Raster"]);}},"Geometry":function(node,obj){obj.geometry={};this.readChildNodes(node,obj.geometry);},"ColorMap":function(node,symbolizer){symbolizer.colorMap=[];this.readChildNodes(node,symbolizer.colorMap);},"ColorMapEntry":function(node,colorMap){var q=node.getAttribute("quantity");var o=node.getAttribute("opacity");colorMap.push({color:node.getAttribute("color"),quantity:q!==null?parseFloat(q):undefined,label:node.getAttribute("label")||undefined,opacity:o!==null?parseFloat(o):undefined});},"LineSymbolizer":function(node,rule){var config={};this.readChildNodes(node,config);if(this.multipleSymbolizers){config.zIndex=this.featureTypeCounter;rule.symbolizers.push(new OpenLayers.Symbolizer.Line(config));}else{rule.symbolizer["Line"]=OpenLayers.Util.applyDefaults(config,rule.symbolizer["Line"]);}},"PolygonSymbolizer":function(node,rule){var config={fill:false,stroke:false};if(!this.multipleSymbolizers){config=rule.symbolizer["Polygon"]||config;}
61684 this.readChildNodes(node,config);if(this.multipleSymbolizers){config.zIndex=this.featureTypeCounter;rule.symbolizers.push(new OpenLayers.Symbolizer.Polygon(config));}else{rule.symbolizer["Polygon"]=config;}},"PointSymbolizer":function(node,rule){var config={fill:false,stroke:false,graphic:false};if(!this.multipleSymbolizers){config=rule.symbolizer["Point"]||config;}
61685 this.readChildNodes(node,config);if(this.multipleSymbolizers){config.zIndex=this.featureTypeCounter;rule.symbolizers.push(new OpenLayers.Symbolizer.Point(config));}else{rule.symbolizer["Point"]=config;}},"Stroke":function(node,symbolizer){symbolizer.stroke=true;this.readChildNodes(node,symbolizer);},"Fill":function(node,symbolizer){symbolizer.fill=true;this.readChildNodes(node,symbolizer);},"CssParameter":function(node,symbolizer){var cssProperty=node.getAttribute("name");var symProperty=this.cssMap[cssProperty];if(symProperty){var value=this.readOgcExpression(node);if(value){symbolizer[symProperty]=value;}}},"Graphic":function(node,symbolizer){symbolizer.graphic=true;var graphic={};this.readChildNodes(node,graphic);var properties=["stroke","strokeColor","strokeWidth","strokeOpacity","strokeLinecap","fill","fillColor","fillOpacity","graphicName","rotation","graphicFormat"];var prop,value;for(var i=0,len=properties.length;i<len;++i){prop=properties[i];value=graphic[prop];if(value!=undefined){symbolizer[prop]=value;}}
61686 if(graphic.opacity!=undefined){symbolizer.graphicOpacity=graphic.opacity;}
61687 if(graphic.size!=undefined){symbolizer.pointRadius=graphic.size/2;}
61688 if(graphic.href!=undefined){symbolizer.externalGraphic=graphic.href;}
61689 if(graphic.rotation!=undefined){symbolizer.rotation=graphic.rotation;}},"ExternalGraphic":function(node,graphic){this.readChildNodes(node,graphic);},"Mark":function(node,graphic){this.readChildNodes(node,graphic);},"WellKnownName":function(node,graphic){graphic.graphicName=this.getChildValue(node);},"Opacity":function(node,obj){var opacity=this.readOgcExpression(node);if(opacity){obj.opacity=opacity;}},"Size":function(node,obj){var size=this.readOgcExpression(node);if(size){obj.size=size;}},"Rotation":function(node,obj){var rotation=this.readOgcExpression(node);if(rotation){obj.rotation=rotation;}},"OnlineResource":function(node,obj){obj.href=this.getAttributeNS(node,this.namespaces.xlink,"href");},"Format":function(node,graphic){graphic.graphicFormat=this.getChildValue(node);}}},OpenLayers.Format.Filter.v1_0_0.prototype.readers),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(sym){var css=null;for(var prop in this.cssMap){if(this.cssMap[prop]==sym){css=prop;break;}}
61690 return css;},getGraphicFormat:function(href){var format,regex;for(var key in this.graphicFormats){if(this.graphicFormats[key].test(href)){format=key;break;}}
61691 return format||this.defautlGraphicFormat;},defaultGraphicFormat:"image/png",graphicFormats:{"image/jpeg":/\.jpe?g$/i,"image/gif":/\.gif$/i,"image/png":/\.png$/i},write:function(sld){return this.writers.sld.StyledLayerDescriptor.apply(this,[sld]);},writers:OpenLayers.Util.applyDefaults({"sld":{"StyledLayerDescriptor":function(sld){var root=this.createElementNSPlus("sld:StyledLayerDescriptor",{attributes:{"version":this.VERSION,"xsi:schemaLocation":this.schemaLocation}});root.setAttribute("xmlns:ogc",this.namespaces.ogc);root.setAttribute("xmlns:gml",this.namespaces.gml);if(sld.name){this.writeNode("Name",sld.name,root);}
61692 if(sld.title){this.writeNode("Title",sld.title,root);}
61693 if(sld.description){this.writeNode("Abstract",sld.description,root);}
61694 if(sld.namedLayers instanceof Array){for(var i=0,len=sld.namedLayers.length;i<len;++i){this.writeNode("NamedLayer",sld.namedLayers[i],root);}}else{for(var name in sld.namedLayers){this.writeNode("NamedLayer",sld.namedLayers[name],root);}}
61695 return root;},"Name":function(name){return this.createElementNSPlus("sld:Name",{value:name});},"Title":function(title){return this.createElementNSPlus("sld:Title",{value:title});},"Abstract":function(description){return this.createElementNSPlus("sld:Abstract",{value:description});},"NamedLayer":function(layer){var node=this.createElementNSPlus("sld:NamedLayer");this.writeNode("Name",layer.name,node);if(layer.namedStyles){for(var i=0,len=layer.namedStyles.length;i<len;++i){this.writeNode("NamedStyle",layer.namedStyles[i],node);}}
61696 if(layer.userStyles){for(var i=0,len=layer.userStyles.length;i<len;++i){this.writeNode("UserStyle",layer.userStyles[i],node);}}
61697 return node;},"NamedStyle":function(name){var node=this.createElementNSPlus("sld:NamedStyle");this.writeNode("Name",name,node);return node;},"UserStyle":function(style){var node=this.createElementNSPlus("sld:UserStyle");if(style.name){this.writeNode("Name",style.name,node);}
61698 if(style.title){this.writeNode("Title",style.title,node);}
61699 if(style.description){this.writeNode("Abstract",style.description,node);}
61700 if(style.isDefault){this.writeNode("IsDefault",style.isDefault,node);}
61701 if(this.multipleSymbolizers&&style.rules){var rulesByZ={0:[]};var zValues=[0];var rule,ruleMap,symbolizer,zIndex,clone;for(var i=0,ii=style.rules.length;i<ii;++i){rule=style.rules[i];if(rule.symbolizers){ruleMap={};for(var j=0,jj=rule.symbolizers.length;j<jj;++j){symbolizer=rule.symbolizers[j];zIndex=symbolizer.zIndex;if(!(zIndex in ruleMap)){clone=rule.clone();clone.symbolizers=[];ruleMap[zIndex]=clone;}
61702 ruleMap[zIndex].symbolizers.push(symbolizer.clone());}
61703 for(zIndex in ruleMap){if(!(zIndex in rulesByZ)){zValues.push(zIndex);rulesByZ[zIndex]=[];}
61704 rulesByZ[zIndex].push(ruleMap[zIndex]);}}else{rulesByZ[0].push(rule.clone());}}
61705 zValues.sort();var rules;for(var i=0,ii=zValues.length;i<ii;++i){rules=rulesByZ[zValues[i]];if(rules.length>0){clone=style.clone();clone.rules=rulesByZ[zValues[i]];this.writeNode("FeatureTypeStyle",clone,node);}}}else{this.writeNode("FeatureTypeStyle",style,node);}
61706 return node;},"IsDefault":function(bool){return this.createElementNSPlus("sld:IsDefault",{value:(bool)?"1":"0"});},"FeatureTypeStyle":function(style){var node=this.createElementNSPlus("sld:FeatureTypeStyle");for(var i=0,len=style.rules.length;i<len;++i){this.writeNode("Rule",style.rules[i],node);}
61707 return node;},"Rule":function(rule){var node=this.createElementNSPlus("sld:Rule");if(rule.name){this.writeNode("Name",rule.name,node);}
61708 if(rule.title){this.writeNode("Title",rule.title,node);}
61709 if(rule.description){this.writeNode("Abstract",rule.description,node);}
61710 if(rule.elseFilter){this.writeNode("ElseFilter",null,node);}else if(rule.filter){this.writeNode("ogc:Filter",rule.filter,node);}
61711 if(rule.minScaleDenominator!=undefined){this.writeNode("MinScaleDenominator",rule.minScaleDenominator,node);}
61712 if(rule.maxScaleDenominator!=undefined){this.writeNode("MaxScaleDenominator",rule.maxScaleDenominator,node);}
61713 var type,symbolizer;if(this.multipleSymbolizers&&rule.symbolizers){var symbolizer;for(var i=0,ii=rule.symbolizers.length;i<ii;++i){symbolizer=rule.symbolizers[i];type=symbolizer.CLASS_NAME.split(".").pop();this.writeNode(type+"Symbolizer",symbolizer,node);}}else{var types=OpenLayers.Style.SYMBOLIZER_PREFIXES;for(var i=0,len=types.length;i<len;++i){type=types[i];symbolizer=rule.symbolizer[type];if(symbolizer){this.writeNode(type+"Symbolizer",symbolizer,node);}}}
61714 return node;},"ElseFilter":function(){return this.createElementNSPlus("sld:ElseFilter");},"MinScaleDenominator":function(scale){return this.createElementNSPlus("sld:MinScaleDenominator",{value:scale});},"MaxScaleDenominator":function(scale){return this.createElementNSPlus("sld:MaxScaleDenominator",{value:scale});},"LineSymbolizer":function(symbolizer){var node=this.createElementNSPlus("sld:LineSymbolizer");this.writeNode("Stroke",symbolizer,node);return node;},"Stroke":function(symbolizer){var node=this.createElementNSPlus("sld:Stroke");if(symbolizer.strokeColor!=undefined){this.writeNode("CssParameter",{symbolizer:symbolizer,key:"strokeColor"},node);}
61715 if(symbolizer.strokeOpacity!=undefined){this.writeNode("CssParameter",{symbolizer:symbolizer,key:"strokeOpacity"},node);}
61716 if(symbolizer.strokeWidth!=undefined){this.writeNode("CssParameter",{symbolizer:symbolizer,key:"strokeWidth"},node);}
61717 if(symbolizer.strokeDashstyle!=undefined&&symbolizer.strokeDashstyle!=="solid"){this.writeNode("CssParameter",{symbolizer:symbolizer,key:"strokeDashstyle"},node);}
61718 if(symbolizer.strokeLinecap!=undefined){this.writeNode("CssParameter",{symbolizer:symbolizer,key:"strokeLinecap"},node);}
61719 return node;},"CssParameter":function(obj){return this.createElementNSPlus("sld:CssParameter",{attributes:{name:this.getCssProperty(obj.key)},value:obj.symbolizer[obj.key]});},"TextSymbolizer":function(symbolizer){var node=this.createElementNSPlus("sld:TextSymbolizer");if(symbolizer.label!=null){this.writeNode("Label",symbolizer.label,node);}
61720 if(symbolizer.fontFamily!=null||symbolizer.fontSize!=null||symbolizer.fontWeight!=null||symbolizer.fontStyle!=null){this.writeNode("Font",symbolizer,node);}
61721 if(symbolizer.haloRadius!=null||symbolizer.haloColor!=null||symbolizer.haloOpacity!=null){this.writeNode("Halo",symbolizer,node);}
61722 if(symbolizer.fillColor!=null||symbolizer.fillOpacity!=null){this.writeNode("Fill",symbolizer,node);}
61723 return node;},"Font":function(symbolizer){var node=this.createElementNSPlus("sld:Font");if(symbolizer.fontFamily){this.writeNode("CssParameter",{symbolizer:symbolizer,key:"fontFamily"},node);}
61724 if(symbolizer.fontSize){this.writeNode("CssParameter",{symbolizer:symbolizer,key:"fontSize"},node);}
61725 if(symbolizer.fontWeight){this.writeNode("CssParameter",{symbolizer:symbolizer,key:"fontWeight"},node);}
61726 if(symbolizer.fontStyle){this.writeNode("CssParameter",{symbolizer:symbolizer,key:"fontStyle"},node);}
61727 return node;},"Label":function(label){var node=this.createElementNSPlus("sld:Label");var tokens=label.split("${");node.appendChild(this.createTextNode(tokens[0]));var item,last;for(var i=1,len=tokens.length;i<len;i++){item=tokens[i];last=item.indexOf("}");if(last>0){this.writeNode("ogc:PropertyName",{property:item.substring(0,last)},node);node.appendChild(this.createTextNode(item.substring(++last)));}else{node.appendChild(this.createTextNode("${"+item));}}
61728 return node;},"Halo":function(symbolizer){var node=this.createElementNSPlus("sld:Halo");if(symbolizer.haloRadius){this.writeNode("Radius",symbolizer.haloRadius,node);}
61729 if(symbolizer.haloColor||symbolizer.haloOpacity){this.writeNode("Fill",{fillColor:symbolizer.haloColor,fillOpacity:symbolizer.haloOpacity},node);}
61730 return node;},"Radius":function(value){return this.createElementNSPlus("sld:Radius",{value:value});},"RasterSymbolizer":function(symbolizer){var node=this.createElementNSPlus("sld:RasterSymbolizer");if(symbolizer.geometry){this.writeNode("Geometry",symbolizer.geometry,node);}
61731 if(symbolizer.opacity){this.writeNode("Opacity",symbolizer.opacity,node);}
61732 if(symbolizer.colorMap){this.writeNode("ColorMap",symbolizer.colorMap,node);}
61733 return node;},"Geometry":function(geometry){var node=this.createElementNSPlus("sld:Geometry");if(geometry.property){this.writeNode("ogc:PropertyName",geometry,node);}
61734 return node;},"ColorMap":function(colorMap){var node=this.createElementNSPlus("sld:ColorMap");for(var i=0,len=colorMap.length;i<len;++i){this.writeNode("ColorMapEntry",colorMap[i],node);}
61735 return node;},"ColorMapEntry":function(colorMapEntry){var node=this.createElementNSPlus("sld:ColorMapEntry");var a=colorMapEntry;node.setAttribute("color",a.color);a.opacity!==undefined&&node.setAttribute("opacity",parseFloat(a.opacity));a.quantity!==undefined&&node.setAttribute("quantity",parseFloat(a.quantity));a.label!==undefined&&node.setAttribute("label",a.label);return node;},"PolygonSymbolizer":function(symbolizer){var node=this.createElementNSPlus("sld:PolygonSymbolizer");if(symbolizer.fill!==false){this.writeNode("Fill",symbolizer,node);}
61736 if(symbolizer.stroke!==false){this.writeNode("Stroke",symbolizer,node);}
61737 return node;},"Fill":function(symbolizer){var node=this.createElementNSPlus("sld:Fill");if(symbolizer.fillColor){this.writeNode("CssParameter",{symbolizer:symbolizer,key:"fillColor"},node);}
61738 if(symbolizer.fillOpacity!=null){this.writeNode("CssParameter",{symbolizer:symbolizer,key:"fillOpacity"},node);}
61739 return node;},"PointSymbolizer":function(symbolizer){var node=this.createElementNSPlus("sld:PointSymbolizer");this.writeNode("Graphic",symbolizer,node);return node;},"Graphic":function(symbolizer){var node=this.createElementNSPlus("sld:Graphic");if(symbolizer.externalGraphic!=undefined){this.writeNode("ExternalGraphic",symbolizer,node);}else{this.writeNode("Mark",symbolizer,node);}
61740 if(symbolizer.graphicOpacity!=undefined){this.writeNode("Opacity",symbolizer.graphicOpacity,node);}
61741 if(symbolizer.pointRadius!=undefined){this.writeNode("Size",symbolizer.pointRadius*2,node);}
61742 if(symbolizer.rotation!=undefined){this.writeNode("Rotation",symbolizer.rotation,node);}
61743 return node;},"ExternalGraphic":function(symbolizer){var node=this.createElementNSPlus("sld:ExternalGraphic");this.writeNode("OnlineResource",symbolizer.externalGraphic,node);var format=symbolizer.graphicFormat||this.getGraphicFormat(symbolizer.externalGraphic);this.writeNode("Format",format,node);return node;},"Mark":function(symbolizer){var node=this.createElementNSPlus("sld:Mark");if(symbolizer.graphicName){this.writeNode("WellKnownName",symbolizer.graphicName,node);}
61744 if(symbolizer.fill!==false){this.writeNode("Fill",symbolizer,node);}
61745 if(symbolizer.stroke!==false){this.writeNode("Stroke",symbolizer,node);}
61746 return node;},"WellKnownName":function(name){return this.createElementNSPlus("sld:WellKnownName",{value:name});},"Opacity":function(value){return this.createElementNSPlus("sld:Opacity",{value:value});},"Size":function(value){return this.createElementNSPlus("sld:Size",{value:value});},"Rotation":function(value){return this.createElementNSPlus("sld:Rotation",{value:value});},"OnlineResource":function(href){return this.createElementNSPlus("sld:OnlineResource",{attributes:{"xlink:type":"simple","xlink:href":href}});},"Format":function(format){return this.createElementNSPlus("sld:Format",{value:format});}}},OpenLayers.Format.Filter.v1_0_0.prototype.writers),CLASS_NAME:"OpenLayers.Format.SLD.v1"});OpenLayers.Format.WFST.v1_0_0=OpenLayers.Class(OpenLayers.Format.Filter.v1_0_0,OpenLayers.Format.WFST.v1,{version:"1.0.0",srsNameInQuery:false,schemaLocations:{"wfs":"http://schemas.opengis.net/wfs/1.0.0/WFS-transaction.xsd"},initialize:function(options){OpenLayers.Format.Filter.v1_0_0.prototype.initialize.apply(this,[options]);OpenLayers.Format.WFST.v1.prototype.initialize.apply(this,[options]);},readers:{"wfs":OpenLayers.Util.applyDefaults({"WFS_TransactionResponse":function(node,obj){obj.insertIds=[];obj.success=false;this.readChildNodes(node,obj);},"InsertResult":function(node,container){var obj={fids:[]};this.readChildNodes(node,obj);container.insertIds.push(obj.fids[0]);},"TransactionResult":function(node,obj){this.readChildNodes(node,obj);},"Status":function(node,obj){this.readChildNodes(node,obj);},"SUCCESS":function(node,obj){obj.success=true;}},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"]},writers:{"wfs":OpenLayers.Util.applyDefaults({"Query":function(options){options=OpenLayers.Util.extend({featureNS:this.featureNS,featurePrefix:this.featurePrefix,featureType:this.featureType,srsName:this.srsName,srsNameInQuery:this.srsNameInQuery},options);var node=this.createElementNSPlus("wfs:Query",{attributes:{typeName:(options.featureNS?options.featurePrefix+":":"")+
61747 options.featureType}});if(options.srsNameInQuery&&options.srsName){node.setAttribute("srsName",options.srsName);}
61748 if(options.featureNS){node.setAttribute("xmlns:"+options.featurePrefix,options.featureNS);}
61749 if(options.propertyNames){for(var i=0,len=options.propertyNames.length;i<len;i++){this.writeNode("ogc:PropertyName",{property:options.propertyNames[i]},node);}}
61750 if(options.filter){this.setFilterProperty(options.filter);this.writeNode("ogc:Filter",options.filter,node);}
61751 return node;}},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.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(options){OpenLayers.Format.Filter.v1_1_0.prototype.initialize.apply(this,[options]);OpenLayers.Format.WFST.v1.prototype.initialize.apply(this,[options]);},readers:{"wfs":OpenLayers.Util.applyDefaults({"FeatureCollection":function(node,obj){obj.numberOfFeatures=parseInt(node.getAttribute("numberOfFeatures"));OpenLayers.Format.WFST.v1.prototype.readers["wfs"]["FeatureCollection"].apply(this,arguments);},"TransactionResponse":function(node,obj){obj.insertIds=[];obj.success=false;this.readChildNodes(node,obj);},"TransactionSummary":function(node,obj){obj.success=true;},"InsertResults":function(node,obj){this.readChildNodes(node,obj);},"Feature":function(node,container){var obj={fids:[]};this.readChildNodes(node,obj);container.insertIds.push(obj.fids[0]);}},OpenLayers.Format.WFST.v1.prototype.readers["wfs"]),"gml":OpenLayers.Format.GML.v3.prototype.readers["gml"],"feature":OpenLayers.Format.GML.v3.prototype.readers["feature"],"ogc":OpenLayers.Format.Filter.v1_1_0.prototype.readers["ogc"]},writers:{"wfs":OpenLayers.Util.applyDefaults({"GetFeature":function(options){var node=OpenLayers.Format.WFST.v1.prototype.writers["wfs"]["GetFeature"].apply(this,arguments);options&&options.resultType&&this.setAttributes(node,{resultType:options.resultType});return node;},"Query":function(options){options=OpenLayers.Util.extend({featureNS:this.featureNS,featurePrefix:this.featurePrefix,featureType:this.featureType,srsName:this.srsName},options);var node=this.createElementNSPlus("wfs:Query",{attributes:{typeName:(options.featureNS?options.featurePrefix+":":"")+
61752 options.featureType,srsName:options.srsName}});if(options.featureNS){node.setAttribute("xmlns:"+options.featurePrefix,options.featureNS);}
61753 if(options.propertyNames){for(var i=0,len=options.propertyNames.length;i<len;i++){this.writeNode("wfs:PropertyName",{property:options.propertyNames[i]},node);}}
61754 if(options.filter){this.setFilterProperty(options.filter);this.writeNode("ogc:Filter",options.filter,node);}
61755 return node;},"PropertyName":function(obj){return this.createElementNSPlus("wfs:PropertyName",{value:obj.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.SOS.v1_0_0=OpenLayers.Class(OpenLayers.Protocol,{fois:null,formatOptions:null,initialize:function(options){OpenLayers.Protocol.prototype.initialize.apply(this,[options]);if(!options.format){this.format=new OpenLayers.Format.SOSGetFeatureOfInterest(this.formatOptions);}},destroy:function(){if(this.options&&!this.options.format){this.format.destroy();}
61756 this.format=null;OpenLayers.Protocol.prototype.destroy.apply(this);},read:function(options){options=OpenLayers.Util.extend({},options);OpenLayers.Util.applyDefaults(options,this.options||{});var response=new OpenLayers.Protocol.Response({requestType:"read"});var format=this.format;var data=OpenLayers.Format.XML.prototype.write.apply(format,[format.writeNode("sos:GetFeatureOfInterest",{fois:this.fois})]);response.priv=OpenLayers.Request.POST({url:options.url,callback:this.createCallback(this.handleRead,response,options),data:data});return response;},handleRead:function(response,options){if(options.callback){var request=response.priv;if(request.status>=200&&request.status<300){response.features=this.parseFeatures(request);response.code=OpenLayers.Protocol.Response.SUCCESS;}else{response.code=OpenLayers.Protocol.Response.FAILURE;}
61757 options.callback.call(options.scope,response);}},parseFeatures:function(request){var doc=request.responseXML;if(!doc||!doc.documentElement){doc=request.responseText;}
61758 if(!doc||doc.length<=0){return null;}
61759 return this.format.read(doc);},CLASS_NAME:"OpenLayers.Protocol.SOS.v1_0_0"});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",initialize:function(options){OpenLayers.Format.SLD.v1.prototype.initialize.apply(this,[options]);},CLASS_NAME:"OpenLayers.Format.SLD.v1_0_0"});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.Protocol.WFS.v1_1_0=OpenLayers.Class(OpenLayers.Protocol.WFS.v1,{version:"1.1.0",CLASS_NAME:"OpenLayers.Protocol.WFS.v1_1_0"});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",defaultPrefix:"owc",extractAttributes:true,xy:true,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(options){OpenLayers.Format.XML.prototype.initialize.apply(this,[options]);OpenLayers.Format.GML.v2.prototype.setGeometryTypes.call(this);},setNestingPath:function(l){if(l.layersContext){for(var i=0,len=l.layersContext.length;i<len;i++){var layerContext=l.layersContext[i];var nPath=[];var nTitle=l.title||"";if(l.metadata&&l.metadata.nestingPath){nPath=l.metadata.nestingPath.slice();}
61760 if(nTitle!=""){nPath.push(nTitle);}
61761 layerContext.metadata.nestingPath=nPath;if(layerContext.layersContext){this.setNestingPath(layerContext);}}}},decomposeNestingPath:function(nPath){var a=[];if(nPath instanceof Array){while(nPath.length>0){a.push(nPath.slice());nPath.pop();}
61762 a.reverse();}
61763 return a;},read:function(data){if(typeof data=="string"){data=OpenLayers.Format.XML.prototype.read.apply(this,[data]);}
61764 if(data&&data.nodeType==9){data=data.documentElement;}
61765 var context={};this.readNode(data,context);this.setNestingPath({layersContext:context.layersContext});var layers=[];this.processLayer(layers,context);delete context.layersContext;context.layersContext=layers;return context;},processLayer:function(layerArray,layer){if(layer.layersContext){for(var i=0,len=layer.layersContext.length;i<len;i++){var l=layer.layersContext[i];layerArray.push(l);if(l.layersContext){this.processLayer(layerArray,l);}}}},write:function(context,options){var name="OWSContext";this.nestingLayerLookup={};options=options||{};OpenLayers.Util.applyDefaults(options,context);var root=this.writeNode(name,options);this.nestingLayerLookup=null;this.setAttributeNS(root,this.namespaces["xsi"],"xsi:schemaLocation",this.schemaLocation);return OpenLayers.Format.XML.prototype.write.apply(this,[root]);},readers:{"kml":{"Document":function(node,obj){obj.features=new OpenLayers.Format.KML({kmlns:this.namespaces.kml,extractStyles:true}).read(node);}},"owc":{"OWSContext":function(node,obj){this.readChildNodes(node,obj);},"General":function(node,obj){this.readChildNodes(node,obj);},"ResourceList":function(node,obj){this.readChildNodes(node,obj);},"Layer":function(node,obj){var layerContext={metadata:{},visibility:(node.getAttribute("hidden")!="1"),queryable:(node.getAttribute("queryable")=="1"),opacity:((node.getAttribute("opacity")!=null)?parseFloat(node.getAttribute("opacity")):null),name:node.getAttribute("name"),categoryLayer:(node.getAttribute("name")==null),formats:[],styles:[]};if(!obj.layersContext){obj.layersContext=[];}
61766 obj.layersContext.push(layerContext);this.readChildNodes(node,layerContext);},"InlineGeometry":function(node,obj){obj.features=[];var elements=this.getElementsByTagNameNS(node,this.namespaces.gml,"featureMember");var el;if(elements.length>=1){el=elements[0];}
61767 if(el&&el.firstChild){var featurenode=(el.firstChild.nextSibling)?el.firstChild.nextSibling:el.firstChild;this.setNamespace("feature",featurenode.namespaceURI);this.featureType=featurenode.localName||featurenode.nodeName.split(":").pop();this.readChildNodes(node,obj);}},"Server":function(node,obj){if((!obj.service&&!obj.version)||(obj.service!=OpenLayers.Format.Context.serviceTypes.WMS)){obj.service=node.getAttribute("service");obj.version=node.getAttribute("version");this.readChildNodes(node,obj);}},"Name":function(node,obj){obj.name=this.getChildValue(node);this.readChildNodes(node,obj);},"Title":function(node,obj){obj.title=this.getChildValue(node);this.readChildNodes(node,obj);},"StyleList":function(node,obj){this.readChildNodes(node,obj.styles);},"Style":function(node,obj){var style={};obj.push(style);this.readChildNodes(node,style);},"LegendURL":function(node,obj){var legend={};obj.legend=legend;this.readChildNodes(node,legend);},"OnlineResource":function(node,obj){obj.url=this.getAttributeNS(node,this.namespaces.xlink,"href");this.readChildNodes(node,obj);}},"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(options){var node=this.createElementNSPlus("OWSContext",{attributes:{version:this.VERSION,id:options.id||OpenLayers.Util.createUniqueID("OpenLayers_OWSContext_")}});this.writeNode("General",options,node);this.writeNode("ResourceList",options,node);return node;},"General":function(options){var node=this.createElementNSPlus("General");this.writeNode("ows:BoundingBox",options,node);this.writeNode("ows:Title",options.title||'OpenLayers OWSContext',node);return node;},"ResourceList":function(options){var node=this.createElementNSPlus("ResourceList");for(var i=0,len=options.layers.length;i<len;i++){var layer=options.layers[i];var decomposedPath=this.decomposeNestingPath(layer.metadata.nestingPath);this.writeNode("_Layer",{layer:layer,subPaths:decomposedPath},node);}
61768 return node;},"Server":function(options){var node=this.createElementNSPlus("Server",{attributes:{version:options.version,service:options.service}});this.writeNode("OnlineResource",options,node);return node;},"OnlineResource":function(options){var node=this.createElementNSPlus("OnlineResource",{attributes:{"xlink:href":options.url}});return node;},"InlineGeometry":function(layer){var node=this.createElementNSPlus("InlineGeometry");this.writeNode("gml:boundedBy",layer.getDataExtent(),node);for(var i=0,len=layer.features.length;i<len;i++){this.writeNode("gml:featureMember",layer.features[i],node);}
61769 return node;},"StyleList":function(styles){var node=this.createElementNSPlus("StyleList");for(var i=0,len=styles.length;i<len;i++){this.writeNode("Style",styles[i],node);}
61770 return node;},"Style":function(style){var node=this.createElementNSPlus("Style");this.writeNode("Name",style,node);this.writeNode("Title",style,node);this.writeNode("LegendURL",style,node);return node;},"Name":function(obj){var node=this.createElementNSPlus("Name",{value:obj.name});return node;},"Title":function(obj){var node=this.createElementNSPlus("Title",{value:obj.title});return node;},"LegendURL":function(style){var node=this.createElementNSPlus("LegendURL");this.writeNode("OnlineResource",style.legend,node);return node;},"_WMS":function(layer){var node=this.createElementNSPlus("Layer",{attributes:{name:layer.params.LAYERS,queryable:layer.queryable?"1":"0",hidden:layer.visibility?"0":"1",opacity:layer.opacity?layer.opacity:null}});this.writeNode("ows:Title",layer.name,node);this.writeNode("ows:OutputFormat",layer.params.FORMAT,node);this.writeNode("Server",{service:OpenLayers.Format.Context.serviceTypes.WMS,version:layer.params.VERSION,url:layer.url},node);if(layer.metadata.styles&&layer.metadata.styles.length>0){this.writeNode("StyleList",layer.metadata.styles,node);}
61771 return node;},"_Layer":function(options){var layer,subPaths,node,title;layer=options.layer;subPaths=options.subPaths;node=null;title=null;if(subPaths.length>0){var path=subPaths[0].join("/");var index=path.lastIndexOf("/");node=this.nestingLayerLookup[path];title=(index>0)?path.substring(index+1,path.length):path;if(!node){node=this.createElementNSPlus("Layer");this.writeNode("ows:Title",title,node);this.nestingLayerLookup[path]=node;}
61772 options.subPaths.shift();this.writeNode("_Layer",options,node);return node;}else{if(layer instanceof OpenLayers.Layer.WMS){node=this.writeNode("_WMS",layer);}else if(layer instanceof OpenLayers.Layer.Vector){if(layer.protocol instanceof OpenLayers.Protocol.WFS.v1){node=this.writeNode("_WFS",layer);}else if(layer.protocol instanceof OpenLayers.Protocol.HTTP){if(layer.protocol.format instanceof OpenLayers.Format.GML){layer.protocol.format.version="2.1.2";node=this.writeNode("_GML",layer);}else if(layer.protocol.format instanceof OpenLayers.Format.KML){layer.protocol.format.version="2.2";node=this.writeNode("_KML",layer);}}else{this.setNamespace("feature",this.featureNS);node=this.writeNode("_InlineGeometry",layer);}}
61773 if(layer.options.maxScale){this.writeNode("sld:MinScaleDenominator",layer.options.maxScale,node);}
61774 if(layer.options.minScale){this.writeNode("sld:MaxScaleDenominator",layer.options.minScale,node);}
61775 this.nestingLayerLookup[layer.name]=node;return node;}},"_WFS":function(layer){var node=this.createElementNSPlus("Layer",{attributes:{name:layer.protocol.featurePrefix+":"+layer.protocol.featureType,hidden:layer.visibility?"0":"1"}});this.writeNode("ows:Title",layer.name,node);this.writeNode("Server",{service:OpenLayers.Format.Context.serviceTypes.WFS,version:layer.protocol.version,url:layer.protocol.url},node);return node;},"_InlineGeometry":function(layer){var node=this.createElementNSPlus("Layer",{attributes:{name:this.featureType,hidden:layer.visibility?"0":"1"}});this.writeNode("ows:Title",layer.name,node);this.writeNode("InlineGeometry",layer,node);return node;},"_GML":function(layer){var node=this.createElementNSPlus("Layer");this.writeNode("ows:Title",layer.name,node);this.writeNode("Server",{service:OpenLayers.Format.Context.serviceTypes.GML,url:layer.protocol.url,version:layer.protocol.format.version},node);return node;},"_KML":function(layer){var node=this.createElementNSPlus("Layer");this.writeNode("ows:Title",layer.name,node);this.writeNode("Server",{service:OpenLayers.Format.Context.serviceTypes.KML,version:layer.protocol.format.version,url:layer.protocol.url},node);return node;}},"gml":OpenLayers.Util.applyDefaults({"boundedBy":function(bounds){var node=this.createElementNSPlus("gml:boundedBy");this.writeNode("gml:Box",bounds,node);return node;}},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,"feature":OpenLayers.Format.GML.v2.prototype.writers.feature},CLASS_NAME:"OpenLayers.Format.OWSContext.v0_3_1"});
61776 (function(){var n=this,t=n._,r={},e=Array.prototype,u=Object.prototype,i=Function.prototype,a=e.push,o=e.slice,c=e.concat,l=u.toString,f=u.hasOwnProperty,s=e.forEach,p=e.map,h=e.reduce,v=e.reduceRight,d=e.filter,g=e.every,m=e.some,y=e.indexOf,b=e.lastIndexOf,x=Array.isArray,_=Object.keys,j=i.bind,w=function(n){return n instanceof w?n:this instanceof w?(this._wrapped=n,void 0):new w(n)};"undefined"!=typeof exports?("undefined"!=typeof module&&module.exports&&(exports=module.exports=w),exports._=w):n._=w,w.VERSION="1.4.4";var A=w.each=w.forEach=function(n,t,e){if(null!=n)if(s&&n.forEach===s)n.forEach(t,e);else if(n.length===+n.length){for(var u=0,i=n.length;i>u;u++)if(t.call(e,n[u],u,n)===r)return}else for(var a in n)if(w.has(n,a)&&t.call(e,n[a],a,n)===r)return};w.map=w.collect=function(n,t,r){var e=[];return null==n?e:p&&n.map===p?n.map(t,r):(A(n,function(n,u,i){e[e.length]=t.call(r,n,u,i)}),e)};var O="Reduce of empty array with no initial value";w.reduce=w.foldl=w.inject=function(n,t,r,e){var u=arguments.length>2;if(null==n&&(n=[]),h&&n.reduce===h)return e&&(t=w.bind(t,e)),u?n.reduce(t,r):n.reduce(t);if(A(n,function(n,i,a){u?r=t.call(e,r,n,i,a):(r=n,u=!0)}),!u)throw new TypeError(O);return r},w.reduceRight=w.foldr=function(n,t,r,e){var u=arguments.length>2;if(null==n&&(n=[]),v&&n.reduceRight===v)return e&&(t=w.bind(t,e)),u?n.reduceRight(t,r):n.reduceRight(t);var i=n.length;if(i!==+i){var a=w.keys(n);i=a.length}if(A(n,function(o,c,l){c=a?a[--i]:--i,u?r=t.call(e,r,n[c],c,l):(r=n[c],u=!0)}),!u)throw new TypeError(O);return r},w.find=w.detect=function(n,t,r){var e;return E(n,function(n,u,i){return t.call(r,n,u,i)?(e=n,!0):void 0}),e},w.filter=w.select=function(n,t,r){var e=[];return null==n?e:d&&n.filter===d?n.filter(t,r):(A(n,function(n,u,i){t.call(r,n,u,i)&&(e[e.length]=n)}),e)},w.reject=function(n,t,r){return w.filter(n,function(n,e,u){return!t.call(r,n,e,u)},r)},w.every=w.all=function(n,t,e){t||(t=w.identity);var u=!0;return null==n?u:g&&n.every===g?n.every(t,e):(A(n,function(n,i,a){return(u=u&&t.call(e,n,i,a))?void 0:r}),!!u)};var E=w.some=w.any=function(n,t,e){t||(t=w.identity);var u=!1;return null==n?u:m&&n.some===m?n.some(t,e):(A(n,function(n,i,a){return u||(u=t.call(e,n,i,a))?r:void 0}),!!u)};w.contains=w.include=function(n,t){return null==n?!1:y&&n.indexOf===y?n.indexOf(t)!=-1:E(n,function(n){return n===t})},w.invoke=function(n,t){var r=o.call(arguments,2),e=w.isFunction(t);return w.map(n,function(n){return(e?t:n[t]).apply(n,r)})},w.pluck=function(n,t){return w.map(n,function(n){return n[t]})},w.where=function(n,t,r){return w.isEmpty(t)?r?null:[]:w[r?"find":"filter"](n,function(n){for(var r in t)if(t[r]!==n[r])return!1;return!0})},w.findWhere=function(n,t){return w.where(n,t,!0)},w.max=function(n,t,r){if(!t&&w.isArray(n)&&n[0]===+n[0]&&65535>n.length)return Math.max.apply(Math,n);if(!t&&w.isEmpty(n))return-1/0;var e={computed:-1/0,value:-1/0};return A(n,function(n,u,i){var a=t?t.call(r,n,u,i):n;a>=e.computed&&(e={value:n,computed:a})}),e.value},w.min=function(n,t,r){if(!t&&w.isArray(n)&&n[0]===+n[0]&&65535>n.length)return Math.min.apply(Math,n);if(!t&&w.isEmpty(n))return 1/0;var e={computed:1/0,value:1/0};return A(n,function(n,u,i){var a=t?t.call(r,n,u,i):n;e.computed>a&&(e={value:n,computed:a})}),e.value},w.shuffle=function(n){var t,r=0,e=[];return A(n,function(n){t=w.random(r++),e[r-1]=e[t],e[t]=n}),e};var k=function(n){return w.isFunction(n)?n:function(t){return t[n]}};w.sortBy=function(n,t,r){var e=k(t);return w.pluck(w.map(n,function(n,t,u){return{value:n,index:t,criteria:e.call(r,n,t,u)}}).sort(function(n,t){var r=n.criteria,e=t.criteria;if(r!==e){if(r>e||r===void 0)return 1;if(e>r||e===void 0)return-1}return n.index<t.index?-1:1}),"value")};var F=function(n,t,r,e){var u={},i=k(t||w.identity);return A(n,function(t,a){var o=i.call(r,t,a,n);e(u,o,t)}),u};w.groupBy=function(n,t,r){return F(n,t,r,function(n,t,r){(w.has(n,t)?n[t]:n[t]=[]).push(r)})},w.countBy=function(n,t,r){return F(n,t,r,function(n,t){w.has(n,t)||(n[t]=0),n[t]++})},w.sortedIndex=function(n,t,r,e){r=null==r?w.identity:k(r);for(var u=r.call(e,t),i=0,a=n.length;a>i;){var o=i+a>>>1;u>r.call(e,n[o])?i=o+1:a=o}return i},w.toArray=function(n){return n?w.isArray(n)?o.call(n):n.length===+n.length?w.map(n,w.identity):w.values(n):[]},w.size=function(n){return null==n?0:n.length===+n.length?n.length:w.keys(n).length},w.first=w.head=w.take=function(n,t,r){return null==n?void 0:null==t||r?n[0]:o.call(n,0,t)},w.initial=function(n,t,r){return o.call(n,0,n.length-(null==t||r?1:t))},w.last=function(n,t,r){return null==n?void 0:null==t||r?n[n.length-1]:o.call(n,Math.max(n.length-t,0))},w.rest=w.tail=w.drop=function(n,t,r){return o.call(n,null==t||r?1:t)},w.compact=function(n){return w.filter(n,w.identity)};var R=function(n,t,r){return A(n,function(n){w.isArray(n)?t?a.apply(r,n):R(n,t,r):r.push(n)}),r};w.flatten=function(n,t){return R(n,t,[])},w.without=function(n){return w.difference(n,o.call(arguments,1))},w.uniq=w.unique=function(n,t,r,e){w.isFunction(t)&&(e=r,r=t,t=!1);var u=r?w.map(n,r,e):n,i=[],a=[];return A(u,function(r,e){(t?e&&a[a.length-1]===r:w.contains(a,r))||(a.push(r),i.push(n[e]))}),i},w.union=function(){return w.uniq(c.apply(e,arguments))},w.intersection=function(n){var t=o.call(arguments,1);return w.filter(w.uniq(n),function(n){return w.every(t,function(t){return w.indexOf(t,n)>=0})})},w.difference=function(n){var t=c.apply(e,o.call(arguments,1));return w.filter(n,function(n){return!w.contains(t,n)})},w.zip=function(){for(var n=o.call(arguments),t=w.max(w.pluck(n,"length")),r=Array(t),e=0;t>e;e++)r[e]=w.pluck(n,""+e);return r},w.object=function(n,t){if(null==n)return{};for(var r={},e=0,u=n.length;u>e;e++)t?r[n[e]]=t[e]:r[n[e][0]]=n[e][1];return r},w.indexOf=function(n,t,r){if(null==n)return-1;var e=0,u=n.length;if(r){if("number"!=typeof r)return e=w.sortedIndex(n,t),n[e]===t?e:-1;e=0>r?Math.max(0,u+r):r}if(y&&n.indexOf===y)return n.indexOf(t,r);for(;u>e;e++)if(n[e]===t)return e;return-1},w.lastIndexOf=function(n,t,r){if(null==n)return-1;var e=null!=r;if(b&&n.lastIndexOf===b)return e?n.lastIndexOf(t,r):n.lastIndexOf(t);for(var u=e?r:n.length;u--;)if(n[u]===t)return u;return-1},w.range=function(n,t,r){1>=arguments.length&&(t=n||0,n=0),r=arguments[2]||1;for(var e=Math.max(Math.ceil((t-n)/r),0),u=0,i=Array(e);e>u;)i[u++]=n,n+=r;return i},w.bind=function(n,t){if(n.bind===j&&j)return j.apply(n,o.call(arguments,1));var r=o.call(arguments,2);return function(){return n.apply(t,r.concat(o.call(arguments)))}},w.partial=function(n){var t=o.call(arguments,1);return function(){return n.apply(this,t.concat(o.call(arguments)))}},w.bindAll=function(n){var t=o.call(arguments,1);return 0===t.length&&(t=w.functions(n)),A(t,function(t){n[t]=w.bind(n[t],n)}),n},w.memoize=function(n,t){var r={};return t||(t=w.identity),function(){var e=t.apply(this,arguments);return w.has(r,e)?r[e]:r[e]=n.apply(this,arguments)}},w.delay=function(n,t){var r=o.call(arguments,2);return setTimeout(function(){return n.apply(null,r)},t)},w.defer=function(n){return w.delay.apply(w,[n,1].concat(o.call(arguments,1)))},w.throttle=function(n,t){var r,e,u,i,a=0,o=function(){a=new Date,u=null,i=n.apply(r,e)};return function(){var c=new Date,l=t-(c-a);return r=this,e=arguments,0>=l?(clearTimeout(u),u=null,a=c,i=n.apply(r,e)):u||(u=setTimeout(o,l)),i}},w.debounce=function(n,t,r){var e,u;return function(){var i=this,a=arguments,o=function(){e=null,r||(u=n.apply(i,a))},c=r&&!e;return clearTimeout(e),e=setTimeout(o,t),c&&(u=n.apply(i,a)),u}},w.once=function(n){var t,r=!1;return function(){return r?t:(r=!0,t=n.apply(this,arguments),n=null,t)}},w.wrap=function(n,t){return function(){var r=[n];return a.apply(r,arguments),t.apply(this,r)}},w.compose=function(){var n=arguments;return function(){for(var t=arguments,r=n.length-1;r>=0;r--)t=[n[r].apply(this,t)];return t[0]}},w.after=function(n,t){return 0>=n?t():function(){return 1>--n?t.apply(this,arguments):void 0}},w.keys=_||function(n){if(n!==Object(n))throw new TypeError("Invalid object");var t=[];for(var r in n)w.has(n,r)&&(t[t.length]=r);return t},w.values=function(n){var t=[];for(var r in n)w.has(n,r)&&t.push(n[r]);return t},w.pairs=function(n){var t=[];for(var r in n)w.has(n,r)&&t.push([r,n[r]]);return t},w.invert=function(n){var t={};for(var r in n)w.has(n,r)&&(t[n[r]]=r);return t},w.functions=w.methods=function(n){var t=[];for(var r in n)w.isFunction(n[r])&&t.push(r);return t.sort()},w.extend=function(n){return A(o.call(arguments,1),function(t){if(t)for(var r in t)n[r]=t[r]}),n},w.pick=function(n){var t={},r=c.apply(e,o.call(arguments,1));return A(r,function(r){r in n&&(t[r]=n[r])}),t},w.omit=function(n){var t={},r=c.apply(e,o.call(arguments,1));for(var u in n)w.contains(r,u)||(t[u]=n[u]);return t},w.defaults=function(n){return A(o.call(arguments,1),function(t){if(t)for(var r in t)null==n[r]&&(n[r]=t[r])}),n},w.clone=function(n){return w.isObject(n)?w.isArray(n)?n.slice():w.extend({},n):n},w.tap=function(n,t){return t(n),n};var I=function(n,t,r,e){if(n===t)return 0!==n||1/n==1/t;if(null==n||null==t)return n===t;n instanceof w&&(n=n._wrapped),t instanceof w&&(t=t._wrapped);var u=l.call(n);if(u!=l.call(t))return!1;switch(u){case"[object String]":return n==t+"";case"[object Number]":return n!=+n?t!=+t:0==n?1/n==1/t:n==+t;case"[object Date]":case"[object Boolean]":return+n==+t;case"[object RegExp]":return n.source==t.source&&n.global==t.global&&n.multiline==t.multiline&&n.ignoreCase==t.ignoreCase}if("object"!=typeof n||"object"!=typeof t)return!1;for(var i=r.length;i--;)if(r[i]==n)return e[i]==t;r.push(n),e.push(t);var a=0,o=!0;if("[object Array]"==u){if(a=n.length,o=a==t.length)for(;a--&&(o=I(n[a],t[a],r,e)););}else{var c=n.constructor,f=t.constructor;if(c!==f&&!(w.isFunction(c)&&c instanceof c&&w.isFunction(f)&&f instanceof f))return!1;for(var s in n)if(w.has(n,s)&&(a++,!(o=w.has(t,s)&&I(n[s],t[s],r,e))))break;if(o){for(s in t)if(w.has(t,s)&&!a--)break;o=!a}}return r.pop(),e.pop(),o};w.isEqual=function(n,t){return I(n,t,[],[])},w.isEmpty=function(n){if(null==n)return!0;if(w.isArray(n)||w.isString(n))return 0===n.length;for(var t in n)if(w.has(n,t))return!1;return!0},w.isElement=function(n){return!(!n||1!==n.nodeType)},w.isArray=x||function(n){return"[object Array]"==l.call(n)},w.isObject=function(n){return n===Object(n)},A(["Arguments","Function","String","Number","Date","RegExp"],function(n){w["is"+n]=function(t){return l.call(t)=="[object "+n+"]"}}),w.isArguments(arguments)||(w.isArguments=function(n){return!(!n||!w.has(n,"callee"))}),"function"!=typeof/./&&(w.isFunction=function(n){return"function"==typeof n}),w.isFinite=function(n){return isFinite(n)&&!isNaN(parseFloat(n))},w.isNaN=function(n){return w.isNumber(n)&&n!=+n},w.isBoolean=function(n){return n===!0||n===!1||"[object Boolean]"==l.call(n)},w.isNull=function(n){return null===n},w.isUndefined=function(n){return n===void 0},w.has=function(n,t){return f.call(n,t)},w.noConflict=function(){return n._=t,this},w.identity=function(n){return n},w.times=function(n,t,r){for(var e=Array(n),u=0;n>u;u++)e[u]=t.call(r,u);return e},w.random=function(n,t){return null==t&&(t=n,n=0),n+Math.floor(Math.random()*(t-n+1))};var M={escape:{"&":"&amp;","<":"&lt;",">":"&gt;",'"':"&quot;","'":"&#x27;","/":"&#x2F;"}};M.unescape=w.invert(M.escape);var S={escape:RegExp("["+w.keys(M.escape).join("")+"]","g"),unescape:RegExp("("+w.keys(M.unescape).join("|")+")","g")};w.each(["escape","unescape"],function(n){w[n]=function(t){return null==t?"":(""+t).replace(S[n],function(t){return M[n][t]})}}),w.result=function(n,t){if(null==n)return null;var r=n[t];return w.isFunction(r)?r.call(n):r},w.mixin=function(n){A(w.functions(n),function(t){var r=w[t]=n[t];w.prototype[t]=function(){var n=[this._wrapped];return a.apply(n,arguments),D.call(this,r.apply(w,n))}})};var N=0;w.uniqueId=function(n){var t=++N+"";return n?n+t:t},w.templateSettings={evaluate:/<%([\s\S]+?)%>/g,interpolate:/<%=([\s\S]+?)%>/g,escape:/<%-([\s\S]+?)%>/g};var T=/(.)^/,q={"'":"'","\\":"\\","\r":"r","\n":"n","        ":"t","\u2028":"u2028","\u2029":"u2029"},B=/\\|'|\r|\n|\t|\u2028|\u2029/g;w.template=function(n,t,r){var e;r=w.defaults({},r,w.templateSettings);var u=RegExp([(r.escape||T).source,(r.interpolate||T).source,(r.evaluate||T).source].join("|")+"|$","g"),i=0,a="__p+='";n.replace(u,function(t,r,e,u,o){return a+=n.slice(i,o).replace(B,function(n){return"\\"+q[n]}),r&&(a+="'+\n((__t=("+r+"))==null?'':_.escape(__t))+\n'"),e&&(a+="'+\n((__t=("+e+"))==null?'':__t)+\n'"),u&&(a+="';\n"+u+"\n__p+='"),i=o+t.length,t}),a+="';\n",r.variable||(a="with(obj||{}){\n"+a+"}\n"),a="var __t,__p='',__j=Array.prototype.join,"+"print=function(){__p+=__j.call(arguments,'');};\n"+a+"return __p;\n";try{e=Function(r.variable||"obj","_",a)}catch(o){throw o.source=a,o}if(t)return e(t,w);var c=function(n){return e.call(this,n,w)};return c.source="function("+(r.variable||"obj")+"){\n"+a+"}",c},w.chain=function(n){return w(n).chain()};var D=function(n){return this._chain?w(n).chain():n};w.mixin(w),A(["pop","push","reverse","shift","sort","splice","unshift"],function(n){var t=e[n];w.prototype[n]=function(){var r=this._wrapped;return t.apply(r,arguments),"shift"!=n&&"splice"!=n||0!==r.length||delete r[0],D.call(this,r)}}),A(["concat","join","slice"],function(n){var t=e[n];w.prototype[n]=function(){return D.call(this,t.apply(this._wrapped,arguments))}}),w.extend(w.prototype,{chain:function(){return this._chain=!0,this},value:function(){return this._wrapped}})}).call(this);/*global setImmediate: false, setTimeout: false, console: false */
61777 (function () {
61778
61779     var async = {};
61780
61781     // global on the server, window in the browser
61782     var root, previous_async;
61783
61784     root = this;
61785     if (root != null) {
61786       previous_async = root.async;
61787     }
61788
61789     async.noConflict = function () {
61790         root.async = previous_async;
61791         return async;
61792     };
61793
61794     function only_once(fn) {
61795         var called = false;
61796         return function() {
61797             if (called) throw new Error("Callback was already called.");
61798             called = true;
61799             fn.apply(root, arguments);
61800         }
61801     }
61802
61803     //// cross-browser compatiblity functions ////
61804
61805     var _each = function (arr, iterator) {
61806         if (arr.forEach) {
61807             return arr.forEach(iterator);
61808         }
61809         for (var i = 0; i < arr.length; i += 1) {
61810             iterator(arr[i], i, arr);
61811         }
61812     };
61813
61814     var _map = function (arr, iterator) {
61815         if (arr.map) {
61816             return arr.map(iterator);
61817         }
61818         var results = [];
61819         _each(arr, function (x, i, a) {
61820             results.push(iterator(x, i, a));
61821         });
61822         return results;
61823     };
61824
61825     var _reduce = function (arr, iterator, memo) {
61826         if (arr.reduce) {
61827             return arr.reduce(iterator, memo);
61828         }
61829         _each(arr, function (x, i, a) {
61830             memo = iterator(memo, x, i, a);
61831         });
61832         return memo;
61833     };
61834
61835     var _keys = function (obj) {
61836         if (Object.keys) {
61837             return Object.keys(obj);
61838         }
61839         var keys = [];
61840         for (var k in obj) {
61841             if (obj.hasOwnProperty(k)) {
61842                 keys.push(k);
61843             }
61844         }
61845         return keys;
61846     };
61847
61848     //// exported async module functions ////
61849
61850     //// nextTick implementation with browser-compatible fallback ////
61851     if (typeof process === 'undefined' || !(process.nextTick)) {
61852         if (typeof setImmediate === 'function') {
61853             async.nextTick = function (fn) {
61854                 // not a direct alias for IE10 compatibility
61855                 setImmediate(fn);
61856             };
61857             async.setImmediate = async.nextTick;
61858         }
61859         else {
61860             async.nextTick = function (fn) {
61861                 setTimeout(fn, 0);
61862             };
61863             async.setImmediate = async.nextTick;
61864         }
61865     }
61866     else {
61867         async.nextTick = process.nextTick;
61868         if (typeof setImmediate !== 'undefined') {
61869             async.setImmediate = setImmediate;
61870         }
61871         else {
61872             async.setImmediate = async.nextTick;
61873         }
61874     }
61875
61876     async.each = function (arr, iterator, callback) {
61877         callback = callback || function () {};
61878         if (!arr.length) {
61879             return callback();
61880         }
61881         var completed = 0;
61882         _each(arr, function (x) {
61883             iterator(x, only_once(function (err) {
61884                 if (err) {
61885                     callback(err);
61886                     callback = function () {};
61887                 }
61888                 else {
61889                     completed += 1;
61890                     if (completed >= arr.length) {
61891                         callback(null);
61892                     }
61893                 }
61894             }));
61895         });
61896     };
61897     async.forEach = async.each;
61898
61899     async.eachSeries = function (arr, iterator, callback) {
61900         callback = callback || function () {};
61901         if (!arr.length) {
61902             return callback();
61903         }
61904         var completed = 0;
61905         var iterate = function () {
61906             iterator(arr[completed], function (err) {
61907                 if (err) {
61908                     callback(err);
61909                     callback = function () {};
61910                 }
61911                 else {
61912                     completed += 1;
61913                     if (completed >= arr.length) {
61914                         callback(null);
61915                     }
61916                     else {
61917                         iterate();
61918                     }
61919                 }
61920             });
61921         };
61922         iterate();
61923     };
61924     async.forEachSeries = async.eachSeries;
61925
61926     async.eachLimit = function (arr, limit, iterator, callback) {
61927         var fn = _eachLimit(limit);
61928         fn.apply(null, [arr, iterator, callback]);
61929     };
61930     async.forEachLimit = async.eachLimit;
61931
61932     var _eachLimit = function (limit) {
61933
61934         return function (arr, iterator, callback) {
61935             callback = callback || function () {};
61936             if (!arr.length || limit <= 0) {
61937                 return callback();
61938             }
61939             var completed = 0;
61940             var started = 0;
61941             var running = 0;
61942
61943             (function replenish () {
61944                 if (completed >= arr.length) {
61945                     return callback();
61946                 }
61947
61948                 while (running < limit && started < arr.length) {
61949                     started += 1;
61950                     running += 1;
61951                     iterator(arr[started - 1], function (err) {
61952                         if (err) {
61953                             callback(err);
61954                             callback = function () {};
61955                         }
61956                         else {
61957                             completed += 1;
61958                             running -= 1;
61959                             if (completed >= arr.length) {
61960                                 callback();
61961                             }
61962                             else {
61963                                 replenish();
61964                             }
61965                         }
61966                     });
61967                 }
61968             })();
61969         };
61970     };
61971
61972
61973     var doParallel = function (fn) {
61974         return function () {
61975             var args = Array.prototype.slice.call(arguments);
61976             return fn.apply(null, [async.each].concat(args));
61977         };
61978     };
61979     var doParallelLimit = function(limit, fn) {
61980         return function () {
61981             var args = Array.prototype.slice.call(arguments);
61982             return fn.apply(null, [_eachLimit(limit)].concat(args));
61983         };
61984     };
61985     var doSeries = function (fn) {
61986         return function () {
61987             var args = Array.prototype.slice.call(arguments);
61988             return fn.apply(null, [async.eachSeries].concat(args));
61989         };
61990     };
61991
61992
61993     var _asyncMap = function (eachfn, arr, iterator, callback) {
61994         var results = [];
61995         arr = _map(arr, function (x, i) {
61996             return {index: i, value: x};
61997         });
61998         eachfn(arr, function (x, callback) {
61999             iterator(x.value, function (err, v) {
62000                 results[x.index] = v;
62001                 callback(err);
62002             });
62003         }, function (err) {
62004             callback(err, results);
62005         });
62006     };
62007     async.map = doParallel(_asyncMap);
62008     async.mapSeries = doSeries(_asyncMap);
62009     async.mapLimit = function (arr, limit, iterator, callback) {
62010         return _mapLimit(limit)(arr, iterator, callback);
62011     };
62012
62013     var _mapLimit = function(limit) {
62014         return doParallelLimit(limit, _asyncMap);
62015     };
62016
62017     // reduce only has a series version, as doing reduce in parallel won't
62018     // work in many situations.
62019     async.reduce = function (arr, memo, iterator, callback) {
62020         async.eachSeries(arr, function (x, callback) {
62021             iterator(memo, x, function (err, v) {
62022                 memo = v;
62023                 callback(err);
62024             });
62025         }, function (err) {
62026             callback(err, memo);
62027         });
62028     };
62029     // inject alias
62030     async.inject = async.reduce;
62031     // foldl alias
62032     async.foldl = async.reduce;
62033
62034     async.reduceRight = function (arr, memo, iterator, callback) {
62035         var reversed = _map(arr, function (x) {
62036             return x;
62037         }).reverse();
62038         async.reduce(reversed, memo, iterator, callback);
62039     };
62040     // foldr alias
62041     async.foldr = async.reduceRight;
62042
62043     var _filter = function (eachfn, arr, iterator, callback) {
62044         var results = [];
62045         arr = _map(arr, function (x, i) {
62046             return {index: i, value: x};
62047         });
62048         eachfn(arr, function (x, callback) {
62049             iterator(x.value, function (v) {
62050                 if (v) {
62051                     results.push(x);
62052                 }
62053                 callback();
62054             });
62055         }, function (err) {
62056             callback(_map(results.sort(function (a, b) {
62057                 return a.index - b.index;
62058             }), function (x) {
62059                 return x.value;
62060             }));
62061         });
62062     };
62063     async.filter = doParallel(_filter);
62064     async.filterSeries = doSeries(_filter);
62065     // select alias
62066     async.select = async.filter;
62067     async.selectSeries = async.filterSeries;
62068
62069     var _reject = function (eachfn, arr, iterator, callback) {
62070         var results = [];
62071         arr = _map(arr, function (x, i) {
62072             return {index: i, value: x};
62073         });
62074         eachfn(arr, function (x, callback) {
62075             iterator(x.value, function (v) {
62076                 if (!v) {
62077                     results.push(x);
62078                 }
62079                 callback();
62080             });
62081         }, function (err) {
62082             callback(_map(results.sort(function (a, b) {
62083                 return a.index - b.index;
62084             }), function (x) {
62085                 return x.value;
62086             }));
62087         });
62088     };
62089     async.reject = doParallel(_reject);
62090     async.rejectSeries = doSeries(_reject);
62091
62092     var _detect = function (eachfn, arr, iterator, main_callback) {
62093         eachfn(arr, function (x, callback) {
62094             iterator(x, function (result) {
62095                 if (result) {
62096                     main_callback(x);
62097                     main_callback = function () {};
62098                 }
62099                 else {
62100                     callback();
62101                 }
62102             });
62103         }, function (err) {
62104             main_callback();
62105         });
62106     };
62107     async.detect = doParallel(_detect);
62108     async.detectSeries = doSeries(_detect);
62109
62110     async.some = function (arr, iterator, main_callback) {
62111         async.each(arr, function (x, callback) {
62112             iterator(x, function (v) {
62113                 if (v) {
62114                     main_callback(true);
62115                     main_callback = function () {};
62116                 }
62117                 callback();
62118             });
62119         }, function (err) {
62120             main_callback(false);
62121         });
62122     };
62123     // any alias
62124     async.any = async.some;
62125
62126     async.every = function (arr, iterator, main_callback) {
62127         async.each(arr, function (x, callback) {
62128             iterator(x, function (v) {
62129                 if (!v) {
62130                     main_callback(false);
62131                     main_callback = function () {};
62132                 }
62133                 callback();
62134             });
62135         }, function (err) {
62136             main_callback(true);
62137         });
62138     };
62139     // all alias
62140     async.all = async.every;
62141
62142     async.sortBy = function (arr, iterator, callback) {
62143         async.map(arr, function (x, callback) {
62144             iterator(x, function (err, criteria) {
62145                 if (err) {
62146                     callback(err);
62147                 }
62148                 else {
62149                     callback(null, {value: x, criteria: criteria});
62150                 }
62151             });
62152         }, function (err, results) {
62153             if (err) {
62154                 return callback(err);
62155             }
62156             else {
62157                 var fn = function (left, right) {
62158                     var a = left.criteria, b = right.criteria;
62159                     return a < b ? -1 : a > b ? 1 : 0;
62160                 };
62161                 callback(null, _map(results.sort(fn), function (x) {
62162                     return x.value;
62163                 }));
62164             }
62165         });
62166     };
62167
62168     async.auto = function (tasks, callback) {
62169         callback = callback || function () {};
62170         var keys = _keys(tasks);
62171         if (!keys.length) {
62172             return callback(null);
62173         }
62174
62175         var results = {};
62176
62177         var listeners = [];
62178         var addListener = function (fn) {
62179             listeners.unshift(fn);
62180         };
62181         var removeListener = function (fn) {
62182             for (var i = 0; i < listeners.length; i += 1) {
62183                 if (listeners[i] === fn) {
62184                     listeners.splice(i, 1);
62185                     return;
62186                 }
62187             }
62188         };
62189         var taskComplete = function () {
62190             _each(listeners.slice(0), function (fn) {
62191                 fn();
62192             });
62193         };
62194
62195         addListener(function () {
62196             if (_keys(results).length === keys.length) {
62197                 callback(null, results);
62198                 callback = function () {};
62199             }
62200         });
62201
62202         _each(keys, function (k) {
62203             var task = (tasks[k] instanceof Function) ? [tasks[k]]: tasks[k];
62204             var taskCallback = function (err) {
62205                 var args = Array.prototype.slice.call(arguments, 1);
62206                 if (args.length <= 1) {
62207                     args = args[0];
62208                 }
62209                 if (err) {
62210                     var safeResults = {};
62211                     _each(_keys(results), function(rkey) {
62212                         safeResults[rkey] = results[rkey];
62213                     });
62214                     safeResults[k] = args;
62215                     callback(err, safeResults);
62216                     // stop subsequent errors hitting callback multiple times
62217                     callback = function () {};
62218                 }
62219                 else {
62220                     results[k] = args;
62221                     async.setImmediate(taskComplete);
62222                 }
62223             };
62224             var requires = task.slice(0, Math.abs(task.length - 1)) || [];
62225             var ready = function () {
62226                 return _reduce(requires, function (a, x) {
62227                     return (a && results.hasOwnProperty(x));
62228                 }, true) && !results.hasOwnProperty(k);
62229             };
62230             if (ready()) {
62231                 task[task.length - 1](taskCallback, results);
62232             }
62233             else {
62234                 var listener = function () {
62235                     if (ready()) {
62236                         removeListener(listener);
62237                         task[task.length - 1](taskCallback, results);
62238                     }
62239                 };
62240                 addListener(listener);
62241             }
62242         });
62243     };
62244
62245     async.waterfall = function (tasks, callback) {
62246         callback = callback || function () {};
62247         if (tasks.constructor !== Array) {
62248           var err = new Error('First argument to waterfall must be an array of functions');
62249           return callback(err);
62250         }
62251         if (!tasks.length) {
62252             return callback();
62253         }
62254         var wrapIterator = function (iterator) {
62255             return function (err) {
62256                 if (err) {
62257                     callback.apply(null, arguments);
62258                     callback = function () {};
62259                 }
62260                 else {
62261                     var args = Array.prototype.slice.call(arguments, 1);
62262                     var next = iterator.next();
62263                     if (next) {
62264                         args.push(wrapIterator(next));
62265                     }
62266                     else {
62267                         args.push(callback);
62268                     }
62269                     async.setImmediate(function () {
62270                         iterator.apply(null, args);
62271                     });
62272                 }
62273             };
62274         };
62275         wrapIterator(async.iterator(tasks))();
62276     };
62277
62278     var _parallel = function(eachfn, tasks, callback) {
62279         callback = callback || function () {};
62280         if (tasks.constructor === Array) {
62281             eachfn.map(tasks, function (fn, callback) {
62282                 if (fn) {
62283                     fn(function (err) {
62284                         var args = Array.prototype.slice.call(arguments, 1);
62285                         if (args.length <= 1) {
62286                             args = args[0];
62287                         }
62288                         callback.call(null, err, args);
62289                     });
62290                 }
62291             }, callback);
62292         }
62293         else {
62294             var results = {};
62295             eachfn.each(_keys(tasks), function (k, callback) {
62296                 tasks[k](function (err) {
62297                     var args = Array.prototype.slice.call(arguments, 1);
62298                     if (args.length <= 1) {
62299                         args = args[0];
62300                     }
62301                     results[k] = args;
62302                     callback(err);
62303                 });
62304             }, function (err) {
62305                 callback(err, results);
62306             });
62307         }
62308     };
62309
62310     async.parallel = function (tasks, callback) {
62311         _parallel({ map: async.map, each: async.each }, tasks, callback);
62312     };
62313
62314     async.parallelLimit = function(tasks, limit, callback) {
62315         _parallel({ map: _mapLimit(limit), each: _eachLimit(limit) }, tasks, callback);
62316     };
62317
62318     async.series = function (tasks, callback) {
62319         callback = callback || function () {};
62320         if (tasks.constructor === Array) {
62321             async.mapSeries(tasks, function (fn, callback) {
62322                 if (fn) {
62323                     fn(function (err) {
62324                         var args = Array.prototype.slice.call(arguments, 1);
62325                         if (args.length <= 1) {
62326                             args = args[0];
62327                         }
62328                         callback.call(null, err, args);
62329                     });
62330                 }
62331             }, callback);
62332         }
62333         else {
62334             var results = {};
62335             async.eachSeries(_keys(tasks), function (k, callback) {
62336                 tasks[k](function (err) {
62337                     var args = Array.prototype.slice.call(arguments, 1);
62338                     if (args.length <= 1) {
62339                         args = args[0];
62340                     }
62341                     results[k] = args;
62342                     callback(err);
62343                 });
62344             }, function (err) {
62345                 callback(err, results);
62346             });
62347         }
62348     };
62349
62350     async.iterator = function (tasks) {
62351         var makeCallback = function (index) {
62352             var fn = function () {
62353                 if (tasks.length) {
62354                     tasks[index].apply(null, arguments);
62355                 }
62356                 return fn.next();
62357             };
62358             fn.next = function () {
62359                 return (index < tasks.length - 1) ? makeCallback(index + 1): null;
62360             };
62361             return fn;
62362         };
62363         return makeCallback(0);
62364     };
62365
62366     async.apply = function (fn) {
62367         var args = Array.prototype.slice.call(arguments, 1);
62368         return function () {
62369             return fn.apply(
62370                 null, args.concat(Array.prototype.slice.call(arguments))
62371             );
62372         };
62373     };
62374
62375     var _concat = function (eachfn, arr, fn, callback) {
62376         var r = [];
62377         eachfn(arr, function (x, cb) {
62378             fn(x, function (err, y) {
62379                 r = r.concat(y || []);
62380                 cb(err);
62381             });
62382         }, function (err) {
62383             callback(err, r);
62384         });
62385     };
62386     async.concat = doParallel(_concat);
62387     async.concatSeries = doSeries(_concat);
62388
62389     async.whilst = function (test, iterator, callback) {
62390         if (test()) {
62391             iterator(function (err) {
62392                 if (err) {
62393                     return callback(err);
62394                 }
62395                 async.whilst(test, iterator, callback);
62396             });
62397         }
62398         else {
62399             callback();
62400         }
62401     };
62402
62403     async.doWhilst = function (iterator, test, callback) {
62404         iterator(function (err) {
62405             if (err) {
62406                 return callback(err);
62407             }
62408             if (test()) {
62409                 async.doWhilst(iterator, test, callback);
62410             }
62411             else {
62412                 callback();
62413             }
62414         });
62415     };
62416
62417     async.until = function (test, iterator, callback) {
62418         if (!test()) {
62419             iterator(function (err) {
62420                 if (err) {
62421                     return callback(err);
62422                 }
62423                 async.until(test, iterator, callback);
62424             });
62425         }
62426         else {
62427             callback();
62428         }
62429     };
62430
62431     async.doUntil = function (iterator, test, callback) {
62432         iterator(function (err) {
62433             if (err) {
62434                 return callback(err);
62435             }
62436             if (!test()) {
62437                 async.doUntil(iterator, test, callback);
62438             }
62439             else {
62440                 callback();
62441             }
62442         });
62443     };
62444
62445     async.queue = function (worker, concurrency) {
62446         if (concurrency === undefined) {
62447             concurrency = 1;
62448         }
62449         function _insert(q, data, pos, callback) {
62450           if(data.constructor !== Array) {
62451               data = [data];
62452           }
62453           _each(data, function(task) {
62454               var item = {
62455                   data: task,
62456                   callback: typeof callback === 'function' ? callback : null
62457               };
62458
62459               if (pos) {
62460                 q.tasks.unshift(item);
62461               } else {
62462                 q.tasks.push(item);
62463               }
62464
62465               if (q.saturated && q.tasks.length === concurrency) {
62466                   q.saturated();
62467               }
62468               async.setImmediate(q.process);
62469           });
62470         }
62471
62472         var workers = 0;
62473         var q = {
62474             tasks: [],
62475             concurrency: concurrency,
62476             saturated: null,
62477             empty: null,
62478             drain: null,
62479             push: function (data, callback) {
62480               _insert(q, data, false, callback);
62481             },
62482             unshift: function (data, callback) {
62483               _insert(q, data, true, callback);
62484             },
62485             process: function () {
62486                 if (workers < q.concurrency && q.tasks.length) {
62487                     var task = q.tasks.shift();
62488                     if (q.empty && q.tasks.length === 0) {
62489                         q.empty();
62490                     }
62491                     workers += 1;
62492                     var next = function () {
62493                         workers -= 1;
62494                         if (task.callback) {
62495                             task.callback.apply(task, arguments);
62496                         }
62497                         if (q.drain && q.tasks.length + workers === 0) {
62498                             q.drain();
62499                         }
62500                         q.process();
62501                     };
62502                     var cb = only_once(next);
62503                     worker(task.data, cb);
62504                 }
62505             },
62506             length: function () {
62507                 return q.tasks.length;
62508             },
62509             running: function () {
62510                 return workers;
62511             }
62512         };
62513         return q;
62514     };
62515
62516     async.cargo = function (worker, payload) {
62517         var working     = false,
62518             tasks       = [];
62519
62520         var cargo = {
62521             tasks: tasks,
62522             payload: payload,
62523             saturated: null,
62524             empty: null,
62525             drain: null,
62526             push: function (data, callback) {
62527                 if(data.constructor !== Array) {
62528                     data = [data];
62529                 }
62530                 _each(data, function(task) {
62531                     tasks.push({
62532                         data: task,
62533                         callback: typeof callback === 'function' ? callback : null
62534                     });
62535                     if (cargo.saturated && tasks.length === payload) {
62536                         cargo.saturated();
62537                     }
62538                 });
62539                 async.setImmediate(cargo.process);
62540             },
62541             process: function process() {
62542                 if (working) return;
62543                 if (tasks.length === 0) {
62544                     if(cargo.drain) cargo.drain();
62545                     return;
62546                 }
62547
62548                 var ts = typeof payload === 'number'
62549                             ? tasks.splice(0, payload)
62550                             : tasks.splice(0);
62551
62552                 var ds = _map(ts, function (task) {
62553                     return task.data;
62554                 });
62555
62556                 if(cargo.empty) cargo.empty();
62557                 working = true;
62558                 worker(ds, function () {
62559                     working = false;
62560
62561                     var args = arguments;
62562                     _each(ts, function (data) {
62563                         if (data.callback) {
62564                             data.callback.apply(null, args);
62565                         }
62566                     });
62567
62568                     process();
62569                 });
62570             },
62571             length: function () {
62572                 return tasks.length;
62573             },
62574             running: function () {
62575                 return working;
62576             }
62577         };
62578         return cargo;
62579     };
62580
62581     var _console_fn = function (name) {
62582         return function (fn) {
62583             var args = Array.prototype.slice.call(arguments, 1);
62584             fn.apply(null, args.concat([function (err) {
62585                 var args = Array.prototype.slice.call(arguments, 1);
62586                 if (typeof console !== 'undefined') {
62587                     if (err) {
62588                         if (console.error) {
62589                             console.error(err);
62590                         }
62591                     }
62592                     else if (console[name]) {
62593                         _each(args, function (x) {
62594                             console[name](x);
62595                         });
62596                     }
62597                 }
62598             }]));
62599         };
62600     };
62601     async.log = _console_fn('log');
62602     async.dir = _console_fn('dir');
62603     /*async.info = _console_fn('info');
62604     async.warn = _console_fn('warn');
62605     async.error = _console_fn('error');*/
62606
62607     async.memoize = function (fn, hasher) {
62608         var memo = {};
62609         var queues = {};
62610         hasher = hasher || function (x) {
62611             return x;
62612         };
62613         var memoized = function () {
62614             var args = Array.prototype.slice.call(arguments);
62615             var callback = args.pop();
62616             var key = hasher.apply(null, args);
62617             if (key in memo) {
62618                 callback.apply(null, memo[key]);
62619             }
62620             else if (key in queues) {
62621                 queues[key].push(callback);
62622             }
62623             else {
62624                 queues[key] = [callback];
62625                 fn.apply(null, args.concat([function () {
62626                     memo[key] = arguments;
62627                     var q = queues[key];
62628                     delete queues[key];
62629                     for (var i = 0, l = q.length; i < l; i++) {
62630                       q[i].apply(null, arguments);
62631                     }
62632                 }]));
62633             }
62634         };
62635         memoized.memo = memo;
62636         memoized.unmemoized = fn;
62637         return memoized;
62638     };
62639
62640     async.unmemoize = function (fn) {
62641       return function () {
62642         return (fn.unmemoized || fn).apply(null, arguments);
62643       };
62644     };
62645
62646     async.times = function (count, iterator, callback) {
62647         var counter = [];
62648         for (var i = 0; i < count; i++) {
62649             counter.push(i);
62650         }
62651         return async.map(counter, iterator, callback);
62652     };
62653
62654     async.timesSeries = function (count, iterator, callback) {
62655         var counter = [];
62656         for (var i = 0; i < count; i++) {
62657             counter.push(i);
62658         }
62659         return async.mapSeries(counter, iterator, callback);
62660     };
62661
62662     async.compose = function (/* functions... */) {
62663         var fns = Array.prototype.reverse.call(arguments);
62664         return function () {
62665             var that = this;
62666             var args = Array.prototype.slice.call(arguments);
62667             var callback = args.pop();
62668             async.reduce(fns, args, function (newargs, fn, cb) {
62669                 fn.apply(that, newargs.concat([function () {
62670                     var err = arguments[0];
62671                     var nextargs = Array.prototype.slice.call(arguments, 1);
62672                     cb(err, nextargs);
62673                 }]))
62674             },
62675             function (err, results) {
62676                 callback.apply(that, [err].concat(results));
62677             });
62678         };
62679     };
62680
62681     var _applyEach = function (eachfn, fns /*args...*/) {
62682         var go = function () {
62683             var that = this;
62684             var args = Array.prototype.slice.call(arguments);
62685             var callback = args.pop();
62686             return eachfn(fns, function (fn, cb) {
62687                 fn.apply(that, args.concat([cb]));
62688             },
62689             callback);
62690         };
62691         if (arguments.length > 2) {
62692             var args = Array.prototype.slice.call(arguments, 2);
62693             return go.apply(this, args);
62694         }
62695         else {
62696             return go;
62697         }
62698     };
62699     async.applyEach = doParallel(_applyEach);
62700     async.applyEachSeries = doSeries(_applyEach);
62701
62702     async.forever = function (fn, callback) {
62703         function next(err) {
62704             if (err) {
62705                 if (callback) {
62706                     return callback(err);
62707                 }
62708                 throw err;
62709             }
62710             fn(next);
62711         }
62712         next();
62713     };
62714
62715     root.async = async;
62716
62717 }());
62718 (function() {
62719
62720     var redblack = {};
62721     var root = this;
62722     var orig = root.redblack;
62723
62724     if (typeof module !== 'undefined' && module.exports) {
62725         module.exports = redblack;
62726     } else {
62727         root.redblack = redblack;
62728     }
62729
62730     redblack.VERSION = '0.1.2';
62731
62732     redblack.noConflict = function() {
62733         root.redblack = orig;
62734         return redblack;
62735     };
62736
62737     redblack.tree = function() {
62738         return new Tree();
62739     };
62740
62741     var BLACK = redblack.BLACK = 'black';
62742     var RED = redblack.RED = 'red';
62743
62744     // Node
62745     // ---------------
62746
62747     function Node(key, value) {
62748         this.key = key;
62749         this.value = value;
62750         this.color = RED;
62751         this.left = null;
62752         this.right = null;
62753         this.parent = null;
62754     };
62755
62756     Node.prototype.grandparent = function() {
62757         if (this.parent === null) return null;
62758         return this.parent.parent;
62759     };
62760
62761     Node.prototype.sibling = function() {
62762         if (this.parent === null) return null;
62763         return this === this.parent.left ? this.parent.right : this.parent.left;
62764     };
62765
62766     Node.prototype.uncle = function() {
62767         if (this.parent === null) return null;
62768         return this.parent.sibling();
62769     };
62770
62771     // Cursor
62772     // ---------------
62773
62774     function Cursor(tree, start, end) {
62775         this.tree = tree;
62776         this.start = start;
62777         this.end = end;
62778
62779         var self = this;
62780         this.walk = function walk(node, iterator) {
62781             if (node === null) return;
62782
62783             if (start !== undefined && node.key < start) {
62784                 walk(node.right, iterator);
62785             } else if (end !== undefined && node.key > end) {
62786                 walk(node.left, iterator);
62787             } else {
62788                 walk(node.left, iterator);
62789                 iterator(node.value, node.key, self.tree);
62790                 walk(node.right, iterator);
62791             }
62792         };
62793     };
62794
62795     Cursor.prototype.forEach = function(iterator) {
62796         this.walk(this.tree.root, iterator);
62797     };
62798
62799     Cursor.prototype.map = function(iterator) {
62800         var results = [];
62801
62802         this.forEach(function(value, key, tree) {
62803             results.push(iterator(value, key, tree));
62804         });
62805
62806         return results;
62807     };
62808
62809     // Tree
62810     // ---------------
62811
62812     function Tree() {
62813         this.root = null;
62814         this.balancer = new Balancer(this);
62815     };
62816
62817     Tree.prototype.get = function(key) {
62818         var node = find(this.root, key);
62819         return node === null ? null : node.value;
62820     };
62821
62822     Tree.prototype.insert = function(key, value) {
62823         var newNode = new Node(key, value);
62824
62825         if (this.root === null) {
62826             this.root = newNode;
62827         } else {
62828             var node = this.root;
62829
62830             while (true) {
62831                 if (key < node.key) {
62832                     if (node.left === null) {
62833                         node.left = newNode;
62834                         break;
62835                     } else {
62836                         node = node.left;
62837                     }
62838                 } else if (key > node.key) {
62839                     if (node.right === null) {
62840                         node.right = newNode;
62841                         break;
62842                     } else {
62843                         node = node.right;
62844                     }
62845                 } else {
62846                     node.value = value;
62847                     return;
62848                 }
62849             }
62850
62851             newNode.parent = node;
62852         }
62853
62854         this.balancer.inserted(newNode);
62855     };
62856
62857     Tree.prototype.delete = function(key) {
62858         var node = find(this.root, key);
62859         if (node === null) return;
62860
62861         if (node.left !== null && node.right !== null) {
62862             var pred = node.left;
62863             while (pred.right !== null) pred = pred.right;
62864
62865             node.key = pred.key;
62866             node.value = pred.value;
62867             node = pred;
62868         }
62869
62870         var child = (node.right === null) ? node.left : node.right;
62871         if (nodeColor(node) === BLACK) {
62872             node.color = nodeColor(child);
62873             this.balancer.deleted(node);
62874         }
62875
62876         this.balancer.replaceNode(node, child);
62877
62878         if (nodeColor(this.root) === RED) {
62879             this.root.color = BLACK;
62880         }
62881     };
62882
62883     Tree.prototype.range = function(start, end) {
62884         return new Cursor(this, start, end);
62885     };
62886
62887     // Proxy cursor methods
62888     for (var method in Cursor.prototype) {
62889         if (Cursor.prototype.hasOwnProperty(method)) {
62890             var func = Cursor.prototype[method];
62891             Tree.prototype[method] = function() {
62892                 var cursor = new Cursor(this);
62893                 return func.apply(cursor, arguments);
62894             };
62895         }
62896     }
62897
62898     // Balancer
62899     // ---------------
62900
62901     function Balancer(tree) {
62902         this.tree = tree;
62903     };
62904
62905     Balancer.prototype.inserted = function(node) {
62906         this.insertCase1(node);
62907     };
62908
62909     Balancer.prototype.deleted = function(node) {
62910         this.deleteCase1(node);
62911     };
62912
62913     Balancer.prototype.replaceNode = function(original, replacement) {
62914         if (original.parent === null) {
62915             this.tree.root = replacement;
62916         } else {
62917             if (original === original.parent.left) {
62918                 original.parent.left = replacement;
62919             } else {
62920                 original.parent.right = replacement;
62921             }
62922         }
62923
62924         if (replacement !== null) {
62925             replacement.parent = original.parent;
62926         }
62927     };
62928
62929     Balancer.prototype.rotateLeft = function(node) {
62930         var right = node.right;
62931         this.replaceNode(node, right);
62932
62933         // Update pointers
62934         node.right = right.left;
62935         if (right.left !== null) right.left.parent = node;
62936         right.left = node;
62937         node.parent = right;
62938     };
62939
62940     Balancer.prototype.rotateRight = function(node) {
62941         var left = node.left;
62942         this.replaceNode(node, left);
62943
62944         // Update pointers
62945         node.left = left.right;
62946         if (left.right !== null) left.right.parent = node;
62947         left.right = node;
62948         node.parent = left;
62949     };
62950
62951     Balancer.prototype.insertCase1 = function(node) {
62952         if (node.parent === null) {
62953             node.color = BLACK;
62954         } else {
62955             this.insertCase2(node);
62956         }
62957     };
62958
62959     Balancer.prototype.insertCase2 = function(node) {
62960         if (nodeColor(node.parent) === BLACK) {
62961             return;
62962         } else {
62963             this.insertCase3(node);
62964         }
62965     };
62966
62967     Balancer.prototype.insertCase3 = function(node) {
62968         var uncle = node.uncle();
62969         var grandparent = node.grandparent();
62970
62971         if (uncle !== null && nodeColor(uncle) === RED) {
62972             node.parent.color = BLACK;
62973             uncle.color = BLACK;
62974             grandparent.color = RED;
62975             this.insertCase1(grandparent);
62976         } else {
62977             this.insertCase4(node);
62978         }
62979     };
62980
62981     Balancer.prototype.insertCase4 = function(node) {
62982         var grandparent = node.grandparent();
62983
62984         if (node === node.parent.right && node.parent === grandparent.left) {
62985             this.rotateLeft(node.parent);
62986             node = node.left;
62987         } else if (node === node.parent.left && node.parent === grandparent.right) {
62988             this.rotateRight(node.parent);
62989             node = node.right;
62990         }
62991
62992         this.insertCase5(node);
62993     };
62994
62995     Balancer.prototype.insertCase5 = function(node) {
62996         var grandparent = node.grandparent();
62997
62998         node.parent.color = BLACK;
62999         grandparent.color = RED;
63000
63001         if (node === node.parent.left && node.parent === grandparent.left) {
63002             this.rotateRight(grandparent);
63003         } else if (node === node.parent.right && node.parent === grandparent.right) {
63004             this.rotateLeft(grandparent);
63005         }
63006     };
63007
63008     Balancer.prototype.deleteCase1 = function(node) {
63009         if (node.parent !== null) this.deleteCase2(node);
63010     };
63011
63012     Balancer.prototype.deleteCase2 = function(node) {
63013         var sibling = node.sibling();
63014
63015         if (nodeColor(sibling) === RED) {
63016             node.parent.color = RED;
63017             sibling.color = BLACK;
63018             if (node === node.parent.left) {
63019                 this.rotateLeft(node.parent);
63020             } else {
63021                 this.rotateRight(node.parent);
63022             }
63023         }
63024
63025         this.deleteCase3(node);
63026     };
63027
63028     Balancer.prototype.deleteCase3 = function(node) {
63029         var sibling = node.sibling();
63030
63031         if (nodeColor(node.parent) === BLACK &&
63032             nodeColor(sibling) === BLACK &&
63033             nodeColor(sibling.left) === BLACK &&
63034             nodeColor(sibling.right) === BLACK) {
63035
63036             sibling.color = RED;
63037             this.deleteCase1(node.parent);
63038         } else {
63039             this.deleteCase4(node);
63040         }
63041     };
63042
63043     Balancer.prototype.deleteCase4 = function(node) {
63044         var sibling = node.sibling();
63045
63046         if (nodeColor(node.parent) === RED &&
63047             nodeColor(sibling) === BLACK &&
63048             nodeColor(sibling.left) === BLACK &&
63049             nodeColor(sibling.right) === BLACK) {
63050
63051             sibling.color = RED;
63052             node.parent.color = BLACK;
63053         } else {
63054             this.deleteCase5(node);
63055         }
63056     };
63057
63058     Balancer.prototype.deleteCase5 = function(node) {
63059         var sibling = node.sibling();
63060
63061         if (node === node.parent.left &&
63062             nodeColor(sibling) === BLACK &&
63063             nodeColor(sibling.left) === RED &&
63064             nodeColor(sibling.right) === BLACK) {
63065
63066             sibling.color = RED;
63067             sibling.left.color = BLACK;
63068             this.rotateRight(sibling);
63069         } else if (node === node.parent.right &&
63070             nodeColor(sibling) === BLACK &&
63071             nodeColor(sibling.right) === RED &&
63072             nodeColor(sibling.left) === BLACK) {
63073
63074             sibling.color = RED;
63075             sibling.right.color = BLACK;
63076             this.rotateLeft(sibling);
63077         }
63078
63079         this.deleteCase6(node);
63080     };
63081
63082     Balancer.prototype.deleteCase6 = function(node) {
63083         var sibling = node.sibling();
63084
63085         sibling.color = nodeColor(node.parent);
63086         node.parent.color = BLACK;
63087
63088         if (node === node.parent.left) {
63089             sibling.right.color = BLACK;
63090             this.rotateLeft(node.parent);
63091         } else {
63092             sibling.left.color = BLACK;
63093             this.rotateRight(node.parent);
63094         }
63095     };
63096
63097     // Helpers
63098     // ---------------
63099
63100     function nodeColor(node) {
63101         return node === null ? BLACK : node.color;
63102     };
63103
63104     function find(node, key) {
63105         while (node !== null) {
63106             if (key === node.key) {
63107                 return node;
63108             } else if (key < node.key) {
63109                 node = node.left;
63110             } else if (key > node.key) {
63111                 node = node.right;
63112             }
63113         }
63114
63115         return node;
63116     };
63117
63118 })();
63119 define.unordered = true;define('ripple/accelerometer', function (require, exports, module) {
63120 /*
63121  *  Copyright 2011 Research In Motion Limited.
63122  *
63123  * Licensed under the Apache License, Version 2.0 (the "License");
63124  * you may not use this file except in compliance with the License.
63125  * You may obtain a copy of the License at
63126  *
63127  * http://www.apache.org/licenses/LICENSE-2.0
63128  *
63129  * Unless required by applicable law or agreed to in writing, software
63130  * distributed under the License is distributed on an "AS IS" BASIS,
63131  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
63132  * See the License for the specific language governing permissions and
63133  * limitations under the License.
63134  */
63135 var _self,
63136     utils = require('ripple/utils'),
63137     exception = require('ripple/exception'),
63138     event = require('ripple/event'),
63139     Rotation = require('ripple/platform/w3c/1.0/Rotation'),
63140     Acceleration = require('ripple/platform/w3c/1.0/Acceleration'),
63141     _motion = {
63142         acceleration: new Acceleration(0, 0, 0),
63143         accelerationIncludingGravity: new Acceleration(0, 0, -9.81),
63144         rotationRate: new Rotation(0, 0, 0),
63145         orientation: new Rotation(0, 0, 0),
63146         interval: 60000,
63147         timestamp: new Date().getTime()
63148     };
63149
63150 function _validateAccelerometerInfo(x, y, z) {
63151     return !(isNaN(x) || isNaN(y) || isNaN(z));
63152 }
63153
63154 _self = {
63155     getInfo: function () {
63156         return utils.copy(_motion);
63157     },
63158
63159     setInfo: function (e) {
63160         var triggerDeviceMotion = false,
63161             triggerDeviceOrientation = false;
63162
63163         if (e.x !== undefined && e.y !== undefined && e.z !== undefined) {
63164             _motion = {
63165                 acceleration: new Acceleration(e.x, e.y, e.z),
63166                 accelerationIncludingGravity: new Acceleration(e.x, e.y, e.z),
63167                 rotationRate: new Rotation(0, 0, 0),
63168                 orientation: new Rotation(e.alpha, e.beta, e.gamma),
63169                 timestamp: new Date().getTime()
63170             };
63171             triggerDeviceMotion = true;
63172             triggerDeviceOrientation = true;
63173         }
63174         else {
63175             _motion = {
63176                 acceleration: new Acceleration(0, 0, 0),
63177                 accelerationIncludingGravity: new Acceleration(0, 0, -9.81),
63178                 rotationRate: new Rotation(0, 0, 0),
63179                 orientation: new Rotation(0, 0, 0),
63180                 timestamp: new Date().getTime()
63181             };
63182         }
63183
63184         if (triggerDeviceMotion) {
63185             event.trigger("DeviceMotionEvent", [_motion]);
63186         }
63187
63188         if (triggerDeviceOrientation) {
63189             event.trigger("DeviceOrientationEvent", [_motion]);
63190         }
63191
63192         event.trigger("AccelerometerInfoChangedEvent", [_motion]);
63193     },
63194
63195     triggerEvent: function() {
63196         event.trigger("DeviceMotionEvent", [_motion]);
63197         event.trigger("DeviceOrientationEvent", [_motion]);
63198         event.trigger("AccelerometerInfoChangedEvent", [_motion]);
63199     },
63200
63201     shake: function (shakeXtimes) {
63202         var id,
63203             count = 1,
63204             stopCount = shakeXtimes || 17,
63205             oldX = _motion.accelerationIncludingGravity.x;
63206
63207         id = setInterval(function () {
63208             var freq = 1,
63209                 amp = 30,
63210                 value = Math.round(amp * Math.sin(freq * count * (180 / Math.PI)) * 100) / 100;
63211
63212             if (count > stopCount) {
63213                 _motion.acceleration.x = oldX;
63214                 _motion.accelerationIncludingGravity.x = oldX;
63215                 event.trigger("AccelerometerInfoChangedEvent", [_motion]);
63216                 clearInterval(id);
63217                 return;
63218             }
63219
63220             _motion.acceleration.x = value;
63221             _motion.accelerationIncludingGravity.x = value;
63222
63223             event.trigger("AccelerometerInfoChangedEvent", [_motion]);
63224
63225             count++;
63226
63227         }, 80);
63228     },
63229
63230     init: function () {
63231         event.on("DeviceMotionEventAddedEvent", function () {
63232             _self.triggerEvent();
63233         });
63234         event.on("DeviceOrientationEventAddedEvent", function () {
63235             _self.triggerEvent();
63236         });
63237     }
63238 };
63239
63240 module.exports = _self;
63241
63242 });
63243 define('ripple/app', function (require, exports, module) {
63244 /*
63245  *  Copyright 2011 Research In Motion Limited.
63246  *
63247  * Licensed under the Apache License, Version 2.0 (the "License");
63248  * you may not use this file except in compliance with the License.
63249  * You may obtain a copy of the License at
63250  *
63251  * http://www.apache.org/licenses/LICENSE-2.0
63252  *
63253  * Unless required by applicable law or agreed to in writing, software
63254  * distributed under the License is distributed on an "AS IS" BASIS,
63255  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
63256  * See the License for the specific language governing permissions and
63257  * limitations under the License.
63258  */
63259 var _data = {},
63260     utils = require('ripple/utils'),
63261     _self;
63262
63263 _self = {
63264     setInfo: function (info) {
63265         if (!info) {
63266             _data = {};
63267         }
63268         _data = info;
63269     },
63270
63271     getInfo: function () {
63272         return utils.copy(_data);
63273     },
63274
63275     isPreferenceReadOnly: function (key) {
63276         return (_data.preferences &&
63277                 _data.preferences[key] &&
63278                 _data.preferences[key].readonly &&
63279                 _data.preferences[key].readonly === true);
63280     },
63281
63282     validateVersion: function (configValidationObject) {
63283         // TODO: WTF figure this out, platform is empty object when require at require time
63284         // could be that the new platform _getBuilder code dies when called, beforre it is initialized
63285         var spec = require('ripple/platform').current();
63286         if (typeof spec.config.validateVersion === "function" && configValidationObject) {
63287             return spec.config.validateVersion(configValidationObject);
63288         }
63289
63290         return true;
63291     },
63292
63293     saveInfo: function (configValidationObject) {
63294         var spec = require('ripple/platform').current(),
63295             info = null;
63296         if (typeof spec.config.extractInfo === "function") {
63297             info = spec.config.extractInfo(configValidationObject);
63298         }
63299
63300         if (info) {
63301             _self.setInfo(info);
63302         }
63303     }
63304
63305 };
63306
63307 module.exports = _self;
63308
63309 });
63310 define('ripple/appcache', function (require, exports, module) {
63311 /*
63312  *  Copyright 2011 Research In Motion Limited.
63313  *
63314  * Licensed under the Apache License, Version 2.0 (the "License");
63315  * you may not use this file except in compliance with the License.
63316  * You may obtain a copy of the License at
63317  *
63318  * http://www.apache.org/licenses/LICENSE-2.0
63319  *
63320  * Unless required by applicable law or agreed to in writing, software
63321  * distributed under the License is distributed on an "AS IS" BASIS,
63322  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
63323  * See the License for the specific language governing permissions and
63324  * limitations under the License.
63325  */
63326 module.exports = {
63327     initialize: function () {
63328         window.addEventListener('load', function (e) {
63329             window.applicationCache.addEventListener('updateready', function (e) {
63330                 if (window.applicationCache.status === window.applicationCache.UPDATEREADY) {
63331                     window.applicationCache.swapCache();
63332                     window.location.reload();
63333                 }
63334             }, false);
63335         }, false);
63336     }
63337 };
63338
63339 });
63340 define('ripple/bootstrap', function (require, exports, module) {
63341 /*
63342  *  Copyright 2011 Research In Motion Limited.
63343  *
63344  * Licensed under the Apache License, Version 2.0 (the "License");
63345  * you may not use this file except in compliance with the License.
63346  * You may obtain a copy of the License at
63347  *
63348  * http://www.apache.org/licenses/LICENSE-2.0
63349  *
63350  * Unless required by applicable law or agreed to in writing, software
63351  * distributed under the License is distributed on an "AS IS" BASIS,
63352  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
63353  * See the License for the specific language governing permissions and
63354  * limitations under the License.
63355  */
63356 var _bound,
63357     _console = require('ripple/console'),
63358     utils = require('ripple/utils'),
63359     ui = require('ripple/ui'),
63360     db = require('ripple/db'),
63361     _CURRENT_URL = "current-url",
63362     resizer = require('ripple/resizer'),
63363     platform = require('ripple/platform');
63364
63365 var _srcChangedObserver = new WebKitMutationObserver(function (mutations) {
63366             utils.forEach(mutations, function (mutation) {
63367                 _bindObjectsToFrame(mutation.target);
63368             });
63369         });
63370
63371 function _observeIframeAdded(doc) {
63372     doc._iframeAddedObserver.observe(doc, {childList: true, subtree: true});
63373 }
63374
63375 function _bindObjects(win, doc) {
63376     if (!win.tinyHippos) {
63377         require('ripple/emulatorBridge').link(win, doc);
63378         /// require('ripple/platform/tizen/2.0/touchEvent').mask(win, doc);
63379         require('ripple/touchEventEmulator').mask(win, doc);
63380         require('ripple/hwKeyEmulator').init(win, doc);
63381         require('ripple/documentEventListener').mask(win, doc);
63382         require('ripple/deviceMotionEmulator').init(win, doc);
63383         require('ripple/resizer').init(win, doc);
63384         win.addEventListener("DOMContentLoaded", function () {
63385             var iframes =  $(this.document).find("iframe");
63386             // Observe iframe added event so that we can bind objects to newly added iframes
63387             if (!this.document._iframeAddedObserver) {
63388                 this.document._iframeAddedObserver = new WebKitMutationObserver(function (mutations) {
63389                     utils.forEach(mutations, function (mutation) {
63390                         for (var i in mutation.addedNodes) {
63391                             var node = mutation.addedNodes[i];
63392                             if (node.tagName && (node.tagName.toUpperCase() === "IFRAME")) {
63393                                 _bindObjectsToFrame(node);
63394                             }
63395                         }
63396                     });
63397                 });
63398                 _observeIframeAdded(this.document);
63399             }
63400             iframes.each(function () {
63401                 _bindObjectsToFrame(this);
63402             });
63403
63404         });
63405         win.frameElement._bound = true;
63406     }
63407 }
63408
63409 function _beforeLoad() {
63410     this._bound = false;
63411     _bindObjects(this.contentWindow, this.contentDocument);
63412     this._intervalId = window.setInterval(function () {
63413         if (this._bound) {
63414             window.clearInterval(this._intervalId);
63415         } else {
63416             _bindObjects(this.contentWindow, this.contentDocument);
63417         }
63418     }.bind(this), 1);
63419 }
63420
63421 function _bindObjectsToFrame(frame) {
63422     _srcChangedObserver.observe(frame, {attributes: true, attributeFilter: ["src"]});
63423     frame.addEventListener("beforeload", _beforeLoad);
63424     // beforeload event of an iframe will not be triggered unless we detach and
63425     // then attach the iframe to the dom tree
63426     var parentNode = frame.parentNode;
63427     var nextNode = frame.nextNode;
63428     if (parentNode) {
63429         // Disable iframe added observer to avoid infinite loop of binding objects
63430         if (frame.ownerDocument && frame.ownerDocument._iframeAddedObserver) {
63431             frame.ownerDocument._iframeAddedObserver.disconnect();
63432         }
63433         parentNode.removeChild(frame);
63434         if (nextNode)
63435             nextNode.insertBefore(frame);
63436         else
63437             parentNode.appendChild(frame);
63438
63439         if (frame.ownerDocument && frame.ownerDocument._iframeAddedObserver) {
63440             _observeIframeAdded(frame.ownerDocument);
63441         }
63442     }
63443 }
63444
63445 function _createFrame(src) {
63446     var frame = document.createElement("iframe");
63447     frame.setAttribute("id", "document");
63448     frame.src = src;
63449
63450     if (ui.registered("omnibar")) {
63451         _bindObjectsToFrame(frame);
63452     }
63453
63454     return frame;
63455 }
63456
63457 function _cleanBody() {
63458     require('ripple/utils').forEach(document.body.children, function (child) {
63459         if (child && child.id && !child.id.match(/ui|tooltip|bus/)) {
63460             document.body.removeChild(child);
63461         }
63462
63463         document.body.removeAttribute("style");
63464         document.body.removeAttribute("id");
63465         document.body.removeAttribute("class");
63466     });
63467 }
63468
63469 function reload() {
63470     window.tinyHipposReload = true;
63471     location.reload();
63472 }
63473
63474 function _post(src) {
63475     var event = require('ripple/event'),
63476         frame = _createFrame(src);
63477
63478     _console.log("Initialization Finished (Make it so.)");
63479
63480     frame.onload = function () {
63481         var bootLoader = document.querySelector("#emulator-booting"),
63482             id,
63483             iframe = document.getElementById('document'),
63484             viewportTagFound = false,
63485             viewportTagContent = {},
63486             viewportTagStr = "",
63487             tagProperties = [],
63488             propertyKey ="",
63489             propertyValue = "",
63490             curViewPortWidth = "",
63491             curViewPortHeight = "",
63492             layout = db.retrieve("layout") || "portrait",
63493             preLayout = "";
63494
63495         if (bootLoader) {
63496             document.querySelector("#ui").removeChild(bootLoader);
63497         }
63498
63499         // Workaround to enforce the content of iframe to rerender when scrolling
63500         document.getElementById('document').contentWindow.onscroll = function() {
63501             jQuery("#device-maskmask").show();
63502             setTimeout(function() {
63503                 jQuery("#device-maskmask").hide();
63504             }, 50);
63505         }
63506
63507         event.trigger("TinyHipposLoaded");
63508         _cleanBody();
63509         id = window.setInterval(_cleanBody, 20);
63510
63511         window.setTimeout(function () {
63512             window.clearInterval(id);
63513         }, 1200);
63514
63515         // Clean data for different app
63516         if (db.retrieve("current-url") !== db.retrieve("previous-url")) {
63517             db.remove("viewport_width");
63518             db.remove("viewport_height");
63519             db.remove("viewportTag");
63520             db.remove("prelayout");
63521         }
63522
63523         curViewPortWidth = db.retrieve("viewport_width");
63524         curViewPortHeight = db.retrieve("viewport_height");
63525         preLayout = db.retrieve("prelayout") || "portrait";
63526         db.save("previous-url", db.retrieve("current-url"));
63527
63528         if (iframe.contentDocument.getElementsByName('viewport')[0] !== undefined) {
63529             viewportTagStr = iframe.contentDocument.getElementsByName('viewport')[0].getAttribute("content");
63530             viewportTagStr = viewportTagStr.replace(/\s/g, '');
63531             tagProperties = viewportTagStr.split(",");
63532
63533             for (var i in tagProperties) {
63534                 propertyKey = tagProperties[i].split("=")[0];
63535                 propertyValue = tagProperties[i].split("=")[1];
63536                 viewportTagContent[propertyKey] = propertyValue;
63537             }
63538             viewportTagFound = true;
63539         }
63540
63541         // if viewport tag found (width, height)
63542         if (viewportTagFound && ((viewportTagContent['width'] !== undefined) || (viewportTagContent['height'] !== undefined))) {
63543             if ((viewportTagContent['width'] !== undefined)) {
63544                 if (curViewPortWidth !== viewportTagContent['width']) {
63545                     db.saveObject("viewportTag", viewportTagContent);
63546                     if (layout !== preLayout) {
63547                         db.save("prelayout", layout);
63548                         resizer.changeLayoutType(layout);
63549                         event.trigger("LayoutChanged", [layout], true);
63550                         frame.contentWindow.location.reload(); // get the updated screenAvailWidth, screenWidth....
63551                     } else {
63552                         resizer.changeLayoutType(layout);
63553                     }
63554                 }
63555             } else {
63556                 if (curViewPortHeight !== viewportTagContent['height']) {
63557                     db.saveObject("viewportTag", viewportTagContent);
63558                     if (layout !== preLayout) {
63559                         db.save("prelayout", layout);
63560                         resizer.changeLayoutType(layout);
63561                         event.trigger("LayoutChanged", [layout], true);
63562                         frame.contentWindow.location.reload(); // get the updated screenAvailWidth, screenWidth....
63563                     } else {
63564                         resizer.changeLayoutType(layout);
63565                     }
63566                 }
63567             }
63568         } else {
63569             // Set layout to portrait if no viewport tag detected
63570             resizer.changeLayoutType('portrait');
63571             event.trigger("LayoutChanged", ['portrait'], true);
63572         }
63573
63574         if (ui.registered("omnibar")) {
63575             //reset the onload function so that when navigating we can destroy
63576             //the iframe and create a new one so we can reinject the platform by
63577             //calling post again.
63578             frame.onload = function () {
63579                 var url = frame.contentWindow.location.href;
63580                 document.getElementById("viewport-container").removeChild(frame);
63581                 event.trigger("FrameHistoryChange", [url]);
63582                 _console.log("-----------------------------------------------------------");
63583                 _console.log("Pay no attention to that man behind the curtain.");
63584                 _console.log("Environment Warning up again (Set main batteries to auto-fire cycle)");
63585                 _post(url);
63586             };
63587         }
63588     };
63589
63590     // append frame
63591     document.getElementById("viewport-container").appendChild(frame);
63592
63593     delete tinyHippos.boot;
63594 }
63595
63596 function _bootstrap() {
63597     // TODO: figure this out for web and ext
63598     //_console.log("-----------------------------------------------------------");
63599     //_console.log("There be dragons above here!");
63600     _console.log("Web Simulator :: Environment Warming Up (Tea. Earl Gray. Hot.)");
63601
63602     window.tinyHippos = require('ripple');
63603
63604     tinyHippos.boot(function () {
63605         var uri = ui.registered('omnibar') ?
63606                 db.retrieve(_CURRENT_URL) || "about:blank" :
63607                 document.documentURI.replace(/enableripple=[^&]*[&]?/i, "").replace(/[\?&]*$/, "");
63608
63609         _post(uri);
63610         delete tinyHippos.boot;
63611     });
63612 }
63613
63614 module.exports = {
63615     bootstrap: _bootstrap,
63616     inject: function (frameWindow, frameDocument) {
63617         _bindObjects(frameWindow, frameDocument);
63618     }
63619 };
63620
63621 });
63622 define('ripple/bus', function (require, exports, module) {
63623 /*
63624  *  Copyright 2011 Research In Motion Limited.
63625  *
63626  * Licensed under the Apache License, Version 2.0 (the "License");
63627  * you may not use this file except in compliance with the License.
63628  * You may obtain a copy of the License at
63629  *
63630  * http://www.apache.org/licenses/LICENSE-2.0
63631  *
63632  * Unless required by applicable law or agreed to in writing, software
63633  * distributed under the License is distributed on an "AS IS" BASIS,
63634  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
63635  * See the License for the specific language governing permissions and
63636  * limitations under the License.
63637  */
63638
63639 var _send = document.getElementById("bus-send"),
63640     _receive = document.getElementById("bus-receive"),
63641     _evt = document.createEvent("Events");
63642
63643 _evt.initEvent('bus-init', true, true);
63644 document.dispatchEvent(_evt);
63645
63646 module.exports = {
63647     send: function (msg, data, callback) {
63648         var m = document.createElement("span");
63649         m.dataset.msg = msg;
63650         m.innerHTML = JSON.stringify(data);
63651
63652         if (callback) {
63653             m.dataset.callback = Math.uuid();
63654             this.receive(m.dataset.callback, callback);
63655         }
63656
63657         _send.appendChild(m);
63658     },
63659
63660     receive: function (msg, handler) {
63661         if (!handler) {
63662             return;
63663         }
63664
63665         _receive.addEventListener("DOMNodeInserted", function (evt) {
63666             if (evt.target.dataset.msg === msg) {
63667                 handler(JSON.parse(evt.target.innerHTML));
63668             }
63669         });
63670     },
63671
63672     ajax: function (method, url, data, success, fail) {
63673         this.send("xhr", {
63674             method: method,
63675             url: url,
63676             data: data
63677         }, function (result) {
63678             if (result.code === 200) {
63679                 success(result.data);
63680             }
63681             else {
63682                 fail(result);
63683             }
63684         });
63685     }
63686 };
63687
63688 });
63689 define('ripple/console', function (require, exports, module) {
63690 /*
63691  *  Copyright 2011 Research In Motion Limited.
63692  *
63693  * Licensed under the Apache License, Version 2.0 (the "License");
63694  * you may not use this file except in compliance with the License.
63695  * You may obtain a copy of the License at
63696  *
63697  * http://www.apache.org/licenses/LICENSE-2.0
63698  *
63699  * Unless required by applicable law or agreed to in writing, software
63700  * distributed under the License is distributed on an "AS IS" BASIS,
63701  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
63702  * See the License for the specific language governing permissions and
63703  * limitations under the License.
63704  */
63705 var _self;
63706
63707 function _log(msg, method) {
63708     try {
63709         console[method](_self.prefix ? _self.prefix + " :: " + msg : msg);
63710     } catch (e) {
63711         // silent
63712     }
63713 }
63714
63715 _self = {
63716     log: function (msg) {
63717         _log(msg, "log");
63718     },
63719
63720     warn: function (msg) {
63721         _log(msg, "warn");
63722     },
63723
63724     error: function (msg) {
63725         _log(msg, "error");
63726     }
63727 };
63728
63729 module.exports = _self;
63730
63731 });
63732 define('ripple/constants', function (require, exports, module) {
63733 /*
63734  *  Copyright 2011 Research In Motion Limited.
63735  *
63736  * Licensed under the Apache License, Version 2.0 (the "License");
63737  * you may not use this file except in compliance with the License.
63738  * You may obtain a copy of the License at
63739  *
63740  * http://www.apache.org/licenses/LICENSE-2.0
63741  *
63742  * Unless required by applicable law or agreed to in writing, software
63743  * distributed under the License is distributed on an "AS IS" BASIS,
63744  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
63745  * See the License for the specific language governing permissions and
63746  * limitations under the License.
63747  */
63748 module.exports = {
63749     "API_URL": "http://api.tinyhippos.com",
63750
63751     "RELEASE_VERSION": "simulator-release-version",
63752
63753     "SERVICES": {
63754         "GOOGLE_MAPS_URI": "http://maps.google.com/maps/api/staticmap?size=476x476&maptype=roadmap",
63755         "GOOGLE_MAPS_API_KEY": "ABQIAAAA-CaPZHXR-0Tzhui_h6gpjhSE_2rGlnYiB7L-ZGVwgaut5s7OYRSlBAaHCzBuZf2_23_vrCOfPxXHjA"
63756     },
63757
63758     "FS_SIZE": 1024 * 1024 * 10,
63759
63760     "COMMON":  {
63761         "APPLICATION_STATE": "ui-application-state-",
63762         "PREFIX": "tinyhippos-",
63763         "DEVICE_CONTAINER" : "device-container",
63764         "MENU_BUTTON" : "menu-button",
63765         "BACK_BUTTON" : "back-button",
63766         "HTML_CONTAINER" : "document",
63767         "INFO_SECTION": "information-sub-container",
63768         "ORIENTATION_SELECT_PORTRAIT_ID" : "layout-portrait",
63769         "ORIENTATION_SELECT_LANDSCAPE_ID" : "layout-landscape",
63770         "PLATFORM_SELECT_ID": "platform-select",
63771         "DEVICE_SELECT_ID": "device-select",
63772         "STORAGE_TABLE_BODY_CLASS": "preferences-list-body",
63773         "STORAGE_COUNT_CONTAINER_ID": "preferences-count",
63774         "GEO_MAP_CONTAINER_ID": "geo-map",
63775         "FILESYSTEM_UPDATE_BUTTON_ID_WITH_HASH": "#update-filesystem-button",
63776         "USER_AGENT_DEFAULT": "default",
63777         "APPLICATIONS_CONTAINER_ID": "widget-applications-content",
63778         "STORAGE_CLEAR_BUTTON_ID": "preferences-clear-button",
63779         "AJAX_LOADER_CONTAINER_CLASS": ".loader",
63780         "IRRELEVANT_CLASS": "irrelevant",
63781         "MULTIMEDIA_VOLUME_SLIDER_ID": "media-volume",
63782         "MULTIMEDIA_VOLUME_FIELD_ID": "media-volume-value",
63783         "MULTIMEDIA_AUDIO_STATE_FIELD_ID": "media-audio-state",
63784         "MULTIMEDIA_AUDIO_PLAYING_FIELD_ID": "multimedia-isaudioplaying",
63785         "MULTIMEDIA_AUDIO_PROGRESS_ID": "media-audio-progress",
63786         "MULTIMEDIA_AUDIO_FILE_FIELD_ID": "media-audio-file",
63787         "MULTIMEDIA_VIDEO_STATE_FIELD_ID": "media-video-state",
63788         "MULTIMEDIA_VIDEO_PLAYING_FIELD_ID": "multimedia-isvideoplaying",
63789         "MULTIMEDIA_VIDEO_PROGRESS_ID": "media-video-progress",
63790         "MULTIMEDIA_VIDEO_FILE_FIELD_ID": "media-video-file",
63791         "EXTENSION_URL_CONTAINER": "extension-url",
63792         "SECURITY_LEVEL": "security-level"
63793     },
63794     "LAUNCHING_HISTORY": "application-launching-history",
63795
63796     "FILESYSTEM": {
63797         "PERSISTENCE_KEY": "filesystem",
63798         "INPUT_PREFIX_ID": "#panel-filesystem-"
63799     },
63800
63801     "PLATFORM":  {
63802         "DEFAULT": {
63803             "name": "tizen",
63804             "version": "1.0"
63805         }
63806     },
63807
63808     "DEVICE":  {
63809         "SAVED_KEY": "device-key"
63810     },
63811
63812     "BATTERY":  {
63813         "TIME": "charging-time",
63814         "VOLUME": "battery-volume",
63815         "CHARGING": "is-charging"
63816     },
63817
63818     "TOUCHEVENT":  {
63819         "OPTION": "touch_option",
63820         "ALTKEY": "touch_altKey",
63821         "METAKEY": "touch_metaKey",
63822         "CTRLKEY": "touch_ctrlKey",
63823         "SHIFTKEY": "touch_shiftKey",
63824         "CANVAS": "touch_canvas"
63825     },
63826
63827     "ENCAPSULATOR":  {
63828         "DEFAULT_HEIGHT": 684,
63829         "DEFAULT_WIDTH": 480,
63830         "LAYOUT": "layout",
63831         "DISPLAY_LAYOUT": {
63832             "LANDSCAPE": "landscape",
63833             "PORTRAIT": "portrait"
63834         },
63835         "ZOOMING": "screen-zooming"
63836     },
63837
63838     "GEO":  {
63839         "OPTIONS" : {
63840             "LATITUDE" : "geo-latitude",
63841             "LONGITUDE" : "geo-longitude",
63842             "ALTITUDE" : "geo-altitude",
63843             "CELL_ID" : "geo-cellid",
63844             "ACCURACY" : "geo-accuracy",
63845             "ALTITUDE_ACCURACY" : "geo-altitudeaccuracy",
63846             "HEADING" : "geo-heading",
63847             "SPEED" : "geo-speed",
63848             "TIME_STAMP" : "geo-timestamp",
63849             "DELAY" : "geo-delay",
63850             "DELAY_LABEL" : "geo-delay-label",
63851             "HEADING_LABEL" : "geo-heading-label",
63852             "HEADING_MAP_LABEL" : "geo-map-direction-label",
63853             "IMAGE" : "geo-map-img",
63854             "MAP_CONTAINER" : "geo-map-container",
63855             "TIMEOUT" : "geo-timeout",
63856             "GPXFILE": "geo-gpxfile",
63857             "GPXGO": "geo-gpx-go",
63858             "GPXMULTIPLIER": "geo-gpxmultiplier-select",
63859             "GPXREPLAYSTATUS": "geo-gpxreplaystatus"
63860         },
63861         "MAP_ZOOM_MAX": 18,
63862         "MAP_ZOOM_MIN": 0,
63863         "MAP_ZOOM_LEVEL_CONTAINER": "geo-map-zoomlevel-value",
63864         "MAP_ZOOM_KEY": "geo-map-zoom-key",
63865         "GPXGO_LABELS": {
63866
63867             "GO": "Go",
63868             "STOP": "Stop"
63869         }
63870     },
63871
63872     "PUSH": {
63873         "OPTIONS" : {
63874             "PAYLOAD" : "push-text"
63875         }
63876     },
63877
63878     "TELEPHONY": {
63879         "CALL_LIST_KEY": "telephony-call-list-key"
63880     },
63881
63882     "PIM": {
63883         "ADDRESS_LIST_KEY": "pim-address-list-key",
63884         "CALENDAR_LIST_KEY": "pim-calendar-list-key"
63885     },
63886
63887     "CAMERA": {
63888         "WINDOW_ANIMATION": "images/tizen-wave.gif",
63889         "WARNING_TEXT": "The runtime simulated saving the camera file to {file}. If you need to access this file in your application, please copy a file to the saved location"
63890     },
63891
63892     "AUDIOPLAYER" : {
63893         "WARNING_TEXT": "The runtime simulated saving the audio file to {file}. If you need to access this file in your application, please copy a file to the saved location"
63894     },
63895
63896     "API_APPLICATION": {
63897         "NO_APPLICATIONS_MESSAGE": "No applications available for your platform"
63898     },
63899
63900     "NOTIFICATIONS":  {
63901         "MESSAGE_CONTAINER_CLASS": "notification-message-div",
63902         "MAIN_CONTAINER_CLASS": "panel-notification",
63903         "CLOSE_BUTTON_CLASS": "panel-notification-closebtn",
63904         "MESSAGE_TEXT_CONTAINER_CLASS": "panel-notification-text",
63905         "CSS_PREFIX": "panel-notification-",
63906         "STATE_TYPES": {
63907             "OPEN": 1,
63908             "CLOSE": 2
63909         }
63910     },
63911
63912     "CSS_PREFIX":  {
63913         "IRRELEVANT" : "irrelevant"
63914     },
63915
63916     "STORAGE":  {
63917         "PAIR_DELIMETER" : ",",
63918         "KEY_VALUE_DELIMETER" : "|"
63919     },
63920
63921     "REGEX":  {
63922         "GEO" : /^geo-/,
63923         "URL": /^((https?|ftp|gopher|telnet|file|notes|ms-help):((\/\/)|(\\\\))+[\w\d:#@%\/;$()~_?\+-=\\\.&]*)$/,
63924         //"Email": /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,4}$/
63925         "EMAIL": /^([^@\s]+)@((?:[\-a-z0-9]+\.)+[a-z]{2,})$/,
63926         "WC3_DTF": /^((\d{4})-(\d\d)-(\d\d)T(\d\d):(\d\d):(\d\d)|(\d{4})-(\d\d)-(\d\d)T(\d\d):(\d\d)|(\d{4})-(\d\d)-(\d\d)|(\d{4})-(\d\d)|(\d\d\d\d))$/,
63927         "LOCAL_URI": /^https?:\/\/(127\.0\.0\.1|localhost)|^file:\/\//,
63928         "EXTERNAL_URI": /(?:(?:[a-zA-Z0-9\/;\?&=:\-_\$\+!\*'\(\|\\~\[\]#%\.](?!www))+(?:\.[Cc]om|\.[Ee]du|\.[gG]ov|\.[Ii]nt|\.[Mm]il|\.[Nn]et|\.[Oo]rg|\.[Bb]iz|\.[Ii]nfo|\.[Nn]ame|\.[Pp]ro|\.[Aa]ero|\.[cC]oop|\.[mM]useum|\.[Cc]at|\.[Jj]obs|\.[Tt]ravel|\.[Aa]rpa|\.[Mm]obi|\.[Aa]c|\.[Aa]d|\.[aA]e|\.[aA]f|\.[aA]g|\.[aA]i|\.[aA]l|\.[aA]m|\.[aA]n|\.[aA]o|\.[aA]q|\.[aA]r|\.[aA]s|\.[aA]t|\.[aA]u|\.[aA]w|\.[aA]z|\.[aA]x|\.[bB]a|\.[bB]b|\.[bB]d|\.[bB]e|\.[bB]f|\.[bB]g|\.[bB]h|\.[bB]i|\.[bB]j|\.[bB]m|\.[bB]n|\.[bB]o|\.[bB]r|\.[bB]s|\.[bB]t|\.[bB]v|\.[bB]w|\.[bB]y|\.[bB]z|\.[cC]a|\.[cC]c|\.[cC]d|\.[cC]f|\.[cC]g|\.[cC]h|\.[cC]i|\.[cC]k|\.[cC]l|\.[cC]m|\.[cC]n|\.[cC]o|\.[cC]r|\.[cC]s|\.[cC]u|\.[cC]v|\.[cC]x|\.[cC]y|\.[cC]z|\.[dD]e|\.[dD]j|\.[dD]k|\.[dD]m|\.[dD]o|\.[dD]z|\.[eE]c|\.[eE]e|\.[eE]g|\.[eE]h|\.[eE]r|\.[eE]s|\.[eE]t|\.[eE]u|\.[fF]i|\.[fF]j|\.[fF]k|\.[fF]m|\.[fF]o|\.[fF]r|\.[gG]a|\.[gG]b|\.[gG]d|\.[gG]e|\.[gG]f|\.[gG]g|\.[gG]h|\.[gG]i|\.[gG]l|\.[gG]m|\.[gG]n|\.[gG]p|\.[gG]q|\.[gG]r|\.[gG]s|\.[gG]t|\.[gG]u|\.[gG]w|\.[gG]y|\.[hH]k|\.[hH]m|\.[hH]n|\.[hH]r|\.[hH]t^[ml]?|\.[hH]u|\.[iI]d|\.[iI]e|\.[iI]l|\.[iI]m|\.[iI]n|\.[iI]o|\.[iI]q|\.[iI]r|\.[iI]s|\.[iI]t|\.[jJ]e|\.[jJ]m|\.[jJ]o|\.[jJ]p|\.[kK]e|\.[kK]g|\.[kK]h|\.[kK]i|\.[kK]m|\.[kK]n|\.[kK]p|\.[kK]r|\.[kK]w|\.[kK]y|\.[kK]z|\.[lL]a|\.[lL]b|\.[lL]c|\.[lL]i|\.[lL]k|\.[lL]r|\.[lL]s|\.[lL]t|\.[lL]u|\.[lL]v|\.[lL]y|\.[mM]a|\.[mM]c|\.[mM]d|\.[mM]g|\.[mM]h|\.[mM]k|\.[mM]l|\.[mM]m|\.[mM]n|\.[mM]o|\.[mM]p|\.[mM]q|\.[mM]r|\.[mM]s|\.[mM]t|\.[mM]u|\.[mM]v|\.[mM]w|\.[mM]x|\.[mM]y|\.[mM]z|\.[nN]a|\.[nN]c|\.[nN]e|\.[nN]f|\.[nN]g|\.[nN]i|\.[nN]l|\.[nN]o|\.[nN]p|\.[nN]r|\.[nN]u|\.[nN]z|\.[oO]m|\.[pP]a|\.[pP]e|\.[pP]f|\.[pP]g|\.[pP]h|\.[pP]k|\.[pP]l|\.[pP]m|\.[pP]n|\.[pP]r|\.[pP]s|\.[pP]t|\.[pP]w|\.[pP]y|\.[qP]a|\.[rR]e|\.[rR]o|\.[rR]u|\.[rR]w|\.[sS]a|\.[sS]b|\.[sS]c|\.[sS]d|\.[sS]e|\.[sS]g|\.[sS]h|\.[Ss]i|\.[sS]j|\.[sS]k|\.[sS]l|\.[sS]m|\.[sS]n|\.[sS]o|\.[sS]r|\.[sS]t|\.[sS]v[^c]|\.[sS]y|\.[sS]z|\.[tT]c|\.[tT]d|\.[tT]f|\.[tT]g|\.[tT]h|\.[tT]j|\.[tT]k|\.[tT]l|\.[tT]m|\.[tT]n|\.[tT]o|\.[tT]p|\.[tT]r|\.[tT]t|\.[tT]v|\.[tT]w|\.[tT]z|\.[uU]a|\.[uU]g|\.[uU]k|\.[uU]m|\.[uU]s|\.[uU]y|\.[uU]z|\.[vV]a|\.[vV]c|\.[vV]e|\.[vV]g|\.[vV]i|\.[vV]n|\.[vV]u|\.[wW]f|\.[wW]s|\.[yY]e|\.[yY]t|\.[yY]u|\.[zZ]a|\.[zZ]m|\.[zZ]w))/
63929     },
63930
63931     "CONFIG": {
63932         "SUCCESS_CSS": {
63933             "true": "ui-text-pass",
63934             "false": "ui-text-fail",
63935             "missing": "ui-text-missing"
63936         }
63937     },
63938
63939     "SETTINGS": {
63940         "TOOLTIPS_TOGGLE_DIV": "#settings-toggletooltips",
63941         "TOOLTIPS_KEY": "tool-tips-key"
63942     },
63943
63944     "PANEL": {
63945         "PANEL_CONFIG_ENABLE": "panel-config-enable"
63946     },
63947
63948     "UI": {
63949         "JQUERY_UI_BUTTON_CLASSES": "ui-button ui-widget ui-state-default ui-corner-all ui-button-text-only",
63950         "JQUERY_UI_INPUT_CLASSES": "ui-state-default ui-corner-all",
63951         "PANEL_TABLE_CLASS": "panel-table",
63952         "RIGHT_RANGE_LABEL_CLASS": "range-label",
63953         "LEFT_RANGE_LABEL_CLASS": "range-label-left",
63954         "TEXT_LABEL_CLASS": "ui-text-label",
63955         "SCREEN_PPI": 96
63956     },
63957
63958     "MULTIMEDIA": {
63959         "AUDIO_STATES": {
63960             "OPENED": "opened",
63961             "STOPPED": "stopped",
63962             "PAUSED": "paused",
63963             "PLAYING": "playing",
63964             "COMPLETED": "completed"
63965         }
63966     },
63967
63968     "LANG": {
63969         "ISO6392_LIST": ["abk", "ace", "ach", "ada", "ady", "aar", "afh", "afr", "afa", "ain", "aka", "akk", "alb/sqi", "gsw", "ale", "alg", "tut", "amh", "anp", "apa", "ara", "arg", "arp", "arw", "arm/hye", "rup", "art", "asm", "ast", "ath", "aus", "map", "ava", "ave", "awa", "aym", "aze", "ban", "bat", "bal", "bam", "bai", "bad", "bnt", "bas", "bak", "baq/eus", "btk", "bej", "bel", "bem", "ben", "ber", "bho", "bih", "bik", "byn", "bin", "bis", "zbl", "nob", "bos", "bra", "bre", "bug", "bul", "bua", "bur/mya", "cad", "spa", "cat", "cau", "ceb", "cel", "cai", "khm", "chg", "cmc", "cha", "che", "chr", "nya", "chy", "chb", "chi/zho", "chn", "chp", "cho", "zha", "chu", "chk", "chv", "nwc", "syc", "rar", "cop", "cor", "cos", "cre", "mus", "crp", "cpe", "cpf", "cpp", "crh", "hrv", "cus", "cze/ces", "dak", "dan", "dar", "del", "div", "zza", "din", "doi", "dgr", "dra", "dua", "dut/nld", "dum", "dyu", "dzo", "frs", "efi", "egy", "eka", "elx", "eng", "enm", "ang", "myv", "epo", "est", "ewe", "ewo", "fan", "fat", "fao", "fij", "fil", "fin", "fiu", "fon", "fre/fra", "frm", "fro", "fur", "ful", "gaa", "gla", "car", "glg", "lug", "gay", "gba", "gez", "geo/kat", "ger/deu", "nds", "gmh", "goh", "gem", "kik", "gil", "gon", "gor", "got", "grb", "grc", "gre/ell", "kal", "grn", "guj", "gwi", "hai", "hat", "hau", "haw", "heb", "her", "hil", "him", "hin", "hmo", "hit", "hmn", "hun", "hup", "iba", "ice/isl", "ido", "ibo", "ijo", "ilo", "arc", "smn", "inc", "ine", "ind", "inh", "ina", "ile", "iku", "ipk", "ira", "gle", "mga", "sga", "iro", "ita", "jpn", "jav", "kac", "jrb", "jpr", "kbd", "kab", "xal", "kam", "kan", "kau", "pam", "kaa", "krc", "krl", "kar", "kas", "csb", "kaw", "kaz", "kha", "khi", "kho", "kmb", "kin", "kir", "tlh", "kom", "kon", "kok", "kor", "kos", "kpe", "kro", "kua", "kum", "kur", "kru", "kut", "lad", "lah", "lam", "day", "lao", "lat", "lav", "ltz", "lez", "lim", "lin", "lit", "jbo", "dsb", "loz", "lub", "lua", "lui", "smj", "lun", "luo", "lus", "mac/mkd", "mad", "mag", "mai", "mak", "mlg", "may/msa", "mal", "mlt", "mnc", "mdr", "man", "mni", "mno", "glv", "mao/mri", "arn", "mar", "chm", "mah", "mwr", "mas", "myn", "men", "mic", "min", "mwl", "moh", "mdf", "rum/ron", "mkh", "lol", "mon", "mos", "mul", "mun", "nqo", "nah", "nau", "nav", "nde", "nbl", "ndo", "nap", "new", "nep", "nia", "nic", "ssa", "niu", "zxx", "nog", "non", "nai", "frr", "sme", "nso", "nor", "nno", "nub", "iii", "nym", "nyn", "nyo", "nzi", "oci", "pro", "oji", "ori", "orm", "osa", "oss", "oto", "pal", "pau", "pli", "pag", "pan", "pap", "paa", "pus", "per/fas", "peo", "phi", "phn", "pon", "pol", "por", "pra", "que", "raj", "rap", "qaa-qtz", "roa", "roh", "rom", "run", "rus", "sal", "sam", "smi", "smo", "sad", "sag", "san", "sat", "srd", "sas", "sco", "sel", "sem", "srp", "srr", "shn", "sna", "scn", "sid", "sgn", "bla", "snd", "sin", "sit", "sio", "sms", "den", "sla", "slo/slk", "slv", "sog", "som", "son", "snk", "wen", "sot", "sai", "alt", "sma", "srn", "suk", "sux", "sun", "sus", "swa", "ssw", "swe", "syr", "tgl", "tah", "tai", "tgk", "tmh", "tam", "tat", "tel", "ter", "tet", "tha", "tib/bod", "tig", "tir", "tem", "tiv", "tli", "tpi", "tkl", "tog", "ton", "tsi", "tso", "tsn", "tum", "tup", "tur", "ota", "tuk", "tvl", "tyv", "twi", "udm", "uga", "uig", "ukr", "umb", "mis", "und", "hsb", "urd", "uzb", "vai", "ven", "vie", "vol", "vot", "wak", "wln", "war", "was", "wel/cym", "fry", "wal", "wol", "xho", "sah", "yao", "yap", "yid", "yor", "ypk", "znd", "zap", "zen", "zul", "zun"]
63970     },
63971
63972     "XHR": {
63973         "PROXY_DISABLED_BUTTON": "settings-xhrproxy-disabled"
63974     },
63975
63976     "PLATFORMS": {
63977         "WAC": {
63978             "APPLICATIONS": [
63979                 "ALARM",
63980                 "BROWSER",
63981                 "CALCULATOR",
63982                 "CALENDAR",
63983                 "CAMERA",
63984                 "CONTACTS",
63985                 "FILES",
63986                 "GAMES",
63987                 "MAIL",
63988                 "MEDIAPLAYER",
63989                 "MESSAGING",
63990                 "PHONECALL",
63991                 "PICTURES",
63992                 "PROG_MANAGER",
63993                 "SETTINGS",
63994                 "TASKS",
63995                 "WIDGET_MANAGER"
63996             ],
63997             "DEVICE": {
63998                 "WIDGET_ENGINE_NAME": "Generic",
63999                 "WIDGET_ENGINE_PROVIDER": "tinyHippos",
64000                 "WIDGET_ENGINE_VERSION": "x.x"
64001             }
64002         }
64003     },
64004
64005     "POWER_RESOURCE": {
64006         "SCREEN": {
64007             "NAME": "SCREEN",
64008             "STATE": {
64009                 "SCREEN_OFF": {
64010                     "NAME": "SCREEN_OFF",
64011                     "MIN": 0,
64012                     "MAX": 0,
64013                     "VALUE": 0
64014                 },
64015                 "SCREEN_DIM": {
64016                     "NAME": "SCREEN_DIM",
64017                     "MIN": 0,
64018                     "MAX": 0.2,
64019                     "VALUE": 0.15
64020                 },
64021                 "SCREEN_NORMAL": {
64022                     "NAME": "SCREEN_NORMAL",
64023                     "MIN": 0.2,
64024                     "MAX": 1,
64025                     "VALUE": 0.8
64026                 },
64027                 "SCREEN_BRIGHT": {
64028                     "NAME": "SCREEN_BRIGHT",
64029                     "MIN": 1,
64030                     "MAX": 1,
64031                     "VALUE": 1
64032                 }
64033             }
64034         },
64035         "CPU": {
64036             "NAME": "CPU",
64037             "STATE": {
64038                 "CPU_AWAKE": {
64039                     "NAME": "CPU_AWAKE",
64040                     "DEFAULT_VALUE" : 0.5
64041                 }
64042             }
64043         }
64044     }
64045 };
64046
64047 });
64048 define('ripple/db', function (require, exports, module) {
64049 /*
64050  *  Copyright 2011 Research In Motion Limited.
64051  *
64052  * Licensed under the Apache License, Version 2.0 (the "License");
64053  * you may not use this file except in compliance with the License.
64054  * You may obtain a copy of the License at
64055  *
64056  * http://www.apache.org/licenses/LICENSE-2.0
64057  *
64058  * Unless required by applicable law or agreed to in writing, software
64059  * distributed under the License is distributed on an "AS IS" BASIS,
64060  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
64061  * See the License for the specific language governing permissions and
64062  * limitations under the License.
64063  */
64064 var _self,
64065     _db,
64066     utils = require('ripple/utils'),
64067     constants = require('ripple/constants'),
64068     event = require('ripple/event'),
64069     _cache = {};
64070
64071 function _validateAndSetPrefix(prefix) {
64072     if (prefix) {
64073         utils.validateArgumentType(prefix, "string");
64074     }
64075
64076     return prefix || constants.COMMON.PREFIX;
64077 }
64078
64079 function _createKey(key, prefix) {
64080     return _validateAndSetPrefix(prefix) + key;
64081 }
64082
64083 function _createItem(key, value, prefix) {
64084     return {
64085         id: _createKey(key, prefix),
64086         key: key,
64087         value: value,
64088         prefix: _validateAndSetPrefix(prefix)
64089     };
64090 }
64091
64092 function _save(key, value, prefix, callback) {
64093     var item = _createItem(key, value, prefix);
64094     _cache[item.id] = item;
64095
64096     _db.transaction(function (tx) {
64097         tx.executeSql('REPLACE INTO persistence (id, key, value, prefix) VALUES (?, ?, ?, ?)', [item.id, item.key, item.value, item.prefix], function () {
64098             return callback && callback();
64099         });
64100     });
64101 }
64102
64103 function _retrieve(key, prefix) {
64104     var item = _cache[_createKey(key, prefix)];
64105     return item ? item.value : undefined;
64106 }
64107
64108 function _retrieveAll(prefix, callback) {
64109     var result = {};
64110
64111     if (prefix) {
64112         utils.forEach(_cache, function (value, key) {
64113             if (value.prefix === prefix) {
64114                 result[value.key] = value.value;
64115             }
64116         });
64117     }
64118
64119     callback.apply(null, [result]);
64120 }
64121
64122 function _remove(key, prefix, callback) {
64123     delete _cache[_createKey(key, prefix)];
64124
64125     _db.transaction(function (tx) {
64126         tx.executeSql('DELETE FROM persistence WHERE key = ? AND prefix = ?', [key, _validateAndSetPrefix(prefix)], function () {
64127             return callback && callback();
64128         });
64129     });
64130 }
64131
64132 function _removeAll(prefix, callback) {
64133     utils.forEach(_cache, function (value, key) {
64134         if (!prefix || key.indexOf(prefix) === 0) {
64135             delete _cache[key];
64136         }
64137     });
64138
64139     _db.transaction(function (tx) {
64140         if (prefix) {
64141             tx.executeSql('DELETE FROM persistence WHERE prefix = ?', [prefix], function () {
64142                 return callback && callback();
64143             });
64144         } else {
64145             tx.executeSql('DELETE FROM persistence', [], function () {
64146                 return callback && callback();
64147             });
64148         }
64149     });
64150 }
64151
64152 _self = {
64153     save: function (key, value, prefix, callback) {
64154         _save(key, value, prefix, callback);
64155         event.trigger("StorageUpdatedEvent");
64156     },
64157
64158     saveObject: function (key, obj, prefix, callback) {
64159         _save(key, JSON.stringify(obj), prefix, callback);
64160         event.trigger("StorageUpdatedEvent");
64161     },
64162
64163     retrieve: function (key, prefix) {
64164         return _retrieve(key, prefix);
64165     },
64166
64167     retrieveObject: function (key, prefix) {
64168         var retrievedValue = _retrieve(key, prefix);
64169         return retrievedValue ? JSON.parse(retrievedValue) : retrievedValue;
64170     },
64171
64172     retrieveAll: function (prefix, callback) {
64173         return _retrieveAll(prefix, callback);
64174     },
64175
64176     remove: function (key, prefix, callback) {
64177         event.trigger("StorageUpdatedEvent");
64178         _remove(key, prefix, callback);
64179     },
64180
64181     removeAll: function (prefix, callback) {
64182         _removeAll(prefix, callback);
64183         event.trigger("StorageUpdatedEvent");
64184     },
64185
64186     initialize: function (previous, baton) {
64187         baton.take();
64188
64189         _db = openDatabase('tinyHippos', '1.0', 'tiny Hippos persistence', 2 * 1024 * 1024);
64190         _db.transaction(function (tx) {
64191             tx.executeSql('CREATE TABLE IF NOT EXISTS persistence (id unique, key, value, prefix)');
64192
64193             tx.executeSql('SELECT id, key, value, prefix FROM persistence', [], function (tx, results) {
64194                 var len = results.rows.length, i, item;
64195
64196                 for (i = 0; i < len; i++) {
64197                     item = results.rows.item(i);
64198                     _cache[item.id] = item;
64199                 }
64200
64201                 baton.pass();
64202             });
64203         });
64204     }
64205 };
64206
64207 module.exports = _self;
64208
64209 });
64210 define('ripple/dbfs', function (require, exports, module) {
64211 /*
64212  *  Copyright 2011 Research In Motion Limited.
64213  *
64214  * Licensed under the Apache License, Version 2.0 (the "License");
64215  * you may not use this file except in compliance with the License.
64216  * You may obtain a copy of the License at
64217  *
64218  * http://www.apache.org/licenses/LICENSE-2.0
64219  *
64220  * Unless required by applicable law or agreed to in writing, software
64221  * distributed under the License is distributed on an "AS IS" BASIS,
64222  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
64223  * See the License for the specific language governing permissions and
64224  * limitations under the License.
64225  */
64226 var db = require('ripple/db'),
64227     utils = require('ripple/utils'),
64228     event = require('ripple/event'),
64229     _cache = {},
64230     _self;
64231
64232 function _get(path) {
64233     return path.replace(/^\//, '').split("/").reduce(function (obj, token) {
64234         return token === "" ? obj : (obj.children ? obj.children[token] || null : null);
64235     }, _cache);
64236 }
64237
64238 function _getInfo(path) {
64239     var parent = ("/" + path.replace(/^\//, '').replace(/\/$/, '')).split("/"),
64240         name = parent.splice(parent.length - 1, 1).join(""),
64241         ext = name.split(".");
64242
64243     return {
64244         name: name,
64245         extension: ext.length > 1 ? ext[ext.length - 1] : "",
64246         hidden: (name.length > 0 && name[0] === ".") || false,
64247         parent: parent.join("/") || "/"
64248     };
64249 }
64250
64251 function _set(path, obj) {
64252     var parent = _cache,
64253         tokens = path.replace(/^\//, '').replace(/\/$/, '').split("/"),
64254         child = tokens.splice(tokens.length - 1, 1).join("");
64255
64256     tokens.forEach(function (token) {
64257         parent = parent.children[token];
64258     });
64259
64260     parent.children = parent.children || {};
64261     obj.properties = obj.properties || {};
64262     parent.children[child] = obj;
64263 }
64264
64265 function _delete(path) {
64266     var parent = _cache,
64267         tokens = path.replace(/^\//, '').split("/"),
64268         child = tokens.splice(tokens.length - 1, 1).join("");
64269
64270     tokens.forEach(function (token) {
64271         parent = parent.children[token];
64272     });
64273
64274     delete parent.children[child];
64275 }
64276
64277 function _save() {
64278     db.saveObject("db-filesystem", _cache);
64279 }
64280
64281 _self = {
64282
64283     initialize: function (prev, baton) {
64284         _cache = db.retrieveObject("db-filesystem") || {};
64285         event.trigger("FileSystemInitialized", null, true);
64286     },
64287
64288     ls: function (path, success, error) {
64289         try {
64290             var dir = _get(path),
64291                 items = [];
64292
64293             if (dir) {
64294                 utils.forEach(dir.children, function (item) {
64295                     if (!item.isDirectory) {
64296                         item.file = function (callback) {
64297                             callback({});
64298                         };
64299                     }
64300                     items.push(item);
64301                 });
64302             }
64303             else {
64304                 items = {};
64305             }
64306
64307             success(utils.copy(items));
64308         }
64309         catch (e) {
64310             e.code = 1;
64311             error(e);
64312         }
64313     },
64314
64315     rm: function (path, success, error, options) {
64316         _delete(path);
64317         _save();
64318         success();
64319     },
64320
64321     rmdir: function (path, success, error, options) {
64322         _delete(path);
64323         _save();
64324         success();
64325     },
64326
64327     mkdir: function (path, success, error) {
64328         var entry = _get(path),
64329             info = _getInfo(path);
64330
64331         if (!entry) {
64332             _set(path, {
64333                 name: info.name,
64334                 isDirectory: true,
64335                 fullPath: path
64336             });
64337             entry = _get(path);
64338         }
64339         
64340         _save();
64341         if (entry) {
64342             success(utils.copy(entry));
64343         }
64344         else {
64345             error({code: 1});
64346         }
64347     },
64348
64349     mv: function (from, to, success, error) {
64350         try {
64351             var fromEntry = _get(from),
64352                 toInfo = _getInfo(to);
64353
64354             fromEntry.fullPath = to;
64355             fromEntry.name = toInfo.name;
64356
64357             _set(to, fromEntry);
64358             _delete(from);
64359             _save();
64360             success(utils.copy(_get(to)));
64361         }
64362         catch (e) {
64363             e.code = 1;
64364             error(e);
64365         }
64366     },
64367
64368     touch: function (path, success, error) {
64369         if (!_get(path)) {
64370             _set(path, {
64371                 fullPath: path
64372             });
64373         }
64374         _save();
64375         success(utils.copy(_get(path)));
64376     },
64377
64378     cp: function (from, to, success, error) {
64379         try {
64380             var fromEntry = _get(from);
64381             fromEntry.fullPath = to;
64382             _set(to, fromEntry);
64383             _save();
64384             success(utils.copy(_get(to)));
64385         }
64386         catch (e) {
64387             e.code = 1;
64388             error(e);
64389         }
64390     },
64391
64392     stat: function (path, success, error) {
64393         var entry = _get(path);
64394         success(utils.copy(entry));
64395     },
64396
64397     write: function (path, contents, success, error, options) {
64398         var info = _getInfo(path);
64399
64400         _set(path, {
64401             lastModifiedDate: new Date(),
64402             name: info.name,
64403             fullPath: path,
64404             isDirectory: false,
64405             properties: {
64406                 type: "",
64407                 size: contents.size
64408             },
64409             data: contents,
64410             file: function (callback) {
64411                 callback({});
64412             }
64413         });
64414
64415         success(utils.copy(_get(path)));
64416     },
64417
64418     read: function (path, success, error) {
64419         var entry = _get(path);
64420
64421         if (entry) {
64422             success(utils.copy(entry.data));
64423         }
64424         else {
64425             error({code: 1});
64426         }
64427     }
64428 };
64429
64430 module.exports = _self;
64431
64432 });
64433 define('ripple/deviceMotionEmulator', function (require, exports, module) {
64434 /*
64435  *  Copyright 2011 Research In Motion Limited.
64436  *
64437  * Licensed under the Apache License, Version 2.0 (the "License");
64438  * you may not use this file except in compliance with the License.
64439  * You may obtain a copy of the License at
64440  *
64441  * http://www.apache.org/licenses/LICENSE-2.0
64442  *
64443  * Unless required by applicable law or agreed to in writing, software
64444  * distributed under the License is distributed on an "AS IS" BASIS,
64445  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
64446  * See the License for the specific language governing permissions and
64447  * limitations under the License.
64448  */
64449
64450 var event = require('ripple/event'),
64451     platform = require('ripple/platform'),
64452     INTERVAL = 60000,
64453     _self;
64454
64455 function _bind(name, win) {
64456     var callback = null;
64457
64458     win.__defineGetter__(name, function () {
64459         return callback;
64460     });
64461
64462     win.__defineSetter__(name, function (cb) {
64463         callback = cb;
64464     });
64465
64466     return {
64467         get: function () {
64468             return callback;
64469         },
64470         set: function (value) {
64471             callback = value;
64472         },
64473         exec: function (arg) {
64474             return callback && callback(arg);
64475         },
64476         unbind: function (cb) {
64477             callback = cb === callback ? null : callback;
64478         }
64479     };
64480 }
64481
64482 _self = {
64483     init: function (win, doc) {
64484         var widgetWindow = win,
64485             _motion,
64486             _orientation,
64487             _calibration,
64488             add = widgetWindow.addEventListener,
64489             remove = widgetWindow.removeEventListener;
64490
64491         //Hang events off window (these are used to check for API existence by developer)
64492         widgetWindow.DeviceMotionEvent = function DeviceMotionEvent() {};
64493         widgetWindow.DeviceOrientationEvent = function DeviceOrientationEvent() {};
64494
64495         _motion = _bind("ondevicemotion", widgetWindow);
64496         _orientation = _bind("ondeviceorientation", widgetWindow);
64497         _calibration = _bind("oncompassneedscalibration", widgetWindow);
64498
64499         widgetWindow.addEventListener = function (e, callback, useCapture) {
64500             switch (e) {
64501             case "deviceorientation":
64502                 _orientation.set(callback);
64503                 event.trigger("DeviceOrientationEventAddedEvent");
64504                 break;
64505             case "devicemotion":
64506                 _motion.set(callback);
64507                 event.trigger("DeviceMotionEventAddedEvent");
64508                 break;
64509             case "compassneedscalibration":
64510                 _calibration.set(callback);
64511                 break;
64512
64513             default:
64514                 add.apply(widgetWindow, arguments);
64515                 break;
64516             }
64517         };
64518
64519         widgetWindow.removeEventListener = function (event, callback) {
64520             _motion.unbind(callback);
64521             _orientation.unbind(callback);
64522             _calibration.unbind(callback);
64523             remove.apply(widgetWindow, arguments);
64524         };
64525
64526         event.on("DeviceMotionEvent", function (motion) {
64527             var _motionEvent, DeviceMotionEvent;
64528
64529             if (platform.current().DeviceMotionEvent) {
64530                 DeviceMotionEvent = platform.current().DeviceMotionEvent;
64531                 if (typeof DeviceMotionEvent !== "function")
64532                     return;
64533
64534                 _motionEvent = new DeviceMotionEvent();
64535                 _motionEvent.initAccelerometerEvent("devicemotion", true, false, motion.acceleration, motion.accelerationIncludingGravity, 
64536                                                     motion.rotationRate, INTERVAL);    
64537             }
64538             else {
64539                 _motionEvent = {
64540                     acceleration: motion.acceleration,
64541                     accelerationIncludingGravity: motion.accelerationIncludingGravity,
64542                     rotationRate: motion.rotationRate
64543                 };
64544             }
64545
64546             _motion.exec(_motionEvent);
64547         });
64548
64549         event.on("DeviceOrientationEvent", function (motion) {
64550             var _orientationEvent, DeviceOrientationEvent;
64551
64552             if (platform.current().DeviceOrientationEvent) {
64553                 DeviceOrientationEvent = platform.current().DeviceOrientationEvent;
64554                 if (typeof DeviceOrientationEvent !== "function")
64555                     return;
64556
64557                 _orientationEvent = new DeviceOrientationEvent();        
64558                 _orientationEvent.initDeviceOrientationEvent("deviceorientation", true, false, motion.orientation.alpha, 
64559                                                               motion.orientation.beta, motion.orientation.gamma, true);
64560             }
64561             else {
64562                 _orientationEvent = motion.orientation;
64563             }
64564
64565             _orientation.exec(_orientationEvent);
64566         });
64567     }
64568 };
64569
64570 module.exports = _self;
64571
64572 });
64573 define('ripple/deviceSettings', function (require, exports, module) {
64574 /*
64575  *  Copyright 2011 Research In Motion Limited.
64576  *
64577  * Licensed under the Apache License, Version 2.0 (the "License");
64578  * you may not use this file except in compliance with the License.
64579  * You may obtain a copy of the License at
64580  *
64581  * http://www.apache.org/licenses/LICENSE-2.0
64582  *
64583  * Unless required by applicable law or agreed to in writing, software
64584  * distributed under the License is distributed on an "AS IS" BASIS,
64585  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
64586  * See the License for the specific language governing permissions and
64587  * limitations under the License.
64588  */
64589 /* DeviceSettings
64590  *  A per object store for a platform's settings.
64591  *  For example, RadioInfo object in WAC has isRadioEnabled that can be true/false
64592  *  setting => {key: {key1: "test"}}
64593  */
64594 var _PERSISTENCE_KEY = "devicesettings",
64595     db = require('ripple/db'),
64596     platform = require('ripple/platform'),
64597     _currentDeviceSettings = {},
64598     _self;
64599
64600 function _default(key) {
64601     var keys = key.split("."),
64602         defaults = platform.current().device;
64603     if (keys.length === 1)
64604         return defaults[key];
64605     return keys.length === 2 &&
64606            defaults[keys[0]] &&
64607            defaults[keys[0]][keys[1]] &&
64608            defaults[keys[0]][keys[1]].control ?
64609            defaults[keys[0]][keys[1]].control.value : undefined;
64610 }
64611
64612 _self = {
64613     initialize: function () {
64614         // TODO: remove deprecated DeviceSettings from persisted ones.
64615         _currentDeviceSettings = db.retrieveObject(_PERSISTENCE_KEY) || {};
64616     },
64617     register: function (key, obj) {
64618         _currentDeviceSettings[key] = obj;
64619     },
64620
64621     persist: function (key, obj) {
64622         if (key) {
64623             _currentDeviceSettings[key] = obj;
64624         }
64625         db.saveObject(_PERSISTENCE_KEY, _currentDeviceSettings);
64626     },
64627
64628     retrieve: function (key) {
64629         return _currentDeviceSettings.hasOwnProperty(key) ?
64630                _currentDeviceSettings[key] : _default(key);
64631     },
64632
64633     retrieveAsInt: function (key) {
64634         return parseInt(_self.retrieve(key), 10);
64635     },
64636
64637     retrieveAsBoolean: function (key) {
64638         return !!_self.retrieve(key);
64639     }
64640 };
64641
64642 module.exports = _self;
64643
64644 });
64645 define('ripple/devices/Bold9700', function (require, exports, module) {
64646 /*
64647  *  Copyright 2011 Research In Motion Limited.
64648  *
64649  * Licensed under the Apache License, Version 2.0 (the "License");
64650  * you may not use this file except in compliance with the License.
64651  * You may obtain a copy of the License at
64652  *
64653  * http://www.apache.org/licenses/LICENSE-2.0
64654  *
64655  * Unless required by applicable law or agreed to in writing, software
64656  * distributed under the License is distributed on an "AS IS" BASIS,
64657  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
64658  * See the License for the specific language governing permissions and
64659  * limitations under the License.
64660  */
64661 module.exports = {
64662
64663     "id": "Bold9700",
64664     "name": "BlackBerry Bold 9700",
64665     "model": "9700",
64666     "osName": "BlackBerry OS",
64667     "uuid": "42",
64668     "osVersion": "6",
64669     "manufacturer": "Research In Motion",
64670
64671     "skin": "Bold9700",
64672
64673     "capabilities": [
64674         "location.gps",
64675         "location.maps",
64676         "media.audio.capture",
64677         "media.video.capture",
64678         "media.recording",
64679         "storage.memorycard",
64680         "network.bluetooth",
64681         "network.wlan",
64682         "network.3gpp"
64683     ],
64684
64685     "screen": {
64686         "width": 480,
64687         "height": 360
64688     },
64689     "viewPort": {
64690         "portrait": {
64691             "width": 480,
64692             "height": 360,
64693             "paddingTop": 0,
64694             "paddingLeft": 0
64695         }
64696     },
64697
64698     "ppi": 245.00,
64699     "userAgent": "Mozilla/5.0 (BlackBerry; U; BlackBerry 9700; en) AppleWebKit/534.1+ (KHTML, Like Gecko) Version/6.0.0.141 Mobile Safari/534.1",
64700     "platforms": ["web", "phonegap", "webworks.handset", "cordova"]
64701 };
64702
64703 });
64704 define('ripple/devices/Bold9900', function (require, exports, module) {
64705 /*
64706  *  Copyright 2011 Research In Motion Limited.
64707  *
64708  * Licensed under the Apache License, Version 2.0 (the "License");
64709  * you may not use this file except in compliance with the License.
64710  * You may obtain a copy of the License at
64711  *
64712  * http://www.apache.org/licenses/LICENSE-2.0
64713  *
64714  * Unless required by applicable law or agreed to in writing, software
64715  * distributed under the License is distributed on an "AS IS" BASIS,
64716  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
64717  * See the License for the specific language governing permissions and
64718  * limitations under the License.
64719  */
64720 module.exports = {
64721
64722     "id": "Bold9900",
64723     "name": "BlackBerry Bold 9900",
64724     "model": "9900",
64725     "osName": "BlackBerry OS",
64726     "uuid": "42",
64727     "osVersion": "7",
64728     "manufacturer": "Research In Motion",
64729
64730     "skin": "Bold9900",
64731
64732     "capabilities": [
64733         "input.touch",
64734         "location.gps",
64735         "location.maps",
64736         "media.audio.capture",
64737         "media.video.capture",
64738         "media.recording",
64739         "storage.memorycard",
64740         "network.bluetooth",
64741         "network.wlan",
64742         "network.3gpp"
64743     ],
64744
64745     "screen": {
64746         "width": 640,
64747         "height": 480
64748     },
64749     "viewPort": {
64750         "portrait": {
64751             "width": 640,
64752             "height": 480,
64753             "paddingTop": 0,
64754             "paddingLeft": 0
64755         }
64756     },
64757
64758     "ppi": 287.00,
64759     "userAgent": "Mozilla/5.0 (BlackBerry; U; BlackBerry 9900; en) AppleWebKit/534.1+ (KHTML, Like Gecko) Version/7.0.0.141 Mobile Safari/534.1",
64760     "platforms": ["web", "phonegap", "webworks.handset", "cordova"]
64761 };
64762
64763 });
64764 define('ripple/devices/Colt', function (require, exports, module) {
64765 /*
64766  *  Copyright 2011 Research In Motion Limited.
64767  *
64768  * Licensed under the Apache License, Version 2.0 (the "License");
64769  * you may not use this file except in compliance with the License.
64770  * You may obtain a copy of the License at
64771  *
64772  * http://www.apache.org/licenses/LICENSE-2.0
64773  *
64774  * Unless required by applicable law or agreed to in writing, software
64775  * distributed under the License is distributed on an "AS IS" BASIS,
64776  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
64777  * See the License for the specific language governing permissions and
64778  * limitations under the License.
64779  */
64780 module.exports = {
64781
64782     "id": "Colt",
64783     "name": "BlackBerry 10 Dev Alpha",
64784     "model": "Colt",
64785     "osName": "BlackBerry",
64786     "uuid": "42",
64787     "osVersion": "10.0.6.99",
64788     "manufacturer": "Research In Motion",
64789     "hardwareId": "0x8500240a",
64790
64791     "skin": "Colt",
64792
64793     "capabilities": [
64794         "input.touch",
64795         "location.gps",
64796         "media.audio.capture",
64797         "media.video.capture",
64798         "media.recording",
64799         "network.bluetooth",
64800         "network.wlan"
64801     ],
64802
64803     "screen": {
64804         "width": 768,
64805         "height": 1280
64806     },
64807     "viewPort": {
64808         "portrait": {
64809             "width": 768,
64810             "height": 1280,
64811             "paddingTop": 0,
64812             "paddingLeft": 0
64813         },
64814         "landscape": {
64815             "width": 1280,
64816             "height": 768,
64817             "paddingTop": 0,
64818             "paddingLeft": 0
64819         }
64820     },
64821
64822     "defaultOrientation": "portrait",
64823
64824     "ppi": 355,
64825     "userAgent": "Mozilla/5.0 (BlackBerry) AppleWebKit/536.2+ (KHTML, like Gecko) Version/10.0.4.182 Mobile Safari/536.2+",
64826     "platforms": ["web", "webworks.bb10", "cordova"]
64827 };
64828
64829 });
64830 define('ripple/devices/Curve9300', function (require, exports, module) {
64831 /*
64832  *  Copyright 2011 Research In Motion Limited.
64833  *
64834  * Licensed under the Apache License, Version 2.0 (the "License");
64835  * you may not use this file except in compliance with the License.
64836  * You may obtain a copy of the License at
64837  *
64838  * http://www.apache.org/licenses/LICENSE-2.0
64839  *
64840  * Unless required by applicable law or agreed to in writing, software
64841  * distributed under the License is distributed on an "AS IS" BASIS,
64842  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
64843  * See the License for the specific language governing permissions and
64844  * limitations under the License.
64845  */
64846 module.exports = {
64847
64848     "id": "Curve9300",
64849     "name": "BlackBerry Curve 9300",
64850     "model": "9300",
64851     "osName": "BlackBerry OS",
64852     "uuid": "42",
64853     "osVersion": "6",
64854     "manufacturer": "Research In Motion",
64855
64856     "skin": "Curve9300",
64857
64858     "capabilities": [
64859         "location.gps",
64860         "location.maps",
64861         "media.audio.capture",
64862         "media.video.capture",
64863         "media.recording",
64864         "storage.memorycard",
64865         "network.bluetooth",
64866         "network.wlan",
64867         "network.3gpp"
64868     ],
64869
64870     "screen": {
64871         "width": 320,
64872         "height": 240
64873     },
64874     "viewPort": {
64875         "portrait": {
64876             "width": 320,
64877             "height": 240,
64878             "paddingTop": 0,
64879             "paddingLeft": 0
64880         }
64881     },
64882
64883     "ppi": 163,
64884     "userAgent": "Mozilla/5.0 (BlackBerry; U; BlackBerry 9300; en) AppleWebKit/534.3+ (KHTML, like Gecko) Version/6.0.0.286 Mobile Safari/534.3+",
64885     "platforms": ["web", "phonegap", "webworks.handset"]
64886 };
64887
64888 });
64889 define('ripple/devices/Curve9350-9360-9370', function (require, exports, module) {
64890 /*
64891  *  Copyright 2011 Research In Motion Limited.
64892  *
64893  * Licensed under the Apache License, Version 2.0 (the "License");
64894  * you may not use this file except in compliance with the License.
64895  * You may obtain a copy of the License at
64896  *
64897  * http://www.apache.org/licenses/LICENSE-2.0
64898  *
64899  * Unless required by applicable law or agreed to in writing, software
64900  * distributed under the License is distributed on an "AS IS" BASIS,
64901  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
64902  * See the License for the specific language governing permissions and
64903  * limitations under the License.
64904  */
64905 module.exports = {
64906
64907     "id": "Curve9350-9360-9370",
64908     "name": "BlackBerry Curve 9350/9360/9370",
64909     "model": "9350-9360-9370",
64910     "osName": "BlackBerry OS",
64911     "uuid": "42",
64912     "osVersion": "7",
64913     "manufacturer": "Research In Motion",
64914
64915     "skin": "Curve9350-9360-9370",
64916
64917     "capabilities": [
64918         "location.gps",
64919         "location.maps",
64920         "media.audio.capture",
64921         "media.video.capture",
64922         "media.recording",
64923         "storage.memorycard",
64924         "network.bluetooth",
64925         "network.wlan",
64926         "network.3gpp"
64927     ],
64928
64929     "screen": {
64930         "width": 480,
64931         "height": 360
64932     },
64933     "viewPort": {
64934         "portrait": {
64935             "width": 480,
64936             "height": 360,
64937             "paddingTop": 0,
64938             "paddingLeft": 0
64939         }
64940     },
64941
64942     "ppi": 246.00,
64943     "userAgent": "Mozilla/5.0 (BlackBerry; U; BlackBerry 9350; en) AppleWebKit/534.1+ (KHTML, Like Gecko) Version/7.0.0.0 Mobile Safari/534.1",
64944     "platforms": ["web", "phonegap", "webworks.handset"]
64945 };
64946
64947 });
64948 define('ripple/devices/FWVGA', function (require, exports, module) {
64949 /*
64950  *  Copyright 2011 Research In Motion Limited.
64951  *
64952  * Licensed under the Apache License, Version 2.0 (the "License");
64953  * you may not use this file except in compliance with the License.
64954  * You may obtain a copy of the License at
64955  *
64956  * http://www.apache.org/licenses/LICENSE-2.0
64957  *
64958  * Unless required by applicable law or agreed to in writing, software
64959  * distributed under the License is distributed on an "AS IS" BASIS,
64960  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
64961  * See the License for the specific language governing permissions and
64962  * limitations under the License.
64963  */
64964 module.exports = {
64965     "group": "Generic Devices",
64966
64967     "id": "FWVGA",
64968     "name": "Generic - FWVGA (480x854)",
64969     "osName": "Generic",
64970     "osVersion": "Generic",
64971     "manufacturer": "Generic",
64972     "model": "Generic",
64973     "uuid": "42",
64974
64975     "screen": {
64976         "width": 480,
64977         "height": 854
64978     },
64979     "viewPort": {
64980         "portrait": {
64981             "width": 480,
64982             "height": 854,
64983             "paddingTop": 0,
64984             "paddingLeft": 0
64985         },
64986         "landscape": {
64987             "width": 854,
64988             "height": 480,
64989             "paddingTop": 0,
64990             "paddingLeft": 0
64991         }
64992     },
64993
64994     "ppi": 96,
64995     "platforms": ["web", "phonegap", "cordova"],
64996     "userAgent": "Mozilla/5.0 (X11; U; Linux x86_64; en-US) AppleWebKit/533.2 (KHTML, like Gecko) Chrome/5.0.342.7 Safari/533.2"
64997 };
64998
64999 });
65000 define('ripple/devices/G1', function (require, exports, module) {
65001 /*
65002  *  Copyright 2011 Research In Motion Limited.
65003  *
65004  * Licensed under the Apache License, Version 2.0 (the "License");
65005  * you may not use this file except in compliance with the License.
65006  * You may obtain a copy of the License at
65007  *
65008  * http://www.apache.org/licenses/LICENSE-2.0
65009  *
65010  * Unless required by applicable law or agreed to in writing, software
65011  * distributed under the License is distributed on an "AS IS" BASIS,
65012  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
65013  * See the License for the specific language governing permissions and
65014  * limitations under the License.
65015  */
65016 module.exports = {
65017
65018     "id": "G1",
65019     "name": "HTC G1",
65020     "model": "G1",
65021     "osName": "Android",
65022     "osVersion": "1.6",
65023     "uuid": "6F196F23-FD0D-4F62-B27B-730147FCC5A3",
65024     "manufacturer": "HTC",
65025
65026     "screen": {
65027         "width": 320,
65028         "height": 480
65029     },
65030     "viewPort": {
65031         "portrait": {
65032             "width": 320,
65033             "height": 480,
65034             "paddingTop": 0,
65035             "paddingLeft": 0
65036         },
65037         "landscape": {
65038             "width": 480,
65039             "height": 320,
65040             "paddingTop": 0,
65041             "paddingLeft": 0
65042         }
65043     },
65044
65045     "ppi": 180.28,
65046     "platforms": ["web", "phonegap"],
65047     "userAgent": "Mozilla/5.0 (Linux; U; Android 1.0; en-us; dream) AppleWebKit/525.10+ (KHTML, like Gecko) Version/3.0.4 Mobile Safari/523.12.2",
65048
65049     "notes": {
65050         "1": "<a href=\"http://www.htc.com/www/product/g1/specification.html\" target=\"_blank\">Specs</a>"
65051     }
65052 };
65053
65054 });
65055 define('ripple/devices/HD', function (require, exports, module) {
65056 /*
65057  *  Copyright 2012 Intel Corporation
65058  *
65059  * Licensed under the Apache License, Version 2.0 (the "License");
65060  * you may not use this file except in compliance with the License.
65061  * You may obtain a copy of the License at
65062  *
65063  * http://www.apache.org/licenses/LICENSE-2.0
65064  *
65065  * Unless required by applicable law or agreed to in writing, software
65066  * distributed under the License is distributed on an "AS IS" BASIS,
65067  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
65068  * See the License for the specific language governing permissions and
65069  * limitations under the License.
65070  */
65071
65072 module.exports = {
65073     "id": "HD",
65074     "name": "HD (720x1280)",
65075     "osName": "Generic",
65076     "osVersion": "Generic",
65077     "manufacturer": "Generic",
65078     "model": "Generic",
65079     "uuid": "42",
65080     "firmware": "Generic",
65081
65082     "screen": {
65083         "width": 720,
65084         "height": 1280
65085     },
65086     "viewPort": {
65087         "portrait": {
65088             "width": 720,
65089             "height": 1280,
65090             "paddingTop": 0,
65091             "paddingLeft": 0
65092         },
65093         "landscape": {
65094             "width": 1280,
65095             "height": 720,
65096             "paddingTop": 0,
65097             "paddingLeft": 0
65098         }
65099     },
65100
65101     "ppi": 316,
65102     "browser": ["Generic"],
65103     "platforms": ["wac", "web", "phonegap", "tizen", "cordova"],
65104     "userAgent": "Mozilla/5.0 (X11; U; Linux x86_64; en-US) AppleWebKit/533.2 (KHTML, like Gecko) Chrome/5.0.342.7 Safari/533.2"
65105 };
65106
65107 });
65108 define('ripple/devices/HPPre3', function (require, exports, module) {
65109 /*
65110  *  Copyright 2011 Research In Motion Limited.
65111  *
65112  * Licensed under the Apache License, Version 2.0 (the "License");
65113  * you may not use this file except in compliance with the License.
65114  * You may obtain a copy of the License at
65115  *
65116  * http://www.apache.org/licenses/LICENSE-2.0
65117  *
65118  * Unless required by applicable law or agreed to in writing, software
65119  * distributed under the License is distributed on an "AS IS" BASIS,
65120  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
65121  * See the License for the specific language governing permissions and
65122  * limitations under the License.
65123  */
65124 module.exports = {
65125     "id": "HPPre3",
65126     "name": "HP Pre 3",
65127     "manufacturer": "HP",
65128     "model": "Pre",
65129     "osName": "WebOS",
65130     "osVersion": "2.x",
65131
65132     "screen": {
65133         "width": 480,
65134         "height": 800
65135     },
65136     "viewPort": {
65137         "portrait": {
65138             "width": 480,
65139             "height": 800,
65140             "paddingTop": 0,
65141             "paddingLeft": 0
65142         },
65143         "landscape": {
65144             "width": 800,
65145             "height": 480,
65146             "paddingTop": 0,
65147             "paddingLeft": 0
65148         }
65149     },
65150
65151     "ppi": 260,
65152     // TODO :: not exactly the correct userAgent webkit version is probably different
65153     "userAgent": "Mozilla/5.0 (webOS/2.0; U; en-US) AppleWebKit/525.27.1 (KHTML, like Gecko) Version/1.0 Safari/525.27.1 Pre/2.0",
65154     "platforms": ["web", "phonegap"],
65155
65156     "notes": {
65157         "1": "<a href=\"http://www.palm.com/us/products/phones/pre3/index.html\" target=\"_blank\">Specs</a>"
65158     }
65159 };
65160
65161 });
65162 define('ripple/devices/HPVeer', function (require, exports, module) {
65163 /*
65164  *  Copyright 2011 Research In Motion Limited.
65165  *
65166  * Licensed under the Apache License, Version 2.0 (the "License");
65167  * you may not use this file except in compliance with the License.
65168  * You may obtain a copy of the License at
65169  *
65170  * http://www.apache.org/licenses/LICENSE-2.0
65171  *
65172  * Unless required by applicable law or agreed to in writing, software
65173  * distributed under the License is distributed on an "AS IS" BASIS,
65174  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
65175  * See the License for the specific language governing permissions and
65176  * limitations under the License.
65177  */
65178 module.exports = {
65179     "id": "HPVeer",
65180     "name": "HP Veer",
65181     "manufacturer": "HP",
65182     "model": "Veer",
65183     "osName": "WebOS",
65184     "osVersion": "2.x",
65185
65186     "screen": {
65187         "width": 320,
65188         "height": 400
65189     },
65190     "viewPort": {
65191         "portrait": {
65192             "width": 320,
65193             "height": 400,
65194             "paddingTop": 0,
65195             "paddingLeft": 0
65196         },
65197         "landscape": {
65198             "width": 400,
65199             "height": 320,
65200             "paddingTop": 0,
65201             "paddingLeft": 0
65202         }
65203     },
65204
65205     "ppi": 197,
65206     // TODO :: not exactly the correct userAgent webkit version is probably different
65207     "userAgent": "Mozilla/5.0 (webOS/2.0; U; en-US) AppleWebKit/525.27.1 (KHTML, like Gecko) Version/1.0 Safari/525.27.1 Pre/2.0",
65208     "platforms": ["web", "phonegap"],
65209
65210     "notes": {
65211         "1": "<a href=\"http://www.palm.com/us/products/phones/veer/index.html\" target=\"_blank\">Specs</a>"
65212     }
65213 };
65214
65215 });
65216 define('ripple/devices/HVGA', function (require, exports, module) {
65217 /*
65218  *  Copyright 2011 Research In Motion Limited.
65219  *
65220  * Licensed under the Apache License, Version 2.0 (the "License");
65221  * you may not use this file except in compliance with the License.
65222  * You may obtain a copy of the License at
65223  *
65224  * http://www.apache.org/licenses/LICENSE-2.0
65225  *
65226  * Unless required by applicable law or agreed to in writing, software
65227  * distributed under the License is distributed on an "AS IS" BASIS,
65228  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
65229  * See the License for the specific language governing permissions and
65230  * limitations under the License.
65231  */
65232 module.exports = {
65233     "group": "Generic Devices",
65234
65235     "id": "HVGA",
65236     "name": "HVGA (320x480)",
65237     "osName": "Generic",
65238     "osVersion": "Generic",
65239     "manufacturer": "Generic",
65240     "model": "Generic",
65241     "uuid": "42",
65242
65243     "screen": {
65244         "width": 320,
65245         "height": 480
65246     },
65247     "viewPort": {
65248         "portrait": {
65249             "width": 320,
65250             "height": 480,
65251             "paddingTop": 0,
65252             "paddingLeft": 0
65253         },
65254         "landscape": {
65255             "width": 480,
65256             "height": 320,
65257             "paddingTop": 0,
65258             "paddingLeft": 0
65259         }
65260     },
65261
65262     "ppi": 316,
65263     "platforms": ["wac", "web", "phonegap", "tizen", "cordova"],
65264     "userAgent": "Mozilla/5.0 (X11; U; Linux x86_64; en-US) AppleWebKit/533.2 (KHTML, like Gecko) Chrome/5.0.342.7 Safari/533.2"
65265 };
65266
65267 });
65268 define('ripple/devices/Legend', function (require, exports, module) {
65269 /*
65270  *  Copyright 2011 Research In Motion Limited.
65271  *
65272  * Licensed under the Apache License, Version 2.0 (the "License");
65273  * you may not use this file except in compliance with the License.
65274  * You may obtain a copy of the License at
65275  *
65276  * http://www.apache.org/licenses/LICENSE-2.0
65277  *
65278  * Unless required by applicable law or agreed to in writing, software
65279  * distributed under the License is distributed on an "AS IS" BASIS,
65280  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
65281  * See the License for the specific language governing permissions and
65282  * limitations under the License.
65283  */
65284 module.exports = {
65285     "id": "Legend",
65286     "name": "HTC Legend",
65287     "osName": "Android",
65288     "osVersion": "1.6",
65289     "manufacturer": "HTC",
65290     "model": "Legend",
65291     "uuid": "6F196F23-FD0D-4F62-B27B-730147FCC5A3",
65292
65293     "screen": {
65294         "width": 320,
65295         "height": 480
65296     },
65297     "viewPort": {
65298         "portrait": {
65299             "width": 320,
65300             "height": 480,
65301             "paddingTop": 0,
65302             "paddingLeft": 0
65303         },
65304         "landscape": {
65305             "width": 480,
65306             "height": 320,
65307             "paddingTop": 0,
65308             "paddingLeft": 0
65309         }
65310     },
65311
65312     "ppi": 180.3,
65313     "userAgent": "Mozilla/5.0 (Linux; U; Android 2.1; fr-fr; HTC Legend 1.32.163.1 Build/ERD79) AppleWebKit/530.17 (KHTML, like Gecko) Version/4.0 Mobile Safari/530.17",
65314     "platforms": ["web", "phonegap"]
65315 };
65316
65317 });
65318 define('ripple/devices/Nexus', function (require, exports, module) {
65319 /*
65320  *  Copyright 2011 Research In Motion Limited.
65321  *
65322  * Licensed under the Apache License, Version 2.0 (the "License");
65323  * you may not use this file except in compliance with the License.
65324  * You may obtain a copy of the License at
65325  *
65326  * http://www.apache.org/licenses/LICENSE-2.0
65327  *
65328  * Unless required by applicable law or agreed to in writing, software
65329  * distributed under the License is distributed on an "AS IS" BASIS,
65330  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
65331  * See the License for the specific language governing permissions and
65332  * limitations under the License.
65333  */
65334 module.exports = {
65335     "id": "Nexus",
65336     "name": "Nexus One",
65337     "manufacturer": "HTC",
65338     "model": "Nexux One",
65339     "osName": "Android",
65340     "uuid": "6F196F23-FD0D-4F62-B27B-730147FCC5A3",
65341     "osVersion": "2.x.x",
65342
65343     "screen": {
65344         "width": 480,
65345         "height": 800
65346     },
65347     "viewPort": {
65348         "portrait": {
65349             "width": 480,
65350             "height": 800,
65351             "paddingTop": 0,
65352             "paddingLeft": 0
65353         },
65354         "landscape": {
65355             "width": 800,
65356             "height": 480,
65357             "paddingTop": 0,
65358             "paddingLeft": 0
65359         }
65360     },
65361
65362     "ppi": 252.15,
65363     "userAgent": "Mozilla/5.0 (Linux; U; Android 2.1; en-us; Nexus One Build/ERD62) AppleWebKit/530.17 (KHTML, like Gecko) Version/4.0 Mobile Safari/530.17",
65364     "platforms": ["web", "phonegap"],
65365
65366     "notes": {
65367         "1": "<a href=\"http://www.google.com/phone/static/en_US-nexusone_tech_specs.html\" target=\"_blank\">Specs</a>"
65368     }
65369 };
65370
65371 });
65372 define('ripple/devices/Nexus7', function (require, exports, module) {
65373 /*
65374  *  Copyright 2011 Research In Motion Limited.
65375  *
65376  * Licensed under the Apache License, Version 2.0 (the "License");
65377  * you may not use this file except in compliance with the License.
65378  * You may obtain a copy of the License at
65379  *
65380  * http://www.apache.org/licenses/LICENSE-2.0
65381  *
65382  * Unless required by applicable law or agreed to in writing, software
65383  * distributed under the License is distributed on an "AS IS" BASIS,
65384  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
65385  * See the License for the specific language governing permissions and
65386  * limitations under the License.
65387  */
65388 module.exports = {
65389     "id" : "Nexus7",
65390     "name": "Nexus 7 (Tablet)",
65391     "manufacturer": "Asus",
65392     "model": "Nexus 7 8/16 GB",
65393     "osName": "Android",
65394     "uuid" : "903802EA-1786-4175-B0F1-1FDF87813CAA",
65395     "osVersion": "4.x.x",
65396
65397     "screen": {
65398         "width": 800,
65399         "height": 1280
65400     },
65401     "viewPort": {
65402         "portrait": {
65403             "width": 800,
65404             "height": 1280,
65405             "paddingTop": 0,
65406             "paddingLeft": 0
65407         },
65408         "landscape": {
65409             "width": 1280,
65410             "height": 800,
65411             "paddingTop": 0,
65412             "paddingLeft": 0
65413         }
65414     },
65415
65416     "ppi": 215,
65417     "userAgent": "Mozilla/5.0 (Linux; Android 4.1.1; Nexus 7 Build/JRO03D) AppleWebKit/535.19 (KHTML, like Gecko) Chrome/18.0.1025.166  Safari/535.19",
65418     "platforms": ["web", "phonegap", "cordova"],
65419
65420     "notes": {
65421         "1": "<a href=\"http://www.google.com/nexus/#/7/specs\" target=\"_blank\">Specs</a>"
65422     }
65423
65424 };
65425
65426 });
65427 define('ripple/devices/NexusGalaxy', function (require, exports, module) {
65428 /*
65429  *  Copyright 2011 Research In Motion Limited.
65430  *
65431  * Licensed under the Apache License, Version 2.0 (the "License");
65432  * you may not use this file except in compliance with the License.
65433  * You may obtain a copy of the License at
65434  *
65435  * http://www.apache.org/licenses/LICENSE-2.0
65436  *
65437  * Unless required by applicable law or agreed to in writing, software
65438  * distributed under the License is distributed on an "AS IS" BASIS,
65439  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
65440  * See the License for the specific language governing permissions and
65441  * limitations under the License.
65442  */
65443 module.exports = {
65444     "id" : "NexusGalaxy",
65445     "name": "Nexus (Galaxy)",
65446     "manufacturer": "Samsung",
65447     "model": "Galaxy Nexus (generic)",
65448     "osName": "Android",
65449     "uuid" : "3D0AD03B-8B46-431A-BEF5-FF01B96BA990",
65450     "osVersion": "4.x.x",
65451
65452     "screen": {
65453         "width": 720,
65454         "height": 1280
65455     },
65456     "viewPort": {
65457         "portrait": {
65458             "width": 720,
65459             "height": 1280,
65460             "paddingTop": 0,
65461             "paddingLeft": 0
65462         },
65463         "landscape": {
65464             "width": 1280,
65465             "height": 720,
65466             "paddingTop": 0,
65467             "paddingLeft": 0
65468         }
65469     },
65470
65471     "ppi": 315,
65472     "userAgent": "Mozilla/5.0 (Linux; Android 4.0.1; Galaxy Nexus Build/ITL41F) AppleWebKit/535.19 (KHTML, like Gecko) Chrome/18.0.1025.166 Mobile Safari/535.19",
65473     "platforms": ["web", "phonegap", "cordova"],
65474
65475     "notes": {
65476         "1": "<a href=\"http://www.google.com/nexus/#/tech-specs\" target=\"_blank\">Specs</a>"
65477     }
65478
65479 };
65480
65481 });
65482 define('ripple/devices/NexusS', function (require, exports, module) {
65483 /*
65484  *  Copyright 2011 Research In Motion Limited.
65485  *
65486  * Licensed under the Apache License, Version 2.0 (the "License");
65487  * you may not use this file except in compliance with the License.
65488  * You may obtain a copy of the License at
65489  *
65490  * http://www.apache.org/licenses/LICENSE-2.0
65491  *
65492  * Unless required by applicable law or agreed to in writing, software
65493  * distributed under the License is distributed on an "AS IS" BASIS,
65494  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
65495  * See the License for the specific language governing permissions and
65496  * limitations under the License.
65497  */
65498 module.exports = {
65499     "id" : "NexusS",
65500     "name": "Nexus S",
65501     "manufacturer": "Samsung",
65502     "model": "Nexux S",
65503     "osName": "Android",
65504     "uuid" : "F54E13F1-C1B7-4212-BFA8-AB3C9C3F088F",
65505     "osVersion": "2.3.x",
65506
65507     "screen": {
65508         "width": 480,
65509         "height": 800
65510     },
65511     "viewPort": {
65512         "portrait": {
65513             "width": 480,
65514             "height": 800,
65515             "paddingTop": 0,
65516             "paddingLeft": 0
65517         },
65518         "landscape": {
65519             "width": 800,
65520             "height": 480,
65521             "paddingTop": 0,
65522             "paddingLeft": 0
65523         }
65524     },
65525
65526     "ppi": 235,
65527     "userAgent": "Mozilla/5.0 (Linux; U; Android 2.3.2; en-us; Nexus S Build/GRH78C) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1",
65528     "platforms": ["web", "phonegap", "cordova"],
65529
65530     "notes": {
65531         "1": "<a href=\"http://www.google.com/nexus/#/tech-specs\" target=\"_blank\">Specs</a>"
65532     }
65533
65534 };
65535
65536 });
65537 define('ripple/devices/NokiaN8', function (require, exports, module) {
65538 /*
65539  *  Copyright 2011 Research In Motion Limited.
65540  *
65541  * Licensed under the Apache License, Version 2.0 (the "License");
65542  * you may not use this file except in compliance with the License.
65543  * You may obtain a copy of the License at
65544  *
65545  * http://www.apache.org/licenses/LICENSE-2.0
65546  *
65547  * Unless required by applicable law or agreed to in writing, software
65548  * distributed under the License is distributed on an "AS IS" BASIS,
65549  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
65550  * See the License for the specific language governing permissions and
65551  * limitations under the License.
65552  */
65553 module.exports = {
65554
65555     "id": "NokiaN8",
65556     "name": "Nokia N8",
65557     "model": "N8",
65558     "osName": "SymbianOS",
65559     "uuid": "42",
65560     "osVersion": "3",
65561     "manufacturer": "Nokia",
65562
65563     "screen": {
65564         "width": 360,
65565         "height": 640
65566     },
65567     "viewPort": {
65568         "portrait": {
65569             "width": 360,
65570             "height": 640,
65571             "paddingTop": 0,
65572             "paddingLeft": 0
65573         },
65574         "landscape": {
65575             "width": 640,
65576             "height": 360,
65577             "paddingTop": 0,
65578             "paddingLeft": 0
65579         }
65580     },
65581
65582     "ppi": 209.8,
65583     "userAgent": "(Symbian/3; S60/5.2 Mozilla/5.0; NokiaN8-00/10.0.000; Profile/MIDP-2.1 Configuration/CLDC-1.1) AppleWebKit/525 (KHTML, like Gecko) BrowserNG/7.2",
65584     "platforms": ["web", "phonegap"],
65585
65586     "notes": {
65587         "1": "<a href=\"http://www.forum.nokia.com/Devices/Device_specifications/N8-00/\" target=\"_blank\">Specs</a>"
65588     }
65589 };
65590
65591 });
65592 define('ripple/devices/NokiaN97', function (require, exports, module) {
65593 /*
65594  *  Copyright 2011 Research In Motion Limited.
65595  *
65596  * Licensed under the Apache License, Version 2.0 (the "License");
65597  * you may not use this file except in compliance with the License.
65598  * You may obtain a copy of the License at
65599  *
65600  * http://www.apache.org/licenses/LICENSE-2.0
65601  *
65602  * Unless required by applicable law or agreed to in writing, software
65603  * distributed under the License is distributed on an "AS IS" BASIS,
65604  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
65605  * See the License for the specific language governing permissions and
65606  * limitations under the License.
65607  */
65608 module.exports = {
65609     "id": "NokiaN97",
65610     "name": "Nokia N97/5800 (touch)",
65611     "manufacturer": "Nokia",
65612     "model": "N97",
65613     "osName": "S60",
65614     "osVersion": "v5",
65615     "uuid": "42",
65616
65617     "screen": {
65618         "width": 360,
65619         "height": 640
65620     },
65621     "viewPort": {
65622         "portrait": {
65623             "width": 360,
65624             "height": 640,
65625             "paddingTop": 0,
65626             "paddingLeft": 0
65627         },
65628         "landscape": {
65629             "width": 640,
65630             "height": 360,
65631             "paddingTop": 0,
65632             "paddingLeft": 0
65633         }
65634     },
65635
65636     "ppi": 232,
65637     "userAgent": "?",
65638     "platforms": ["web", "phonegap"]
65639 };
65640
65641 });
65642 define('ripple/devices/PalmPre', function (require, exports, module) {
65643 /*
65644  *  Copyright 2011 Research In Motion Limited.
65645  *
65646  * Licensed under the Apache License, Version 2.0 (the "License");
65647  * you may not use this file except in compliance with the License.
65648  * You may obtain a copy of the License at
65649  *
65650  * http://www.apache.org/licenses/LICENSE-2.0
65651  *
65652  * Unless required by applicable law or agreed to in writing, software
65653  * distributed under the License is distributed on an "AS IS" BASIS,
65654  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
65655  * See the License for the specific language governing permissions and
65656  * limitations under the License.
65657  */
65658 module.exports = {
65659     "id": "PalmPre",
65660     "name": "Palm Pre",
65661     "manufacturer": "Palm",
65662     "model": "Pre",
65663     "osName": "WebOS",
65664     "osVersion": "1.x",
65665
65666     "screen": {
65667         "width": 320,
65668         "height": 480
65669     },
65670     "viewPort": {
65671         "portrait": {
65672             "width": 320,
65673             "height": 480,
65674             "paddingTop": 0,
65675             "paddingLeft": 0
65676         },
65677         "landscape": {
65678             "width": 480,
65679             "height": 320,
65680             "paddingTop": 0,
65681             "paddingLeft": 0
65682         }
65683     },
65684
65685     "ppi": 186.09,
65686     "userAgent": "Mozilla/5.0 (webOS/1.0; U; en-US) AppleWebKit/525.27.1 (KHTML, like Gecko) Version/1.0 Safari/525.27.1 Pre/1.0",
65687     "platforms": ["web", "phonegap"],
65688
65689     "notes": {
65690         "1": "<a href=\"http://www.palm.com/us/products/phones/pre/#tab2\" target=\"_blank\">Specs</a>"
65691     }
65692 };
65693
65694 });
65695 define('ripple/devices/PalmPre2', function (require, exports, module) {
65696 /*
65697  *  Copyright 2011 Research In Motion Limited.
65698  *
65699  * Licensed under the Apache License, Version 2.0 (the "License");
65700  * you may not use this file except in compliance with the License.
65701  * You may obtain a copy of the License at
65702  *
65703  * http://www.apache.org/licenses/LICENSE-2.0
65704  *
65705  * Unless required by applicable law or agreed to in writing, software
65706  * distributed under the License is distributed on an "AS IS" BASIS,
65707  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
65708  * See the License for the specific language governing permissions and
65709  * limitations under the License.
65710  */
65711 module.exports = {
65712     "id": "PalmPre2",
65713     "name": "Palm Pre 2",
65714     "manufacturer": "Palm",
65715     "model": "Pre",
65716     "osName": "WebOS",
65717     "osVersion": "2.x",
65718
65719     "screen": {
65720         "width": 320,
65721         "height": 480
65722     },
65723     "viewPort": {
65724         "portrait": {
65725             "width": 320,
65726             "height": 480,
65727             "paddingTop": 0,
65728             "paddingLeft": 0
65729         },
65730         "landscape": {
65731             "width": 480,
65732             "height": 320,
65733             "paddingTop": 0,
65734             "paddingLeft": 0
65735         }
65736     },
65737
65738     "ppi": 186.09,
65739     // TODO :: not exactly the correct userAgent webkit version is probably different
65740     "userAgent": "Mozilla/5.0 (webOS/2.0; U; en-US) AppleWebKit/525.27.1 (KHTML, like Gecko) Version/1.0 Safari/525.27.1 Pre/2.0",
65741     "platforms": ["web", "phonegap"],
65742
65743     "notes": {
65744         "1": "<a href=\"http://www.palm.com/us/products/phones/pre2/#tab2\" target=\"_blank\">Specs</a>"
65745     }
65746 };
65747
65748 });
65749 define('ripple/devices/Pearl9100', function (require, exports, module) {
65750 /*
65751  *  Copyright 2011 Research In Motion Limited.
65752  *
65753  * Licensed under the Apache License, Version 2.0 (the "License");
65754  * you may not use this file except in compliance with the License.
65755  * You may obtain a copy of the License at
65756  *
65757  * http://www.apache.org/licenses/LICENSE-2.0
65758  *
65759  * Unless required by applicable law or agreed to in writing, software
65760  * distributed under the License is distributed on an "AS IS" BASIS,
65761  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
65762  * See the License for the specific language governing permissions and
65763  * limitations under the License.
65764  */
65765 module.exports = {
65766
65767     "id": "Pearl9100",
65768     "name": "BlackBerry Pearl 9100",
65769     "model": "9100",
65770     "osName": "BlackBerry OS",
65771     "uuid": "42",
65772     "osVersion": "6",
65773     "manufacturer": "Research In Motion",
65774
65775     "skin": "Pearl9100",
65776
65777     "capabilities": [
65778         "input.keyboard.issuretype",
65779         "location.gps",
65780         "location.maps",
65781         "media.audio.capture",
65782         "media.video.capture",
65783         "media.recording",
65784         "storage.memorycard",
65785         "network.bluetooth",
65786         "network.wlan",
65787         "network.3gpp"
65788     ],
65789
65790     "screen": {
65791         "width": 360,
65792         "height": 400
65793     },
65794     "viewPort": {
65795         "portrait": {
65796             "width": 360,
65797             "height": 400,
65798             "paddingTop": 0,
65799             "paddingLeft": 0
65800         }
65801     },
65802
65803     "ppi": 239,
65804     "userAgent": "Mozilla/5.0 (BlackBerry; U; BlackBerry 9100; en) AppleWebKit/534.3+ (KHTML, like Gecko) Version/6.0.0.286 Mobile Safari/534.3+",
65805     "platforms": ["web", "phonegap", "webworks.handset"]
65806 };
65807
65808 });
65809 define('ripple/devices/Playbook', function (require, exports, module) {
65810 /*
65811  *  Copyright 2011 Research In Motion Limited.
65812  *
65813  * Licensed under the Apache License, Version 2.0 (the "License");
65814  * you may not use this file except in compliance with the License.
65815  * You may obtain a copy of the License at
65816  *
65817  * http://www.apache.org/licenses/LICENSE-2.0
65818  *
65819  * Unless required by applicable law or agreed to in writing, software
65820  * distributed under the License is distributed on an "AS IS" BASIS,
65821  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
65822  * See the License for the specific language governing permissions and
65823  * limitations under the License.
65824  */
65825 module.exports = {
65826
65827     "id": "Playbook",
65828     "name": "BlackBerry Playbook",
65829     "model": "100669958",
65830     "osName": "BlackBerry PlayBook OS",
65831     "uuid": "42",
65832     "osVersion": "BlackBerry PlayBook OS",
65833     "manufacturer": "Research In Motion",
65834
65835     "skin": "Playbook",
65836
65837     "capabilities": [
65838         "input.touch",
65839         "location.gps",
65840         "media.audio.capture",
65841         "media.video.capture",
65842         "media.recording",
65843         "network.bluetooth",
65844         "network.wlan"
65845     ],
65846
65847     "screen": {
65848         "width": 1024,
65849         "height": 600
65850     },
65851     "viewPort": {
65852         "portrait": {
65853             "width": 1024,
65854             "height": 600,
65855             "paddingTop": 0,
65856             "paddingLeft": 0
65857         },
65858         "landscape": {
65859             "width": 600,
65860             "height": 1024,
65861             "paddingTop": 0,
65862             "paddingLeft": 0
65863         }
65864     },
65865
65866     "defaultOrientation": "landscape",
65867
65868     "ppi": 169.55,
65869     "userAgent": "Mozilla/5.0 (PlayBook; U; RIM Tablet OS 2.1.0; en-US) AppleWebKit/536.2+ (KHTML, like Gecko) Version/7.2.1.0 Safari/536.2+",
65870     "platforms": ["web", "webworks.tablet", "phonegap", "cordova"]
65871 };
65872
65873 });
65874 define('ripple/devices/QVGA', function (require, exports, module) {
65875 /*
65876  *  Copyright 2011 Research In Motion Limited.
65877  *
65878  * Licensed under the Apache License, Version 2.0 (the "License");
65879  * you may not use this file except in compliance with the License.
65880  * You may obtain a copy of the License at
65881  *
65882  * http://www.apache.org/licenses/LICENSE-2.0
65883  *
65884  * Unless required by applicable law or agreed to in writing, software
65885  * distributed under the License is distributed on an "AS IS" BASIS,
65886  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
65887  * See the License for the specific language governing permissions and
65888  * limitations under the License.
65889  */
65890 module.exports = {
65891     "id": "QVGA",
65892     "name": "Generic - QVGA (240X320)",
65893     "osName": "Generic",
65894     "osVersion": "Generic",
65895     "manufacturer": "Generic",
65896     "model": "Generic",
65897     "uuid": "42",
65898
65899     "screen": {
65900         "width": 240,
65901         "height": 320
65902     },
65903     "viewPort": {
65904         "portrait": {
65905             "width": 240,
65906             "height": 320,
65907             "paddingTop": 0,
65908             "paddingLeft": 0
65909         },
65910         "landscape": {
65911             "width": 320,
65912             "height": 240,
65913             "paddingTop": 0,
65914             "paddingLeft": 0
65915         }
65916     },
65917
65918     "ppi": 96,
65919     "platforms": ["web", "phonegap", "cordova", "tizen"],
65920     "userAgent": "Mozilla/5.0 (X11; U; Linux x86_64; en-US) AppleWebKit/533.2 (KHTML, like Gecko) Chrome/5.0.342.7 Safari/533.2"
65921 };
65922
65923 });
65924 define('ripple/devices/Style9670', function (require, exports, module) {
65925 /*
65926  *  Copyright 2011 Research In Motion Limited.
65927  *
65928  * Licensed under the Apache License, Version 2.0 (the "License");
65929  * you may not use this file except in compliance with the License.
65930  * You may obtain a copy of the License at
65931  *
65932  * http://www.apache.org/licenses/LICENSE-2.0
65933  *
65934  * Unless required by applicable law or agreed to in writing, software
65935  * distributed under the License is distributed on an "AS IS" BASIS,
65936  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
65937  * See the License for the specific language governing permissions and
65938  * limitations under the License.
65939  */
65940 module.exports = {
65941
65942     "id": "Style9670",
65943     "name": "BlackBerry Style 9670",
65944     "model": "9670",
65945     "osName": "BlackBerry OS",
65946     "uuid": "42",
65947     "osVersion": "6",
65948     "manufacturer": "Research In Motion",
65949
65950     "skin": "Style9670",
65951
65952     "capabilities": [
65953         "location.gps",
65954         "location.maps",
65955         "media.audio.capture",
65956         "media.video.capture",
65957         "media.recording",
65958         "storage.memorycard",
65959         "network.bluetooth",
65960         "network.wlan",
65961         "network.3gpp"
65962     ],
65963
65964     "screen": {
65965         "width": 360,
65966         "height": 400
65967     },
65968     "viewPort": {
65969         "portrait": {
65970             "width": 360,
65971             "height": 400,
65972             "paddingTop": 0,
65973             "paddingLeft": 0
65974         }
65975     },
65976
65977     "ppi": 200,
65978     "userAgent": "Mozilla/5.0 (BlackBerry; U; BlackBerry 9670; en) AppleWebKit/534.3+ (KHTML, like Gecko) Version/6.0.0.286 Mobile Safari/534.3+",
65979     "platforms": ["web", "phonegap", "webworks.handset"]
65980 };
65981
65982 });
65983 define('ripple/devices/Tattoo', function (require, exports, module) {
65984 /*
65985  *  Copyright 2011 Research In Motion Limited.
65986  *
65987  * Licensed under the Apache License, Version 2.0 (the "License");
65988  * you may not use this file except in compliance with the License.
65989  * You may obtain a copy of the License at
65990  *
65991  * http://www.apache.org/licenses/LICENSE-2.0
65992  *
65993  * Unless required by applicable law or agreed to in writing, software
65994  * distributed under the License is distributed on an "AS IS" BASIS,
65995  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
65996  * See the License for the specific language governing permissions and
65997  * limitations under the License.
65998  */
65999 module.exports = {
66000     "id": "Tattoo",
66001     "name": "HTC Tattoo",
66002     "manufacturer": "HTC",
66003     "model": "Tattoo",
66004     "osVersion": "1.6",
66005     "uuid": "6F196F23-FD0D-4F62-B27B-730147FCC5A3",
66006     "osName": "Android",
66007
66008     "screen": {
66009         "width": 240,
66010         "height": 320
66011     },
66012     "viewPort": {
66013         "portrait": {
66014             "width": 240,
66015             "height": 320,
66016             "paddingTop": 0,
66017             "paddingLeft": 0
66018         }
66019     },
66020
66021     "ppi": 142.9,
66022     "userAgent": "Mozilla/5.0 (Linux; U; Android 1.6; en-us; HTC_TATTOO_A3288 Build/DRC79) AppleWebKit/528.5+ (KHTML, like Gecko) Version/3.1.2 Mobile Safari/525.20.1",
66023     "platforms": ["web", "phonegap"]
66024 };
66025
66026 });
66027 define('ripple/devices/Torch9800', function (require, exports, module) {
66028 /*
66029  *  Copyright 2011 Research In Motion Limited.
66030  *
66031  * Licensed under the Apache License, Version 2.0 (the "License");
66032  * you may not use this file except in compliance with the License.
66033  * You may obtain a copy of the License at
66034  *
66035  * http://www.apache.org/licenses/LICENSE-2.0
66036  *
66037  * Unless required by applicable law or agreed to in writing, software
66038  * distributed under the License is distributed on an "AS IS" BASIS,
66039  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
66040  * See the License for the specific language governing permissions and
66041  * limitations under the License.
66042  */
66043 module.exports = {
66044
66045     "id": "Torch9800",
66046     "name": "BlackBerry Torch 9800",
66047     "model": "9800",
66048     "osName": "BlackBerry OS",
66049     "uuid": "42",
66050     "osVersion": "6",
66051     "manufacturer": "Research In Motion",
66052
66053     "skin": "Torch9800",
66054
66055     "capabilities": [
66056         "input.touch",
66057         "location.gps",
66058         "location.maps",
66059         "media.audio.capture",
66060         "media.video.capture",
66061         "media.recording",
66062         "storage.memorycard",
66063         "network.bluetooth",
66064         "network.wlan",
66065         "network.3gpp"
66066     ],
66067
66068     "screen": {
66069         "width": 360,
66070         "height": 480
66071     },
66072     "viewPort": {
66073         "portrait": {
66074             "width": 360,
66075             "height": 480,
66076             "paddingTop": 0,
66077             "paddingLeft": 0
66078         },
66079         "landscape": {
66080             "width": 480,
66081             "height": 360,
66082             "paddingTop": 0,
66083             "paddingLeft": 0
66084         }
66085     },
66086
66087     "ppi": 188.68,
66088     "userAgent": "Mozilla/5.0 (BlackBerry; U; BlackBerry 9800; en) AppleWebKit/534.1+ (KHTML, Like Gecko) Version/6.0.0.141 Mobile Safari/534.1",
66089     "platforms": ["web", "phonegap", "webworks.handset"]
66090 };
66091
66092 });
66093 define('ripple/devices/Torch9810', function (require, exports, module) {
66094 /*
66095  *  Copyright 2011 Research In Motion Limited.
66096  *
66097  * Licensed under the Apache License, Version 2.0 (the "License");
66098  * you may not use this file except in compliance with the License.
66099  * You may obtain a copy of the License at
66100  *
66101  * http://www.apache.org/licenses/LICENSE-2.0
66102  *
66103  * Unless required by applicable law or agreed to in writing, software
66104  * distributed under the License is distributed on an "AS IS" BASIS,
66105  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
66106  * See the License for the specific language governing permissions and
66107  * limitations under the License.
66108  */
66109 module.exports = {
66110
66111     "id": "Torch9810",
66112     "name": "BlackBerry Torch 9810",
66113     "model": "9810",
66114     "osName": "BlackBerry OS",
66115     "uuid": "42",
66116     "osVersion": "7",
66117     "manufacturer": "Research In Motion",
66118
66119     "skin": "Torch9810",
66120
66121     "capabilities": [
66122         "input.touch",
66123         "location.gps",
66124         "location.maps",
66125         "media.audio.capture",
66126         "media.video.capture",
66127         "media.recording",
66128         "storage.memorycard",
66129         "network.bluetooth",
66130         "network.wlan",
66131         "network.3gpp"
66132     ],
66133
66134     "screen": {
66135         "width": 480,
66136         "height": 640
66137     },
66138     "viewPort": {
66139         "portrait": {
66140             "width": 480,
66141             "height": 640,
66142             "paddingTop": 0,
66143             "paddingLeft": 0
66144         },
66145         "landscape": {
66146             "width": 640,
66147             "height": 480,
66148             "paddingTop": 0,
66149             "paddingLeft": 0
66150         }
66151     },
66152
66153     "ppi": 253,
66154     "userAgent": "Mozilla/5.0 (BlackBerry; U; BlackBerry 9810; en) AppleWebKit/534.1+ (KHTML, Like Gecko) Version/7.0.0.0 Mobile Safari/534.1",
66155     "platforms": ["web", "phonegap", "webworks.handset"]
66156 };
66157
66158 });
66159 define('ripple/devices/Torch9860-9850', function (require, exports, module) {
66160 /*
66161  *  Copyright 2011 Research In Motion Limited.
66162  *
66163  * Licensed under the Apache License, Version 2.0 (the "License");
66164  * you may not use this file except in compliance with the License.
66165  * You may obtain a copy of the License at
66166  *
66167  * http://www.apache.org/licenses/LICENSE-2.0
66168  *
66169  * Unless required by applicable law or agreed to in writing, software
66170  * distributed under the License is distributed on an "AS IS" BASIS,
66171  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
66172  * See the License for the specific language governing permissions and
66173  * limitations under the License.
66174  */
66175 module.exports = {
66176
66177     "id": "Torch9860-9850",
66178     "name": "BlackBerry Torch 9860/9850",
66179     "model": "9860-9850",
66180     "osName": "BlackBerry OS",
66181     "uuid": "42",
66182     "osVersion": "7",
66183     "manufacturer": "Research In Motion",
66184
66185     "skin": "Torch9860-9850",
66186
66187     "capabilities": [
66188         "input.touch",
66189         "location.gps",
66190         "location.maps",
66191         "media.audio.capture",
66192         "media.video.capture",
66193         "media.recording",
66194         "storage.memorycard",
66195         "network.bluetooth",
66196         "network.wlan",
66197         "network.3gpp"
66198     ],
66199
66200     "screen": {
66201         "width": 480,
66202         "height": 800
66203     },
66204     "viewPort": {
66205         "portrait": {
66206             "width": 480,
66207             "height": 800,
66208             "paddingTop": 0,
66209             "paddingLeft": 0
66210         },
66211         "landscape": {
66212             "width": 800,
66213             "height": 480,
66214             "paddingTop": 0,
66215             "paddingLeft": 0
66216         }
66217     },
66218
66219     "ppi": 253,
66220     "userAgent": "Mozilla/5.0 (BlackBerry; U; BlackBerry 9860; en) AppleWebKit/534.1+ (KHTML, Like Gecko) Version/7.0.0.0 Mobile Safari/534.1",
66221     "platforms": ["web", "phonegap", "webworks.handset"]
66222 };
66223
66224 });
66225 define('ripple/devices/WQVGA', function (require, exports, module) {
66226 /*
66227  *  Copyright 2011 Research In Motion Limited.
66228  *
66229  * Licensed under the Apache License, Version 2.0 (the "License");
66230  * you may not use this file except in compliance with the License.
66231  * You may obtain a copy of the License at
66232  *
66233  * http://www.apache.org/licenses/LICENSE-2.0
66234  *
66235  * Unless required by applicable law or agreed to in writing, software
66236  * distributed under the License is distributed on an "AS IS" BASIS,
66237  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
66238  * See the License for the specific language governing permissions and
66239  * limitations under the License.
66240  */
66241 module.exports = {
66242     "id": "WQVGA",
66243     "name": "Generic - WQVGA (240x480)",
66244     "osName": "Generic",
66245     "osVersion": "Generic",
66246     "manufacturer": "Generic",
66247     "model": "Generic",
66248     "uuid": "42",
66249
66250     "screen": {
66251         "width": 240,
66252         "height": 480
66253     },
66254     "viewPort": {
66255         "portrait": {
66256             "width": 240,
66257             "height": 480,
66258             "paddingTop": 0,
66259             "paddingLeft": 0
66260         },
66261         "landscape": {
66262             "width": 480,
66263             "height": 240,
66264             "paddingTop": 0,
66265             "paddingLeft": 0
66266         }
66267     },
66268
66269     "ppi": 96,
66270     "browser": ["Generic"],
66271     "platforms": ["web", "phonegap", "tizen"],
66272     "userAgent": "Mozilla/5.0 (X11; U; Linux x86_64; en-US) AppleWebKit/533.2 (KHTML, like Gecko) Chrome/5.0.342.7 Safari/533.2"
66273 };
66274
66275 });
66276 define('ripple/devices/WSVGA', function (require, exports, module) {
66277 /*
66278  *  Copyright 2011 Research In Motion Limited.
66279  *
66280  * Licensed under the Apache License, Version 2.0 (the "License");
66281  * you may not use this file except in compliance with the License.
66282  * You may obtain a copy of the License at
66283  *
66284  * http://www.apache.org/licenses/LICENSE-2.0
66285  *
66286  * Unless required by applicable law or agreed to in writing, software
66287  * distributed under the License is distributed on an "AS IS" BASIS,
66288  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
66289  * See the License for the specific language governing permissions and
66290  * limitations under the License.
66291  */
66292 module.exports = {
66293     "id": "WSVGA",
66294     "name": "WSVGA (600x1024)",
66295     "osName": "Generic",
66296     "osVersion": "Generic",
66297     "manufacturer": "Generic",
66298     "model": "Generic",
66299     "uuid": "42",
66300     "firmware": "Generic",
66301
66302     "screen": {
66303         "width": 600,
66304         "height": 1024
66305     },
66306     "viewPort": {
66307         "portrait": {
66308             "width": 600,
66309             "height": 1024,
66310             "paddingTop": 0,
66311             "paddingLeft": 0
66312         },
66313         "landscape": {
66314             "width": 1024,
66315             "height": 600,
66316             "paddingTop": 0,
66317             "paddingLeft": 0
66318         }
66319     },
66320
66321     "ppi": 316,
66322     "browser": ["Generic"],
66323     "platforms": ["wac", "web", "phonegap", "tizen", "cordova"],
66324     "userAgent": "Mozilla/5.0 (X11; U; Linux x86_64; en-US) AppleWebKit/533.2 (KHTML, like Gecko) Chrome/5.0.342.7 Safari/533.2"
66325 };
66326
66327 });
66328 define('ripple/devices/WVGA', function (require, exports, module) {
66329 /*
66330  *  Copyright 2011 Research In Motion Limited.
66331  *
66332  * Licensed under the Apache License, Version 2.0 (the "License");
66333  * you may not use this file except in compliance with the License.
66334  * You may obtain a copy of the License at
66335  *
66336  * http://www.apache.org/licenses/LICENSE-2.0
66337  *
66338  * Unless required by applicable law or agreed to in writing, software
66339  * distributed under the License is distributed on an "AS IS" BASIS,
66340  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
66341  * See the License for the specific language governing permissions and
66342  * limitations under the License.
66343  */
66344 module.exports = {
66345     "id": "WVGA",
66346     "name": "WVGA (480x800)",
66347     "osName": "Generic",
66348     "osVersion": "Generic",
66349     "manufacturer": "Generic",
66350     "model": "Generic",
66351     "uuid": "42",
66352
66353     "screen": {
66354         "width": 480,
66355         "height": 800
66356     },
66357     "viewPort": {
66358         "portrait": {
66359             "width": 480,
66360             "height": 800,
66361             "paddingTop": 0,
66362             "paddingLeft": 0
66363         },
66364         "landscape": {
66365             "width": 800,
66366             "height": 480,
66367             "paddingTop": 0,
66368             "paddingLeft": 0
66369         }
66370     },
66371
66372     "ppi": 316,
66373     "browser": ["Generic"],
66374     "platforms": ["web", "phonegap", "tizen", "cordova"],
66375     "userAgent": "Mozilla/5.0 (X11; U; Linux x86_64; en-US) AppleWebKit/533.2 (KHTML, like Gecko) Chrome/5.0.342.7 Safari/533.2"
66376 };
66377
66378 });
66379 define('ripple/devices/Wave', function (require, exports, module) {
66380 /*
66381  *  Copyright 2011 Research In Motion Limited.
66382  *
66383  * Licensed under the Apache License, Version 2.0 (the "License");
66384  * you may not use this file except in compliance with the License.
66385  * You may obtain a copy of the License at
66386  *
66387  * http://www.apache.org/licenses/LICENSE-2.0
66388  *
66389  * Unless required by applicable law or agreed to in writing, software
66390  * distributed under the License is distributed on an "AS IS" BASIS,
66391  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
66392  * See the License for the specific language governing permissions and
66393  * limitations under the License.
66394  */
66395 module.exports = {
66396     "id": "Wave",
66397     "name": "Samsung Wave",
66398     "manufacturer": "Samsung",
66399     "model": "Wave",
66400     "osName": "Bada",
66401     "osVersion": "n/a",
66402
66403     "screen": {
66404         "width": 480,
66405         "height": 800
66406     },
66407     "viewPort": {
66408         "portrait": {
66409             "width": 480,
66410             "height": 800,
66411             "paddingTop": 0,
66412             "paddingLeft": 0
66413         },
66414         "landscape": {
66415             "width": 800,
66416             "height": 480,
66417             "paddingTop": 0,
66418             "paddingLeft": 0
66419         }
66420     },
66421
66422     "ppi": 283,
66423     "userAgent": "?",
66424     "platforms": ["web"]
66425 };
66426
66427 });
66428 define('ripple/devices/custom', function (require, exports, module) {
66429 /*
66430  *  Copyright 2012 Intel Corporation
66431  *
66432  * Licensed under the Apache License, Version 2.0 (the "License");
66433  * you may not use this file except in compliance with the License.
66434  * You may obtain a copy of the License at
66435  *
66436  * http://www.apache.org/licenses/LICENSE-2.0
66437  *
66438  * Unless required by applicable law or agreed to in writing, software
66439  * distributed under the License is distributed on an "AS IS" BASIS,
66440  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
66441  * See the License for the specific language governing permissions and
66442  * limitations under the License.
66443  */
66444
66445 module.exports = {
66446     "id": "CUSTOM",
66447     "name": "Custom",
66448     "osName": "Generic",
66449     "osVersion": "Generic",
66450     "manufacturer": "Generic",
66451     "model": "Generic",
66452     "uuid": "42",
66453     "firmware": "Generic",
66454
66455     "screen": {
66456         "width": 600,
66457         "height": 800
66458     },
66459     "viewPort": {
66460         "portrait": {
66461             "width": 600,
66462             "height": 800,
66463             "paddingTop": 0,
66464             "paddingLeft": 0
66465         },
66466         "landscape": {
66467             "width": 600,
66468             "height": 800,
66469             "paddingTop": 0,
66470             "paddingLeft": 0
66471         }
66472     },
66473
66474     "ppi": 316,
66475     "browser": ["Generic"],
66476     "platforms": [],
66477     "userAgent": "Mozilla/5.0 (X11; U; Linux x86_64; en-US) AppleWebKit/533.2 (KHTML, like Gecko) Chrome/5.0.342.7 Safari/533.2"
66478 };
66479
66480 });
66481 define('ripple/devices/iPad', function (require, exports, module) {
66482 /*
66483  *  Copyright 2011 Research In Motion Limited.
66484  *
66485  * Licensed under the Apache License, Version 2.0 (the "License");
66486  * you may not use this file except in compliance with the License.
66487  * You may obtain a copy of the License at
66488  *
66489  * http://www.apache.org/licenses/LICENSE-2.0
66490  *
66491  * Unless required by applicable law or agreed to in writing, software
66492  * distributed under the License is distributed on an "AS IS" BASIS,
66493  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
66494  * See the License for the specific language governing permissions and
66495  * limitations under the License.
66496  */
66497 module.exports = {
66498
66499     "id": "iPad",
66500     "name": "iPad",
66501     "model": "iPad",
66502     "osName": "iOS",
66503     "uuid": "e0101010d38bde8e6740011221af335301010333",
66504     "osVersion": "1.6",
66505     "manufacturer": "Apple",
66506
66507     "screen": {
66508         "width": 768,
66509         "height": 1024
66510     },
66511     "viewPort": {
66512         "portrait": {
66513             "width": 768,
66514             "height": 1024,
66515             "paddingTop": 0,
66516             "paddingLeft": 0
66517         },
66518         "landscape": {
66519             "width": 1024,
66520             "height": 768,
66521             "paddingTop": 0,
66522             "paddingLeft": 0
66523         }
66524     },
66525
66526     "ppi": 132,
66527     "userAgent": "Mozilla/5.0 (iPad; U; CPU OS 3_2 like Mac OS X; en-us) AppleWebKit/531.21.10 (KHTML, like Gecko) Version/4.0.4 Mobile/7B367 Safari/531.21.10",
66528     "platforms": ["web", "phonegap", "cordova"],
66529
66530     "notes": {
66531         "1": "<a href=\"http://www.apple.com/ipad/specs/\" target=\"_blank\">Specs</a>"
66532     }
66533 };
66534
66535 });
66536 define('ripple/devices/iPhone3', function (require, exports, module) {
66537 /*
66538  *  Copyright 2011 Research In Motion Limited.
66539  *
66540  * Licensed under the Apache License, Version 2.0 (the "License");
66541  * you may not use this file except in compliance with the License.
66542  * You may obtain a copy of the License at
66543  *
66544  * http://www.apache.org/licenses/LICENSE-2.0
66545  *
66546  * Unless required by applicable law or agreed to in writing, software
66547  * distributed under the License is distributed on an "AS IS" BASIS,
66548  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
66549  * See the License for the specific language governing permissions and
66550  * limitations under the License.
66551  */
66552 module.exports = {
66553
66554     "id": "iPhone3",
66555     "name": "iPhone 3G/3Gs/4/4s",
66556     "model": "3G",
66557     "osName": "iPhone",
66558     "osVersion": "3",
66559     "uuid": "e0101010d38bde8e6740011221af335301010333",
66560     "manufacturer": "Apple",
66561
66562     "screen": {
66563         "width": 320,
66564         "height": 480
66565     },
66566     "viewPort": {
66567         "portrait": {
66568             "width": 320,
66569             "height": 480,
66570             "paddingTop": 0,
66571             "paddingLeft": 0
66572         },
66573         "landscape": {
66574             "width": 480,
66575             "height": 320,
66576             "paddingTop": 0,
66577             "paddingLeft": 0
66578         }
66579     },
66580
66581     "ppi": 164.8,
66582     "userAgent": "Mozilla/5.0 (iPhone; U; CPU iPhone OS 3_0 like Mac OS X; en-us) AppleWebKit/420.1 (KHTML, like Gecko) Version/3.0 Mobile/1A542a Safari/419.3",
66583     "platforms": ["web", "phonegap", "cordova"]
66584 };
66585
66586 });
66587 define('ripple/devices/tizen-HD', function (require, exports, module) {
66588 /*
66589  *  Copyright 2012 Intel Corporation
66590  *
66591  * Licensed under the Apache License, Version 2.0 (the "License");
66592  * you may not use this file except in compliance with the License.
66593  * You may obtain a copy of the License at
66594  *
66595  * http://www.apache.org/licenses/LICENSE-2.0
66596  *
66597  * Unless required by applicable law or agreed to in writing, software
66598  * distributed under the License is distributed on an "AS IS" BASIS,
66599  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
66600  * See the License for the specific language governing permissions and
66601  * limitations under the License.
66602  */
66603
66604 module.exports = {
66605     "id": "tizen-HD",
66606     "name": "Tizen HD (720x1280)",
66607     "osName": "Generic",
66608     "osVersion": "Generic",
66609     "manufacturer": "Tizen",
66610     "model": "Generic",
66611     "uuid": "42",
66612     "firmware": "Generic",
66613
66614     "screen": {
66615         "width": 720,
66616         "height": 1280
66617     },
66618     "viewPort": {
66619         "portrait": {
66620             "width": 360,
66621             "height": 640,
66622             "paddingTop": 0,
66623             "paddingLeft": 0
66624         },
66625         "landscape": {
66626             "width": 640,
66627             "height": 360,
66628             "paddingTop": 0,
66629             "paddingLeft": 0
66630         }
66631     },
66632
66633     "ppi": 316,
66634     "browser": ["Generic"],
66635     "platforms": ["wac", "web", "phonegap", "tizen", "cordova"],
66636     "userAgent": "Mozilla/5.0 (X11; U; Linux x86_64; en-US) AppleWebKit/533.2 (KHTML, like Gecko) Chrome/5.0.342.7 Safari/533.2"
66637 };
66638
66639 });
66640 define('ripple/devices/tizen-WVGA', function (require, exports, module) {
66641 /*
66642  *  Copyright 2011 Research In Motion Limited.
66643  *
66644  * Licensed under the Apache License, Version 2.0 (the "License");
66645  * you may not use this file except in compliance with the License.
66646  * You may obtain a copy of the License at
66647  *
66648  * http://www.apache.org/licenses/LICENSE-2.0
66649  *
66650  * Unless required by applicable law or agreed to in writing, software
66651  * distributed under the License is distributed on an "AS IS" BASIS,
66652  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
66653  * See the License for the specific language governing permissions and
66654  * limitations under the License.
66655  */
66656 module.exports = {
66657     "id": "tizen-WVGA",
66658     "name": "Tizen WVGA (480x800)",
66659     "osName": "Generic",
66660     "osVersion": "Generic",
66661     "manufacturer": "Tizen",
66662     "model": "Generic",
66663     "uuid": "42",
66664
66665     "screen": {
66666         "width": 480,
66667         "height": 800
66668     },
66669     "viewPort": {
66670         "portrait": {
66671             "width": 320,
66672             "height": 534,
66673             "paddingTop": 0,
66674             "paddingLeft": 0
66675         },
66676         "landscape": {
66677             "width": 534,
66678             "height": 320,
66679             "paddingTop": 0,
66680             "paddingLeft": 0
66681         }
66682     },
66683
66684     "ppi": 316,
66685     "browser": ["Generic"],
66686     "platforms": ["web", "phonegap", "tizen", "cordova"],
66687     "userAgent": "Mozilla/5.0 (X11; U; Linux x86_64; en-US) AppleWebKit/533.2 (KHTML, like Gecko) Chrome/5.0.342.7 Safari/533.2"
66688 };
66689
66690 });
66691 define('ripple/devices', function (require, exports, module) {
66692 /*
66693  *  Copyright 2011 Research In Motion Limited.
66694  *
66695  * Licensed under the Apache License, Version 2.0 (the "License");
66696  * you may not use this file except in compliance with the License.
66697  * You may obtain a copy of the License at
66698  *
66699  * http://www.apache.org/licenses/LICENSE-2.0
66700  *
66701  * Unless required by applicable law or agreed to in writing, software
66702  * distributed under the License is distributed on an "AS IS" BASIS,
66703  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
66704  * See the License for the specific language governing permissions and
66705  * limitations under the License.
66706  */
66707 var _self,
66708     db = require('ripple/db'),
66709     utils = require('ripple/utils'),
66710     platform = require('ripple/platform'),
66711     event = require('ripple/event'),
66712     _devices = {};
66713
66714 event.on("HardwareKeyDefault", function (key) {
66715     if (key === 0 || key === "0") { //back button key
66716         require('ripple/emulatorBridge').window().history.back();
66717     }
66718 });
66719
66720 _self = module.exports = {
66721     initialize: function () {
66722         _devices = [
66723 /* 
66724            "Bold9700",
66725             "Bold9900",
66726             "Colt",
66727             "Curve9300",
66728             "Curve9350-9360-9370",
66729             "FWVGA",
66730             "G1",
66731 */
66732             "tizen-WVGA",
66733 /*
66734             "HPPre3",
66735             "HPVeer",
66736 */
66737 //            "HVGA",
66738 /*
66739             "iPad",
66740             "iPhone3",
66741             "Legend",
66742             "Nexus",
66743             "NexusS",
66744             "NexusGalaxy",
66745             "Nexus7",
66746             "NokiaN8",
66747             "NokiaN97",
66748             "PalmPre",
66749             "PalmPre2",
66750             "Pearl9100",
66751             "Playbook",
66752             "QVGA",
66753             "Style9670",
66754             "Tattoo",
66755             "Torch9800",
66756             "Torch9810",
66757             "Torch9860-9850",
66758             "Wave",
66759             "WQVGA",
66760 */
66761 //            "WSVGA",
66762             "WVGA",
66763             "HD",
66764             "tizen-HD",
66765             "custom"
66766         ].reduce(function (hash, deviceID) {
66767             hash[deviceID] = require('ripple/devices/' + deviceID);
66768             return hash;
66769         }, {});
66770
66771         var current = this.getCurrentDevice();
66772         require('ripple/bus').send('userAgent', current.userAgent);
66773     },
66774
66775     getCurrentDevice: function () {
66776         var deviceId = db.retrieve("device-key"),
66777             device = this.getDevice(deviceId),
66778             platformId = platform.current().id,
66779             does = function (device) {
66780                 return {
66781                     include: function (platformId) {
66782                         return device.platforms.some(function (id) {
66783                             return platformId === id;
66784                         });
66785                     }
66786                 };
66787             };
66788
66789         if (deviceId !== "custom" && (!device || !does(device).include(platformId))) {
66790             deviceId = utils.reduce(_devices, function (current, device, id) {
66791                 return does(device).include(platformId) ? id : current;
66792             });
66793             device = this.getDevice(deviceId);
66794         }
66795
66796         return device;
66797     },
66798
66799     getDevice: function (deviceId) {
66800         var device, width, height, viewportWidth, viewportHeight, layout, viewportTag, ratio;
66801
66802         device = _devices[deviceId] ? utils.copy(_devices[deviceId]) : null;
66803         width = db.retrieve("custom_width") || 600;
66804         height = db.retrieve("custom_height") || 800;
66805         viewportTag = db.retrieveObject("viewportTag");
66806         layout = db.retrieve("layout") || "portrait" ;
66807
66808         if (deviceId === undefined)
66809             return null;
66810         width =  parseInt(width, 10);
66811         height =  parseInt(height, 10);
66812
66813         if (viewportTag !== undefined) {
66814             if (viewportTag['width'] !== undefined) {
66815                 viewportWidth = parseInt(viewportTag['width'], 10);
66816                 if (isNaN(viewportWidth)) {
66817                     viewportWidth = viewportWidth = device.viewPort[layout].width;
66818                 }
66819                 db.saveObject("viewport_width", viewportWidth);
66820
66821                 if (layout === "portrait") {
66822                     if (deviceId !== "custom") {
66823                         ratio = device.screen.height / device.screen.width;
66824                     } else {
66825                         ratio = height / width;
66826                     }
66827                     viewportHeight = viewportWidth * ratio;
66828                     db.saveObject("viewport_height", viewportHeight);
66829                 } else {
66830                     if (deviceId !== "custom") {
66831                         ratio = device.screen.width / device.screen.height;
66832                     } else {
66833                         ratio = width / height;
66834                     }
66835                     viewportHeight = viewportWidth * ratio;
66836                     db.saveObject("viewport_height", viewportHeight);
66837                 }
66838             } else if(viewportTag['height'] !== undefined) {
66839                 viewportHeight = parseInt(viewportTag['height'], 10);
66840                 if (isNaN(viewportHeight)) {
66841                     viewportHeight = viewportHeight = device.viewPort[layout].height;
66842                 }
66843                 db.saveObject("viewport_height", viewportHeight);
66844
66845                 if (layout === "portrait") {
66846                     if (deviceId !== "custom") {
66847                         ratio = device.screen.height / device.screen.width;
66848                     } else {
66849                         ratio = height / width;
66850                     }
66851                     viewportWidth = viewportHeight / ratio;
66852                     db.saveObject("viewport_width", viewportWidth);
66853                 } else {
66854                     if (deviceId !== "custom") {
66855                         ratio = device.screen.width / device.screen.height;
66856                     } else {
66857                         ratio = width / height;
66858                     }
66859                     viewportWidth = viewportHeight / ratio;
66860                     db.saveObject("viewport_width", viewportWidth);
66861                 }
66862             }
66863         }
66864
66865         if (viewportWidth === undefined) {
66866             if (deviceId === "custom") {
66867                 viewportWidth = width;
66868             } else {
66869                 viewportWidth = device.viewPort[layout].width;
66870             }
66871         }
66872
66873         if (viewportHeight === undefined) {
66874             if (deviceId === "custom") {
66875                 viewportHeight = height;
66876             } else {
66877                 viewportHeight = device.viewPort[layout].height;
66878             }
66879         }
66880
66881         $('#resolution-custom-width').val(width);
66882         $('#resolution-custom-height').val(height);
66883
66884         if (deviceId === "custom") {
66885             device.screen.width = width;
66886             device.screen.height = height;
66887             $('input:radio[name="resolution-type"][value="custom"]').click();
66888         }
66889
66890         if (layout === "portrait") {
66891             device.viewPort.portrait.width = viewportWidth;
66892             device.viewPort.portrait.height = viewportHeight;
66893             device.viewPort.landscape.width = viewportHeight;
66894             device.viewPort.landscape.height = viewportWidth;
66895         } else {
66896             device.viewPort.portrait.width = viewportHeight;
66897             device.viewPort.portrait.height = viewportWidth;
66898             device.viewPort.landscape.width = viewportWidth;
66899             device.viewPort.landscape.height = viewportHeight;
66900         }
66901         return device;
66902     },
66903
66904     getDevicesForPlatform: function (platformId) {
66905         return utils.filter(_devices, function (device) {
66906             return device.platforms.indexOf(platformId) > -1;
66907         });
66908     }
66909 };
66910
66911 });
66912 define('ripple/documentEventListener', function (require, exports, module) {
66913 /*
66914  *  Copyright 2012 Intel Corporation.
66915  *
66916  * Licensed under the Apache License, Version 2.0 (the "License");
66917  * you may not use this file except in compliance with the License.
66918  * You may obtain a copy of the License at
66919  *
66920  * http://www.apache.org/licenses/LICENSE-2.0
66921  *
66922  * Unless required by applicable law or agreed to in writing, software
66923  * distributed under the License is distributed on an "AS IS" BASIS,
66924  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
66925  * See the License for the specific language governing permissions and
66926  * limitations under the License.
66927  */
66928
66929 var event = require('ripple/event'),
66930     constants = require('ripple/constants'),
66931     deviceSettings = require('ripple/deviceSettings'),
66932     ui = require('ripple/ui'),
66933     _self,
66934     _ComWinShow = false;
66935
66936 function _bind(name, win) {
66937     var _listeners = [];
66938
66939     return {
66940         add: function (callback, useCapture) {
66941             // ignore non-function
66942             if (typeof callback === "function") {
66943                 // ignore useCapture as we could not handle it
66944                 if (!useCapture) {
66945                     if (!_listeners.some(function (listener) {
66946                         return (listener === callback);
66947                     })) {
66948                         _listeners.push(callback);
66949                     }
66950                 }
66951             }
66952         },
66953         exec: function (arg) {
66954             _listeners.forEach(function (listener) {
66955                 listener.apply(win, arg);
66956             });
66957         },
66958         remove: function (callback, useCapture) {
66959             // ignore non-function
66960             if (typeof callback === "function") {
66961                 // ignore useCapture as we do not add them into _listeners
66962                 if (!useCapture) {
66963                     _listeners = _listeners.filter(function (listener) {
66964                         return (listener !== callback);
66965                     });
66966                 }
66967             }
66968         }
66969     };
66970 }
66971
66972 function _isComWinSHow() {
66973     return _ComWinShow;
66974 }
66975
66976 _self = {
66977     mask: function (frame, doc) {
66978         /* 
66979          * The current issue is that "document.addEventListener(visibilitychange, function(){...})" 
66980          * does not work if it is invoked in the document.DOMContentLoaded listeners, for example, at 
66981          * JQuery(document).ready function.
66982
66983          * The reason is that window.DOMContentLoaded is fired after the document.DOMContentLoaded. 
66984          * Currently we have not found a proper event to override the document.addEventListener. 
66985          * The beforeload is fine for window.addEventListener, while does not work for document.addEventListener 
66986          * because the contentDocument will be reset after loading. 
66987          */
66988         frame.addEventListener("DOMContentLoaded", function () {
66989             var widgetDocument = doc,
66990                 _pageVisibility,
66991                 add = widgetDocument.addEventListener,
66992                 remove = widgetDocument.removeEventListener;
66993
66994             widgetDocument.PAGE_HIDDEN  = "hidden";
66995             widgetDocument.PAGE_VISIBLE = "visible";
66996             widgetDocument.PAGE_PREVIEW = "preview";
66997
66998             function _lockScreen(on) {
66999                 var hidden = on;
67000
67001                 if (on) {
67002                     ui.showOverlay("lock-screen-window", function (background) {});
67003                 } else {
67004                     ui.hideOverlay("lock-screen-window", function (background) {});
67005                 }
67006
67007                 event.trigger("visibilitychange", [hidden]);
67008             }
67009
67010             function _isLockScreenOn() {
67011                 return deviceSettings.retrieve("Config.lockScreen");
67012             }
67013
67014             _lockScreen(_isLockScreenOn());
67015
67016             _pageVisibility = _bind("visibilitychange", frame.contentWindow);
67017
67018             widgetDocument.addEventListener = function (event, callback, useCapture) {
67019                 switch (event) {
67020                 case "visibilitychange":
67021                     _pageVisibility.add(callback, useCapture);
67022                     break;
67023
67024                 default:
67025                     add.apply(widgetDocument, arguments);
67026                     break;
67027                 }
67028             };
67029
67030             widgetDocument.removeEventListener = function (event, callback, useCapture) {
67031                 _pageVisibility.remove(callback, useCapture);
67032                 remove.apply(widgetDocument, arguments);
67033             };
67034
67035             event.on("LockScreenChanged", function (on) {
67036                 if (_isComWinSHow() === false) {
67037                     _lockScreen(on);
67038                 }
67039                 else {
67040                     if (on === true) {
67041                         ui.hideOverlay("communication-window");
67042                         _lockScreen(on);
67043                     }
67044                     else {
67045                         _lockScreen(on);
67046                         ui.showOverlay("communication-window");
67047                     }
67048                 }
67049             });
67050
67051             event.on("CommWinShow", function (status) {
67052                 _ComWinShow = status;
67053                 if (_isLockScreenOn() === true) {
67054                     if (status === false) {
67055                         _lockScreen(true);
67056                     }
67057                     else {
67058                         jQuery("#lock-screen-window").hide();
67059                     }
67060                 }
67061             });
67062
67063             event.on("visibilitychange", function (hidden) {
67064                 widgetDocument.hidden = hidden;
67065                 widgetDocument.visibilityState = hidden ? widgetDocument.PAGE_HIDDEN : widgetDocument.PAGE_VISIBLE;
67066                 _pageVisibility.exec();
67067             });
67068         });
67069     }
67070 };
67071
67072 module.exports = _self;
67073
67074 });
67075 define('ripple/emulatorBridge', function (require, exports, module) {
67076 /*
67077  *  Copyright 2011 Research In Motion Limited.
67078  *
67079  * Licensed under the Apache License, Version 2.0 (the "License");
67080  * you may not use this file except in compliance with the License.
67081  * You may obtain a copy of the License at
67082  *
67083  * http://www.apache.org/licenses/LICENSE-2.0
67084  *
67085  * Unless required by applicable law or agreed to in writing, software
67086  * distributed under the License is distributed on an "AS IS" BASIS,
67087  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
67088  * See the License for the specific language governing permissions and
67089  * limitations under the License.
67090  */
67091 var platform = require('ripple/platform'),
67092     builder = require('ripple/platform/builder'),
67093     utils = require('ripple/utils'),
67094     _xhr, _win, _doc;
67095
67096 function _getEmulatedViewportStyle(attr) {
67097     var vp = document.getElementById("viewport-container");
67098     return vp["client" + attr];
67099 }
67100
67101 function _getEmulatedDeviceStyle(attr) {
67102     var vp = document.getElementById("device-container"), value;
67103     value = vp.style[attr].replace(/\s/g, '');
67104     value = value.split("px")[0] - 4;
67105     return (value);
67106 }
67107
67108 function _screenAvailWidth() {
67109     return _getEmulatedDeviceStyle("width");
67110 }
67111
67112 function _screenAvailHeight() {
67113     return _getEmulatedDeviceStyle("height");
67114 }
67115
67116 function _screenWidth() {
67117     return _getEmulatedDeviceStyle("width");
67118 }
67119
67120 function _screenHeight() {
67121     return _getEmulatedDeviceStyle("height");
67122 }
67123
67124 function _window_innerWidth() {
67125     return _getEmulatedViewportStyle("Width");
67126 }
67127
67128 function _window_innerHeight() {
67129     return _getEmulatedViewportStyle("Height");
67130 }
67131
67132 function _marshalScreen(win) {
67133     utils.forEach({
67134         "availWidth": _screenAvailWidth,
67135         "availHeight": _screenAvailHeight,
67136         "width": _screenWidth,
67137         "height": _screenHeight
67138     }, function (mappedFunc, prop) {
67139         win.screen.__defineGetter__(prop, mappedFunc);
67140     });
67141
67142     utils.forEach({
67143         "innerWidth": _window_innerWidth,
67144         "innerHeight": _window_innerHeight
67145     }, function (mappedFunc, prop) {
67146         win.__defineGetter__(prop, mappedFunc);
67147     });
67148 }
67149
67150 module.exports = {
67151     link: function  (win, doc) {
67152         // Only cache the device window and route onmessage to it
67153         if (win.parent.parent === win.parent &&
67154                 win.frameElement.getAttribute('id') === 'document') {
67155             _win = win;
67156             _doc = doc;
67157             _xhr = win.XMLHttpRequest;
67158
67159             window.onmessage = function (e) {
67160                 if (typeof win.onmessage === 'function') {
67161                     win.onmessage(e);
67162                 }
67163             };
67164         }
67165
67166         require('ripple/widgetConfig').initialize();
67167
67168         var marshal = function (obj, key) {
67169                 window[key] = win[key] = obj;
67170             },
67171             currentPlatform = platform.current(),
67172             sandbox = {};
67173
67174         marshal(window.tinyHippos, "tinyHippos");
67175         marshal(window.XMLHttpRequest, "XMLHttpRequest");
67176         marshal(window.Date, "Date");
67177
67178         if (currentPlatform.initialize) {
67179             currentPlatform.initialize(win);
67180         }
67181
67182         builder.build(platform.current().objects).into(sandbox);
67183         utils.forEach(sandbox, marshal);
67184
67185         _marshalScreen(win);
67186         _marshalScreen(window);
67187     },
67188
67189     document: function () {
67190         return _doc;
67191     },
67192
67193     window: function () {
67194         return _win;
67195     },
67196
67197     xhr: function () {
67198         return _xhr;
67199     }
67200 };
67201
67202 });
67203 define('ripple/event', function (require, exports, module) {
67204 /*
67205  *  Copyright 2011 Research In Motion Limited.
67206  *
67207  * Licensed under the Apache License, Version 2.0 (the "License");
67208  * you may not use this file except in compliance with the License.
67209  * You may obtain a copy of the License at
67210  *
67211  * http://www.apache.org/licenses/LICENSE-2.0
67212  *
67213  * Unless required by applicable law or agreed to in writing, software
67214  * distributed under the License is distributed on an "AS IS" BASIS,
67215  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
67216  * See the License for the specific language governing permissions and
67217  * limitations under the License.
67218  */
67219 var utils = require('ripple/utils'),
67220     exception = require('ripple/exception'),
67221     _listeners = {};
67222
67223 function _on(eventType, listener, scope, once) {
67224     if (!eventType) {
67225         throw "eventType must be truthy";
67226     }
67227     _listeners[eventType] = _listeners[eventType] || [];
67228     _listeners[eventType].push({
67229         func: listener,
67230         scope: scope,
67231         once: !!once
67232     });
67233 }
67234
67235 function _deleteEventHandler(eventType, listenerFunc, scope) {
67236     var i, listeners;
67237
67238     if (!eventType) {
67239         throw "eventType must be truthy";
67240     }
67241
67242     listeners = _listeners[eventType];
67243
67244     // only delete once
67245     for (i = 0; i < listeners.length; i++) {
67246         if (listeners[i].func === listenerFunc) {
67247             listeners.splice(i, 1);
67248             break;
67249         }
67250     }
67251 }
67252
67253 function _trigger(listener, args, sync) {
67254     try {
67255         if (sync) {
67256             listener.func.apply(listener.scope, args);
67257         }
67258         else {
67259             setTimeout(function () {
67260                 listener.func.apply(listener.scope, args);
67261             }, 1);
67262         }
67263     }
67264     catch (e) {
67265         exception.handle(e);
67266     }
67267 }
67268
67269 module.exports = {
67270     on: function (eventType, listener, scope) {
67271         _on(eventType, listener, scope, false);
67272     },
67273
67274     once: function (eventType, listener, scope) {
67275         _on(eventType, listener, scope, true);
67276     },
67277
67278     trigger: function (eventType, args, sync) {
67279         args = args || [];
67280         sync = sync || false;
67281
67282         var listeners = _listeners[eventType];
67283
67284         if (listeners) {
67285             listeners.forEach(function (listener) {
67286                 _trigger(listener, args, sync);
67287             });
67288
67289             _listeners[eventType] = listeners.filter(function (listener) {
67290                 return !listener.once;
67291             });
67292         }
67293     },
67294
67295     eventHasSubscriber: function (eventType) {
67296         return !!_listeners[eventType];
67297     },
67298
67299     getEventSubscribers: function (eventType) {
67300         return utils.copy(_listeners[eventType]) || [];
67301     },
67302
67303     clear: function (eventType) {
67304         if (eventType) {
67305             delete _listeners[eventType];
67306         }
67307     },
67308
67309     deleteEventHandler: function (eventType, listener, scope) {
67310         _deleteEventHandler(eventType, listener, scope);
67311     }
67312 };
67313
67314 });
67315 define('ripple/exception', function (require, exports, module) {
67316 /*
67317  *  Copyright 2011 Research In Motion Limited.
67318  *
67319  * Licensed under the Apache License, Version 2.0 (the "License");
67320  * you may not use this file except in compliance with the License.
67321  * You may obtain a copy of the License at
67322  *
67323  * http://www.apache.org/licenses/LICENSE-2.0
67324  *
67325  * Unless required by applicable law or agreed to in writing, software
67326  * distributed under the License is distributed on an "AS IS" BASIS,
67327  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
67328  * See the License for the specific language governing permissions and
67329  * limitations under the License.
67330  */
67331 var _console = require('ripple/console');
67332
67333 function _getStack(depth) {
67334     var caller,
67335         stack = "",
67336         count = 0;
67337
67338     try {
67339         caller = arguments.callee.caller.arguments.callee.caller;
67340
67341         while (count <= depth && caller) {
67342             stack += "function: " + caller.toString().match(/function\s?(.*)\{/)[1] + "\n";
67343             caller = caller.arguments.callee.caller;
67344             count++;
67345         }
67346     } catch (e) {
67347         stack = "failed to determine stack trace (" + (e.name || e.type) + " :: " + e.message + ")";
67348     }
67349
67350     return stack;
67351 }
67352
67353 module.exports = {
67354
67355     types: {
67356         Application: "Application",
67357         ArgumentLength: "ArgumentLength",
67358         ArgumentType: "ArgumentType",
67359         Argument: "Argument",
67360         NotificationType: "NotificationType",
67361         NotificationStateType: "NotificationStateType",
67362         DomObjectNotFound: "DomObjectNotFound",
67363         LayoutType: "LayoutType",
67364         OrientationType: "OrientationType",
67365         DeviceNotFound: "DeviceNotFound",
67366         tinyHipposMaskedException: "tinyHipposMaskedException",
67367         Geo: "Geo",
67368         Accelerometer: "Accelerometer",
67369         MethodNotImplemented: "MethodNotImplemented",
67370         InvalidState: "InvalidState",
67371         ApplicationState: "ApplicationState"
67372     },
67373
67374     handle: function handle(exception, reThrow) {
67375         reThrow = reThrow || false;
67376
67377         var eMsg = exception.message || "exception caught!",
67378         msg = eMsg + "\n\n" + (exception.stack || "*no stack provided*") + "\n\n";
67379
67380         _console.error(msg);
67381
67382         if (reThrow) {
67383             throw exception;
67384         }
67385     },
67386
67387     raise: function raise(exceptionType, message, customExceptionObject) {
67388         var obj = customExceptionObject || {
67389                 type: "",
67390                 message: "",
67391
67392                 toString: function () {
67393                     var result = this.name + ': "' + this.message + '"';
67394
67395                     if (this.stack) {
67396                         result += "\n" + this.stack;
67397                     }
67398                     return result;
67399                 }
67400             };
67401
67402         message = message || "";
67403
67404         obj.name = exceptionType;
67405         obj.type = exceptionType;
67406         // TODO: include the exception objects original message if exists
67407         obj.message = message;
67408         obj.stack = _getStack(5);
67409
67410         throw obj;
67411     },
67412
67413     throwMaskedException: function throwMaskedException(exceptionType, message, customExceptionObject) {
67414         try {
67415             this.raise.apply(this, arguments);
67416         } catch (e) {
67417             this.handle(e);
67418         }
67419         this.raise(this.types.tinyHipposMaskedException, "tinyhippos terminated your script due to exception");
67420     }
67421
67422 };
67423
67424 });
67425 define('ripple/fileSystem', function (require, exports, module) {
67426 /*
67427  *  Copyright 2011 Research In Motion Limited.
67428  *
67429  * Licensed under the Apache License, Version 2.0 (the "License");
67430  * you may not use this file except in compliance with the License.
67431  * You may obtain a copy of the License at
67432  *
67433  * http://www.apache.org/licenses/LICENSE-2.0
67434  *
67435  * Unless required by applicable law or agreed to in writing, software
67436  * distributed under the License is distributed on an "AS IS" BASIS,
67437  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
67438  * See the License for the specific language governing permissions and
67439  * limitations under the License.
67440  */
67441 var constants = require('ripple/constants'),
67442     db = require('ripple/db'),
67443     exception = require('ripple/exception'),
67444     event = require('ripple/event'),
67445     _console = require('ripple/console'),
67446     utils = require('ripple/utils'),
67447     _fileSystemPaths = {
67448         "photos": { "uri": "" },
67449         "videos": { "uri": "" },
67450         "music": { "uri": "" },
67451         "downloads": { "uri": "" },
67452         "widgethome": { "uri": "" }
67453     },
67454     _fileSystemRegex = {
67455         "photos": { "virtualPathRegex": /^\/virtual\/photos\//i },
67456         "videos": { "virtualPathRegex": /^\/virtual\/videos\//i },
67457         "music": { "virtualPathRegex": /^\/virtual\/music\//i },
67458         "downloads": { "virtualPathRegex": /^\/virtual\/downloads\//i },
67459         "widgethome": { "virtualPathRegex": /^\/virtual\/widgethome\//i }
67460     },
67461     _overrides = {};
67462
67463 module.exports = {
67464     initialize: function () {
67465         _fileSystemPaths = db.retrieveObject(constants.FILESYSTEM.PERSISTENCE_KEY) || _fileSystemPaths;
67466         _fileSystemPaths.widgethome.uri = window.location.protocol + "//" + window.location.host + window.location.pathname.substring(0, window.location.pathname.lastIndexOf('/') + 1);
67467     },
67468
67469     getURI: function getURI(origURI) {
67470         var newURI = origURI,
67471             found = false;
67472
67473         if (_overrides[origURI]) {
67474             return _overrides[origURI];
67475         }
67476
67477         utils.forEach(_fileSystemPaths, function (value, key) {
67478             if (found) {
67479                 return;
67480             }
67481
67482             var uri = value.uri.replace(/\/$/, "");
67483             if (origURI.match(_fileSystemRegex[key].virtualPathRegex)) {
67484                 newURI = origURI.replace(_fileSystemRegex[key].virtualPathRegex, uri + "/");
67485                 found = true;
67486             }
67487         });
67488
67489         return newURI;
67490     },
67491
67492     exists: function (path) {
67493         try {
67494             var scrubbedUri = this.getURI(path),
67495                 xhr = new XMLHttpRequest();
67496
67497             xhr.open("GET", scrubbedUri, false);
67498             xhr.send();
67499
67500             //HACK: this should return maybe for 403
67501             return xhr.status !== 404;
67502         }
67503         catch (e) {
67504             exception.handle(e);
67505             _console.log("failed to check if [" + path + "] exists");
67506             return false;
67507         }
67508     },
67509
67510
67511     getFileSystemPaths: function getFileSystemPaths() {
67512         return utils.copy(_fileSystemPaths);
67513     },
67514
67515     updateFileSystemPaths: function updateFileSystemPaths(filePathsObject) {
67516         _fileSystemPaths = utils.copy(filePathsObject);
67517         _fileSystemPaths.widgethome.uri = window.location.protocol + "//" + window.location.host + window.location.pathname;
67518         db.saveObject(constants.FILESYSTEM.PERSISTENCE_KEY, filePathsObject);
67519     },
67520
67521     override : function (from, to) {
67522         _overrides[from] = to;
67523     }
67524 };
67525
67526 });
67527 define('ripple/fs', function (require, exports, module) {
67528 /*
67529  *  Copyright 2011 Research In Motion Limited.
67530  *
67531  * Licensed under the Apache License, Version 2.0 (the "License");
67532  * you may not use this file except in compliance with the License.
67533  * You may obtain a copy of the License at
67534  *
67535  * http://www.apache.org/licenses/LICENSE-2.0
67536  *
67537  * Unless required by applicable law or agreed to in writing, software
67538  * distributed under the License is distributed on an "AS IS" BASIS,
67539  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
67540  * See the License for the specific language governing permissions and
67541  * limitations under the License.
67542  */
67543 var utils = require('ripple/utils'),
67544     constants = require('ripple/constants'),
67545     event = require('ripple/event'),
67546     _console = require('ripple/console'),
67547     _self, _fs;
67548
67549 function _map(array, callback) {
67550     var map = [], i;
67551     for (i = 0; i < array.length; i++) {
67552         map[i] = callback(array[i], i);
67553     }
67554     return map;
67555 }
67556
67557 function _resolveLocalFileSystemURL(path, success, error) {
67558     return (window.resolveLocalFileSystemURL || window.webkitResolveLocalFileSystemURL)(path, success, error);
67559 }
67560
67561 function _blobBuilder() {
67562     var BlobBuilder = window.BlobBuilder || window.WebKitBlobBuilder;
67563     return new BlobBuilder();
67564 }
67565
67566 function _error(e) {
67567     var msg = '';
67568
67569     switch (e.code) {
67570     case FileError.QUOTA_EXCEEDED_ERR:
67571         msg = 'QUOTA_EXCEEDED_ERR';
67572         break;
67573     case FileError.NOT_FOUND_ERR:
67574         msg = 'NOT_FOUND_ERR';
67575         break;
67576     case FileError.SECURITY_ERR:
67577         msg = 'SECURITY_ERR';
67578         break;
67579     case FileError.INVALID_MODIFICATION_ERR:
67580         msg = 'INVALID_MODIFICATION_ERR';
67581         break;
67582     case FileError.INVALID_STATE_ERR:
67583         msg = 'INVALID_STATE_ERR';
67584         break;
67585     default:
67586         msg = 'Unknown Error';
67587         break;
67588     }
67589
67590     _console.log('FileSystem error: ' + msg);
67591 }
67592
67593 _self = {
67594     initialize: function (prev, baton) {
67595         try {
67596             var requestFileSystem = window.requestFileSystem || window.webkitRequestFileSystem;
67597
67598             if (requestFileSystem) {
67599                 baton.take();
67600             }
67601
67602             requestFileSystem(window.TEMPORARY, constants.FS_SIZE, function (fs) {
67603                 _fs = fs;
67604                 event.trigger("FileSystemInitialized", null, true);
67605                 baton.pass();
67606             }, _error);
67607         }
67608         catch (e) {
67609             console.log("File System Not Available");
67610         }
67611     },
67612
67613     ls: function (path, success, error) {
67614         path = path || "/";
67615
67616         _fs.root.getDirectory(path, {}, function (dirEntry) {
67617             var dirReader = dirEntry.createReader();
67618             dirReader.readEntries(function (entries) {
67619                 success(_map(entries, function (entry, index) {
67620                     return entry;
67621                 }));
67622             }, error);
67623         }, error);
67624     },
67625
67626     rm: function (path, success, error, options) {
67627         options = options || {};
67628
67629         _fs.root[options.recursive ? "getDirectory" : "getFile"](path, {create: false}, function (entry) {
67630             entry[options.recursive ? "removeRecursively" : "remove"](function () {
67631                 success();
67632             }, error);
67633         }, error);
67634     },
67635
67636     rmdir: function (path, success, error, options) {
67637         options = options || {};
67638
67639         _fs.root.getDirectory(path, {create: false}, function (entry) {
67640             entry.remove(function () {
67641                 success();
67642             }, error);
67643         }, error);
67644     },
67645
67646     mkdir: function (path, success, error) {
67647         _fs.root.getDirectory(path, {create: true}, function (dirEntry) {
67648             success(dirEntry);
67649         }, error);
67650     },
67651
67652     mv: function (from, to, success, error) {
67653         var path = to.replace(/^\//, "").split("/"),
67654             fileName = path.splice(path.length - 1, 1).toString();
67655
67656         _self.stat(from, function (entry) {
67657             _self.stat(path.length > 0 ? path.join("/") : "/", function (dest) {
67658                 entry.moveTo(dest, fileName, function (finalDestination) {
67659                     success(finalDestination);
67660                 }, error);
67661             }, error);
67662         }, error);
67663     },
67664
67665     touch: function (path, success, error) {
67666         _fs.root.getFile(path, {create: true}, function (fileEntry) {
67667             success(fileEntry);
67668         }, error);
67669     },
67670
67671     cp: function (from, to, success, error) {
67672         var path = to.replace(/^\//, "").split("/"),
67673             fileName = path.splice(path.length - 1, 1).toString();
67674
67675         _self.stat(from, function (entry) {
67676             _self.stat(path.length > 0 ? path.join("/") : "/", function (dest) {
67677                 entry.copyTo(dest, fileName, function (finalDestination) {
67678                     success(finalDestination);
67679                 }, error);
67680             }, error);
67681         }, error);
67682     },
67683
67684     stat: function (path, success, error) {
67685         var url = "filesystem:" + utils.location().origin + "/temporary/" + path;
67686         _resolveLocalFileSystemURL(url, function (entry) {
67687             success(entry);
67688         }, error);
67689     },
67690
67691     write: function (path, contents, success, error, options) {
67692         options = options || {};
67693
67694         function write(entry) {
67695             entry.createWriter(function (fileWriter) {
67696                 var bb = _blobBuilder();
67697
67698                 fileWriter.onwriteend = function (progressEvent) {
67699                     success(entry);
67700                 };
67701                 fileWriter.onerror = error;
67702
67703                 if (options.mode === "append") {
67704                     fileWriter.seek(fileWriter.length);
67705                 }
67706
67707                 bb.append(contents);
67708                 fileWriter.write(bb.getBlob('text/plain'));
67709             }, error);
67710         }
67711
67712         _self.stat(path, function (entry) {
67713             if (options.mode === "append") {
67714                 write(entry);
67715             } else {
67716                 _self.rm(path, function () {
67717                     _self.touch(path, write, error);
67718                 }, error);
67719             }
67720         }, function (e) {
67721             if (e.code === FileError.NOT_FOUND_ERR) {
67722                 _self.touch(path, write, error);
67723             } else {
67724                 error(e);
67725             }
67726         });
67727     },
67728
67729     read: function (path, success, error) {
67730         _self.stat(path, function (entry) {
67731             entry.file(function (file) {
67732                 var reader = new FileReader();
67733
67734                 reader.onloadend = function (progressEvent) {
67735                     success(progressEvent.target.result);
67736                 };
67737                 reader.onerror = error;
67738
67739                 reader.readAsText(file);
67740             }, error);
67741         }, error);
67742     }
67743 };
67744
67745 module.exports = _self;
67746
67747 });
67748 define('ripple/geo', function (require, exports, module) {
67749 /*
67750  *  Copyright 2011 Research In Motion Limited.
67751  *
67752  * Licensed under the Apache License, Version 2.0 (the "License");
67753  * you may not use this file except in compliance with the License.
67754  * You may obtain a copy of the License at
67755  *
67756  * http://www.apache.org/licenses/LICENSE-2.0
67757  *
67758  * Unless required by applicable law or agreed to in writing, software
67759  * distributed under the License is distributed on an "AS IS" BASIS,
67760  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
67761  * See the License for the specific language governing permissions and
67762  * limitations under the License.
67763  */
67764 var db = require('ripple/db'),
67765     exception = require('ripple/exception'),
67766     event = require('ripple/event'),
67767     utils = require('ripple/utils'),
67768     _positionInfo = {
67769         "latitude": 39.968362,
67770         "longitude": 116.410186,
67771         "altitude": 50,
67772         "accuracy": 150,
67773         "altitudeAccuracy": 80,
67774         "heading": 0,
67775         "speed": 0,
67776         "cellID": 1130433
67777     },
67778     self;
67779
67780 function _serialize(settings) {
67781     var tempSettings = utils.copy(settings);
67782     tempSettings.position.timeStamp = "new Date(" + tempSettings.position.timeStamp.getTime() + ")";
67783     return tempSettings;
67784 }
67785
67786 function _validatePositionInfo(pInfo) {
67787     return (pInfo &&
67788         !(isNaN(pInfo.latitude) ||
67789         isNaN(pInfo.longitude) ||
67790         isNaN(pInfo.altitude) ||
67791         isNaN(pInfo.accuracy) ||
67792         isNaN(pInfo.altitudeAccuracy) ||
67793         isNaN(pInfo.heading) ||
67794         isNaN(pInfo.speed) ||
67795         isNaN(pInfo.cellID))) ? true : false;
67796 }
67797
67798 self = module.exports = {
67799     initialize: function () {
67800         var settings = db.retrieveObject("geosettings");
67801         if (settings) {
67802             utils.forEach(_positionInfo, function (value, key) {
67803                 _positionInfo[key] = parseFloat(settings.position[key] || value);
67804             });
67805
67806             self.timeout = settings.timeout;
67807             self.delay = settings.delay || 0;
67808
67809         }
67810     },
67811
67812     getPositionInfo: function () {
67813         var pi = utils.copy(_positionInfo);
67814         pi.timeStamp = new Date();
67815
67816         return pi;
67817     },
67818
67819     updatePositionInfo: function (newPositionInfo, delay, timeout) {
67820         if (!_validatePositionInfo(newPositionInfo)) {
67821             exception.raise(exception.types.Geo, "invalid positionInfo object");
67822         }
67823
67824         _positionInfo = utils.copy(newPositionInfo);
67825         _positionInfo.timeStamp = new Date();
67826
67827         self.delay = delay || 0;
67828         self.timeout = timeout;
67829
67830         db.saveObject("geosettings", _serialize({
67831             position: _positionInfo,
67832             delay: self.delay,
67833             timeout: self.timeout
67834         }));
67835
67836         event.trigger("PositionInfoUpdatedEvent", [_positionInfo]);
67837     },
67838
67839     timeout: false,
67840     delay: 0,
67841     map: {}
67842 };
67843
67844 });
67845 define('ripple/honeypot', function (require, exports, module) {
67846 /*
67847  *  Copyright 2011 Research In Motion Limited.
67848  *
67849  * Licensed under the Apache License, Version 2.0 (the "License");
67850  * you may not use this file except in compliance with the License.
67851  * You may obtain a copy of the License at
67852  *
67853  * http://www.apache.org/licenses/LICENSE-2.0
67854  *
67855  * Unless required by applicable law or agreed to in writing, software
67856  * distributed under the License is distributed on an "AS IS" BASIS,
67857  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
67858  * See the License for the specific language governing permissions and
67859  * limitations under the License.
67860  */
67861
67862 var noop = function () {};
67863
67864 module.exports = {
67865     monitor: function (context, target) {
67866
67867         var setup = function (get, set) {
67868             set = set || noop;
67869
67870             context.__defineGetter__(target, noop);
67871             context.__defineSetter__(target, function (value) {
67872                 context.__defineGetter__(target, get);
67873                 set(value);
67874             });
67875         };
67876
67877         return {
67878             andReturn: function (value) {
67879                 setup(function () {
67880                     return value;
67881                 });
67882             },
67883             andRun: function (get, set) {
67884                 setup(get, set);
67885             }
67886         };
67887     }
67888 };
67889
67890 });
67891 define('ripple/hwKeyEmulator', function (require, exports, module) {
67892 /*
67893  *  Copyright 2011 Research In Motion Limited.
67894  *
67895  * Licensed under the Apache License, Version 2.0 (the "License");
67896  * you may not use this file except in compliance with the License.
67897  * You may obtain a copy of the License at
67898  *
67899  * http://www.apache.org/licenses/LICENSE-2.0
67900  *
67901  * Unless required by applicable law or agreed to in writing, software
67902  * distributed under the License is distributed on an "AS IS" BASIS,
67903  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
67904  * See the License for the specific language governing permissions and
67905  * limitations under the License.
67906  */
67907
67908 var event = require('ripple/event'),
67909    _self;
67910
67911 function _HWKeyEvent(keyName) {
67912     var doc = document.getElementById('document').contentDocument,
67913     event;
67914
67915     event = doc.createEvent('Event');
67916     event.initEvent("tizenhwkey", true, false);
67917     event.__defineGetter__("keyName", function () {
67918         return keyName;
67919     });
67920     doc.dispatchEvent(event);
67921 }
67922
67923
67924 _self = {
67925     init: function (win, doc) {
67926         event.clear("tizenhwkeyEvent");
67927         event.on("tizenhwkeyEvent", function (keyName) {
67928             _HWKeyEvent(keyName);
67929         });
67930     }
67931 };
67932
67933 module.exports = _self;
67934
67935 });
67936 define('ripple/notifications', function (require, exports, module) {
67937 /*
67938  *  Copyright 2011 Research In Motion Limited.
67939  *
67940  * Licensed under the Apache License, Version 2.0 (the "License");
67941  * you may not use this file except in compliance with the License.
67942  * You may obtain a copy of the License at
67943  *
67944  * http://www.apache.org/licenses/LICENSE-2.0
67945  *
67946  * Unless required by applicable law or agreed to in writing, software
67947  * distributed under the License is distributed on an "AS IS" BASIS,
67948  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
67949  * See the License for the specific language governing permissions and
67950  * limitations under the License.
67951  */
67952 var constants = require('ripple/constants'),
67953     exception = require('ripple/exception'),
67954     utils = require('ripple/utils'),
67955     event = require('ripple/event');
67956
67957 function _validateAndInitNType(nType) {
67958     nType = nType || "normal";
67959
67960     if (nType !== "normal" && nType !== "error") {
67961         exception.raise(exception.types.NotificationType, "Unknown Notification Type == " + nType + ",when dealing with Console notification.");
67962     }
67963
67964     return nType;
67965 }
67966
67967 function _processNotification(nType, stateType, message) {
67968     nType = _validateAndInitNType(nType);
67969     message = message || "";
67970
67971     var display,
67972         displayText,
67973         className,
67974         notificationIcon,
67975         box = document.getElementById(constants.NOTIFICATIONS.MAIN_CONTAINER_CLASS),
67976         msgBox = document.getElementById(constants.NOTIFICATIONS.MESSAGE_TEXT_CONTAINER_CLASS);
67977
67978     className = "ui-widget";
67979
67980     switch (stateType) {
67981
67982     case constants.NOTIFICATIONS.STATE_TYPES.CLOSE:
67983         display = "display: none;"; //need to do this better.
67984         displayText = "";
67985         break;
67986
67987     case constants.NOTIFICATIONS.STATE_TYPES.OPEN:
67988         display = "display: block;"; //need to do this better.
67989         displayText = message;
67990         if (nType === "error") {
67991             displayText = "Oh Snap!\n\n" + displayText;
67992             className += " ui-state-error ui-corner-all";
67993             notificationIcon = '<span class="ui-icon ui-icon-alert" style="float: left; margin-right: .3em;"></span>';
67994         }
67995         else {
67996             className += " ui-state-highlight ui-corner-all";
67997             notificationIcon = '<span class="ui-icon ui-icon-info" style="float: left; margin-right: .3em;"></span>';
67998         }
67999         break;
68000
68001     default:
68002         exception.raise(exception.types.NotificationStateType, "Unknown StateType == " + stateType.toString());
68003     }
68004
68005     msgBox.innerHTML = notificationIcon + displayText;
68006     box.setAttribute("class", className);
68007     box.setAttribute("style", display);
68008
68009 }
68010
68011 module.exports = {
68012     openNotification: function (nType, msg) {
68013         _processNotification(nType, constants.NOTIFICATIONS.STATE_TYPES.OPEN, msg);
68014     },
68015
68016     closeNotification: function (nType) {
68017         _processNotification(nType, constants.NOTIFICATIONS.STATE_TYPES.CLOSE);
68018     }
68019 };
68020
68021 });
68022 define('ripple/omgwtf', function (require, exports, module) {
68023 /*
68024  *  Copyright 2011 Research In Motion Limited.
68025  *
68026  * Licensed under the Apache License, Version 2.0 (the "License");
68027  * you may not use this file except in compliance with the License.
68028  * You may obtain a copy of the License at
68029  *
68030  * http://www.apache.org/licenses/LICENSE-2.0
68031  *
68032  * Unless required by applicable law or agreed to in writing, software
68033  * distributed under the License is distributed on an "AS IS" BASIS,
68034  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
68035  * See the License for the specific language governing permissions and
68036  * limitations under the License.
68037  */
68038 var event = require('ripple/event'),
68039     db = require('ripple/db'),
68040     _loaded = false,
68041     _self;
68042
68043 function _delay(action) {
68044     window.setTimeout(function () {
68045         if (!_loaded) {
68046             if (jQuery(".first-run-window").is(":visible")) {
68047                 _delay(action);
68048             } else {
68049                 action();
68050             }
68051         }
68052     }, 10000);
68053 }
68054
68055 function _hide() {
68056     jQuery(".error-window").css({display: 'none'});
68057     jQuery(".error-dialog").css({display: 'none'});
68058 }
68059
68060 function _show() {
68061     jQuery(".error-window").css({display: 'block'});
68062
68063     jQuery(".error-dialog").css({
68064         display: 'block',
68065         left: (jQuery(document).width() / 2) - 277 + "px"
68066     });
68067
68068     jQuery("#error-wait").click(function () {
68069         _hide();
68070         _delay(_show);
68071     });
68072
68073     jQuery("#error-panic").click(function () {
68074         db.removeAll(null, function () {
68075             window.tinyHipposReload = true;
68076             localStorage.clear();
68077             location.reload();
68078         });
68079     });
68080 }
68081
68082 _delay(_show);
68083
68084 _self = {
68085     initialize: function (previous, baton) {
68086         event.on("TinyHipposLoaded", function () {
68087             _loaded = true;
68088         });
68089     },
68090     show: _show,
68091     hide: _hide
68092 };
68093
68094 module.exports = _self;
68095
68096 });
68097 define('ripple/platform/builder', function (require, exports, module) {
68098 /*
68099  *  Copyright 2011 Research In Motion Limited.
68100  *
68101  * Licensed under the Apache License, Version 2.0 (the "License");
68102  * you may not use this file except in compliance with the License.
68103  * You may obtain a copy of the License at
68104  *
68105  * http://www.apache.org/licenses/LICENSE-2.0
68106  *
68107  * Unless required by applicable law or agreed to in writing, software
68108  * distributed under the License is distributed on an "AS IS" BASIS,
68109  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
68110  * See the License for the specific language governing permissions and
68111  * limitations under the License.
68112  */
68113 var utils = require('ripple/utils'),
68114     db = require('ripple/db'),
68115     app = require('ripple/app'),
68116     constants = require('ripple/constants');
68117
68118 function _objectFactory(context, objects/*, allowed*/) {
68119     utils.forEach(objects, function (obj, key) {
68120         var result = {}, objFeatures = {}, rst, f, widgetFeatures;
68121
68122 //        if (allowed(obj)) {
68123         result = obj.path ? require('ripple/platform/' + obj.path) : {};
68124         if (typeof result === "function" && obj.handleSubfeatures && obj.handleSubfeatures === true) {
68125             rst = new result();
68126             if (obj.feature) {
68127                 objFeatures = obj.feature.split('|');
68128                 if (rst.handleSubFeatures) {
68129                     widgetFeatures = app.getInfo().features; // features in config.xml
68130                     f = {};
68131                     utils.forEach(objFeatures, function (o) {
68132                         if (widgetFeatures && !!widgetFeatures[o]) {
68133                             f[widgetFeatures[o].id] = widgetFeatures[o];
68134                         }
68135                     });
68136                     rst.handleSubFeatures(f);
68137                     delete rst.handleSubFeatures;
68138                 }
68139             }
68140             result = rst;
68141         }
68142 //        }
68143
68144         if (obj.children) {
68145             _objectFactory(result, obj.children/*, allowed*/);
68146         }
68147
68148         // inject into the context if it is allowed or it has children that were allowed
68149 //        if (allowed(obj) || utils.count(result)) {
68150         context[key] = result;
68151 //        }
68152 //        else {
68153 //            if (context.hasOwnProperty(key))
68154 //                console.log("delete " + key);
68155 //            delete context[key];
68156 //        }
68157     });
68158 }
68159
68160 module.exports = {
68161     build: function (objects) {
68162         return {
68163             into: function (sandbox) {
68164 /*                var features = utils.copy(app.getInfo().features);
68165                     allowed = function (obj) {
68166                         var contains = function (requirements) {
68167                             return requirements.split('|').some(function (feature) {
68168                                 return !!features[feature];
68169                             });
68170                         };
68171                         //object is allowed if:
68172                         // 1. it has no feature requirement
68173                         // 2. the config file doesn't exist (features collection is null)
68174                         // 3. the feature exists in the defined features
68175                         return !obj.feature || !features || (features && contains(obj.feature));
68176                     };
68177 */
68178
68179                 _objectFactory(sandbox, objects/*, allowed*/);
68180             }
68181         };
68182     }
68183 };
68184
68185 });
68186 define('ripple/platform/cordova/2.0.0/JavaPluginManager', function (require, exports, module) {
68187 module.exports = {
68188     exec: function () {
68189         throw "this really shouldn't be called. like ever!";
68190     },
68191     resume: function () {
68192         throw "this shouldn't be called";
68193     },
68194     pause: function () {
68195         throw "this shouldn't be called";
68196     },
68197     destroy: function () {
68198         throw "this shouldn't be called";
68199     }
68200 };
68201
68202 });
68203 define('ripple/platform/cordova/2.0.0/MediaError', function (require, exports, module) {
68204 /*
68205  *  Copyright 2011 Research In Motion Limited.
68206  *
68207  * Licensed under the Apache License, Version 2.0 (the "License");
68208  * you may not use this file except in compliance with the License.
68209  * You may obtain a copy of the License at
68210  *
68211  * http://www.apache.org/licenses/LICENSE-2.0
68212  *
68213  * Unless required by applicable law or agreed to in writing, software
68214  * distributed under the License is distributed on an "AS IS" BASIS,
68215  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
68216  * See the License for the specific language governing permissions and
68217  * limitations under the License.
68218  */
68219 var MediaError = function (code, msg) {
68220     this.code = (code !== undefined ? code : null);
68221     this.message = msg || "";
68222 };
68223
68224 MediaError.MEDIA_ERR_NONE_ACTIVE    = 0;
68225 MediaError.MEDIA_ERR_ABORTED        = 1;
68226 MediaError.MEDIA_ERR_NETWORK        = 2;
68227 MediaError.MEDIA_ERR_DECODE         = 3;
68228 MediaError.MEDIA_ERR_NONE_SUPPORTED = 4;
68229
68230 module.exports = MediaError;
68231
68232 });
68233 define('ripple/platform/cordova/2.0.0/bridge/accelerometer', function (require, exports, module) {
68234 /*
68235  *  Copyright 2011 Research In Motion Limited.
68236  *
68237  * Licensed under the Apache License, Version 2.0 (the "License");
68238  * you may not use this file except in compliance with the License.
68239  * You may obtain a copy of the License at
68240  *
68241  * http://www.apache.org/licenses/LICENSE-2.0
68242  *
68243  * Unless required by applicable law or agreed to in writing, software
68244  * distributed under the License is distributed on an "AS IS" BASIS,
68245  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
68246  * See the License for the specific language governing permissions and
68247  * limitations under the License.
68248  */
68249 var event = require('ripple/event'),
68250     _success,
68251     _error,
68252     _current = {x: 0, y: 0, z: 0, timestamp: (new Date()).getTime()},
68253     _interval;
68254
68255 event.on("AccelerometerInfoChangedEvent", function (accelerometerInfo) {
68256     _current.x = accelerometerInfo.accelerationIncludingGravity.x;
68257     _current.y = accelerometerInfo.accelerationIncludingGravity.y;
68258     _current.z = accelerometerInfo.accelerationIncludingGravity.z;
68259     _current.timestamp = (new Date()).getTime();
68260 });
68261
68262 module.exports = {
68263     start: function (success, error, args) {
68264         _success = success;
68265         _error = error;
68266         // Possible HACK? update the timestamp of the last data to something current
68267         _interval = window.setInterval(function () {
68268             _current.timestamp = (new Date()).getTime();
68269             _success(_current);
68270         }, 50);
68271     },
68272
68273     stop: function () {
68274         _success = null;
68275         _error = null;
68276         window.clearInterval(_interval);
68277     }
68278 };
68279
68280 });
68281 define('ripple/platform/cordova/2.0.0/bridge/app', function (require, exports, module) {
68282 /*
68283  *  Copyright 2011 Research In Motion Limited.
68284  *
68285  * Licensed under the Apache License, Version 2.0 (the "License");
68286  * you may not use this file except in compliance with the License.
68287  * You may obtain a copy of the License at
68288  *
68289  * http://www.apache.org/licenses/LICENSE-2.0
68290  *
68291  * Unless required by applicable law or agreed to in writing, software
68292  * distributed under the License is distributed on an "AS IS" BASIS,
68293  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
68294  * See the License for the specific language governing permissions and
68295  * limitations under the License.
68296  */
68297 var camera = require('ripple/ui/plugins/camera'),
68298     event = require('ripple/event');
68299
68300 module.exports = {
68301     show: function (success, error, args) {
68302         return success && success();
68303     }
68304 };
68305
68306 });
68307 define('ripple/platform/cordova/2.0.0/bridge/camera', function (require, exports, module) {
68308 /*
68309  *  Copyright 2011 Research In Motion Limited.
68310  *
68311  * Licensed under the Apache License, Version 2.0 (the "License");
68312  * you may not use this file except in compliance with the License.
68313  * You may obtain a copy of the License at
68314  *
68315  * http://www.apache.org/licenses/LICENSE-2.0
68316  *
68317  * Unless required by applicable law or agreed to in writing, software
68318  * distributed under the License is distributed on an "AS IS" BASIS,
68319  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
68320  * See the License for the specific language governing permissions and
68321  * limitations under the License.
68322  */
68323 var camera = require('ripple/ui/plugins/camera'),
68324     event = require('ripple/event');
68325
68326 module.exports = {
68327     takePicture: function (success, error, args) {
68328         event.once("captured-image", function (uri, file) {
68329             success(uri);
68330         });
68331         camera.show();
68332     },
68333     cleanup: function (success, error, args) {
68334         success();
68335     }
68336 };
68337
68338 });
68339 define('ripple/platform/cordova/2.0.0/bridge/capture', function (require, exports, module) {
68340 /*
68341  *  Copyright 2011 Research In Motion Limited.
68342  *
68343  * Licensed under the Apache License, Version 2.0 (the "License");
68344  * you may not use this file except in compliance with the License.
68345  * You may obtain a copy of the License at
68346  *
68347  * http://www.apache.org/licenses/LICENSE-2.0
68348  *
68349  * Unless required by applicable law or agreed to in writing, software
68350  * distributed under the License is distributed on an "AS IS" BASIS,
68351  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
68352  * See the License for the specific language governing permissions and
68353  * limitations under the License.
68354  */
68355
68356 var camera = require('ripple/ui/plugins/camera'),
68357     event = require('ripple/event');
68358
68359 module.exports = {
68360     captureImage: function (success, error, args) {
68361         event.once("captured-image", function (uri, file) {
68362             file.fullPath = uri;
68363             success([file]);
68364         });
68365         camera.show();
68366     }
68367 };
68368
68369 });
68370 define('ripple/platform/cordova/2.0.0/bridge/compass', function (require, exports, module) {
68371 /*
68372  *  Copyright 2011 Research In Motion Limited.
68373  *
68374  * Licensed under the Apache License, Version 2.0 (the "License");
68375  * you may not use this file except in compliance with the License.
68376  * You may obtain a copy of the License at
68377  *
68378  * http://www.apache.org/licenses/LICENSE-2.0
68379  *
68380  * Unless required by applicable law or agreed to in writing, software
68381  * distributed under the License is distributed on an "AS IS" BASIS,
68382  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
68383  * See the License for the specific language governing permissions and
68384  * limitations under the License.
68385  */
68386 var geo = require('ripple/geo');
68387
68388 module.exports = {
68389     getHeading: function (success, error, args) {
68390         // TODO: build facility to trigger onError() from emulator
68391         // see pivotal item: https://www.pivotaltracker.com/story/show/7040343
68392         success({
68393             magneticHeading: geo.getPositionInfo().heading, 
68394             trueHeading: geo.getPositionInfo().heading, 
68395             headingAccuracy: 100, 
68396             timestamp: new Date().getSeconds()
68397         });
68398     },
68399
68400     stopHeading: function () { 
68401         //do nothing
68402     }
68403 };
68404
68405 });
68406 define('ripple/platform/cordova/2.0.0/bridge/console', function (require, exports, module) {
68407 /*
68408  *  Copyright 2011 Research In Motion Limited.
68409  *
68410  * Licensed under the Apache License, Version 2.0 (the "License");
68411  * you may not use this file except in compliance with the License.
68412  * You may obtain a copy of the License at
68413  *
68414  * http://www.apache.org/licenses/LICENSE-2.0
68415  *
68416  * Unless required by applicable law or agreed to in writing, software
68417  * distributed under the License is distributed on an "AS IS" BASIS,
68418  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
68419  * See the License for the specific language governing permissions and
68420  * limitations under the License.
68421  */
68422
68423 module.exports = {
68424     log: function (win, fail, args) {
68425         console.log(args[0]);
68426     }
68427 };
68428
68429 });
68430 define('ripple/platform/cordova/2.0.0/bridge/contacts', function (require, exports, module) {
68431 /*
68432  *  Copyright 2011 Research In Motion Limited.
68433  *
68434  * Licensed under the Apache License, Version 2.0 (the "License");
68435  * you may not use this file except in compliance with the License.
68436  * You may obtain a copy of the License at
68437  *
68438  * http://www.apache.org/licenses/LICENSE-2.0
68439  *
68440  * Unless required by applicable law or agreed to in writing, software
68441  * distributed under the License is distributed on an "AS IS" BASIS,
68442  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
68443  * See the License for the specific language governing permissions and
68444  * limitations under the License.
68445  */
68446 var db = require('ripple/db'),
68447     utils = require('ripple/utils'),
68448     _self;
68449
68450 function _default() {
68451     return [{
68452         "name": {formatted: "Brent Lintner"},
68453         "displayName": "Brent Lintner",
68454         "emails": [{type: "work", value: "brent@tinyhippos.com", pref: false}]
68455     }, {
68456         "name": {formatted: "PJ Lowe"},
68457         "displayName": "PJ Lowe",
68458         "emails": [{type: "work", value: "pj@tinyhippos.com", pref: false}]
68459     }, {
68460         "name": {formatted: "Dan Silivestru"},
68461         "displayName": "Dan Silivestru",
68462         "emails": [{type: "work", value: "dan@tinyhippos.com", pref: false}]
68463     }, {
68464         "name": {formatted: "Gord Tanner"},
68465         "displayName": "Gord Tanner",
68466         "emails": [{type: "work", value: "gord@tinyhippos.com", pref: true}]
68467     }, {
68468         "name": {formatted: "Mark McArdle"},
68469         "displayName": "Mark McArdle",
68470         "emails": [{type: "work", value: "mark@tinyhippos.com", pref: false}]
68471     }].map(function (obj) {
68472         obj.id = Math.uuid(undefined, 16);
68473         return navigator.contacts.create(obj);
68474     });
68475 }
68476
68477 function _get() {
68478     return db.retrieveObject("cordova-contacts") || _default();
68479 }
68480
68481 function _save(contacts) {
68482     db.saveObject("cordova-contacts", contacts);
68483 }
68484
68485 function _filtered(compare, options) {
68486     // this could be done a lot better..
68487     var found = false;
68488     if (!options.filter || options.filter === "") {
68489         found = true;
68490     } else if (typeof compare === "string" &&
68491               compare.match(new RegExp(".*" + options.filter + ".*", "i"))) {
68492         found = true;
68493     } else if (typeof compare === "object" || compare instanceof Array) {
68494         utils.forEach(compare, function (value) {
68495             if (!found) {
68496                 found = _filtered(value, options);
68497             }
68498         });
68499     }
68500     return found;
68501 }
68502
68503 _self = {
68504     search: function (success, error, args) {
68505         var fields = args[0],
68506             options = args[1],
68507             foundContacts = [],
68508             tempContact = navigator.contacts.create(),
68509             contacts = _get();
68510
68511         options = options || {};
68512
68513         // handle special case of ["*"] to return all fields
68514         if (fields.length === 1 && fields[0] === "*") {
68515             fields = utils.map(tempContact, function (v, k) {
68516                 return k;
68517             });
68518         }
68519
68520         if (fields.length > 0) {
68521             contacts.forEach(function (contact, index) {
68522                 var newContact = navigator.contacts.create(contact);
68523
68524                 if (options && (!_filtered(contact, options))) {
68525                     return;
68526                 }
68527
68528                 utils.forEach(newContact, function (value, prop) {
68529                     if (typeof newContact[prop] !== "function" && prop !== "id" &&
68530                         !fields.some(function (field) {
68531                             return field === prop;
68532                         })) {
68533                         delete newContact[prop];
68534                     }
68535                 });
68536
68537                 foundContacts.push(newContact);
68538             });
68539         }
68540
68541         // TODO: don't loop over entire db just to slice the array
68542         if (options.multiple === false) {
68543             foundContacts = foundContacts.splice(0, 1);
68544         }
68545         success(foundContacts);
68546     },
68547
68548     save: function (success, error, args) {
68549         var contacts = _get(),
68550             contact = args[0],
68551             index;
68552
68553         if (!contact.id) {
68554             contact.id = Math.uuid(undefined, 16);
68555             contacts.push(contact);
68556         } else {
68557             index = contacts.reduce(function (result, value, index) {
68558                 return value.id === contact.id ? index : result;
68559             }, -1);
68560
68561             if (index >= 0) {
68562                 utils.mixin(contact, contacts[index]);
68563                 contact = contacts[index];
68564             } else {
68565                 contact = null;
68566             }
68567         }
68568
68569         _save(contacts);
68570         if (success) {
68571             success(contact);
68572         }
68573     },
68574
68575     remove: function (success, error, args) {
68576         var contacts = _get(),
68577             id = args[0],
68578             toDelete = contacts.reduce(function (result, current, index) {
68579                 return current.id === id ? index : result;
68580             }, -1);
68581
68582         if (toDelete >= 0) {
68583             contacts.splice(toDelete, 1);
68584             _save(contacts);
68585             if (success) {
68586                 success();
68587             }
68588         } else {
68589             error({code: 3, message: "could not find contact with id (" + id + ")"}); // PENDING_OPERATION_ERROR
68590         }
68591     }
68592 };
68593
68594 module.exports = _self;
68595
68596 });
68597 define('ripple/platform/cordova/2.0.0/bridge/device', function (require, exports, module) {
68598 /*
68599  *  Copyright 2011 Research In Motion Limited.
68600  *
68601  * Licensed under the Apache License, Version 2.0 (the "License");
68602  * you may not use this file except in compliance with the License.
68603  * You may obtain a copy of the License at
68604  *
68605  * http://www.apache.org/licenses/LICENSE-2.0
68606  *
68607  * Unless required by applicable law or agreed to in writing, software
68608  * distributed under the License is distributed on an "AS IS" BASIS,
68609  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
68610  * See the License for the specific language governing permissions and
68611  * limitations under the License.
68612  */
68613 var devices = require('ripple/devices');
68614
68615 module.exports = {
68616     getDeviceInfo: function (success, fail, args) {
68617         var device = devices.getCurrentDevice();
68618
68619         success({
68620             available: true,
68621             platform: device.osName,
68622             version: device.osVersion,
68623             name: device.name,
68624             uuid: device.uuid,
68625             cordova: "2.0.0"
68626         });
68627     }
68628 };
68629
68630 });
68631 define('ripple/platform/cordova/2.0.0/bridge/file', function (require, exports, module) {
68632 // HACK: fs keeps a reference to the last-used FileSystem requested via requestFileSystem
68633 // this is a hack because if you keep switching between TEMPORARY vs. PERSISTENT file systems requested,
68634 // and run Cordova File API methods, no parameter is passed into exec specifying the underlying File System.
68635 // This should be fixed in Cordova!
68636 var fs, 
68637     topCordova = require('ripple/platform/cordova/2.0.0/spec'),
68638     rlfsu;
68639
68640 function cleanPath(path) {
68641     while (path[0] && path[0] === '/') {
68642         path = path.substr(1);
68643     }
68644     return path;
68645 }
68646
68647 module.exports = {
68648     requestFileSystem: function (win, fail, args) {
68649         // HACK: may not be webkit
68650         var rfs = window.webkitRequestFileSystem,
68651             type = args[0],
68652             size = args[1];
68653
68654         // HACK: assume any FS requested over a gig in size will throw an error
68655         if (size > (1024 * 1024 * 1024 /* gigabyte */)) {
68656             if (fail) fail(FileError.QUOTA_EXCEEDED_ERR);
68657         } else {
68658             return rfs(type, size, function (effes) {
68659                 fs = effes;
68660                 win(effes);
68661             }, fail);
68662         }
68663     },
68664     resolveLocalFileSystemURI: function (win, fail, args) {
68665         var uri = args[0],
68666             fulluri = fs.root.toURL();
68667
68668         // HACK: iOS-specific bs right here. See lib/ios/plugin/ios/Entry.js in cordova.js for details
68669         // Cordova badly needs a unified File System abstraction.
68670         if (uri.indexOf("file://localhost") === 0) {
68671             uri = uri.substr(16);
68672         }
68673         uri = cleanPath(uri);
68674
68675         fulluri += uri;
68676
68677         return window.webkitResolveLocalFileSystemURL(fulluri, function (entry) {
68678             if (win) win(entry);
68679         }, function (error) {
68680             if (fail) fail(error.code);
68681         });
68682     },
68683     getFile: function (win, fail, args) {
68684         var path = args[0],
68685             filename = args[1],
68686             options = args[2],
68687             file = '';
68688
68689         path = cleanPath(path);
68690         filename = cleanPath(filename);
68691
68692         if (path) {
68693             file = path + '/';
68694         }
68695         file += filename;
68696
68697         fs.root.getFile(file, options, function (entry) {
68698             if (win) win(entry);
68699         }, function (err) {
68700             if (fail) fail(err.code);
68701         });
68702     },
68703     remove: function (win, fail, args) {
68704         var file = args[0];
68705         window.webkitResolveLocalFileSystemURL(fs.root.toURL() + file, function (entry) {
68706             entry.remove(function () {
68707                 if (win) win();
68708             }, function (err) {
68709                 if (fail) fail(err.code);
68710             });
68711         }, fail);
68712     },
68713     readEntries: function (win, fail, args) {
68714         var root = fs.root.toURL(),
68715             path = args[0],
68716             reader;
68717
68718         path = cleanPath(path);
68719         path = root + path;
68720
68721         window.webkitResolveLocalFileSystemURL(path, function (entry) {
68722             reader = entry.createReader();
68723             reader.readEntries(function (entries) {
68724                 if (win) win(entries);
68725             }, function (err) {
68726                 if (fail) fail(err.code);
68727             });
68728         }, function (err) {
68729             if (fail) fail(err.code);
68730         });
68731     },
68732     getDirectory: function (win, fail, args) {
68733         var path = args[0],
68734             filename = args[1],
68735             options = args[2],
68736             file = '';
68737
68738         path = cleanPath(path);
68739         filename = cleanPath(filename);
68740
68741         if (path) {
68742             file = path + '/';
68743         }
68744         file += filename;
68745
68746         fs.root.getDirectory(file, options, function (entry) {
68747             if (win) win(entry);
68748         }, function (err) {
68749             if (fail) fail(err.code);
68750         });
68751     },
68752     removeRecursively: function (win, fail, args) {
68753         var root = fs.root.toURL(),
68754             path = args[0];
68755
68756         path = cleanPath(path);
68757
68758         window.webkitResolveLocalFileSystemURL(root + path, function (dirEntry) {
68759             dirEntry.removeRecursively(function () {
68760                 if (win) win();
68761             }, function (err) {
68762                 if (fail) fail(err.code);
68763             });
68764         }, function (err) {
68765             if (fail) fail(err.code);
68766         });
68767     },
68768     getFileMetadata: function (win, fail, args) {
68769         var path = args[0],
68770             root = fs.root.toURL();
68771
68772         path = cleanPath(path);
68773
68774         window.webkitResolveLocalFileSystemURL(root + path, function (entry) {
68775             entry.file(function (file) {
68776                 if (win) win(file);
68777             }, function (err) {
68778                 if (fail) fail(err.code);
68779             });
68780         }, function (err) {
68781             if (fail) fail(err.code);
68782         });
68783     },
68784     getMetadata: function (win, fail, args) {
68785         var path = args[0],
68786             root = fs.root.toURL();
68787
68788         path = cleanPath(path);
68789         
68790         window.webkitResolveLocalFileSystemURL(root + path, function (entry) {
68791             entry.getMetadata(function (data) {
68792                 if (win) win(data);
68793             }, function (err) {
68794                 if (fail) fail(err.code);
68795             });
68796         }, function (err) {
68797             if (fail) fail(err.code);
68798         });
68799     },
68800     getParent: function (win, fail, args) {
68801         var path = args[0],
68802             root = fs.root.toURL();
68803
68804         path = cleanPath(path);
68805
68806         window.webkitResolveLocalFileSystemURL(root + path, function (entry) {
68807             entry.getParent(function (dirEntry) {
68808                 if (win) win(dirEntry);
68809             }, function (err) {
68810                 if (fail) fail(err.code);
68811             });
68812         }, function (err) {
68813             if (fail) fail(err.code);
68814         });
68815     },
68816     copyTo: function (win, fail, args) {
68817         var src = args[0],
68818             parent = args[1],
68819             name = args[2],
68820             root = fs.root.toURL();
68821
68822         parent = cleanPath(parent);
68823         src = cleanPath(src);
68824
68825         rlfsu = window.webkitResolveLocalFileSystemURL;
68826         // get the directoryentry that we will copy TO
68827         rlfsu(root + parent, function (parentDirToCopyTo) {
68828             rlfsu(root + src, function (sourceDir) {
68829                 sourceDir.copyTo(parentDirToCopyTo, name, function (newEntry) {
68830                     if (win) win(newEntry);
68831                 }, function (err) {
68832                     if (fail) fail(err.code);
68833                 });
68834             }, function (err) {
68835                 if (fail) fail(err.code);
68836             });
68837         }, function (err) {
68838             if (fail) fail(err.code);
68839         });
68840     },
68841     moveTo: function (win, fail, args) {
68842         var src = args[0],
68843             parent = args[1],
68844             name = args[2],
68845             root = fs.root.toURL();
68846
68847         parent = cleanPath(parent);
68848         src = cleanPath(src);
68849
68850         rlfsu = window.webkitResolveLocalFileSystemURL;
68851         // get the directoryentry that we will move TO
68852         rlfsu(root + parent, function (parentDirToMoveTo) {
68853             rlfsu(root + src, function (sourceDir) {
68854                 sourceDir.moveTo(parentDirToMoveTo, name, function (newEntry) {
68855                     if (win) win(newEntry);
68856                 }, function (err) {
68857                     if (fail) fail(err.code);
68858                 });
68859             }, function (err) {
68860                 if (fail) fail(err.code);
68861             });
68862         }, function (err) {
68863             if (fail) fail(err.code);
68864         });
68865     },
68866     write: function (win, fail, args) {
68867         var file = args[0],
68868             text = args[1],
68869             position = args[2],
68870             sourcepath,
68871             BB = window.BlobBuilder || window.WebKitBlobBuilder,
68872             bb = new BB();
68873
68874         // Format source path
68875         sourcepath = (file.fullPath ? file.fullPath : '') + file.name;
68876         sourcepath = cleanPath(sourcepath);
68877
68878         // Create a blob for the text to be written
68879         bb.append(text);
68880
68881         // Get the FileEntry, create if necessary
68882         fs.root.getFile(sourcepath, {create: true}, function (entry) {
68883             // Create a FileWriter for this entry
68884             entry.createWriter(function (writer) {
68885                 writer.onwriteend = function (progressEvt) {
68886                     if (win) win(progressEvt.total);
68887                 };
68888                 writer.onerror = function (err) {
68889                     if (fail) fail(err.code);
68890                 };
68891
68892                 if (position && position > 0) {
68893                     writer.seek(position);
68894                 }
68895                 writer.write(bb.getBlob('text/plain'));
68896             }, function (err) {
68897                 if (fail) fail(err.code);
68898             });
68899         }, function (err) {
68900             if (fail) fail(err.code);
68901         });
68902     },
68903     readAsText: function (win, fail, args) {
68904         var path = args[0],
68905             encoding = args[1],
68906             FileReader = topCordova.nativeMethods.FileReader,
68907             fr = new window.FileReader();
68908
68909         // Set up FileReader events
68910         fr.onerror = function (err) {
68911             if (fail) fail(err.code);
68912         };
68913         fr.onload = function (evt) {
68914             if (win) win(evt.target.result);
68915         };
68916
68917         path = cleanPath(path);
68918
68919         fs.root.getFile(path, {create: false}, function (entry) {
68920             entry.file(function (blob) {
68921                 fr.readAsText(blob, encoding);
68922             }, function (err) {
68923                 if (fail) fail(err.code);
68924             });
68925         }, function (err) {
68926             if (fail) fail(err.code);
68927         });
68928     },
68929     readAsDataURL: function (win, fail, args) {
68930         var path = args[0],
68931             FileReader = topCordova.nativeMethods.FileReader,
68932             fr = new window.FileReader();
68933
68934         // Set up FileReader events
68935         fr.onerror = function (err) {
68936             if (fail) fail(err.code);
68937         };
68938         fr.onload = function (evt) {
68939             if (win) win(evt.target.result);
68940         };
68941
68942         path = cleanPath(path);
68943
68944         fs.root.getFile(path, {create: false}, function (entry) {
68945             entry.file(function (blob) {
68946                 fr.readAsDataURL(blob);
68947             }, function (err) {
68948                 if (fail) fail(err.code);
68949             });
68950         }, function (err) {
68951             if (fail) fail(err.code);
68952         });
68953     },
68954     truncate: function (win, fail, args) {
68955         var file = args[0],
68956             position = args[1],
68957             sourcepath;
68958
68959         // Format source path
68960         sourcepath = (file.fullPath ? file.fullPath : '') + file.name;
68961         sourcepath = cleanPath(sourcepath);
68962
68963         // Get the FileEntry, create if necessary
68964         fs.root.getFile(sourcepath, {create: false}, function (entry) {
68965             // Create a FileWriter for this entry
68966             entry.createWriter(function (writer) {
68967                 writer.onwriteend = function (progressEvt) {
68968                     if (win) win(progressEvt.target.length);
68969                 };
68970                 writer.onerror = function (err) {
68971                     if (fail) fail(err.code);
68972                 };
68973
68974                 writer.truncate(position);
68975             }, function (err) {
68976                 if (fail) fail(err.code);
68977             });
68978         }, function (err) {
68979             if (fail) fail(err.code);
68980         });
68981     }
68982 };
68983
68984 });
68985 define('ripple/platform/cordova/2.0.0/bridge/geolocation', function (require, exports, module) {
68986 /*
68987  *  Copyright 2011 Research In Motion Limited.
68988  *
68989  * Licensed under the Apache License, Version 2.0 (the "License");
68990  * you may not use this file except in compliance with the License.
68991  * You may obtain a copy of the License at
68992  *
68993  * http://www.apache.org/licenses/LICENSE-2.0
68994  *
68995  * Unless required by applicable law or agreed to in writing, software
68996  * distributed under the License is distributed on an "AS IS" BASIS,
68997  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
68998  * See the License for the specific language governing permissions and
68999  * limitations under the License.
69000  */
69001 var event = require('ripple/event'),
69002     geo = require('ripple/geo'),
69003     utils = require('ripple/utils'),
69004     PositionError = require('ripple/platform/w3c/1.0/PositionError'),
69005     _watches = {},
69006     _current = {
69007         "latitude": 43.465187,
69008         "longitude": -80.522372,
69009         "altitude": 100,
69010         "accuracy": 150,
69011         "altitudeAccuracy": 80,
69012         "heading": 0,
69013         "velocity": 0,
69014     },
69015     _error;
69016
69017 function _getCurrentPosition(win, fail) {
69018     if (geo.timeout) {
69019         if (fail) {
69020             var positionError = new PositionError();
69021
69022             positionError.code = PositionError.TIMEOUT;
69023             positionError.message = "postion timed out";
69024             fail(positionError);
69025         }
69026     }
69027     else {
69028         win(geo.getPositionInfo());
69029     }
69030 }
69031
69032 event.on("PositionInfoUpdatedEvent", function (pi) {
69033     _current.latitude = pi.latitude;
69034     _current.longitude = pi.longitude;
69035     _current.altitude = pi.altitude;
69036     _current.accuracy = pi.accuracy;
69037     _current.altitudeAccuracy = pi.altitudeAccuracy;
69038     _current.heading = pi.heading;
69039     _current.velocity = pi.speed;
69040
69041     utils.forEach(_watches, function (watch) {
69042         try {
69043             _getCurrentPosition(watch.win, watch.fail);
69044         } catch (e) {
69045             console.log(e);
69046         }
69047     });
69048 });
69049
69050 module.exports = {
69051     getLocation: function (success, error, args) {
69052         _getCurrentPosition(success, error);
69053     },
69054
69055     addWatch: function (success, error, args) {
69056         _watches[args[0]] = {
69057             win: success,
69058             fail: error
69059         };
69060         _getCurrentPosition(success, error);
69061     },
69062
69063     clearWatch: function (id) {
69064         delete _watches[id];
69065     }
69066 };
69067
69068 });
69069 define('ripple/platform/cordova/2.0.0/bridge/media', function (require, exports, module) {
69070 /*
69071  *  Copyright 2011 Research In Motion Limited.
69072  *
69073  * Licensed under the Apache License, Version 2.0 (the "License");
69074  * you may not use this file except in compliance with the License.
69075  * You may obtain a copy of the License at
69076  *
69077  * http://www.apache.org/licenses/LICENSE-2.0
69078  *
69079  * Unless required by applicable law or agreed to in writing, software
69080  * distributed under the License is distributed on an "AS IS" BASIS,
69081  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
69082  * See the License for the specific language governing permissions and
69083  * limitations under the License.
69084  */
69085 var audioObjects = {},
69086     noop = function () {};
69087
69088 function createAudio(id, src, error) {
69089     var a = new Audio();
69090     a.addEventListener("error", function (e) {
69091         error(new window.MediaError(1, e.toString()));
69092     });
69093     a.addEventListener("durationchange", function () {
69094         //HACK: I don't like this but best way for us to update the duration
69095         cordova.require("cordova/plugin/Media").onStatus(id, 2, this.duration);
69096     });
69097     a.src = src;
69098
69099     return a;
69100 }
69101
69102 module.exports = {
69103     create: function (success, error, args) {
69104         if (!args.length) {
69105             error("Media Object id was not sent in arguments");
69106             return;
69107         }
69108
69109         var id = args[0],
69110             src = args[1];
69111
69112         error = error || noop;
69113         success = success || noop;
69114
69115         audioObjects[id] = createAudio(id, src, error);
69116         success();
69117     },
69118     startPlayingAudio: function (success, error, args) {
69119         error = error || noop;
69120         success = success || noop;
69121         if (!args.length) {
69122             error("Media Object id was not sent in arguments");
69123             return;
69124         }
69125
69126         var id = args[0],
69127             audio = audioObjects[id];
69128
69129         if (args.length === 1) {
69130             error("Media source argument not found");
69131             return;
69132         }
69133
69134         if (audio) {
69135             audio.pause();
69136             audioObjects[id] = undefined;
69137         }
69138
69139         audio = audioObjects[id] = createAudio(id, args[1], error);
69140         audio.play();
69141
69142         success();
69143     },
69144     stopPlayingAudio: function (success, error, args) {
69145         error = error || noop;
69146         success = success || noop;
69147         if (!args.length) {
69148             error("Media Object id was not sent in arguments");
69149             return;
69150         }
69151
69152         var id = args[0],
69153             audio = audioObjects[id];
69154
69155         if (!audio) {
69156             error("Audio Object has not been initialized");
69157             return;
69158         }
69159
69160         audio.pause();
69161         audioObjects[id] = undefined;
69162
69163         success();
69164     },
69165     seekToAudio: function (success, error, args) {
69166         error = error || noop;
69167         success = success || noop;
69168         if (!args.length) {
69169             error("Media Object id was not sent in arguments");
69170             return;
69171         }
69172
69173         var id = args[0],
69174             audio = audioObjects[id];
69175
69176         if (!audio) {
69177             error("Audio Object has not been initialized");
69178             return;
69179         } else if (args.length === 1) {
69180             error("Media seek time argument not found");
69181             return;
69182         } else {
69183             try {
69184                 audio.currentTime = args[1];
69185             } catch (e) {
69186                 error("Error seeking audio: " + e);
69187             }
69188         }
69189
69190         success();
69191     },
69192     pausePlayingAudio: function (success, error, args) {
69193         error = error || noop;
69194         success = success || noop;
69195         if (!args.length) {
69196             error("Media Object id was not sent in arguments");
69197             return;
69198         }
69199
69200         var id = args[0],
69201             audio = audioObjects[id];
69202
69203         if (!audio) {
69204             error("Audio Object has not been initialized");
69205             return;
69206         }
69207
69208         audio.pause();
69209         success();
69210     },
69211     getCurrentPositionAudio: function (success, error, args) {
69212         error = error || noop;
69213         success = success || noop;
69214         if (!args.length) {
69215             error("Media Object id was not sent in arguments");
69216             return;
69217         }
69218
69219         var id = args[0],
69220             audio = audioObjects[id];
69221
69222         if (!audio) {
69223             error("Audio Object has not been initialized");
69224             return;
69225         }
69226
69227         success(audio.currentTime);
69228     },
69229     getDuration: function (success, error, args) {
69230         error = error || noop;
69231         success = success || noop;
69232         if (!args.length) {
69233             error("Media Object id was not sent in arguments");
69234             return;
69235         }
69236
69237         var id = args[0],
69238             audio = audioObjects[id];
69239
69240         if (!audio) {
69241             error("Audio Object has not been initialized");
69242             return;
69243         }
69244
69245         success(audio.duration);
69246     },
69247     startRecordingAudio: function (success, error, args) {
69248         error = error || noop;
69249         error("Not supported");
69250     },
69251     stopRecordingAudio: function (success, error, args) {
69252         error = error || noop;
69253         error("Not supported");
69254     },
69255     release: function (success, error, args) {
69256         error = error || noop;
69257         success = success || noop;
69258         if (!args.length) {
69259             error("Media Object id was not sent in arguments");
69260             return;
69261         }
69262
69263         var id = args[0],
69264             audio = audioObjects[id];
69265
69266         if (audio) {
69267             audioObjects[id] = undefined;
69268             audio.src = undefined;
69269             //delete audio;
69270         }
69271
69272         success();
69273     }
69274 };
69275
69276 });
69277 define('ripple/platform/cordova/2.0.0/bridge/network', function (require, exports, module) {
69278 /*
69279  *  Copyright 2011 Research In Motion Limited.
69280  *
69281  * Licensed under the Apache License, Version 2.0 (the "License");
69282  * you may not use this file except in compliance with the License.
69283  * You may obtain a copy of the License at
69284  *
69285  * http://www.apache.org/licenses/LICENSE-2.0
69286  *
69287  * Unless required by applicable law or agreed to in writing, software
69288  * distributed under the License is distributed on an "AS IS" BASIS,
69289  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
69290  * See the License for the specific language governing permissions and
69291  * limitations under the License.
69292  */
69293
69294 var deviceSettings = require('ripple/deviceSettings'),
69295     event = require('ripple/event'),
69296     _success;
69297
69298 event.on("ConnectionChanged", function () {
69299     return _success && _success(deviceSettings.retrieve("NetworkStatus.connectionType"));
69300 });
69301
69302 module.exports = {
69303     getConnectionInfo: function (success, fail, args) {
69304         _success = success;
69305         success(deviceSettings.retrieve("NetworkStatus.connectionType"));
69306     }
69307 };
69308
69309 });
69310 define('ripple/platform/cordova/2.0.0/bridge/notification', function (require, exports, module) {
69311 /*
69312  *  Copyright 2011 Research In Motion Limited.
69313  *
69314  * Licensed under the Apache License, Version 2.0 (the "License");
69315  * you may not use this file except in compliance with the License.
69316  * You may obtain a copy of the License at
69317  *
69318  * http://www.apache.org/licenses/LICENSE-2.0
69319  *
69320  * Unless required by applicable law or agreed to in writing, software
69321  * distributed under the License is distributed on an "AS IS" BASIS,
69322  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
69323  * See the License for the specific language governing permissions and
69324  * limitations under the License.
69325  */
69326 var notifications = require('ripple/notifications'),
69327     _console = require('ripple/console'),
69328     goodVibrations = require('ripple/ui/plugins/goodVibrations');
69329
69330 module.exports = {
69331     alert: function (success, error, args) {
69332         notifications.openNotification("normal", args[0]);
69333         return success && success();
69334     },
69335
69336     confirm: function (success, error, args) {
69337         throw "Not Implemented";
69338     },
69339
69340     activityStart: function (success, error, args) {
69341     },
69342
69343     activityStop: function (success, error, args) { 
69344     },
69345
69346     progressStart: function (success, error, args) {
69347     },
69348
69349     vibrate: function (success, error, args) {
69350         var ms = args[0] || 500;
69351         goodVibrations.vibrateDevice(ms);
69352     },
69353
69354     beep: function (success, error, args) {
69355         for (var i = args[0]; i > 0; i--) {
69356             _console.log("beep!");
69357         }
69358         notifications.openNotification("normal", "BEEP x " + args[0]);
69359     }
69360 };
69361
69362 });
69363 define('ripple/platform/cordova/2.0.0/bridge', function (require, exports, module) {
69364 /*
69365  *  Copyright 2011 Research In Motion Limited.
69366  *
69367  * Licensed under the Apache License, Version 2.0 (the "License");
69368  * you may not use this file except in compliance with the License.
69369  * You may obtain a copy of the License at
69370  *
69371  * http://www.apache.org/licenses/LICENSE-2.0
69372  *
69373  * Unless required by applicable law or agreed to in writing, software
69374  * distributed under the License is distributed on an "AS IS" BASIS,
69375  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
69376  * See the License for the specific language governing permissions and
69377  * limitations under the License.
69378  */
69379 var _prompt = require('ripple/ui/plugins/exec-dialog');
69380
69381 module.exports = {
69382     exec: function (success, fail, service, action, args) {
69383         var emulator = {
69384             "App": require('ripple/platform/cordova/2.0.0/bridge/app'),
69385             "Accelerometer": require('ripple/platform/cordova/2.0.0/bridge/accelerometer'),
69386             "Compass": require('ripple/platform/cordova/2.0.0/bridge/compass'),
69387             "Camera": require('ripple/platform/cordova/2.0.0/bridge/camera'),
69388             "Capture": require('ripple/platform/cordova/2.0.0/bridge/capture'),
69389             "Contacts": require('ripple/platform/cordova/2.0.0/bridge/contacts'),
69390             "Debug Console": require('ripple/platform/cordova/2.0.0/bridge/console'),
69391             "Device": require('ripple/platform/cordova/2.0.0/bridge/device'),
69392             "File": require('ripple/platform/cordova/2.0.0/bridge/file'),
69393             "Geolocation": require('ripple/platform/cordova/2.0.0/bridge/geolocation'),
69394             "Media": require('ripple/platform/cordova/2.0.0/bridge/media'),
69395             "Network Status": require('ripple/platform/cordova/2.0.0/bridge/network'),
69396             "NetworkStatus": require('ripple/platform/cordova/2.0.0/bridge/network'),
69397             "Notification": require('ripple/platform/cordova/2.0.0/bridge/notification')
69398         };
69399
69400         try {
69401             emulator[service][action](success, fail, args);
69402         }
69403         catch (e) {
69404             console.log("missing exec:" + service + "." + action);
69405             console.log(args);
69406             console.log(e);
69407             console.log(e.stack);
69408             //TODO: this should really not log the above lines, but they are very nice for development right now
69409             _prompt.show(service, action, success, fail);
69410         }
69411     }
69412 };
69413
69414 });
69415 define('ripple/platform/cordova/2.0.0/logger', function (require, exports, module) {
69416 module.exports = {
69417     log: function (msg) {
69418         console.log(msg);
69419     }
69420 };
69421
69422 });
69423 define('ripple/platform/cordova/2.0.0/spec/config', function (require, exports, module) {
69424 /*
69425  *  Copyright 2011 Research In Motion Limited.
69426  *
69427  * Licensed under the Apache License, Version 2.0 (the "License");
69428  * you may not use this file except in compliance with the License.
69429  * You may obtain a copy of the License at
69430  *
69431  * http://www.apache.org/licenses/LICENSE-2.0
69432  *
69433  * Unless required by applicable law or agreed to in writing, software
69434  * distributed under the License is distributed on an "AS IS" BASIS,
69435  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
69436  * See the License for the specific language governing permissions and
69437  * limitations under the License.
69438  */
69439 var constants = require('ripple/constants');
69440
69441 module.exports = {
69442     fileName: "config.xml",
69443     validateVersion: function (configValidationObject) {
69444         var valid = true;
69445         valid = !((!configValidationObject.widget.validationResult[0].attributes.xmlns.valid) ||
69446             (!configValidationObject.widget.validationResult[0].attributes["xmlns:gap"].valid));
69447
69448         return valid;
69449     },
69450     extractInfo: function (configValidationObject) {
69451         if (!configValidationObject) {
69452             return null;
69453         }
69454
69455         var widgetInfo = {};
69456
69457         widgetInfo.id = configValidationObject.widget.validationResult[0].attributes.id.value || "";
69458         widgetInfo.name = configValidationObject.widget.children.name.validationResult[0].value;
69459         widgetInfo.icon = configValidationObject.widget.children.icon.validationResult[0].attributes.src.value;
69460         widgetInfo.version = configValidationObject.widget.validationResult[0].attributes.version.value;
69461
69462         return widgetInfo;
69463     },
69464     schema: {
69465         rootElement: "widget",
69466         widget: {
69467             nodeName: "widget",
69468             required: true,
69469             occurrence: 1,
69470             attributes: {
69471                 xmlns: {
69472                     attributeName: "xmlns",
69473                     required: true,
69474                     type: "list",
69475                     listValues: ["http://www.w3.org/ns/widgets"]
69476                 },
69477                 "xmlns:gap": {
69478                     attributeName: "xmlns:gap",
69479                     required: true,
69480                     type: "list",
69481                     listValues: ["http://phonegap.com/ns/1.0"]
69482                 },
69483                 "xml:lang": {
69484                     attributeName: "xml:lang",
69485                     required: false,
69486                     type: "iso-language"
69487                 },
69488                 dir: {
69489                     attributeName: "dir",
69490                     required: false,
69491                     type: "list",
69492                     listValues: ["ltr", "rtl", "lro", "rlo"]
69493                 },
69494                 id: {
69495                     attributeName: "id",
69496                     required: false,
69497                     type: "string"
69498                 },
69499                 version: {
69500                     attributeName: "version",
69501                     required: false,
69502                     type: "string"
69503                 },
69504                 height: {
69505                     attributeName: "height",
69506                     required: false,
69507                     type: "integer"
69508                 },
69509                 width: {
69510                     attributeName: "width",
69511                     required: false,
69512                     type: "integer"
69513                 },
69514                 viewmodes: {
69515                     attributeName: "viewmodes",
69516                     required: false,
69517                     type: "list",
69518                     listValues: ["floating", "fullscreen"]
69519                 }
69520             },
69521             children: {
69522                 name: {
69523                     nodeName: "name",
69524                     required: false,
69525                     occurrence: 0,
69526                     type: "string",
69527                     attributes: {
69528                         "short": {
69529                             attributeName: "short",
69530                             type: "string",
69531                             required: false
69532                         },
69533                         "xml:lang": {
69534                             attributeName: "xml:lang",
69535                             type: "string",
69536                             required: false,
69537                             unique: true
69538                         }
69539                     }
69540                 },
69541                 description: {
69542                     nodeName: "description",
69543                     required: false,
69544                     occurrence: 0,
69545                     type: "string",
69546                     attributes: {
69547                         "xml:lang": {
69548                             attributeName: "xml:lang",
69549                             type: "string",
69550                             required: false,
69551                             unique: true
69552                         }
69553                     }
69554                 },
69555                 author: {
69556                     nodeName: "author",
69557                     required: false,
69558                     occurrence: 1,
69559                     type: "string",
69560                     attributes: {
69561                         email: {
69562                             attributeName: "email",
69563                             type: "regex",
69564                             required: false,
69565                             regex: constants.REGEX.EMAIL
69566                         },
69567                         href: {
69568                             attributeName: "href",
69569                             type: "regex",
69570                             required: false,
69571                             regex: constants.REGEX.URL
69572                         }
69573                     }
69574                 },
69575                 license: {
69576                     nodeName: "license",
69577                     required: false,
69578                     occurrence: 1,
69579                     type: "string",
69580                     attributes: {
69581                         href: {
69582                             attributeName: "href",
69583                             type: "regex",
69584                             required: false,
69585                             regex: constants.REGEX.URL
69586                         },
69587                         "xml:lang": {
69588                             attributeName: "xml:lang",
69589                             type: "string",
69590                             required: false,
69591                             unique: true
69592                         }
69593                     }
69594                 },
69595                 icon: {
69596                     nodeName: "icon",
69597                     required: false,
69598                     occurrence: 0,
69599                     attributes: {
69600                         src: {
69601                             attributeName: "src",
69602                             type: "string",
69603                             required: true
69604                         },
69605                         height: {
69606                             attributeName: "height",
69607                             required: false,
69608                             type: "integer"
69609                         },
69610                         width: {
69611                             attributeName: "width",
69612                             required: false,
69613                             type: "integer"
69614                         }
69615                     }
69616                 },
69617                 content: {
69618                     nodeName: "content",
69619                     required: false,
69620                     occurrence: 1,
69621                     attributes: {
69622                         src: {
69623                             attributeName: "src",
69624                             type: "string",
69625                             required: true
69626                         },
69627                         encoding: {
69628                             attributeName: "encoding",
69629                             type: "string",
69630                             required: false
69631                         },
69632                         type: {
69633                             attributeName: "type",
69634                             type: "string",
69635                             required: false
69636                         }
69637                     }
69638                 },
69639                 feature: {
69640                     nodeName: "feature",
69641                     required: false,
69642                     occurrence: 0,
69643                     attributes: {
69644                         name: {
69645                             attributeName: "name",
69646                             type: "list",
69647                             required: true,
69648                             listValues: ["http://api.phonegap.com/1.0/accelerometer", "http://api.phonegap.com/1.0/camera",
69649                                 "http://api.phonegap.com/1.0/compass", "http://api.phonegap.com/1.0/contacts", "http://api.phonegap.com/1.0/device",
69650                                 "http://api.phonegap.com/1.0/events", "http://api.phonegap.com/1.0/file", "http://api.phonegap.com/1.0/geolocation",
69651                                 "http://api.phonegap.com/1.0/media", "http://api.phonegap.com/1.0/network", "http://api.phonegap.com/1.0/notification",
69652                                 "http://api.phonegap.com/1.0/storage"]
69653                         },
69654                         required: {
69655                             attributeName: "required",
69656                             type: "boolean",
69657                             required: false
69658                         }
69659                     }
69660                 },
69661                 preference: {
69662                     nodeName: "preference",
69663                     required: false,
69664                     occurrence: 0,
69665                     attributes: {
69666                         name: {
69667                             attributeName: "name",
69668                             type: "string",
69669                             required: true
69670                         },
69671                         value: {
69672                             type: "string",
69673                             attributeName: "value",
69674                             required: false
69675                         },
69676                         readonly: {
69677                             attributeName: "readonly",
69678                             type: "boolean",
69679                             required: false
69680                         }
69681                     }
69682                 }
69683             }
69684         }
69685     }
69686 };
69687
69688 });
69689 define('ripple/platform/cordova/2.0.0/spec/device', function (require, exports, module) {
69690 /*
69691  *  Copyright 2011 Research In Motion Limited.
69692  *
69693  * Licensed under the Apache License, Version 2.0 (the "License");
69694  * you may not use this file except in compliance with the License.
69695  * You may obtain a copy of the License at
69696  *
69697  * http://www.apache.org/licenses/LICENSE-2.0
69698  *
69699  * Unless required by applicable law or agreed to in writing, software
69700  * distributed under the License is distributed on an "AS IS" BASIS,
69701  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
69702  * See the License for the specific language governing permissions and
69703  * limitations under the License.
69704  */
69705 var event = require('ripple/event');
69706
69707 module.exports = {
69708     "NetworkStatus": {
69709         "connectionType": {
69710             "name": "Connection Type",
69711             "control": {
69712                 "type": "select",
69713                 "value": "ethernet"
69714             },
69715             "options": {
69716                 "unknown": "UNKNOWN",
69717                 "ethernet": "ETHERNET",
69718                 "wifi": "WIFI",
69719                 "2g": "CELL_2G",
69720                 "3g": "CELL_3G",
69721                 "4g": "CELL_4G",
69722                 "none": "none"
69723             },
69724             "callback": function (setting) {
69725                 var connected = setting !== "none";
69726                 require('ripple/bus').send("network", connected);
69727             }
69728         },
69729         "lag": {
69730             "name": "Lag the network",
69731             "control": {
69732                 type: "checkbox",
69733                 value: false
69734             },
69735             "callback": function (setting) {
69736                 require('ripple/bus').send("lag", setting);
69737             }
69738         },
69739     }
69740 };
69741
69742 });
69743 define('ripple/platform/cordova/2.0.0/spec/events', function (require, exports, module) {
69744 /*
69745  *  Copyright 2011 Research In Motion Limited.
69746  *
69747  * Licensed under the Apache License, Version 2.0 (the "License");
69748  * you may not use this file except in compliance with the License.
69749  * You may obtain a copy of the License at
69750  *
69751  * http://www.apache.org/licenses/LICENSE-2.0
69752  *
69753  * Unless required by applicable law or agreed to in writing, software
69754  * distributed under the License is distributed on an "AS IS" BASIS,
69755  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
69756  * See the License for the specific language governing permissions and
69757  * limitations under the License.
69758  */
69759 function _fires(name, data) {
69760     return function () {
69761         cordova.fireDocumentEvent(name, data);
69762     };
69763 }
69764
69765 module.exports = {
69766     "deviceready": {
69767         callback: _fires("deviceready")
69768     },
69769     "backbutton": {
69770         callback: _fires("backbutton")
69771     },
69772     "menubutton": {
69773         callback: _fires("menubutton")
69774     },
69775     "pause": {
69776         callback: _fires("pause")
69777     },
69778     "resume": {
69779         callback: _fires("resume")
69780     },
69781     "searchbutton": {
69782         callback: _fires("searchbutton")
69783     },
69784     "online": {
69785         callback: _fires("online")
69786     },
69787     "offline": {
69788         callback: _fires("offline")
69789     }
69790 };
69791
69792 });
69793 define('ripple/platform/cordova/2.0.0/spec/ui', function (require, exports, module) {
69794 /*
69795  *  Copyright 2011 Research In Motion Limited.
69796  *
69797  * Licensed under the Apache License, Version 2.0 (the "License");
69798  * you may not use this file except in compliance with the License.
69799  * You may obtain a copy of the License at
69800  *
69801  * http://www.apache.org/licenses/LICENSE-2.0
69802  *
69803  * Unless required by applicable law or agreed to in writing, software
69804  * distributed under the License is distributed on an "AS IS" BASIS,
69805  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
69806  * See the License for the specific language governing permissions and
69807  * limitations under the License.
69808  */
69809 module.exports = {
69810     plugins: [
69811         "accelerometer",
69812         "deviceSettings",
69813         "geoView",
69814         "widgetConfig",
69815         "platformEvents"
69816     ]
69817 };
69818
69819 });
69820 define('ripple/platform/cordova/2.0.0/spec', function (require, exports, module) {
69821 function loadWebworks(win, device) {
69822     var builder = require('ripple/platform/builder'),
69823         platform = device.id === "Playbook" || device.id === "Colt" ? "tablet" : "handset",
69824         webworks = require('ripple/platform/webworks.' + platform + '/2.0.0/spec');
69825
69826     builder.build(webworks.objects).into(win);
69827     builder.build(webworks.objects).into(window);
69828 }
69829
69830 module.exports = {
69831     id: "cordova",
69832     version: "2.0.0",
69833     name: "Apache Cordova",
69834     type: "platform",
69835     nativeMethods: {},
69836
69837     config: require('ripple/platform/cordova/2.0.0/spec/config'),
69838     device: require('ripple/platform/cordova/2.0.0/spec/device'),
69839     ui: require('ripple/platform/cordova/2.0.0/spec/ui'),
69840     events: require('ripple/platform/cordova/2.0.0/spec/events'),
69841
69842     initialize: function (win) {
69843         var honeypot = require('ripple/honeypot'),
69844             devices = require('ripple/devices'),
69845             device = devices.getCurrentDevice(),
69846             bridge = require('ripple/platform/cordova/2.0.0/bridge'),
69847             cordova,
69848             topCordova = window.top.require('ripple/platform/cordova/2.0.0/spec'),
69849             get = function () {
69850                 return cordova;
69851             },
69852             set = function (orig) {
69853                 if (cordova) {
69854                     return;
69855                 }
69856
69857                 cordova = orig;
69858
69859                 cordova.define.remove("cordova/exec");
69860                 cordova.define("cordova/exec", function (require, exports, module) {
69861                     module.exports = bridge.exec;
69862                 });
69863
69864                 cordova.UsePolling = true;
69865
69866                 //do nothing here as we will just call the callbacks ourselves
69867                 cordova.define.remove("cordova/plugin/android/polling");
69868                 cordova.define("cordova/plugin/android/polling", function (require, exports, module) {
69869                     module.exports = function () {};
69870                 });
69871
69872                 var builder = cordova.require('cordova/builder'),
69873                     allTheThings = window,
69874                     base = cordova.require('cordova/common'),
69875                     iosPlugin;
69876
69877                 //HACK: Overwrite all the things, handles when cordova.js executes before we start booting
69878                 builder.build(base.objects).intoAndClobber(allTheThings);
69879                 cordova.require('cordova/channel').onNativeReady.fire();
69880                 //  DIRTY HACK: once cordova is cleaned up, we do not
69881                 //  need this.
69882                 // reference issue: https://issues.apache.org/jira/browse/CB-1013
69883                 try {
69884                     iosPlugin = cordova.require('cordova/plugin/ios/device');
69885                     bridge.exec(function (info) {
69886                         iosPlugin.setInfo(info);
69887                     }, null, 'Device', 'getDeviceInfo', []);
69888                 } catch (e) {
69889                     cordova.require('cordova/channel').onCordovaInfoReady.fire();
69890                 }
69891             };
69892
69893         if (window.FileReader && !topCordova.nativeMethods.FileReader) {
69894             topCordova.nativeMethods.FileReader = window.FileReader;
69895         }
69896
69897         if (device.manufacturer === "Research In Motion") {
69898             loadWebworks(win, device);
69899         }
69900
69901         honeypot.monitor(win, "cordova").andRun(get, set);
69902     },
69903
69904     objects: {
69905         MediaError: {
69906             path: "cordova/2.0.0/MediaError"
69907         },
69908         org: {
69909             children: {
69910                 apache: {
69911                     children: {
69912                         cordova: {
69913                             children: {
69914                                 Logger: {
69915                                     path: "cordova/2.0.0/logger"
69916                                 },
69917                                 JavaPluginManager: {
69918                                     path: "cordova/2.0.0/JavaPluginManager"
69919                                 }
69920                             }
69921                         }
69922                     }
69923                 }
69924             }
69925         }
69926     }
69927 };
69928
69929 });
69930 define('ripple/platform/phonegap/1.0.0/AVCodecsAttributes', function (require, exports, module) {
69931 /*
69932  *  Copyright 2011 Research In Motion Limited.
69933  *
69934  * Licensed under the Apache License, Version 2.0 (the "License");
69935  * you may not use this file except in compliance with the License.
69936  * You may obtain a copy of the License at
69937  *
69938  * http://www.apache.org/licenses/LICENSE-2.0
69939  *
69940  * Unless required by applicable law or agreed to in writing, software
69941  * distributed under the License is distributed on an "AS IS" BASIS,
69942  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
69943  * See the License for the specific language governing permissions and
69944  * limitations under the License.
69945  */
69946 module.exports = function (info, id, audioCodecs, videoCodecs) {
69947     return {
69948         info: info,
69949         id: id,
69950         audioCodecs: audioCodecs,
69951         videoCodecs: videoCodecs
69952     };
69953 };
69954
69955 });
69956 define('ripple/platform/phonegap/1.0.0/Acceleration', function (require, exports, module) {
69957 /*
69958  *  Copyright 2011 Research In Motion Limited.
69959  *
69960  * Licensed under the Apache License, Version 2.0 (the "License");
69961  * you may not use this file except in compliance with the License.
69962  * You may obtain a copy of the License at
69963  *
69964  * http://www.apache.org/licenses/LICENSE-2.0
69965  *
69966  * Unless required by applicable law or agreed to in writing, software
69967  * distributed under the License is distributed on an "AS IS" BASIS,
69968  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
69969  * See the License for the specific language governing permissions and
69970  * limitations under the License.
69971  */
69972 module.exports = function (x, y, z) {
69973     return {
69974         x: x || 0,
69975         y: y || 0,
69976         z: z || 0,
69977         timestamp: new Date().getTime()
69978     };
69979 };
69980
69981 });
69982 define('ripple/platform/phonegap/1.0.0/AudioCodecAttributes', function (require, exports, module) {
69983 /*
69984  *  Copyright 2011 Research In Motion Limited.
69985  *
69986  * Licensed under the Apache License, Version 2.0 (the "License");
69987  * you may not use this file except in compliance with the License.
69988  * You may obtain a copy of the License at
69989  *
69990  * http://www.apache.org/licenses/LICENSE-2.0
69991  *
69992  * Unless required by applicable law or agreed to in writing, software
69993  * distributed under the License is distributed on an "AS IS" BASIS,
69994  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
69995  * See the License for the specific language governing permissions and
69996  * limitations under the License.
69997  */
69998 module.exports = function (info, id, compFormats, encode, decode) {
69999     return {
70000         info: info,
70001         id: id,
70002         compFormats: compFormats,
70003         encode: encode,
70004         decode: decode
70005     };
70006 };
70007
70008 });
70009 define('ripple/platform/phonegap/1.0.0/AudioDeviceAttributes', function (require, exports, module) {
70010 /*
70011  *  Copyright 2011 Research In Motion Limited.
70012  *
70013  * Licensed under the Apache License, Version 2.0 (the "License");
70014  * you may not use this file except in compliance with the License.
70015  * You may obtain a copy of the License at
70016  *
70017  * http://www.apache.org/licenses/LICENSE-2.0
70018  *
70019  * Unless required by applicable law or agreed to in writing, software
70020  * distributed under the License is distributed on an "AS IS" BASIS,
70021  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
70022  * See the License for the specific language governing permissions and
70023  * limitations under the License.
70024  */
70025 module.exports = function (type, freqRangeLow, freqRangeHigh, volumeLevel, info) {
70026     return {
70027         type: type,
70028         freqRangeLow: freqRangeLow,
70029         freqRangeHigh: freqRangeHigh,
70030         volumeLevel: volumeLevel,
70031         info: info
70032     };
70033
70034 };
70035
70036 });
70037 define('ripple/platform/phonegap/1.0.0/BrailleDeviceAttributes', function (require, exports, module) {
70038 /*
70039  *  Copyright 2011 Research In Motion Limited.
70040  *
70041  * Licensed under the Apache License, Version 2.0 (the "License");
70042  * you may not use this file except in compliance with the License.
70043  * You may obtain a copy of the License at
70044  *
70045  * http://www.apache.org/licenses/LICENSE-2.0
70046  *
70047  * Unless required by applicable law or agreed to in writing, software
70048  * distributed under the License is distributed on an "AS IS" BASIS,
70049  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
70050  * See the License for the specific language governing permissions and
70051  * limitations under the License.
70052  */
70053 module.exports = function (nbCells, info) {
70054     return {
70055         nbCells: nbCells,
70056         info: info
70057     };
70058
70059 };
70060
70061 });
70062 define('ripple/platform/phonegap/1.0.0/CPUAttributes', function (require, exports, module) {
70063 /*
70064  *  Copyright 2011 Research In Motion Limited.
70065  *
70066  * Licensed under the Apache License, Version 2.0 (the "License");
70067  * you may not use this file except in compliance with the License.
70068  * You may obtain a copy of the License at
70069  *
70070  * http://www.apache.org/licenses/LICENSE-2.0
70071  *
70072  * Unless required by applicable law or agreed to in writing, software
70073  * distributed under the License is distributed on an "AS IS" BASIS,
70074  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
70075  * See the License for the specific language governing permissions and
70076  * limitations under the License.
70077  */
70078 module.exports = function (info, id, usage) {
70079     return {
70080         info: info,
70081         id: id,
70082         usage: usage
70083     };
70084 };
70085
70086 });
70087 define('ripple/platform/phonegap/1.0.0/CameraAttributes', function (require, exports, module) {
70088 /*
70089  *  Copyright 2011 Research In Motion Limited.
70090  *
70091  * Licensed under the Apache License, Version 2.0 (the "License");
70092  * you may not use this file except in compliance with the License.
70093  * You may obtain a copy of the License at
70094  *
70095  * http://www.apache.org/licenses/LICENSE-2.0
70096  *
70097  * Unless required by applicable law or agreed to in writing, software
70098  * distributed under the License is distributed on an "AS IS" BASIS,
70099  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
70100  * See the License for the specific language governing permissions and
70101  * limitations under the License.
70102  */
70103 module.exports = function (supportsVideo, hasFlash, sensorPixels, maxZoomFactor) {
70104     return {
70105         supportsVideo: supportsVideo,
70106         hasFlash: hasFlash,
70107         sensorPixels: sensorPixels,
70108         maxZoomFactor: maxZoomFactor
70109     };
70110
70111 };
70112
70113 });
70114 define('ripple/platform/phonegap/1.0.0/Connection', function (require, exports, module) {
70115 /*
70116  *  Copyright 2011 Research In Motion Limited.
70117  *
70118  * Licensed under the Apache License, Version 2.0 (the "License");
70119  * you may not use this file except in compliance with the License.
70120  * You may obtain a copy of the License at
70121  *
70122  * http://www.apache.org/licenses/LICENSE-2.0
70123  *
70124  * Unless required by applicable law or agreed to in writing, software
70125  * distributed under the License is distributed on an "AS IS" BASIS,
70126  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
70127  * See the License for the specific language governing permissions and
70128  * limitations under the License.
70129  */
70130 module.exports = {
70131     UNKNOWN: "unknown",
70132     ETHERNET: "ethernet",
70133     WIFI: "wifi",
70134     CELL_2G: "2g",
70135     CELL_3G: "3g",
70136     CELL_4G: "4g",
70137     NONE: "none"
70138 };
70139
70140 });
70141 define('ripple/platform/phonegap/1.0.0/ConnectionAttributes', function (require, exports, module) {
70142 /*
70143  *  Copyright 2011 Research In Motion Limited.
70144  *
70145  * Licensed under the Apache License, Version 2.0 (the "License");
70146  * you may not use this file except in compliance with the License.
70147  * You may obtain a copy of the License at
70148  *
70149  * http://www.apache.org/licenses/LICENSE-2.0
70150  *
70151  * Unless required by applicable law or agreed to in writing, software
70152  * distributed under the License is distributed on an "AS IS" BASIS,
70153  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
70154  * See the License for the specific language governing permissions and
70155  * limitations under the License.
70156  */
70157 module.exports = function (info, id, type, currentOrientation, currentUploadBandwidth, maxDownloadBandwidth, maxUploadBandwidth, currentSignalStrength, roaming) {
70158     return {
70159         info: info,
70160         id: id,
70161         type: type,
70162         currentDownloadBandwidth: currentOrientation,
70163         currentUploadBandwidth: currentUploadBandwidth,
70164         maxDownloadBandwidth: maxDownloadBandwidth,
70165         maxUploadBandwidth: maxUploadBandwidth,
70166         currentSignalStrength: currentSignalStrength,
70167         roaming: roaming
70168     };
70169 };
70170
70171 });
70172 define('ripple/platform/phonegap/1.0.0/Contact', function (require, exports, module) {
70173 /*
70174  *  Copyright 2011 Research In Motion Limited.
70175  *
70176  * Licensed under the Apache License, Version 2.0 (the "License");
70177  * you may not use this file except in compliance with the License.
70178  * You may obtain a copy of the License at
70179  *
70180  * http://www.apache.org/licenses/LICENSE-2.0
70181  *
70182  * Unless required by applicable law or agreed to in writing, software
70183  * distributed under the License is distributed on an "AS IS" BASIS,
70184  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
70185  * See the License for the specific language governing permissions and
70186  * limitations under the License.
70187  */
70188 var utils = require('ripple/utils'),
70189     event = require('ripple/event');
70190
70191 function _properties(obj) {
70192     var prop, newObj = {};
70193     for (prop in obj) {
70194         if (Object.prototype.hasOwnProperty.call(obj, prop)) {
70195             if (typeof obj[prop] !== "function") {
70196                 newObj[prop] = utils.copy(obj[prop]);
70197             }
70198         }
70199     }
70200     return newObj;
70201 }
70202
70203 module.exports = function (
70204         id,
70205         displayName,
70206         name,
70207         nickname,
70208         phoneNumbers,
70209         emails,
70210         addresses,
70211         ims,
70212         organizations,
70213         birthday,
70214         note,
70215         photos,
70216         categories,
70217         urls
70218 ) {
70219
70220     return {
70221         id: id || Math.uuid(undefined, 16),
70222         displayName: displayName || null,
70223         name: name || null,
70224         nickname: nickname || null,
70225         phoneNumbers: phoneNumbers || null,
70226         emails: emails || null,
70227         addresses: addresses || null,
70228         ims: ims || null,
70229         organizations: organizations || null,
70230         birthday: birthday || null,
70231         note: note || null,
70232         photos: photos || null,
70233         categories: categories || null,
70234         urls: urls || null,
70235         save: function (success, error) {
70236             var _self = this,
70237                 lastUpdated = this.updated; // hackish
70238
70239             this.updated = new Date();
70240
70241             if (!this.id) {
70242                 this.id = Math.uuid(undefined, 16);
70243             }
70244
70245             event.trigger("phonegap-contact-save", [_properties(this), success, function (e) {
70246                 _self.updated = lastUpdated;
70247                 error(e);
70248             }]);
70249         },
70250         remove: function (success, error) {
70251             event.trigger("phonegap-contact-remove", [this.id, success, error]);
70252         },
70253         clone: function () {
70254             var copy = utils.copy(this);
70255             copy.id = null;
70256             return copy;
70257         }
70258     };
70259 };
70260
70261 });
70262 define('ripple/platform/phonegap/1.0.0/ContactAccount', function (require, exports, module) {
70263 /*
70264  *  Copyright 2011 Research In Motion Limited.
70265  *
70266  * Licensed under the Apache License, Version 2.0 (the "License");
70267  * you may not use this file except in compliance with the License.
70268  * You may obtain a copy of the License at
70269  *
70270  * http://www.apache.org/licenses/LICENSE-2.0
70271  *
70272  * Unless required by applicable law or agreed to in writing, software
70273  * distributed under the License is distributed on an "AS IS" BASIS,
70274  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
70275  * See the License for the specific language governing permissions and
70276  * limitations under the License.
70277  */
70278 module.exports = function (domain, username, userid) {
70279     return {
70280         domain: domain,
70281         username: username,
70282         userid: userid
70283     };
70284 };
70285
70286 });
70287 define('ripple/platform/phonegap/1.0.0/ContactAddress', function (require, exports, module) {
70288 /*
70289  *  Copyright 2011 Research In Motion Limited.
70290  *
70291  * Licensed under the Apache License, Version 2.0 (the "License");
70292  * you may not use this file except in compliance with the License.
70293  * You may obtain a copy of the License at
70294  *
70295  * http://www.apache.org/licenses/LICENSE-2.0
70296  *
70297  * Unless required by applicable law or agreed to in writing, software
70298  * distributed under the License is distributed on an "AS IS" BASIS,
70299  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
70300  * See the License for the specific language governing permissions and
70301  * limitations under the License.
70302  */
70303 module.exports = function (pref, type, formatted, streetAddress, locality, region, postalCode, country, id) {
70304     return {
70305         pref: pref || null,
70306         type: type || null,
70307         formatted: formatted || null,
70308         streetAddress: streetAddress || null,
70309         locality: locality || null,
70310         region: region || null,
70311         postalCode: postalCode || null,
70312         country: country || null,
70313         id: id || null
70314     };
70315 };
70316
70317 });
70318 define('ripple/platform/phonegap/1.0.0/ContactError', function (require, exports, module) {
70319 /*
70320  *  Copyright 2011 Research In Motion Limited.
70321  *
70322  * Licensed under the Apache License, Version 2.0 (the "License");
70323  * you may not use this file except in compliance with the License.
70324  * You may obtain a copy of the License at
70325  *
70326  * http://www.apache.org/licenses/LICENSE-2.0
70327  *
70328  * Unless required by applicable law or agreed to in writing, software
70329  * distributed under the License is distributed on an "AS IS" BASIS,
70330  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
70331  * See the License for the specific language governing permissions and
70332  * limitations under the License.
70333  */
70334 function ContactError(code) {
70335     this.code = code || null;
70336 }
70337
70338 ContactError.UNKNOWN_ERROR = 0;
70339 ContactError.INVALID_ARGUMENT_ERROR = 1;
70340 ContactError.NOT_FOUND_ERROR = 2;
70341 ContactError.TIMEOUT_ERROR = 3;
70342 ContactError.PENDING_OPERATION_ERROR = 4;
70343 ContactError.IO_ERROR = 5;
70344 ContactError.NOT_SUPPORTED_ERROR = 6;
70345 ContactError.PERMISSION_DENIED_ERROR = 20;
70346
70347 module.exports = ContactError;
70348
70349 });
70350 define('ripple/platform/phonegap/1.0.0/ContactField', function (require, exports, module) {
70351 /*
70352  *  Copyright 2011 Research In Motion Limited.
70353  *
70354  * Licensed under the Apache License, Version 2.0 (the "License");
70355  * you may not use this file except in compliance with the License.
70356  * You may obtain a copy of the License at
70357  *
70358  * http://www.apache.org/licenses/LICENSE-2.0
70359  *
70360  * Unless required by applicable law or agreed to in writing, software
70361  * distributed under the License is distributed on an "AS IS" BASIS,
70362  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
70363  * See the License for the specific language governing permissions and
70364  * limitations under the License.
70365  */
70366 module.exports = function (type, value, pref) {
70367     return {
70368         type: type,
70369         value: value,
70370         pref: pref || false
70371     };
70372 };
70373
70374 });
70375 define('ripple/platform/phonegap/1.0.0/ContactFindOptions', function (require, exports, module) {
70376 /*
70377  *  Copyright 2011 Research In Motion Limited.
70378  *
70379  * Licensed under the Apache License, Version 2.0 (the "License");
70380  * you may not use this file except in compliance with the License.
70381  * You may obtain a copy of the License at
70382  *
70383  * http://www.apache.org/licenses/LICENSE-2.0
70384  *
70385  * Unless required by applicable law or agreed to in writing, software
70386  * distributed under the License is distributed on an "AS IS" BASIS,
70387  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
70388  * See the License for the specific language governing permissions and
70389  * limitations under the License.
70390  */
70391 module.exports = function (filter, multiple, updatedSince) {
70392     return {
70393         filter: filter || "",
70394         multiple: multiple || false,
70395         updatedSince: updatedSince || ""
70396     };
70397 };
70398
70399 });
70400 define('ripple/platform/phonegap/1.0.0/ContactName', function (require, exports, module) {
70401 /*
70402  *  Copyright 2011 Research In Motion Limited.
70403  *
70404  * Licensed under the Apache License, Version 2.0 (the "License");
70405  * you may not use this file except in compliance with the License.
70406  * You may obtain a copy of the License at
70407  *
70408  * http://www.apache.org/licenses/LICENSE-2.0
70409  *
70410  * Unless required by applicable law or agreed to in writing, software
70411  * distributed under the License is distributed on an "AS IS" BASIS,
70412  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
70413  * See the License for the specific language governing permissions and
70414  * limitations under the License.
70415  */
70416 module.exports = function (formatted, familyName, givenName, middleName, honorificPrefix, honorificSuffix) {
70417     return {
70418         formatted: formatted,
70419         familyName: familyName,
70420         givenName: givenName,
70421         middleName: middleName,
70422         honorificPrefix: honorificPrefix,
70423         honorificSuffix: honorificSuffix
70424     };
70425 };
70426
70427 });
70428 define('ripple/platform/phonegap/1.0.0/ContactOrganization', function (require, exports, module) {
70429 /*
70430  *  Copyright 2011 Research In Motion Limited.
70431  *
70432  * Licensed under the Apache License, Version 2.0 (the "License");
70433  * you may not use this file except in compliance with the License.
70434  * You may obtain a copy of the License at
70435  *
70436  * http://www.apache.org/licenses/LICENSE-2.0
70437  *
70438  * Unless required by applicable law or agreed to in writing, software
70439  * distributed under the License is distributed on an "AS IS" BASIS,
70440  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
70441  * See the License for the specific language governing permissions and
70442  * limitations under the License.
70443  */
70444 module.exports = function (pref, type, name, dept, title) {
70445     return {
70446         pref: pref || null,
70447         type: type || null,
70448         name: name || null,
70449         department: dept || null,
70450         title: title || null
70451     };
70452 };
70453
70454 });
70455 define('ripple/platform/phonegap/1.0.0/DisplayDeviceAttributes', function (require, exports, module) {
70456 /*
70457  *  Copyright 2011 Research In Motion Limited.
70458  *
70459  * Licensed under the Apache License, Version 2.0 (the "License");
70460  * you may not use this file except in compliance with the License.
70461  * You may obtain a copy of the License at
70462  *
70463  * http://www.apache.org/licenses/LICENSE-2.0
70464  *
70465  * Unless required by applicable law or agreed to in writing, software
70466  * distributed under the License is distributed on an "AS IS" BASIS,
70467  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
70468  * See the License for the specific language governing permissions and
70469  * limitations under the License.
70470  */
70471 module.exports = function (orientation, brightness, contrast, blanked, dotsPerInchW, dotsPerInchH, physicalWidth, physicalHeight, info) {
70472     return {
70473         orientation: orientation,
70474         brightness: brightness,
70475         contrast: contrast,
70476         blanked: blanked,
70477         dotsPerInchW: dotsPerInchW,
70478         dotsPerInchH: dotsPerInchH,
70479         physicalWidth: physicalWidth,
70480         physicalHeight: physicalHeight,
70481         info: info
70482     };
70483 };
70484
70485 });
70486 define('ripple/platform/phonegap/1.0.0/InputDevicesAttributes', function (require, exports, module) {
70487 /*
70488  *  Copyright 2011 Research In Motion Limited.
70489  *
70490  * Licensed under the Apache License, Version 2.0 (the "License");
70491  * you may not use this file except in compliance with the License.
70492  * You may obtain a copy of the License at
70493  *
70494  * http://www.apache.org/licenses/LICENSE-2.0
70495  *
70496  * Unless required by applicable law or agreed to in writing, software
70497  * distributed under the License is distributed on an "AS IS" BASIS,
70498  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
70499  * See the License for the specific language governing permissions and
70500  * limitations under the License.
70501  */
70502 module.exports = function (info, id, pointingDevices, activePointingDevices, keyboards, activeKeyboards, cameras, activeCameras, microphones, activeMicrophones) {
70503     return {
70504         info: info,
70505         id: id,
70506         pointingDevices: pointingDevices,
70507         activePointingDevices: activePointingDevices,
70508         keyboards: keyboards,
70509         activeKeyboards: activeKeyboards,
70510         cameras: cameras,
70511         activeCameras: activeCameras,
70512         microphones: microphones,
70513         activeMicrophones: activeMicrophones
70514     };
70515
70516 };
70517
70518 });
70519 define('ripple/platform/phonegap/1.0.0/KeyboardAttributes', function (require, exports, module) {
70520 /*
70521  *  Copyright 2011 Research In Motion Limited.
70522  *
70523  * Licensed under the Apache License, Version 2.0 (the "License");
70524  * you may not use this file except in compliance with the License.
70525  * You may obtain a copy of the License at
70526  *
70527  * http://www.apache.org/licenses/LICENSE-2.0
70528  *
70529  * Unless required by applicable law or agreed to in writing, software
70530  * distributed under the License is distributed on an "AS IS" BASIS,
70531  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
70532  * See the License for the specific language governing permissions and
70533  * limitations under the License.
70534  */
70535 module.exports = function (type, isHardware, info) {
70536     return {
70537         type: type,
70538         isHardware: isHardware,
70539         info: info
70540     };
70541 };
70542
70543 });
70544 define('ripple/platform/phonegap/1.0.0/MicrophoneAttributes', function (require, exports, module) {
70545 /*
70546  *  Copyright 2011 Research In Motion Limited.
70547  *
70548  * Licensed under the Apache License, Version 2.0 (the "License");
70549  * you may not use this file except in compliance with the License.
70550  * You may obtain a copy of the License at
70551  *
70552  * http://www.apache.org/licenses/LICENSE-2.0
70553  *
70554  * Unless required by applicable law or agreed to in writing, software
70555  * distributed under the License is distributed on an "AS IS" BASIS,
70556  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
70557  * See the License for the specific language governing permissions and
70558  * limitations under the License.
70559  */
70560 module.exports = function (type, freqRangeLow, freqRangeHigh, info, name, types) {
70561     return {
70562         type: type,
70563         freqRangeLow: freqRangeLow,
70564         freqRangeHigh: freqRangeHigh,
70565         info: info,
70566         name: name,
70567         types: types
70568     };
70569 };
70570
70571 });
70572 define('ripple/platform/phonegap/1.0.0/NetworkAttributes', function (require, exports, module) {
70573 /*
70574  *  Copyright 2011 Research In Motion Limited.
70575  *
70576  * Licensed under the Apache License, Version 2.0 (the "License");
70577  * you may not use this file except in compliance with the License.
70578  * You may obtain a copy of the License at
70579  *
70580  * http://www.apache.org/licenses/LICENSE-2.0
70581  *
70582  * Unless required by applicable law or agreed to in writing, software
70583  * distributed under the License is distributed on an "AS IS" BASIS,
70584  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
70585  * See the License for the specific language governing permissions and
70586  * limitations under the License.
70587  */
70588 module.exports = function (info, id, activeConnections) {
70589     return {
70590         info: info,
70591         id: id,
70592         activeConnections: activeConnections || []
70593     };
70594 };
70595
70596 });
70597 define('ripple/platform/phonegap/1.0.0/NetworkStatus', function (require, exports, module) {
70598 /*
70599  *  Copyright 2011 Research In Motion Limited.
70600  *
70601  * Licensed under the Apache License, Version 2.0 (the "License");
70602  * you may not use this file except in compliance with the License.
70603  * You may obtain a copy of the License at
70604  *
70605  * http://www.apache.org/licenses/LICENSE-2.0
70606  *
70607  * Unless required by applicable law or agreed to in writing, software
70608  * distributed under the License is distributed on an "AS IS" BASIS,
70609  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
70610  * See the License for the specific language governing permissions and
70611  * limitations under the License.
70612  */
70613 module.exports = {
70614     NOT_REACHABLE: 0,
70615     REACHABLE_VIA_CARRIER_DATA_NETWORK: 1,
70616     REACHABLE_VIA_WIFI_NETWORK: 2
70617 };
70618
70619 });
70620 define('ripple/platform/phonegap/1.0.0/OutputDevicesAttributes', function (require, exports, module) {
70621 /*
70622  *  Copyright 2011 Research In Motion Limited.
70623  *
70624  * Licensed under the Apache License, Version 2.0 (the "License");
70625  * you may not use this file except in compliance with the License.
70626  * You may obtain a copy of the License at
70627  *
70628  * http://www.apache.org/licenses/LICENSE-2.0
70629  *
70630  * Unless required by applicable law or agreed to in writing, software
70631  * distributed under the License is distributed on an "AS IS" BASIS,
70632  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
70633  * See the License for the specific language governing permissions and
70634  * limitations under the License.
70635  */
70636 module.exports = function (info, id, displayDevices, activeDisplayDevices, printingDevices, activePrintingDevice, brailleDevices, activeBrailleDevice, audioDevices, activeAudioDevices) {
70637     return {
70638         info: info,
70639         id: id,
70640         displayDevices: displayDevices,
70641         activeDisplayDevices: activeDisplayDevices,
70642         printingDevices: printingDevices,
70643         activePrintingDevice: activePrintingDevice,
70644         brailleDevices: brailleDevices,
70645         activeBrailleDevice: activeBrailleDevice,
70646         audioDevices: audioDevices,
70647         activeAudioDevices: activeAudioDevices
70648     };
70649 };
70650
70651 });
70652 define('ripple/platform/phonegap/1.0.0/PhoneGap', function (require, exports, module) {
70653 /*
70654  *  Copyright 2011 Research In Motion Limited.
70655  *
70656  * Licensed under the Apache License, Version 2.0 (the "License");
70657  * you may not use this file except in compliance with the License.
70658  * You may obtain a copy of the License at
70659  *
70660  * http://www.apache.org/licenses/LICENSE-2.0
70661  *
70662  * Unless required by applicable law or agreed to in writing, software
70663  * distributed under the License is distributed on an "AS IS" BASIS,
70664  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
70665  * See the License for the specific language governing permissions and
70666  * limitations under the License.
70667  */
70668 module.exports = {
70669     available: true
70670 };
70671
70672 });
70673 define('ripple/platform/phonegap/1.0.0/PointerAttributes', function (require, exports, module) {
70674 /*
70675  *  Copyright 2011 Research In Motion Limited.
70676  *
70677  * Licensed under the Apache License, Version 2.0 (the "License");
70678  * you may not use this file except in compliance with the License.
70679  * You may obtain a copy of the License at
70680  *
70681  * http://www.apache.org/licenses/LICENSE-2.0
70682  *
70683  * Unless required by applicable law or agreed to in writing, software
70684  * distributed under the License is distributed on an "AS IS" BASIS,
70685  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
70686  * See the License for the specific language governing permissions and
70687  * limitations under the License.
70688  */
70689 module.exports = function (type, supportsMultiTouch, info) {
70690     return {
70691         type: type,
70692         supportsMultiTouch: supportsMultiTouch,
70693         info: info
70694     };
70695 };
70696
70697 });
70698 define('ripple/platform/phonegap/1.0.0/PowerAttributes', function (require, exports, module) {
70699 /*
70700  *  Copyright 2011 Research In Motion Limited.
70701  *
70702  * Licensed under the Apache License, Version 2.0 (the "License");
70703  * you may not use this file except in compliance with the License.
70704  * You may obtain a copy of the License at
70705  *
70706  * http://www.apache.org/licenses/LICENSE-2.0
70707  *
70708  * Unless required by applicable law or agreed to in writing, software
70709  * distributed under the License is distributed on an "AS IS" BASIS,
70710  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
70711  * See the License for the specific language governing permissions and
70712  * limitations under the License.
70713  */
70714 module.exports = function (info, id, level, timeRemaining, isBattery, isCharging) {
70715     return {
70716         info: info,
70717         id: id,
70718         level: level,
70719         timeRemaining: timeRemaining,
70720         isBattery: isBattery,
70721         isCharging: isCharging
70722     };
70723 };
70724
70725 });
70726 define('ripple/platform/phonegap/1.0.0/PrintingDeviceAttributes', function (require, exports, module) {
70727 /*
70728  *  Copyright 2011 Research In Motion Limited.
70729  *
70730  * Licensed under the Apache License, Version 2.0 (the "License");
70731  * you may not use this file except in compliance with the License.
70732  * You may obtain a copy of the License at
70733  *
70734  * http://www.apache.org/licenses/LICENSE-2.0
70735  *
70736  * Unless required by applicable law or agreed to in writing, software
70737  * distributed under the License is distributed on an "AS IS" BASIS,
70738  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
70739  * See the License for the specific language governing permissions and
70740  * limitations under the License.
70741  */
70742 module.exports = function (type, resolution, color, info) {
70743     return {
70744         type: type,
70745         resolution: resolution,
70746         color: color,
70747         info: info
70748     };
70749 };
70750
70751 });
70752 define('ripple/platform/phonegap/1.0.0/SensorAttributes', function (require, exports, module) {
70753 /*
70754  *  Copyright 2011 Research In Motion Limited.
70755  *
70756  * Licensed under the Apache License, Version 2.0 (the "License");
70757  * you may not use this file except in compliance with the License.
70758  * You may obtain a copy of the License at
70759  *
70760  * http://www.apache.org/licenses/LICENSE-2.0
70761  *
70762  * Unless required by applicable law or agreed to in writing, software
70763  * distributed under the License is distributed on an "AS IS" BASIS,
70764  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
70765  * See the License for the specific language governing permissions and
70766  * limitations under the License.
70767  */
70768 module.exports = function (value, min, max, normalizedValue) {
70769     return {
70770         value: value,
70771         min: min,
70772         max: max,
70773         normalizedValue: normalizedValue
70774     };
70775 };
70776
70777 });
70778 define('ripple/platform/phonegap/1.0.0/StorageUnitAttributes', function (require, exports, module) {
70779 /*
70780  *  Copyright 2011 Research In Motion Limited.
70781  *
70782  * Licensed under the Apache License, Version 2.0 (the "License");
70783  * you may not use this file except in compliance with the License.
70784  * You may obtain a copy of the License at
70785  *
70786  * http://www.apache.org/licenses/LICENSE-2.0
70787  *
70788  * Unless required by applicable law or agreed to in writing, software
70789  * distributed under the License is distributed on an "AS IS" BASIS,
70790  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
70791  * See the License for the specific language governing permissions and
70792  * limitations under the License.
70793  */
70794 module.exports = function (info, id, type, isWritable, capacity, availableCapacity, isRemoveable) {
70795     return {
70796         info: info,
70797         id: id,
70798         type: type,
70799         isWritable: isWritable,
70800         capacity: capacity,
70801         availableCapacity: availableCapacity,
70802         isRemoveable: isRemoveable
70803     };
70804 };
70805
70806 });
70807 define('ripple/platform/phonegap/1.0.0/SystemInfoOptions', function (require, exports, module) {
70808 /*
70809  *  Copyright 2011 Research In Motion Limited.
70810  *
70811  * Licensed under the Apache License, Version 2.0 (the "License");
70812  * you may not use this file except in compliance with the License.
70813  * You may obtain a copy of the License at
70814  *
70815  * http://www.apache.org/licenses/LICENSE-2.0
70816  *
70817  * Unless required by applicable law or agreed to in writing, software
70818  * distributed under the License is distributed on an "AS IS" BASIS,
70819  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
70820  * See the License for the specific language governing permissions and
70821  * limitations under the License.
70822  */
70823 module.exports = function (highThreshold, lowThreshold, thresholdTarget, timeout, id) {
70824     return {
70825         highThreshold: highThreshold,
70826         lowThreshold: lowThreshold,
70827         thresholdTarget: thresholdTarget,
70828         timeout: timeout,
70829         id: id
70830     };
70831 };
70832
70833 });
70834 define('ripple/platform/phonegap/1.0.0/ThermalAttributes', function (require, exports, module) {
70835 /*
70836  *  Copyright 2011 Research In Motion Limited.
70837  *
70838  * Licensed under the Apache License, Version 2.0 (the "License");
70839  * you may not use this file except in compliance with the License.
70840  * You may obtain a copy of the License at
70841  *
70842  * http://www.apache.org/licenses/LICENSE-2.0
70843  *
70844  * Unless required by applicable law or agreed to in writing, software
70845  * distributed under the License is distributed on an "AS IS" BASIS,
70846  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
70847  * See the License for the specific language governing permissions and
70848  * limitations under the License.
70849  */
70850 module.exports = function (info, id, state) {
70851     return {
70852         info: info,
70853         id: id,
70854         state: state
70855     };
70856 };
70857
70858 });
70859 define('ripple/platform/phonegap/1.0.0/VideoCodecAttributes', function (require, exports, module) {
70860 /*
70861  *  Copyright 2011 Research In Motion Limited.
70862  *
70863  * Licensed under the Apache License, Version 2.0 (the "License");
70864  * you may not use this file except in compliance with the License.
70865  * You may obtain a copy of the License at
70866  *
70867  * http://www.apache.org/licenses/LICENSE-2.0
70868  *
70869  * Unless required by applicable law or agreed to in writing, software
70870  * distributed under the License is distributed on an "AS IS" BASIS,
70871  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
70872  * See the License for the specific language governing permissions and
70873  * limitations under the License.
70874  */
70875 module.exports = function (info, id, compFormats, containerFormats, hwAccel, profiles, frameTypes, rateTypes) {
70876     return {
70877         info: info,
70878         id: id,
70879         compFormats: compFormats,
70880         containerFormats: containerFormats,
70881         hwAccel: hwAccel,
70882         profiles: profiles,
70883         frameTypes: frameTypes,
70884         rateTypes: rateTypes
70885     };
70886 };
70887
70888 });
70889 define('ripple/platform/phonegap/1.0.0/accelerometer', function (require, exports, module) {
70890 /*
70891  *  Copyright 2011 Research In Motion Limited.
70892  *
70893  * Licensed under the Apache License, Version 2.0 (the "License");
70894  * you may not use this file except in compliance with the License.
70895  * You may obtain a copy of the License at
70896  *
70897  * http://www.apache.org/licenses/LICENSE-2.0
70898  *
70899  * Unless required by applicable law or agreed to in writing, software
70900  * distributed under the License is distributed on an "AS IS" BASIS,
70901  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
70902  * See the License for the specific language governing permissions and
70903  * limitations under the License.
70904  */
70905 var Acceleration = require('ripple/platform/phonegap/1.0.0/Acceleration'),
70906     utils = require('ripple/utils'),
70907     event = require('ripple/event'),
70908     _accelerometerInfo = new Acceleration(),
70909     _watches = {},
70910     self;
70911
70912 module.exports = self = {
70913     getCurrentAcceleration: function (onSuccess, onError) {
70914         // TODO: implement error call if accelerometer is not available, to be driven by behaviours?
70915
70916         if (typeof onSuccess === "function") {
70917             setTimeout(function () {
70918                 // TODO: build facility to trigger onError() from emulator
70919                 // see pivotal item: https://www.pivotaltracker.com/story/show/7040343
70920                 onSuccess(utils.copy(_accelerometerInfo));
70921             }, 1);
70922         }
70923
70924     },
70925
70926     watchAcceleration: function (accelerometerSuccess, accelerometerError, accelerometerOptions) {
70927         var watchId = (new Date()).getTime().toString(),
70928             watchObj = {};
70929
70930
70931         if (accelerometerOptions &&
70932                 accelerometerOptions.frequency && typeof
70933                 accelerometerOptions.frequency === "number" &&
70934                 accelerometerOptions.frequency === Math.floor(accelerometerOptions.frequency)) {
70935
70936             watchObj = {
70937                 onSuccess: accelerometerSuccess,
70938                 onError: accelerometerError,
70939                 interval: accelerometerOptions.frequency
70940             };
70941
70942             _watches[watchId] = watchObj;
70943
70944             _watches[watchId].intervalId = setInterval(function () {
70945                 self.getCurrentAcceleration(_watches[watchId].onSuccess, _watches[watchId].onError);
70946             }, accelerometerOptions.frequency);
70947
70948         }
70949         else {
70950             if (typeof accelerometerError === "function") {
70951                 setTimeout(function () {
70952                     accelerometerError();
70953                 }, 1);
70954             }
70955         }
70956
70957         return watchId;
70958     },
70959
70960     clearWatch: function (watchId) {
70961         clearInterval(_watches[watchId].intervalId);
70962     }
70963 };
70964
70965 event.on("AccelerometerInfoChangedEvent", function (accelerometerInfo) {
70966     _accelerometerInfo.x = accelerometerInfo.accelerationIncludingGravity.x / 9.8;
70967     _accelerometerInfo.y = accelerometerInfo.accelerationIncludingGravity.y / 9.8;
70968     _accelerometerInfo.z = accelerometerInfo.accelerationIncludingGravity.z / 9.8;
70969     _accelerometerInfo.timestamp = (new Date()).getTime();
70970 });
70971
70972 });
70973 define('ripple/platform/phonegap/1.0.0/camera', function (require, exports, module) {
70974 /*
70975  *  Copyright 2011 Research In Motion Limited.
70976  *
70977  * Licensed under the Apache License, Version 2.0 (the "License");
70978  * you may not use this file except in compliance with the License.
70979  * You may obtain a copy of the License at
70980  *
70981  * http://www.apache.org/licenses/LICENSE-2.0
70982  *
70983  * Unless required by applicable law or agreed to in writing, software
70984  * distributed under the License is distributed on an "AS IS" BASIS,
70985  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
70986  * See the License for the specific language governing permissions and
70987  * limitations under the License.
70988  */
70989 module.exports = {
70990     getPicture: function (cameraSuccess, cameraError, cameraOptions) {
70991         if (cameraError) {
70992             cameraError.apply(null, ["not implemented"]);
70993         }
70994         else {
70995             throw "not implemented";
70996         }
70997     }
70998 };
70999
71000 });
71001 define('ripple/platform/phonegap/1.0.0/compass', function (require, exports, module) {
71002 /*
71003  *  Copyright 2011 Research In Motion Limited.
71004  *
71005  * Licensed under the Apache License, Version 2.0 (the "License");
71006  * you may not use this file except in compliance with the License.
71007  * You may obtain a copy of the License at
71008  *
71009  * http://www.apache.org/licenses/LICENSE-2.0
71010  *
71011  * Unless required by applicable law or agreed to in writing, software
71012  * distributed under the License is distributed on an "AS IS" BASIS,
71013  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
71014  * See the License for the specific language governing permissions and
71015  * limitations under the License.
71016  */
71017 var geo = require('ripple/geo');
71018
71019 function _getHeading() {
71020     return geo.getPositionInfo().heading;
71021 }
71022
71023 module.exports = {
71024     getCurrentHeading: function (compassSuccess, compassError, compassOptions) {
71025         setTimeout(function () {
71026             compassSuccess(_getHeading());
71027         }, 1);
71028     },
71029     watchHeading: function (compassSuccess, compassError, compassOptions) {
71030         compassOptions = compassOptions || {};
71031         return setInterval(function () {
71032             compassSuccess(_getHeading());
71033         }, compassOptions.frequency || 100);
71034     },
71035     clearWatch: function (watchId) {
71036         clearInterval(watchId);
71037     }
71038 };
71039
71040 });
71041 define('ripple/platform/phonegap/1.0.0/contacts', function (require, exports, module) {
71042 /*
71043  *  Copyright 2011 Research In Motion Limited.
71044  *
71045  * Licensed under the Apache License, Version 2.0 (the "License");
71046  * you may not use this file except in compliance with the License.
71047  * You may obtain a copy of the License at
71048  *
71049  * http://www.apache.org/licenses/LICENSE-2.0
71050  *
71051  * Unless required by applicable law or agreed to in writing, software
71052  * distributed under the License is distributed on an "AS IS" BASIS,
71053  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
71054  * See the License for the specific language governing permissions and
71055  * limitations under the License.
71056  */
71057 var Contact = require('./Contact'),
71058     ContactName = require('./ContactName'),
71059     ContactError = require('./ContactError'),
71060     ContactField = require('./ContactField'),
71061     utils = require('ripple/utils'),
71062     db = require('ripple/db'),
71063     event = require('ripple/event'),
71064     _defaultContacts = 
71065     [{
71066         "id": Math.uuid(undefined, 16),
71067         "name": new ContactName("Brent Lintner"),
71068         "displayName": "Brent Lintner",
71069         "emails": [new ContactField("work", "brent@tinyhippos.com", false)]
71070     }, {
71071         "id": Math.uuid(undefined, 16),
71072         "name": new ContactName("PJ Lowe"),
71073         "displayName": "PJ Lowe",
71074         "emails": [new ContactField("work", "pj@tinyhippos.com", false)]
71075     }, {
71076         "id": Math.uuid(undefined, 16),
71077         "name": new ContactName("Dan Silivestru"),
71078         "displayName": "Dan Silivestru",
71079         "emails": [new ContactField("work", "dan@tinyhippos.com", false)]
71080     }, {
71081         "id": Math.uuid(undefined, 16),
71082         "name": new ContactName("Gord Tanner"),
71083         "displayName": "Gord Tanner",
71084         "emails": [new ContactField("work", "gord@tinyhippos.com", true)]
71085     }, {
71086         "id": Math.uuid(undefined, 16),
71087         "name": new ContactName("Mark McArdle"),
71088         "displayName": "Mark McArdle",
71089         "emails": [new ContactField("work", "mark@tinyhippos.com", false)]
71090     }],
71091     self;
71092
71093 function _error(callback, code, msg) {
71094     var e = new ContactError();
71095     e.code = code;
71096     e.message = msg;
71097     window.setTimeout(function () {
71098         callback(e);
71099     }, 1);
71100 }
71101
71102
71103 function _getContacts() {
71104     return db.retrieveObject("phonegap-contacts") || 
71105         _defaultContacts.map(function (person) {
71106             var contact = new Contact();
71107             contact.updated = new Date();
71108             utils.forEach(person, function (value, prop) {
71109                 contact[prop] = value;
71110             });
71111
71112             return contact;
71113         });
71114 }
71115
71116 function _saveContacts(contacts) {
71117     db.saveObject("phonegap-contacts", contacts);
71118 }
71119
71120 function _filtered(compare, options) {
71121     // this could be done a lot better..
71122     var found = false;
71123     if (!options.filter || options.filter === "") {
71124         found = true;
71125     } else if (typeof compare === "string" &&
71126               compare.match(new RegExp(".*" + options.filter + ".*", "i"))) {
71127         found = true;
71128     } else if (typeof compare === "object" || compare instanceof Array) {
71129         utils.forEach(compare, function (value) {
71130             if (!found) {
71131                 found = _filtered(value, options);
71132             }
71133         });
71134     }
71135     return found;
71136 }
71137
71138 event.on("phonegap-contact-save", function (contactProperties, success, error) {
71139     var contacts = _getContacts(),
71140         existsIndex = contacts.reduce(function (result, value, index) {
71141             return value.id === contactProperties.id ? index : result;
71142         }, -1),
71143         contact = existsIndex >= 0 ? contacts[existsIndex] : new Contact();
71144
71145     utils.mixin(contactProperties, contact);
71146     if (existsIndex < 0) {
71147         contacts.push(contact);
71148     }
71149     _saveContacts(contacts);
71150     success(contact);
71151 });
71152
71153 event.on("phonegap-contact-remove", function (id, success, error) {
71154     if (!id) {
71155         _error(error, ContactError.NOT_FOUND_ERROR, "id is falsy (" + id + ")");
71156     } else {
71157         var contacts = _getContacts(),
71158             toDelete = contacts.reduce(function (result, current, index) {
71159                 return current.id === id ? index : result;
71160             }, -1);
71161
71162         if (toDelete >= 0) {
71163             contacts.splice(toDelete, 1);
71164             _saveContacts(contacts);
71165             success();
71166         } else {
71167             _error(error, ContactError.NOT_FOUND_ERROR, "could not find contact with id (" + id + ")");
71168         }
71169     }
71170 });
71171
71172 self = module.exports = {
71173     create: function (properties) {
71174         var contact = new Contact();
71175         utils.forEach(properties, function (value, key) {
71176             contact[key] = value;
71177         });
71178         return contact;
71179     },
71180     find: function (fields, success, error, options) {
71181         var foundContacts = [],
71182             tempContact = self.create(),
71183             contacts = _getContacts(),
71184             errorFlag = false;
71185
71186         options = options || {};
71187
71188         // not a fan of error handling at the moment
71189         if (!fields || !("forEach" in fields)) {
71190             errorFlag = true;
71191             _error(error, ContactError.INVALID_ARGUMENT_ERROR, "missing contact fields array");
71192             return;
71193         }
71194
71195         // handle special case of ["*"] to return all fields
71196         if (fields.length === 1 && fields[0] === "*") {
71197             fields = utils.map(tempContact, function (v, k) {
71198                 return k;
71199             });
71200         }
71201
71202         fields.forEach(function (prop) {
71203             if (!(tempContact.hasOwnProperty(prop))) {
71204                 errorFlag = true;
71205                 _error(error, ContactError.INVALID_ARGUMENT_ERROR, "invalid contact field (" + prop + ")");
71206             }
71207         });
71208
71209         if (typeof success !== "function" && !errorFlag) {
71210             errorFlag = true;
71211             _error(error, ContactError.INVALID_ARGUMENT_ERROR, "missing success callback");
71212         }
71213
71214         if (errorFlag) {
71215             return;
71216         }
71217
71218         if (fields.length > 0) {
71219             contacts.forEach(function (contact, index) {
71220                 var newContact = utils.copy(contact);
71221
71222                 if (options && (!_filtered(contact, options) ||
71223                         options.updatedSince && contact.updated && contact.updated.getTime() < options.updatedSince.getTime())) {
71224                     return;
71225                 }
71226
71227                 utils.forEach(newContact, function (value, prop) {
71228                     if (typeof newContact[prop] !== "function" && prop !== "id" &&
71229                         !fields.some(function (field) {
71230                             return field === prop;
71231                         })) {
71232                         delete newContact[prop];
71233                     }
71234                 });
71235
71236                 foundContacts.push(newContact);
71237             });
71238         }
71239
71240         window.setTimeout(function () {
71241             // TODO: don't loop over entire db just to slice the array
71242             if (options.multiple === false) {
71243                 foundContacts = foundContacts.splice(0, 1);
71244             }
71245             success(foundContacts);
71246         }, 1);
71247     }
71248 };
71249
71250 });
71251 define('ripple/platform/phonegap/1.0.0/device', function (require, exports, module) {
71252 /*
71253  *  Copyright 2011 Research In Motion Limited.
71254  *
71255  * Licensed under the Apache License, Version 2.0 (the "License");
71256  * you may not use this file except in compliance with the License.
71257  * You may obtain a copy of the License at
71258  *
71259  * http://www.apache.org/licenses/LICENSE-2.0
71260  *
71261  * Unless required by applicable law or agreed to in writing, software
71262  * distributed under the License is distributed on an "AS IS" BASIS,
71263  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
71264  * See the License for the specific language governing permissions and
71265  * limitations under the License.
71266  */
71267 var _self = {},
71268     event = require('ripple/event'),
71269     devices = require('ripple/devices');
71270
71271
71272 event.on("HardwareKey", function (key) {
71273     event.trigger("HardwareKeyDefault", [key]);
71274 });
71275
71276 _self.__defineGetter__("name", function () {
71277     return devices.getCurrentDevice().name;
71278 });
71279
71280 _self.__defineGetter__("platform", function () {
71281     return devices.getCurrentDevice().osName;
71282 });
71283
71284 _self.__defineGetter__("uuid", function () {
71285     return devices.getCurrentDevice().uuid;
71286 });
71287
71288 _self.__defineGetter__("version", function () {
71289     return devices.getCurrentDevice().osVersion;
71290 });
71291
71292 _self.phonegap = "placeholder string";
71293
71294 module.exports = _self;
71295
71296 });
71297 define('ripple/platform/phonegap/1.0.0/map', function (require, exports, module) {
71298 /*
71299  *  Copyright 2011 Research In Motion Limited.
71300  *
71301  * Licensed under the Apache License, Version 2.0 (the "License");
71302  * you may not use this file except in compliance with the License.
71303  * You may obtain a copy of the License at
71304  *
71305  * http://www.apache.org/licenses/LICENSE-2.0
71306  *
71307  * Unless required by applicable law or agreed to in writing, software
71308  * distributed under the License is distributed on an "AS IS" BASIS,
71309  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
71310  * See the License for the specific language governing permissions and
71311  * limitations under the License.
71312  */
71313 module.exports = {
71314     show: function () {
71315         throw "not implemented";
71316     }
71317 };
71318
71319 });
71320 define('ripple/platform/phonegap/1.0.0/navigator', function (require, exports, module) {
71321 /*
71322  *  Copyright 2011 Research In Motion Limited.
71323  *
71324  * Licensed under the Apache License, Version 2.0 (the "License");
71325  * you may not use this file except in compliance with the License.
71326  * You may obtain a copy of the License at
71327  *
71328  * http://www.apache.org/licenses/LICENSE-2.0
71329  *
71330  * Unless required by applicable law or agreed to in writing, software
71331  * distributed under the License is distributed on an "AS IS" BASIS,
71332  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
71333  * See the License for the specific language governing permissions and
71334  * limitations under the License.
71335  */
71336 var nav = require('ripple/platform/w3c/1.0/navigator'),
71337     event = require('ripple/event'),
71338     _console = require('ripple/console'),
71339     utils = require('ripple/utils'),
71340     emulatorBridge = require('ripple/emulatorBridge'),
71341     _self = {};
71342
71343 event.on("TinyHipposLoaded", function () {
71344     var doc = emulatorBridge.document(),
71345         evt = doc.createEvent("Events");
71346     evt.initEvent("deviceready", true, true);
71347     doc.dispatchEvent(evt);
71348     _console.log("fired deviceready event!");
71349 });
71350
71351 utils.mixin(nav, _self);
71352
71353 module.exports = _self;
71354
71355 });
71356 define('ripple/platform/phonegap/1.0.0/network', function (require, exports, module) {
71357 /*
71358  *  Copyright 2011 Research In Motion Limited.
71359  *
71360  * Licensed under the Apache License, Version 2.0 (the "License");
71361  * you may not use this file except in compliance with the License.
71362  * You may obtain a copy of the License at
71363  *
71364  * http://www.apache.org/licenses/LICENSE-2.0
71365  *
71366  * Unless required by applicable law or agreed to in writing, software
71367  * distributed under the License is distributed on an "AS IS" BASIS,
71368  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
71369  * See the License for the specific language governing permissions and
71370  * limitations under the License.
71371  */
71372 var deviceSettings = require('ripple/deviceSettings'),
71373     _self = {
71374         connection: {
71375         }
71376     };
71377
71378 _self.connection.__defineGetter__("type", function () {
71379     return deviceSettings.retrieve("NetworkStatus.connectionType");
71380 });
71381
71382 module.exports = _self;
71383
71384 });
71385 define('ripple/platform/phonegap/1.0.0/notification', function (require, exports, module) {
71386 /*
71387  *  Copyright 2011 Research In Motion Limited.
71388  *
71389  * Licensed under the Apache License, Version 2.0 (the "License");
71390  * you may not use this file except in compliance with the License.
71391  * You may obtain a copy of the License at
71392  *
71393  * http://www.apache.org/licenses/LICENSE-2.0
71394  *
71395  * Unless required by applicable law or agreed to in writing, software
71396  * distributed under the License is distributed on an "AS IS" BASIS,
71397  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
71398  * See the License for the specific language governing permissions and
71399  * limitations under the License.
71400  */
71401 var notifications = require('ripple/notifications'),
71402     constants = require('ripple/constants'),
71403     _console = require('ripple/console'),
71404     ui = require('ripple/ui'),
71405     goodVibrations = require('ripple/ui/plugins/goodVibrations');
71406
71407 module.exports = {
71408     alert: function (message, title, buttonName) {
71409         notifications.openNotification("normal", message);
71410     },
71411
71412     beep: function (times) {
71413         for (var i = times; i > 0; i--) {
71414             _console.log("beep!");
71415         }
71416         notifications.openNotification("normal", "BEEP x " + times);
71417     },
71418
71419     vibrate: function (milliseconds) {
71420         milliseconds = milliseconds || 500;
71421         goodVibrations.vibrateDevice(milliseconds);
71422     }
71423 };
71424
71425 });
71426 define('ripple/platform/phonegap/1.0.0/orientation', function (require, exports, module) {
71427 /*
71428  *  Copyright 2011 Research In Motion Limited.
71429  *
71430  * Licensed under the Apache License, Version 2.0 (the "License");
71431  * you may not use this file except in compliance with the License.
71432  * You may obtain a copy of the License at
71433  *
71434  * http://www.apache.org/licenses/LICENSE-2.0
71435  *
71436  * Unless required by applicable law or agreed to in writing, software
71437  * distributed under the License is distributed on an "AS IS" BASIS,
71438  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
71439  * See the License for the specific language governing permissions and
71440  * limitations under the License.
71441  */
71442 module.exports = {
71443     currentOrientation: null,
71444     getCurrentOrientation: function (onSuccess, onFail) {
71445         throw "not implemented";
71446     },
71447     watchOrientation: function () {
71448         throw "not implemented";
71449     }
71450 };
71451
71452 });
71453 define('ripple/platform/phonegap/1.0.0/service', function (require, exports, module) {
71454 /*
71455  *  Copyright 2011 Research In Motion Limited.
71456  *
71457  * Licensed under the Apache License, Version 2.0 (the "License");
71458  * you may not use this file except in compliance with the License.
71459  * You may obtain a copy of the License at
71460  *
71461  * http://www.apache.org/licenses/LICENSE-2.0
71462  *
71463  * Unless required by applicable law or agreed to in writing, software
71464  * distributed under the License is distributed on an "AS IS" BASIS,
71465  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
71466  * See the License for the specific language governing permissions and
71467  * limitations under the License.
71468  */
71469 // for form, but could probably just delete
71470 module.exports = {};
71471
71472 });
71473 define('ripple/platform/phonegap/1.0.0/sms', function (require, exports, module) {
71474 /*
71475  *  Copyright 2011 Research In Motion Limited.
71476  *
71477  * Licensed under the Apache License, Version 2.0 (the "License");
71478  * you may not use this file except in compliance with the License.
71479  * You may obtain a copy of the License at
71480  *
71481  * http://www.apache.org/licenses/LICENSE-2.0
71482  *
71483  * Unless required by applicable law or agreed to in writing, software
71484  * distributed under the License is distributed on an "AS IS" BASIS,
71485  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
71486  * See the License for the specific language governing permissions and
71487  * limitations under the License.
71488  */
71489 module.exports = {
71490     send: function () {
71491         throw "not implemented";
71492     }
71493 };
71494
71495 });
71496 define('ripple/platform/phonegap/1.0.0/spec/config', function (require, exports, module) {
71497 /*
71498  *  Copyright 2011 Research In Motion Limited.
71499  *
71500  * Licensed under the Apache License, Version 2.0 (the "License");
71501  * you may not use this file except in compliance with the License.
71502  * You may obtain a copy of the License at
71503  *
71504  * http://www.apache.org/licenses/LICENSE-2.0
71505  *
71506  * Unless required by applicable law or agreed to in writing, software
71507  * distributed under the License is distributed on an "AS IS" BASIS,
71508  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
71509  * See the License for the specific language governing permissions and
71510  * limitations under the License.
71511  */
71512 var constants = require('ripple/constants');
71513
71514 module.exports = {
71515     fileName: "config.xml",
71516     validateVersion: function (configValidationObject) {
71517         var valid = true;
71518         valid = !((!configValidationObject.widget.validationResult[0].attributes.xmlns.valid) ||
71519             (!configValidationObject.widget.validationResult[0].attributes["xmlns:gap"].valid));
71520
71521         return valid;
71522     },
71523     extractInfo: function (configValidationObject) {
71524         if (!configValidationObject) {
71525             return null;
71526         }
71527
71528         var widgetInfo = {};
71529
71530         widgetInfo.id = configValidationObject.widget.validationResult[0].attributes.id.value || "";
71531         widgetInfo.name = configValidationObject.widget.children.name.validationResult[0].value;
71532         widgetInfo.icon = configValidationObject.widget.children.icon.validationResult[0].attributes.src.value;
71533         widgetInfo.version = configValidationObject.widget.validationResult[0].attributes.version.value;
71534
71535         return widgetInfo;
71536     },
71537     schema: {
71538         rootElement: "widget",
71539         widget: {
71540             nodeName: "widget",
71541             required: true,
71542             occurrence: 1,
71543             attributes: {
71544                 xmlns: {
71545                     attributeName: "xmlns",
71546                     required: true,
71547                     type: "list",
71548                     listValues: ["http://www.w3.org/ns/widgets"]
71549                 },
71550                 "xmlns:gap": {
71551                     attributeName: "xmlns:gap",
71552                     required: true,
71553                     type: "list",
71554                     listValues: ["http://phonegap.com/ns/1.0"]
71555                 },
71556                 "xml:lang": {
71557                     attributeName: "xml:lang",
71558                     required: false,
71559                     type: "iso-language"
71560                 },
71561                 dir: {
71562                     attributeName: "dir",
71563                     required: false,
71564                     type: "list",
71565                     listValues: ["ltr", "rtl", "lro", "rlo"]
71566                 },
71567                 id: {
71568                     attributeName: "id",
71569                     required: false,
71570                     type: "string"
71571                 },
71572                 version: {
71573                     attributeName: "version",
71574                     required: false,
71575                     type: "string"
71576                 },
71577                 height: {
71578                     attributeName: "height",
71579                     required: false,
71580                     type: "integer"
71581                 },
71582                 width: {
71583                     attributeName: "width",
71584                     required: false,
71585                     type: "integer"
71586                 },
71587                 viewmodes: {
71588                     attributeName: "viewmodes",
71589                     required: false,
71590                     type: "list",
71591                     listValues: ["floating", "fullscreen"]
71592                 }
71593             },
71594             children: {
71595                 name: {
71596                     nodeName: "name",
71597                     required: false,
71598                     occurrence: 0,
71599                     type: "string",
71600                     attributes: {
71601                         "short": {
71602                             attributeName: "short",
71603                             type: "string",
71604                             required: false
71605                         },
71606                         "xml:lang": {
71607                             attributeName: "xml:lang",
71608                             type: "string",
71609                             required: false,
71610                             unique: true
71611                         }
71612                     }
71613                 },
71614                 description: {
71615                     nodeName: "description",
71616                     required: false,
71617                     occurrence: 0,
71618                     type: "string",
71619                     attributes: {
71620                         "xml:lang": {
71621                             attributeName: "xml:lang",
71622                             type: "string",
71623                             required: false,
71624                             unique: true
71625                         }
71626                     }
71627                 },
71628                 author: {
71629                     nodeName: "author",
71630                     required: false,
71631                     occurrence: 1,
71632                     type: "string",
71633                     attributes: {
71634                         email: {
71635                             attributeName: "email",
71636                             type: "regex",
71637                             required: false,
71638                             regex: constants.REGEX.EMAIL
71639                         },
71640                         href: {
71641                             attributeName: "href",
71642                             type: "regex",
71643                             required: false,
71644                             regex: constants.REGEX.URL
71645                         }
71646                     }
71647                 },
71648                 license: {
71649                     nodeName: "license",
71650                     required: false,
71651                     occurrence: 1,
71652                     type: "string",
71653                     attributes: {
71654                         href: {
71655                             attributeName: "href",
71656                             type: "regex",
71657                             required: false,
71658                             regex: constants.REGEX.URL
71659                         },
71660                         "xml:lang": {
71661                             attributeName: "xml:lang",
71662                             type: "string",
71663                             required: false,
71664                             unique: true
71665                         }
71666                     }
71667                 },
71668                 icon: {
71669                     nodeName: "icon",
71670                     required: false,
71671                     occurrence: 0,
71672                     attributes: {
71673                         src: {
71674                             attributeName: "src",
71675                             type: "string",
71676                             required: true
71677                         },
71678                         height: {
71679                             attributeName: "height",
71680                             required: false,
71681                             type: "integer"
71682                         },
71683                         width: {
71684                             attributeName: "width",
71685                             required: false,
71686                             type: "integer"
71687                         }
71688                     }
71689                 },
71690                 content: {
71691                     nodeName: "content",
71692                     required: false,
71693                     occurrence: 1,
71694                     attributes: {
71695                         src: {
71696                             attributeName: "src",
71697                             type: "string",
71698                             required: true
71699                         },
71700                         encoding: {
71701                             attributeName: "encoding",
71702                             type: "string",
71703                             required: false
71704                         },
71705                         type: {
71706                             attributeName: "type",
71707                             type: "string",
71708                             required: false
71709                         }
71710                     }
71711                 },
71712                 feature: {
71713                     nodeName: "feature",
71714                     required: false,
71715                     occurrence: 0,
71716                     attributes: {
71717                         name: {
71718                             attributeName: "name",
71719                             type: "list",
71720                             required: true,
71721                             listValues: ["http://api.phonegap.com/1.0/accelerometer", "http://api.phonegap.com/1.0/camera",
71722                                 "http://api.phonegap.com/1.0/compass", "http://api.phonegap.com/1.0/contacts", "http://api.phonegap.com/1.0/device",
71723                                 "http://api.phonegap.com/1.0/events", "http://api.phonegap.com/1.0/file", "http://api.phonegap.com/1.0/geolocation",
71724                                 "http://api.phonegap.com/1.0/media", "http://api.phonegap.com/1.0/network", "http://api.phonegap.com/1.0/notification",
71725                                 "http://api.phonegap.com/1.0/storage"]
71726                         },
71727                         required: {
71728                             attributeName: "required",
71729                             type: "boolean",
71730                             required: false
71731                         }
71732                     }
71733                 },
71734                 preference: {
71735                     nodeName: "preference",
71736                     required: false,
71737                     occurrence: 0,
71738                     attributes: {
71739                         name: {
71740                             attributeName: "name",
71741                             type: "string",
71742                             required: true
71743                         },
71744                         value: {
71745                             type: "string",
71746                             attributeName: "value",
71747                             required: false
71748                         },
71749                         readonly: {
71750                             attributeName: "readonly",
71751                             type: "boolean",
71752                             required: false
71753                         }
71754                     }
71755                 }
71756             }
71757         }
71758     }
71759 };
71760
71761 });
71762 define('ripple/platform/phonegap/1.0.0/spec/device', function (require, exports, module) {
71763 /*
71764  *  Copyright 2011 Research In Motion Limited.
71765  *
71766  * Licensed under the Apache License, Version 2.0 (the "License");
71767  * you may not use this file except in compliance with the License.
71768  * You may obtain a copy of the License at
71769  *
71770  * http://www.apache.org/licenses/LICENSE-2.0
71771  *
71772  * Unless required by applicable law or agreed to in writing, software
71773  * distributed under the License is distributed on an "AS IS" BASIS,
71774  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
71775  * See the License for the specific language governing permissions and
71776  * limitations under the License.
71777  */
71778 var event = require('ripple/event');
71779
71780 module.exports = {
71781     "NetworkStatus": {
71782         "connectionType": {
71783             "name": "Connection Type",
71784             "control": {
71785                 "type": "select",
71786                 "value": "ethernet"
71787             },
71788             "options": {
71789                 "unknown": "UNKNOWN",
71790                 "ethernet": "ETHERNET",
71791                 "wifi": "WIFI",
71792                 "2g": "CELL_2G",
71793                 "3g": "CELL_3G",
71794                 "4g": "CELL_4G",
71795                 "none": "none"
71796             },
71797             "callback": function (setting) {
71798                 var connected = setting !== "none";
71799                 require('ripple/bus').send("network", connected);
71800             }
71801         },
71802         "lag": {
71803             "name": "Lag the network",
71804             "control": {
71805                 type: "checkbox",
71806                 value: false
71807             },
71808             "callback": function (setting) {
71809                 require('ripple/bus').send("lag", setting);
71810             }
71811         },
71812     }
71813 };
71814
71815 });
71816 define('ripple/platform/phonegap/1.0.0/spec/events', function (require, exports, module) {
71817 function _fires(name, data) {
71818     return function () {
71819         var doc = require("ripple/emulatorBridge").document(),
71820             evt = doc.createEvent("Events");
71821
71822         evt.initEvent(name, true, false);
71823         doc.dispatchEvent(evt);
71824     };
71825 }
71826
71827 module.exports = {
71828     "deviceready": {
71829         callback: _fires("deviceready")
71830     },
71831     "backbutton": {
71832         callback: _fires("backbutton")
71833     },
71834     "menubutton": {
71835         callback: _fires("menubutton")
71836     },
71837     "pause": {
71838         callback: _fires("pause")
71839     },
71840     "resume": {
71841         callback: _fires("resume")
71842     },
71843     "searchbutton": {
71844         callback: _fires("searchbutton")
71845     },
71846     "online": {
71847         callback: _fires("online")
71848     },
71849     "offline": {
71850         callback: _fires("offline")
71851     }
71852 };
71853
71854 });
71855 define('ripple/platform/phonegap/1.0.0/spec/ui', function (require, exports, module) {
71856 /*
71857  *  Copyright 2011 Research In Motion Limited.
71858  *
71859  * Licensed under the Apache License, Version 2.0 (the "License");
71860  * you may not use this file except in compliance with the License.
71861  * You may obtain a copy of the License at
71862  *
71863  * http://www.apache.org/licenses/LICENSE-2.0
71864  *
71865  * Unless required by applicable law or agreed to in writing, software
71866  * distributed under the License is distributed on an "AS IS" BASIS,
71867  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
71868  * See the License for the specific language governing permissions and
71869  * limitations under the License.
71870  */
71871 module.exports = {
71872     plugins: [
71873         "accelerometer",
71874         "deviceSettings",
71875         "geoView",
71876         "widgetConfig",
71877         "platformEvents"
71878     ]
71879 };
71880
71881 });
71882 define('ripple/platform/phonegap/1.0.0/spec', function (require, exports, module) {
71883 module.exports = {
71884     id: "phonegap",
71885     version: "1.0.0",
71886     name: "PhoneGap",
71887     type: "platform",
71888
71889     persistencePrefix: "phonegap-",
71890
71891     config: require('ripple/platform/phonegap/1.0.0/spec/config'),
71892     device: require('ripple/platform/phonegap/1.0.0/spec/device'),
71893     ui: require('ripple/platform/phonegap/1.0.0/spec/ui'),
71894     events: require('ripple/platform/phonegap/1.0.0/spec/events'),
71895
71896     initialize: function () { },
71897
71898     objects: {
71899         PhoneGap: {
71900             path: "phonegap/1.0.0/PhoneGap"
71901         },
71902         Coordinates: {
71903             path: "w3c/1.0/Coordinates"
71904         },
71905         Position: {
71906             path: "w3c/1.0/Position"
71907         },
71908         PositionError: {
71909             path: "w3c/1.0/PositionError"
71910         },
71911         Acceleration: {
71912             path: "phonegap/1.0.0/Acceleration"
71913         },
71914         navigator: {
71915             path: "phonegap/1.0.0/navigator",
71916             children: {
71917                 accelerometer: {
71918                     path: "phonegap/1.0.0/accelerometer"
71919                 },
71920                 geolocation: {
71921                     path: "w3c/1.0/geolocation"
71922                 },
71923                 notification: {
71924                     path: "phonegap/1.0.0/notification"
71925                 },
71926                 contacts: {
71927                     path: "phonegap/1.0.0/contacts"
71928                 },
71929                 network: {
71930                     path: "phonegap/1.0.0/network"
71931                 },
71932                 camera: {
71933                     path: "phonegap/1.0.0/camera"
71934                 },
71935                 sms: {
71936                     path: "phonegap/1.0.0/sms"
71937                 },
71938                 telephony: {
71939                     path: "phonegap/1.0.0/telephony"
71940                 },
71941                 map: {
71942                     path: "phonegap/1.0.0/map"
71943                 },
71944                 orientation: {
71945                     path: "phonegap/1.0.0/orientation"
71946                 },
71947                 system: {
71948                     path: "phonegap/1.0.0/system"
71949                 },
71950                 compass: {
71951                     path: "phonegap/1.0.0/compass"
71952                 }
71953             }
71954         },
71955         ContactError: {
71956             path: "phonegap/1.0.0/ContactError"
71957         },
71958         Contact: {
71959             path: "phonegap/1.0.0/Contact"
71960         },
71961         ContactName: {
71962             path: "phonegap/1.0.0/ContactName"
71963         },
71964         ContactAccount: {
71965             path: "phonegap/1.0.0/ContactAccount"
71966         },
71967         ContactAddress: {
71968             path: "phonegap/1.0.0/ContactAddress"
71969         },
71970         ContactOrganization: {
71971             path: "phonegap/1.0.0/ContactOrganization"
71972         },
71973         ContactFindOptions: {
71974             path: "phonegap/1.0.0/ContactFindOptions"
71975         },
71976         ContactField: {
71977             path: "phonegap/1.0.0/ContactField"
71978         },
71979         NetworkStatus: {
71980             path: "phonegap/1.0.0/NetworkStatus"
71981         },
71982         device: {
71983             path: "phonegap/1.0.0/device"
71984         },
71985         SystemInfoOptions: {
71986             path: "phonegap/1.0.0/SystemInfoOptions"
71987         },
71988         PowerAttributes: {
71989             path: "phonegap/1.0.0/PowerAttributes"
71990         },
71991         CPUAttributes: {
71992             path: "phonegap/1.0.0/CPUAttributes"
71993         },
71994         ThermalAttributes: {
71995             path: "phonegap/1.0.0/ThermalAttributes"
71996         },
71997         NetworkAttributes: {
71998             path: "phonegap/1.0.0/NetworkAttributes"
71999         },
72000         Connection: {
72001             path: "phonegap/1.0.0/Connection"
72002         },
72003         ConnectionAttributes: {
72004             path: "phonegap/1.0.0/ConnectionAttributes"
72005         },
72006         SensorAttributes: {
72007             path: "phonegap/1.0.0/SensorAttributes"
72008         },
72009         AVCodecsAttributes: {
72010             path: "phonegap/1.0.0/AVCodecsAttributes"
72011         },
72012         AudioCodecAttributes: {
72013             path: "phonegap/1.0.0/AudioCodecAttributes"
72014         },
72015         VideoCodecAttributes: {
72016             path: "phonegap/1.0.0/VideoCodecAttributes"
72017         },
72018         StorageUnitAttributes: {
72019             path: "phonegap/1.0.0/StorageUnitAttributes"
72020         },
72021         InputDevicesAttributes: {
72022             path: "phonegap/1.0.0/InputDevicesAttributes"
72023         },
72024         OutputDevicesAttributes: {
72025             path: "phonegap/1.0.0/OutputDevicesAttributes"
72026         },
72027         DisplayDeviceAttributes: {
72028             path: "phonegap/1.0.0/DisplayDeviceAttributes"
72029         },
72030         AudioDeviceAttributes: {
72031             path: "phonegap/1.0.0/AudioDeviceAttributes"
72032         },
72033         PrintingDeviceAttributes: {
72034             path: "phonegap/1.0.0/PrintingDeviceAttributes"
72035         },
72036         BrailleDeviceAttributes: {
72037             path: "phonegap/1.0.0/BrailleDeviceAttributes"
72038         },
72039         PointerAttributes: {
72040             path: "phonegap/1.0.0/PointerAttributes"
72041         },
72042         KeyboardAttributes: {
72043             path: "phonegap/1.0.0/KeyboardAttributes"
72044         },
72045         CameraAttributes: {
72046             path: "phonegap/1.0.0/CameraAttributes"
72047         },
72048         MicrophoneAttributes: {
72049             path: "phonegap/1.0.0/MicrophoneAttributes"
72050         }
72051     }
72052
72053 };
72054
72055 });
72056 define('ripple/platform/phonegap/1.0.0/system', function (require, exports, module) {
72057 module.exports = {
72058     get: function () {
72059         throw "not implemented";
72060     },
72061     has: function () {
72062         throw "not implemented";
72063     },
72064     monitor: function () {
72065         throw "not implemented";
72066     }
72067 };
72068
72069 });
72070 define('ripple/platform/phonegap/1.0.0/telephony', function (require, exports, module) {
72071 /*
72072  *  Copyright 2011 Research In Motion Limited.
72073  *
72074  * Licensed under the Apache License, Version 2.0 (the "License");
72075  * you may not use this file except in compliance with the License.
72076  * You may obtain a copy of the License at
72077  *
72078  * http://www.apache.org/licenses/LICENSE-2.0
72079  *
72080  * Unless required by applicable law or agreed to in writing, software
72081  * distributed under the License is distributed on an "AS IS" BASIS,
72082  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
72083  * See the License for the specific language governing permissions and
72084  * limitations under the License.
72085  */
72086 module.exports = {
72087     send: function () {
72088         throw "not implemented";
72089     }
72090 };
72091
72092 });
72093 define('ripple/platform/spec', function (require, exports, module) {
72094 /*
72095  *  Copyright 2011 Research In Motion Limited.
72096  *
72097  * Licensed under the Apache License, Version 2.0 (the "License");
72098  * you may not use this file except in compliance with the License.
72099  * You may obtain a copy of the License at
72100  *
72101  * http://www.apache.org/licenses/LICENSE-2.0
72102  *
72103  * Unless required by applicable law or agreed to in writing, software
72104  * distributed under the License is distributed on an "AS IS" BASIS,
72105  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
72106  * See the License for the specific language governing permissions and
72107  * limitations under the License.
72108  */
72109 module.exports = {
72110     //"phonegap": {"1.0.0": require('ripple/platform/phonegap/1.0.0/spec')},
72111     "tizen": {"2.0": require('ripple/platform/tizen/2.0/spec')},
72112     //"cordova": {"2.0.0": require('ripple/platform/cordova/2.0.0/spec')},
72113     //"webworks.bb10": {"1.0.0": require('ripple/platform/webworks.bb10/1.0.0/spec')},
72114     //"webworks.handset": {"2.0.0": require('ripple/platform/webworks.handset/2.0.0/spec')},
72115     //"webworks.tablet": {"2.0.0": require('ripple/platform/webworks.tablet/2.0.0/spec')},
72116     //"web": {"default": require('ripple/platform/web/default/spec')},
72117
72118     "get": function (name, version) {
72119         var platform = module.exports[name] || {};
72120         return (platform[version] || platform[Object.keys(platform)[0]]);
72121     }
72122 };
72123
72124 });
72125 define('ripple/platform/tizen/2.0/AccountBase', function (require, exports, module) {
72126 /*
72127  *  Copyright 2012 Intel Corporation.
72128  *
72129  * Licensed under the Apache License, Version 2.0 (the "License");
72130  * you may not use this file except in compliance with the License.
72131  * You may obtain a copy of the License at
72132  *
72133  * http://www.apache.org/licenses/LICENSE-2.0
72134  *
72135  * Unless required by applicable law or agreed to in writing, software
72136  * distributed under the License is distributed on an "AS IS" BASIS,
72137  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
72138  * See the License for the specific language governing permissions and
72139  * limitations under the License.
72140  */
72141
72142 module.exports = function (appId, userName, displayName, service) {
72143     var _self,
72144         _id = Math.uuid(null, 16);
72145
72146     _self = {
72147         appId : appId || "",
72148         userName : userName || "",
72149         displayName : displayName || "",
72150         service : service || {}
72151     };
72152
72153     _self.__defineGetter__("id", function () {
72154         return _id;
72155     });
72156
72157     return _self;
72158 };
72159
72160 });
72161 define('ripple/platform/tizen/2.0/AccountService', function (require, exports, module) {
72162 /*
72163  *  Copyright 2012 Intel Corporation.
72164  *
72165  * Licensed under the Apache License, Version 2.0 (the "License");
72166  * you may not use this file except in compliance with the License.
72167  * You may obtain a copy of the License at
72168  *
72169  * http://www.apache.org/licenses/LICENSE-2.0
72170  *
72171  * Unless required by applicable law or agreed to in writing, software
72172  * distributed under the License is distributed on an "AS IS" BASIS,
72173  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
72174  * See the License for the specific language governing permissions and
72175  * limitations under the License.
72176  */
72177
72178 module.exports = function (serviceName, serviceType, tag, displayName, icon, settings) {
72179     var _self,
72180         _id = Math.uuid(null, 16);
72181
72182     _self = {
72183         serviceName : serviceName || "",
72184         serviceType : serviceType || "",
72185         displayName : displayName || null,
72186         icon : icon || null,
72187         settings : settings || null,
72188         tag : tag || []
72189     };
72190
72191     _self.__defineGetter__("id", function () {
72192         return _id;
72193     });
72194
72195     return _self;
72196 };
72197
72198 });
72199 define('ripple/platform/tizen/2.0/AlarmAbsolute', function (require, exports, module) {
72200 /*
72201  *  Copyright 2012 Intel Corporation.
72202  *
72203  * Licensed under the Apache License, Version 2.0 (the "License");
72204  * you may not use this file except in compliance with the License.
72205  * You may obtain a copy of the License at
72206  *
72207  * http://www.apache.org/licenses/LICENSE-2.0
72208  *
72209  * Unless required by applicable law or agreed to in writing, software
72210  * distributed under the License is distributed on an "AS IS" BASIS,
72211  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
72212  * See the License for the specific language governing permissions and
72213  * limitations under the License.
72214  */
72215
72216 var utils = require('ripple/utils'),
72217     tizen1_utils = require('ripple/platform/tizen/2.0/tizen1_utils'),
72218     errorcode = require('ripple/platform/tizen/2.0/errorcode'),
72219     WebAPIError = require('ripple/platform/tizen/2.0/WebAPIError'),
72220     AlarmBase = require('ripple/platform/tizen/2.0/AlarmBase'),
72221     _byDayValue = ["SU", "MO", "TU", "WE", "TH", "FR", "SA"],
72222     PERIOD_WEEK = (7 * 24 * 60 * 60), MILLI_SECOND = 1000,
72223     AlarmAbsolute;
72224
72225 AlarmAbsolute = function (date, frequency) {
72226     var alarm, period = null, daysOfTheWeek = [], ascDays = [];
72227
72228     function checkDayValue(days) {
72229         var isDayType = false, i;
72230         for (i in days) {
72231             isDayType = utils.arrayContains(_byDayValue, days[i]);
72232             if (!isDayType)
72233                 throw new WebAPIError(errorcode.TYPE_MISMATCH_ERR);
72234         }
72235         return days;
72236     }
72237
72238     function getScheduleDateByPeriod(current, date, period) {
72239         var diff = period * MILLI_SECOND,
72240             triggerDate = new Date(date);
72241
72242         while (current > (triggerDate - MILLI_SECOND)) { // In advance 1s - MILLI_SECOND
72243             triggerDate.setTime(triggerDate.getTime() + diff);
72244         }
72245         return triggerDate;
72246     }
72247
72248     function getSchedulteDateByDay(current, triggerTime, startDay, endDay) {
72249         startDay = (7 + (endDay - startDay)) % 7;
72250         current.setHours(triggerTime.getHours());
72251         current.setMinutes(triggerTime.getMinutes());
72252         current.setSeconds(triggerTime.getSeconds());
72253         current.setMilliseconds(triggerTime.getMilliseconds());
72254         current.setDate(current.getDate() + startDay);
72255         return current;
72256     }
72257
72258     function getAscDays() { // Get asc order array
72259         for (var i in daysOfTheWeek) {
72260             ascDays.push(_byDayValue.lastIndexOf(daysOfTheWeek[i]));
72261         }
72262         return ascDays.sort();
72263     }
72264
72265     /*
72266      * Return
72267      *     true:  A is bigger than B
72268      *     false: otherwise
72269      */
72270     function compareTime(current, triggerTime) {
72271         var diff = current.getHours() - triggerTime.getHours();
72272         if (diff !== 0)
72273             return (diff > 0);
72274
72275         diff = current.getMinutes() - triggerTime.getMinutes();
72276         if (diff !== 0)
72277             return (diff > 0);
72278
72279         diff = current.getSeconds() - triggerTime.getSeconds();
72280         if (diff < -1) // Delay 1s
72281             return false;
72282
72283         return true;
72284     }
72285
72286     alarm = new AlarmBase(this);
72287     date = new Date(date);
72288     if (frequency !== undefined) {
72289         if (tizen1_utils.isValidArray(frequency)) {
72290             daysOfTheWeek = checkDayValue(frequency);
72291             if (daysOfTheWeek.length !== 0) {
72292                 period = PERIOD_WEEK;
72293             }
72294         } else {
72295             period = frequency;
72296         }
72297     }
72298
72299     this.getNextScheduledDate = function () {
72300         var current = new Date(),
72301             diff, isPass, today, total, i, nextDate;
72302
72303         diff = current - date;
72304         if (diff < -1000) // Advance 1s
72305             return date; // Before first trigger, return date
72306
72307         if (period === null)
72308             return null;
72309
72310         if (period !== PERIOD_WEEK)
72311             return getScheduleDateByPeriod(current, date, period); // Repeat by period
72312
72313         today = current.getDay(); // 0~6
72314         ascDays = getAscDays();
72315         total = ascDays.length;
72316
72317         if ((ascDays[0] <= today) && (today <= ascDays[total - 1])) { // Today out of ascDays
72318             for (i in ascDays) { // Today in ascDays
72319                 if (ascDays[i] < today) {
72320                     continue;
72321                 } else if (ascDays[i] > today) {
72322                     nextDate = ascDays[i];
72323                     break;
72324                 } else {
72325                     isPass = compareTime(current, date); // Is triggerTime pass
72326                     if (isPass) {
72327                         nextDate = ascDays[(i < total - 1) ? (parseInt(i, 10) + 1) : 0];
72328                     } else {
72329                         nextDate = today;
72330                     }
72331                     break;
72332                 }
72333             }
72334         } else {
72335             nextDate = ascDays[0];
72336         }
72337
72338         return getSchedulteDateByDay(current, date, today, nextDate);
72339     };
72340
72341     this.__defineGetter__("date", function () {
72342         return date;
72343     });
72344
72345     this.__defineGetter__("period", function () {
72346         return period;
72347     });
72348
72349     this.__defineGetter__("daysOfTheWeek", function () {
72350         return daysOfTheWeek;
72351     });
72352 };
72353
72354 module.exports = AlarmAbsolute;
72355
72356 });
72357 define('ripple/platform/tizen/2.0/AlarmBase', function (require, exports, module) {
72358 /*
72359  *  Copyright 2012 Intel Corporation.
72360  *
72361  * Licensed under the Apache License, Version 2.0 (the "License");
72362  * you may not use this file except in compliance with the License.
72363  * You may obtain a copy of the License at
72364  *
72365  * http://www.apache.org/licenses/LICENSE-2.0
72366  *
72367  * Unless required by applicable law or agreed to in writing, software
72368  * distributed under the License is distributed on an "AS IS" BASIS,
72369  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
72370  * See the License for the specific language governing permissions and
72371  * limitations under the License.
72372  */
72373
72374 module.exports = function (self) {
72375     self = self || this;
72376
72377     self.__defineGetter__("id", function () {
72378         return null;
72379     });
72380 };
72381
72382 });
72383 define('ripple/platform/tizen/2.0/AlarmRelative', function (require, exports, module) {
72384 /*
72385  *  Copyright 2012 Intel Corporation.
72386  *
72387  * Licensed under the Apache License, Version 2.0 (the "License");
72388  * you may not use this file except in compliance with the License.
72389  * You may obtain a copy of the License at
72390  *
72391  * http://www.apache.org/licenses/LICENSE-2.0
72392  *
72393  * Unless required by applicable law or agreed to in writing, software
72394  * distributed under the License is distributed on an "AS IS" BASIS,
72395  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
72396  * See the License for the specific language governing permissions and
72397  * limitations under the License.
72398  */
72399
72400 var AlarmBase = require('ripple/platform/tizen/2.0/AlarmBase'),
72401     AlarmRelative;
72402
72403 AlarmRelative = function (delay, period) {
72404     var alarm, date;
72405
72406     alarm  = new AlarmBase(this);
72407     delay  = delay || 0;
72408     period = period || null;
72409     date   = new Date(); // Alarm settime
72410
72411     this.getRemainingSeconds = function () {
72412         var current, diff, triggerDate, MILLI_SECOND = 1000;
72413         current     = new Date();
72414         triggerDate = new Date(delay * MILLI_SECOND + date.getTime()); // First triggerDate
72415         diff        = Math.round((triggerDate - current) / MILLI_SECOND);
72416
72417         if (diff > 0) // Before first trigger
72418             return diff;
72419
72420         if (period === null)
72421             return null; // Alarm is expired
72422
72423         while (current - triggerDate >= 0) { // Trigger repeatly
72424             triggerDate = new Date(period * MILLI_SECOND + triggerDate.getTime());
72425         }
72426         diff = Math.round(((triggerDate - current) / MILLI_SECOND));
72427         return diff;
72428     };
72429
72430     this.__defineGetter__("delay", function () {
72431         return delay;
72432     });
72433
72434     this.__defineGetter__("period", function () {
72435         return period;
72436     });
72437 };
72438
72439 module.exports = AlarmRelative;
72440
72441 });
72442 define('ripple/platform/tizen/2.0/ApplicationBase', function (require, exports, module) {
72443 /*
72444  *  Copyright 2012 Intel Corporation.
72445  *
72446  * Licensed under the Apache License, Version 2.0 (the "License");
72447  * you may not use this file except in compliance with the License.
72448  * You may obtain a copy of the License at
72449  *
72450  * http://www.apache.org/licenses/LICENSE-2.0
72451  *
72452  * Unless required by applicable law or agreed to in writing, software
72453  * distributed under the License is distributed on an "AS IS" BASIS,
72454  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
72455  * See the License for the specific language governing permissions and
72456  * limitations under the License.
72457  */
72458 var event = require('ripple/event'),
72459     ApplicationControl = require('ripple/platform/tizen/2.0/ApplicationControl'),
72460     RequestedApplicationControl = require('ripple/platform/tizen/2.0/RequestedApplicationControl');
72461
72462 module.exports = function (appInfo, contextId, metaData) {
72463     var _self, request = null, _metaData = metaData;
72464
72465     _self = {
72466         appInfo : appInfo,
72467         contextId : contextId,
72468         exit : function () {
72469             event.trigger("tizen-application-exit", [contextId]);
72470         },
72471         hide : function () {
72472             event.trigger("tizen-application-hide", [contextId]);
72473         },
72474         getRequestedAppControl : function () {
72475             request = new RequestedApplicationControl(
72476                                 new ApplicationControl(
72477                                     _metaData.operation,
72478                                     _metaData.appControl.uri,
72479                                     _metaData.appControl.mime,
72480                                     _metaData.appControl.category,
72481                                     _metaData.appControl.data));
72482             return request;
72483         }
72484     };
72485
72486     _self.__defineGetter__("appInfo", function () {
72487         return appInfo;
72488     });
72489     _self.__defineGetter__("contextId", function () {
72490         return contextId;
72491     });
72492
72493     return _self;
72494 };
72495
72496 });
72497 define('ripple/platform/tizen/2.0/ApplicationCertificate', function (require, exports, module) {
72498 /*
72499  *  Copyright 2012 Intel Corporation.
72500  *
72501  * Licensed under the Apache License, Version 2.0 (the "License");
72502  * you may not use this file except in compliance with the License.
72503  * You may obtain a copy of the License at
72504  *
72505  * http://www.apache.org/licenses/LICENSE-2.0
72506  *
72507  * Unless required by applicable law or agreed to in writing, software
72508  * distributed under the License is distributed on an "AS IS" BASIS,
72509  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
72510  * See the License for the specific language governing permissions and
72511  * limitations under the License.
72512  */
72513
72514 module.exports = function (type, value) {
72515     var _self;
72516
72517     _self = {
72518         type : type,
72519         value : value
72520     };
72521
72522     _self.__defineGetter__("type", function () {
72523         return type;
72524     });
72525     _self.__defineGetter__("value", function () {
72526         return value;
72527     });
72528
72529     return _self;
72530 };
72531
72532 });
72533 define('ripple/platform/tizen/2.0/ApplicationContext', function (require, exports, module) {
72534 /*
72535  *  Copyright 2012 Intel Corporation.
72536  *
72537  * Licensed under the Apache License, Version 2.0 (the "License");
72538  * you may not use this file except in compliance with the License.
72539  * You may obtain a copy of the License at
72540  *
72541  * http://www.apache.org/licenses/LICENSE-2.0
72542  *
72543  * Unless required by applicable law or agreed to in writing, software
72544  * distributed under the License is distributed on an "AS IS" BASIS,
72545  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
72546  * See the License for the specific language governing permissions and
72547  * limitations under the License.
72548  */
72549
72550 module.exports = function (id, appId) {
72551     var _self;
72552
72553     _self = {
72554         id : id,
72555         appId: appId
72556     };
72557
72558     _self.__defineGetter__("id", function () {
72559         return id;
72560     });
72561     _self.__defineGetter__("appId", function () {
72562         return appId;
72563     });
72564
72565     return _self;
72566 };
72567
72568 });
72569 define('ripple/platform/tizen/2.0/ApplicationControl', function (require, exports, module) {
72570 /*
72571  *  Copyright 2012 Intel Corporation.
72572  *
72573  * Licensed under the Apache License, Version 2.0 (the "License");
72574  * you may not use this file except in compliance with the License.
72575  * You may obtain a copy of the License at
72576  *
72577  * http://www.apache.org/licenses/LICENSE-2.0
72578  *
72579  * Unless required by applicable law or agreed to in writing, software
72580  * distributed under the License is distributed on an "AS IS" BASIS,
72581  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
72582  * See the License for the specific language governing permissions and
72583  * limitations under the License.
72584  */
72585
72586 var t = require('ripple/platform/tizen/2.0/typecast');
72587
72588 var ApplicationControl = function (operation, uri, mime, category, data) {
72589     var _data = [];
72590
72591     this.operation = t.DOMString(operation);
72592     this.uri = t.DOMString(uri, "?") || null;
72593     this.mime = t.DOMString(mime, "?");
72594     this.category = t.DOMString(category, "?");
72595
72596     if (data) {
72597         _data = t.ApplicationControlData(data, "[]?");
72598     }
72599
72600     this.__defineGetter__("data", function () {
72601         return _data;
72602     });
72603
72604     this.__defineSetter__("data", function (data) {
72605         data = data || [];
72606         _data = t.ApplicationControlData(data, "[]");
72607     });
72608 };
72609
72610 module.exports = ApplicationControl;
72611
72612 });
72613 define('ripple/platform/tizen/2.0/ApplicationControlData', function (require, exports, module) {
72614 /*
72615  *  Copyright 2012 Intel Corporation.
72616  *
72617  * Licensed under the Apache License, Version 2.0 (the "License");
72618  * you may not use this file except in compliance with the License.
72619  * You may obtain a copy of the License at
72620  *
72621  * http://www.apache.org/licenses/LICENSE-2.0
72622  *
72623  * Unless required by applicable law or agreed to in writing, software
72624  * distributed under the License is distributed on an "AS IS" BASIS,
72625  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
72626  * See the License for the specific language governing permissions and
72627  * limitations under the License.
72628  */
72629
72630 var t = require('ripple/platform/tizen/2.0/typecast');
72631
72632 var ApplicationControlData = function (key, value) {
72633     var val = [];
72634
72635     this.key = t.DOMString(key);
72636     val = t.DOMString(value, '[]');
72637
72638     this.__defineGetter__("value", function () {
72639         return val;
72640     });
72641
72642     this.__defineSetter__("value", function (value) {
72643         value = value || [];
72644         val = t.DOMString(value, '[]');
72645     });
72646 };
72647
72648 module.exports = ApplicationControlData;
72649
72650 });
72651 define('ripple/platform/tizen/2.0/ApplicationInformation', function (require, exports, module) {
72652 /*
72653  *  Copyright 2012 Intel Corporation.
72654  *
72655  * Licensed under the Apache License, Version 2.0 (the "License");
72656  * you may not use this file except in compliance with the License.
72657  * You may obtain a copy of the License at
72658  *
72659  * http://www.apache.org/licenses/LICENSE-2.0
72660  *
72661  * Unless required by applicable law or agreed to in writing, software
72662  * distributed under the License is distributed on an "AS IS" BASIS,
72663  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
72664  * See the License for the specific language governing permissions and
72665  * limitations under the License.
72666  */
72667
72668 module.exports = function (id, name, iconPath, version, show, categories, installDate, size, packageId) {
72669     var _self = this;
72670
72671     _self.__defineGetter__("id", function () {
72672         return id;
72673     });
72674     _self.__defineGetter__("name", function () {
72675         return name;
72676     });
72677     _self.__defineGetter__("iconPath", function () {
72678         return iconPath;
72679     });
72680     _self.__defineGetter__("version", function () {
72681         return version;
72682     });
72683     _self.__defineGetter__("show", function () {
72684         return show;
72685     });
72686     _self.__defineGetter__("categories", function () {
72687         return categories;
72688     });
72689     _self.__defineGetter__("installDate", function () {
72690         return installDate;
72691     });
72692     _self.__defineGetter__("size", function () {
72693         return size;
72694     });
72695     _self.__defineGetter__("packageId", function () {
72696         return packageId;
72697     });
72698
72699     return _self;
72700 };
72701
72702 });
72703 define('ripple/platform/tizen/2.0/AttributeFilter', function (require, exports, module) {
72704 /*
72705  *  Copyright 2012 Intel Corporation.
72706  *
72707  * Licensed under the Apache License, Version 2.0 (the "License");
72708  * you may not use this file except in compliance with the License.
72709  * You may obtain a copy of the License at
72710  *
72711  * http://www.apache.org/licenses/LICENSE-2.0
72712  *
72713  * Unless required by applicable law or agreed to in writing, software
72714  * distributed under the License is distributed on an "AS IS" BASIS,
72715  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
72716  * See the License for the specific language governing permissions and
72717  * limitations under the License.
72718  */
72719
72720 module.exports = function (_attributeName, _matchFlag, _matchValue) {
72721     return {
72722         attributeName: _attributeName,
72723         matchFlag: _matchFlag,
72724         matchValue: _matchValue
72725     };
72726 };
72727
72728 });
72729 define('ripple/platform/tizen/2.0/AttributeRangeFilter', function (require, exports, module) {
72730 /*
72731  *  Copyright 2012 Intel Corporation.
72732  *
72733  * Licensed under the Apache License, Version 2.0 (the "License");
72734  * you may not use this file except in compliance with the License.
72735  * You may obtain a copy of the License at
72736  *
72737  * http://www.apache.org/licenses/LICENSE-2.0
72738  *
72739  * Unless required by applicable law or agreed to in writing, software
72740  * distributed under the License is distributed on an "AS IS" BASIS,
72741  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
72742  * See the License for the specific language governing permissions and
72743  * limitations under the License.
72744  */
72745
72746 module.exports = function (_attributeName, _initialValue, _endValue) {
72747     return {
72748         attributeName: _attributeName,
72749         initialValue: _initialValue,
72750         endValue: _endValue
72751     };
72752 };
72753
72754 });
72755 define('ripple/platform/tizen/2.0/BluetoothClass', function (require, exports, module) {
72756 /*
72757  *  Copyright 2012 Intel Corporation
72758  *
72759  * Licensed under the Apache License, Version 2.0 (the "License");
72760  * you may not use _self file except in compliance with the License.
72761  * You may obtain a copy of the License at
72762  *
72763  * http://www.apache.org/licenses/LICENSE-2.0
72764  *
72765  * Unless required by applicable law or agreed to in writing, software
72766  * distributed under the License is distributed on an "AS IS" BASIS,
72767  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
72768  * See the License for the specific language governing permissions and
72769  * limitations under the License.
72770  */
72771
72772 var errorcode = require('ripple/platform/tizen/2.0/errorcode'),
72773     WebAPIError = require('ripple/platform/tizen/2.0/WebAPIError');
72774
72775 module.exports = function (prop, metaData) {
72776     var _self,
72777         _major = prop.major || 0,
72778         _minor = prop.minor || 0,
72779         _security = metaData,
72780         _services = prop.services || [];
72781
72782     _self = {
72783         hasService: function (service) {
72784             if (!_security.all && !_security.hasService) {
72785                 throw new WebAPIError(errorcode.SECURITY_ERR);
72786             }
72787             if (typeof service !== "number") {
72788                 throw new WebAPIError(errorcode.TYPE_MISMATCH_ERR);
72789             }
72790             return (_services.join(",").indexOf(service) !== -1);
72791         }
72792     };
72793
72794     _self.__defineGetter__("major", function () {
72795         return _major;
72796     });
72797     _self.__defineGetter__("minor", function () {
72798         return _minor;
72799     });
72800     _self.__defineGetter__("services", function () {
72801         return _services;
72802     });
72803     return _self;
72804 };
72805
72806 });
72807 define('ripple/platform/tizen/2.0/BluetoothClassDeviceMajor', function (require, exports, module) {
72808 /*
72809  *  Copyright 2012 Intel Corporation
72810  *
72811  * Licensed under the Apache License, Version 2.0 (the "License");
72812  * you may not use _self file except in compliance with the License.
72813  * You may obtain a copy of the License at
72814  *
72815  * http://www.apache.org/licenses/LICENSE-2.0
72816  *
72817  * Unless required by applicable law or agreed to in writing, software
72818  * distributed under the License is distributed on an "AS IS" BASIS,
72819  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
72820  * See the License for the specific language governing permissions and
72821  * limitations under the License.
72822  */
72823
72824 module.exports = function () {
72825     var _self = {};
72826
72827     _self.__defineGetter__("MISC", function () {
72828         return 0x00;
72829     });
72830     _self.__defineGetter__("COMPUTER", function () {
72831         return 0x01;
72832     });
72833     _self.__defineGetter__("PHONE", function () {
72834         return 0x02;
72835     });
72836     _self.__defineGetter__("NETWORK", function () {
72837         return 0x03;
72838     });
72839     _self.__defineGetter__("AUDIO_VIDEO", function () {
72840         return 0x04;
72841     });
72842     _self.__defineGetter__("PERIPHERAL", function () {
72843         return 0x05;
72844     });
72845     _self.__defineGetter__("IMAGING", function () {
72846         return 0x06;
72847     });
72848     _self.__defineGetter__("WEARABLE", function () {
72849         return 0x07;
72850     });
72851     _self.__defineGetter__("TOY", function () {
72852         return 0x08;
72853     });
72854     _self.__defineGetter__("HEALTH", function () {
72855         return 0x09;
72856     });
72857     _self.__defineGetter__("UNCATEGORIZED", function () {
72858         return 0x1F;
72859     });
72860
72861     return _self;
72862 };
72863
72864 });
72865 define('ripple/platform/tizen/2.0/BluetoothClassDeviceMinor', function (require, exports, module) {
72866 /*
72867  *  Copyright 2012 Intel Corporation
72868  *
72869  * Licensed under the Apache License, Version 2.0 (the "License");
72870  * you may not use _self file except in compliance with the License.
72871  * You may obtain a copy of the License at
72872  *
72873  * http://www.apache.org/licenses/LICENSE-2.0
72874  *
72875  * Unless required by applicable law or agreed to in writing, software
72876  * distributed under the License is distributed on an "AS IS" BASIS,
72877  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
72878  * See the License for the specific language governing permissions and
72879  * limitations under the License.
72880  */
72881
72882 module.exports = function () {
72883     var _self = {};
72884
72885     _self.__defineGetter__("COMPUTER_UNCATEGORIZED", function () {
72886         return 0x00;
72887     });
72888     _self.__defineGetter__("COMPUTER_DESKTOP", function () {
72889         return 0x01;
72890     });
72891     _self.__defineGetter__("COMPUTER_SERVER", function () {
72892         return 0x02;
72893     });
72894     _self.__defineGetter__("COMPUTER_LAPTOP", function () {
72895         return 0x03;
72896     });
72897     _self.__defineGetter__("COMPUTER_HANDHELD_PC_OR_PDA", function () {
72898         return 0x04;
72899     });
72900     _self.__defineGetter__("COMPUTER_PALM_PC_OR_PDA", function () {
72901         return 0x05;
72902     });
72903     _self.__defineGetter__("COMPUTER_WEARABLE", function () {
72904         return 0x06;
72905     });
72906
72907     _self.__defineGetter__("PHONE_UNCATEGORIZED", function () {
72908         return 0x00;
72909     });
72910     _self.__defineGetter__("PHONE_CELLULAR", function () {
72911         return 0x01;
72912     });
72913     _self.__defineGetter__("PHONE_CORDLESS", function () {
72914         return 0x02;
72915     });
72916     _self.__defineGetter__("PHONE_SMARTPHONE", function () {
72917         return 0x03;
72918     });
72919     _self.__defineGetter__("PHONE_MODEM_OR_GATEWAY", function () {
72920         return 0x04;
72921     });
72922     _self.__defineGetter__("PHONE_ISDN", function () {
72923         return 0x05;
72924     });
72925
72926     _self.__defineGetter__("AV_UNRECOGNIZED", function () {
72927         return 0x00;
72928     });
72929     _self.__defineGetter__("AV_WEARABLE_HEADSET", function () {
72930         return 0x01;
72931     });
72932     _self.__defineGetter__("AV_HANDSFREE", function () {
72933         return 0x02;
72934     });
72935     _self.__defineGetter__("AV_MICROPHONE", function () {
72936         return 0x04;
72937     });
72938     _self.__defineGetter__("AV_LOUDSPEAKER", function () {
72939         return 0x05;
72940     });
72941     _self.__defineGetter__("AV_HEADPHONES", function () {
72942         return 0x06;
72943     });
72944     _self.__defineGetter__("AV_PORTABLE_AUDIO", function () {
72945         return 0x07;
72946     });
72947     _self.__defineGetter__("AV_CAR_AUDIO", function () {
72948         return 0x08;
72949     });
72950     _self.__defineGetter__("AV_SETTOP_BOX", function () {
72951         return 0x09;
72952     });
72953     _self.__defineGetter__("AV_HIFI", function () {
72954         return 0x0a;
72955     });
72956     _self.__defineGetter__("AV_VCR", function () {
72957         return 0x0b;
72958     });
72959     _self.__defineGetter__("AV_VIDEO_CAMERA", function () {
72960         return 0x0c;
72961     });
72962     _self.__defineGetter__("AV_CAMCORDER", function () {
72963         return 0x0d;
72964     });
72965     _self.__defineGetter__("AV_MONITOR", function () {
72966         return 0x0e;
72967     });
72968     _self.__defineGetter__("AV_DISPLAY_AND_LOUDSPEAKER", function () {
72969         return 0x0f;
72970     });
72971     _self.__defineGetter__("AV_VIDEO_CONFERENCING", function () {
72972         return 0x10;
72973     });
72974     _self.__defineGetter__("AV_GAMING_TOY", function () {
72975         return 0x12;
72976     });
72977
72978     _self.__defineGetter__("PERIPHERAL_UNCATEGORIZED", function () {
72979         return 0;
72980     });
72981     _self.__defineGetter__("PERIPHERAL_KEYBOARD", function () {
72982         return 0x10;
72983     });
72984     _self.__defineGetter__("PERIPHERAL_POINTING_DEVICE", function () {
72985         return 0x20;
72986     });
72987     _self.__defineGetter__("PERIPHERAL_KEYBOARD_AND_POINTING_DEVICE", function () {
72988         return 0x30;
72989     });
72990     _self.__defineGetter__("PERIPHERAL_JOYSTICK", function () {
72991         return 0x01;
72992     });
72993     _self.__defineGetter__("PERIPHERAL_GAMEPAD", function () {
72994         return 0x02;
72995     });
72996     _self.__defineGetter__("PERIPHERAL_REMOTE_CONTROL", function () {
72997         return 0x03;
72998     });
72999     _self.__defineGetter__("PERIPHERAL_SENSING_DEVICE", function () {
73000         return 0x04;
73001     });
73002     _self.__defineGetter__("PERIPHERAL_DEGITIZER_TABLET", function () {
73003         return 0x05;
73004     });
73005     _self.__defineGetter__("PERIPHERAL_CARD_READER", function () {
73006         return 0x06;
73007     });
73008     _self.__defineGetter__("PERIPHERAL_DIGITAL_PEN", function () {
73009         return 0x07;
73010     });
73011     _self.__defineGetter__("PERIPHERAL_HANDHELD_SCANNER", function () {
73012         return 0x08;
73013     });
73014     _self.__defineGetter__("PERIPHERAL_HANDHELD_INPUT_DEVICE", function () {
73015         return 0x09;
73016     });
73017
73018     _self.__defineGetter__("IMAGING_UNCATEGORIZED", function () {
73019         return 0x00;
73020     });
73021     _self.__defineGetter__("IMAGING_DISPLAY", function () {
73022         return 0x04;
73023     });
73024     _self.__defineGetter__("IMAGING_CAMERA", function () {
73025         return 0x08;
73026     });
73027     _self.__defineGetter__("IMAGING_SCANNER", function () {
73028         return 0x10;
73029     });
73030     _self.__defineGetter__("IMAGING_PRINTER", function () {
73031         return 0x20;
73032     });
73033
73034     _self.__defineGetter__("WEARABLE_WRITST_WATCH", function () {
73035         return 0x01;
73036     });
73037     _self.__defineGetter__("WEARABLE_PAGER", function () {
73038         return 0x02;
73039     });
73040     _self.__defineGetter__("WEARABLE_JACKET", function () {
73041         return 0x03;
73042     });
73043     _self.__defineGetter__("WEARABLE_HELMET", function () {
73044         return 0x04;
73045     });
73046     _self.__defineGetter__("WEARABLE_GLASSES", function () {
73047         return 0x05;
73048     });
73049
73050     _self.__defineGetter__("TOY_ROBOT", function () {
73051         return 0x01;
73052     });
73053     _self.__defineGetter__("TOY_VEHICLE", function () {
73054         return 0x02;
73055     });
73056     _self.__defineGetter__("TOY_DOLL", function () {
73057         return 0x03;
73058     });
73059     _self.__defineGetter__("TOY_CONTROLLER", function () {
73060         return 0x04;
73061     });
73062     _self.__defineGetter__("TOY_GAME", function () {
73063         return 0x05;
73064     });
73065
73066     _self.__defineGetter__("HEALTH_UNDEFINED", function () {
73067         return 0x00;
73068     });
73069     _self.__defineGetter__("HEALTH_BLOOD_PRESSURE_MONITOR", function () {
73070         return 0x01;
73071     });
73072     _self.__defineGetter__("HEALTH_THERMOMETER", function () {
73073         return 0x02;
73074     });
73075     _self.__defineGetter__("HEALTH_WEIGHING_SCALE", function () {
73076         return 0x03;
73077     });
73078     _self.__defineGetter__("HEALTH_GLUCOSE_METER", function () {
73079         return 0x04;
73080     });
73081     _self.__defineGetter__("HEALTH_PULSE_OXIMETER", function () {
73082         return 0x05;
73083     });
73084     _self.__defineGetter__("HEALTH_PULSE_RATE_MONITOR", function () {
73085         return 0x06;
73086     });
73087     _self.__defineGetter__("HEALTH_DATA_DISPLAY", function () {
73088         return 0x07;
73089     });
73090     _self.__defineGetter__("HEALTH_STEP_COUNTER", function () {
73091         return 0x08;
73092     });
73093     _self.__defineGetter__("HEALTH_BODY_COMPOSITION_ANALYZER", function () {
73094         return 0x09;
73095     });
73096     _self.__defineGetter__("HEALTH_PEAK_FLOW_MONITOR", function () {
73097         return 0x0a;
73098     });
73099     _self.__defineGetter__("HEALTH_MEDICATION_MONITOR", function () {
73100         return 0x0b;
73101     });
73102     _self.__defineGetter__("HEALTH_KNEE_PROSTHESIS", function () {
73103         return 0x0c;
73104     });
73105     _self.__defineGetter__("HEALTH_ANKLE_PROSTHESIS", function () {
73106         return 0x0d;
73107     });
73108
73109     return _self;
73110 };
73111
73112 });
73113 define('ripple/platform/tizen/2.0/BluetoothClassDeviceService', function (require, exports, module) {
73114 /*
73115  *  Copyright 2012 Intel Corporation
73116  *
73117  * Licensed under the Apache License, Version 2.0 (the "License");
73118  * you may not use _self file except in compliance with the License.
73119  * You may obtain a copy of the License at
73120  *
73121  * http://www.apache.org/licenses/LICENSE-2.0
73122  *
73123  * Unless required by applicable law or agreed to in writing, software
73124  * distributed under the License is distributed on an "AS IS" BASIS,
73125  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
73126  * See the License for the specific language governing permissions and
73127  * limitations under the License.
73128  */
73129
73130 module.exports = function () {
73131     var _self = {};
73132
73133     _self.__defineGetter__("LIMITED_DISCOVERABILITY", function () {
73134         return 0x0001;
73135     });
73136     _self.__defineGetter__("POSITIONING", function () {
73137         return 0x0008;
73138     });
73139     _self.__defineGetter__("NETWORKING", function () {
73140         return 0x0010;
73141     });
73142     _self.__defineGetter__("RENDERING", function () {
73143         return 0x0020;
73144     });
73145     _self.__defineGetter__("CAPTURING", function () {
73146         return 0x0040;
73147     });
73148     _self.__defineGetter__("OBJECT_TRANSFER", function () {
73149         return 0x0080;
73150     });
73151     _self.__defineGetter__("AUDIO", function () {
73152         return 0x0100;
73153     });
73154     _self.__defineGetter__("TELEPHONY", function () {
73155         return 0x0200;
73156     });
73157     _self.__defineGetter__("INFORMATION", function () {
73158         return 0x0400;
73159     });
73160
73161     return _self;
73162 };
73163
73164 });
73165 define('ripple/platform/tizen/2.0/BluetoothDevice', function (require, exports, module) {
73166 /*
73167  *  Copyright 2012 Intel Corporation
73168  *
73169  * Licensed under the Apache License, Version 2.0 (the "License");
73170  * you may not use _self file except in compliance with the License.
73171  * You may obtain a copy of the License at
73172  *
73173  * http://www.apache.org/licenses/LICENSE-2.0
73174  *
73175  * Unless required by applicable law or agreed to in writing, software
73176  * distributed under the License is distributed on an "AS IS" BASIS,
73177  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
73178  * See the License for the specific language governing permissions and
73179  * limitations under the License.
73180  */
73181
73182 var utils = require('ripple/utils'),
73183     event = require('ripple/event'),
73184     tizen1_utils = require('ripple/platform/tizen/2.0/tizen1_utils'),
73185     errorcode = require('ripple/platform/tizen/2.0/errorcode'),
73186     WebAPIError = require('ripple/platform/tizen/2.0/WebAPIError'),
73187     BluetoothClass = require('ripple/platform/tizen/2.0/BluetoothClass'),
73188     BluetoothSocket = require('ripple/platform/tizen/2.0/BluetoothSocket');
73189
73190 module.exports = function (prop) {
73191     var _self,
73192         _name = prop.name || "",
73193         _address = prop.address || "",
73194         _deviceClass = new BluetoothClass(prop.deviceClass, prop.metaData) || {},
73195         _isBonded = prop.isBonded || false,
73196         _isTrusted = prop.isTrusted || false,
73197         _isConnected = prop.isConnected || false,
73198         _services = prop.services,
73199         _security = prop.metaData,
73200         _uuids = [],
73201         _sockets = {};
73202
73203     _self = {
73204         connectToServiceByUUID: function (uuid, successCallback, errorCallback, protocol) {
73205             if (!_security.all && !_security.connectToServiceByUUID) {
73206                 throw new WebAPIError(errorcode.SECURITY_ERR);
73207             }
73208
73209             if (typeof uuid !== "string") {
73210                 throw new WebAPIError(errorcode.TYPE_MISMATCH_ERR);
73211             }
73212
73213             tizen1_utils.validateArgumentType(successCallback, "function",
73214                     new WebAPIError(errorcode.TYPE_MISMATCH_ERR));
73215
73216             if (errorCallback) {
73217                 tizen1_utils.validateArgumentType(errorCallback, "function",
73218                         new WebAPIError(errorcode.TYPE_MISMATCH_ERR));
73219             }
73220
73221             if (protocol) {
73222                 if (protocol !== "RFCOMM" && protocol !== "L2CAP") {
73223                     new WebAPIError(errorcode.TYPE_MISMATCH_ERR);
73224                 }
73225             }
73226
73227             if (_uuids.join(",").indexOf(uuid) === -1) {
73228                 if (errorCallback) {
73229                     errorCallback(new WebAPIError(errorcode.NOT_FOUND_ERR));
73230                 }
73231                 return;
73232             }
73233             _isConnected = true;
73234             event.trigger("bt-device-connected-changed", [_address, true]);
73235             Object.defineProperty(_sockets[uuid], "state", {value: "OPEN", writable: false});
73236             event.trigger("bt-service-state-changed", [_address, uuid, true]);
73237             successCallback(_sockets[uuid]);
73238         }
73239     };
73240     
73241         event.on("bt-device-connected-update", function (addr, isConnected) {
73242                 if (addr === _address) {
73243                         _isConnected = isConnected;
73244                         event.trigger("bt-device-connected-changed", [_address, _isConnected]);
73245                 }
73246         });
73247
73248     utils.forEach(_services, function (service) {
73249                 _uuids.push(service.uuid);
73250         _sockets[service.uuid] = new BluetoothSocket({
73251             uuid: service.uuid,
73252             protocol: service.protocol,
73253             state: "CLOSED",
73254             peer: _self,
73255             metaData: _security
73256         });
73257     });
73258
73259     _self.__defineGetter__("name", function () {
73260         return _name;
73261     });
73262     _self.__defineGetter__("address", function () {
73263         return _address;
73264     });
73265     _self.__defineGetter__("deviceClass", function () {
73266         return _deviceClass;
73267     });
73268     _self.__defineGetter__("isBonded", function () {
73269         return _isBonded;
73270     });
73271     _self.__defineGetter__("isTrusted", function () {
73272         return _isTrusted;
73273     });
73274     _self.__defineGetter__("isConnected", function () {
73275         return _isConnected;
73276     });
73277     _self.__defineGetter__("uuids", function () {
73278         return _uuids;
73279     });
73280
73281     return _self;
73282 };
73283
73284 });
73285 define('ripple/platform/tizen/2.0/BluetoothServiceHandler', function (require, exports, module) {
73286 /*
73287  *  Copyright 2012 Intel Corporation
73288  *
73289  * Licensed under the Apache License, Version 2.0 (the "License");
73290  * you may not use _self file except in compliance with the License.
73291  * You may obtain a copy of the License at
73292  *
73293  * http://www.apache.org/licenses/LICENSE-2.0
73294  *
73295  * Unless required by applicable law or agreed to in writing, software
73296  * distributed under the License is distributed on an "AS IS" BASIS,
73297  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
73298  * See the License for the specific language governing permissions and
73299  * limitations under the License.
73300  */
73301
73302 var tizen1_utils = require('ripple/platform/tizen/2.0/tizen1_utils'),
73303     errorcode = require('ripple/platform/tizen/2.0/errorcode'),
73304     event = require('ripple/event'),
73305     WebAPIError = require('ripple/platform/tizen/2.0/WebAPIError');
73306
73307 module.exports = function (prop) {
73308     var _self,
73309         _uuid = prop.uuid || "",
73310         _name = prop.name || "",
73311         _isConnected = prop.isConnected || false,
73312         _security = prop.metaData || {};
73313
73314     _self = {
73315         onconnect : null,
73316         unregister : function (successCallback, errorCallback) {
73317             if (!_security.all && !_security.unregister) {
73318                 throw new WebAPIError(errorcode.SECURITY_ERR);
73319             }
73320
73321             tizen1_utils.validateCallbackType(successCallback, errorCallback);
73322             event.trigger("bt-unregister-service", [_uuid, successCallback, errorCallback]);
73323         }
73324     };
73325
73326     _self.__defineGetter__("uuid", function () {
73327         return _uuid;
73328     });
73329     _self.__defineGetter__("name", function () {
73330         return _name;
73331     });
73332     _self.__defineGetter__("isConnected", function () {
73333         return _isConnected;
73334     });
73335
73336     return _self;
73337 };
73338
73339 });
73340 define('ripple/platform/tizen/2.0/BluetoothSocket', function (require, exports, module) {
73341 /*
73342  *  Copyright 2012 Intel Corporation
73343  *
73344  * Licensed under the Apache License, Version 2.0 (the "License");
73345  * you may not use _self file except in compliance with the License.
73346  * You may obtain a copy of the License at
73347  *
73348  * http://www.apache.org/licenses/LICENSE-2.0
73349  *
73350  * Unless required by applicable law or agreed to in writing, software
73351  * distributed under the License is distributed on an "AS IS" BASIS,
73352  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
73353  * See the License for the specific language governing permissions and
73354  * limitations under the License.
73355  */
73356
73357 var utils = require('ripple/utils'),
73358     tizen1_utils = require('ripple/platform/tizen/2.0/tizen1_utils'),
73359     event = require('ripple/event'),
73360     errorcode = require('ripple/platform/tizen/2.0/errorcode'),
73361     WebAPIError = require('ripple/platform/tizen/2.0/WebAPIError');
73362
73363 module.exports = function (prop) {
73364     var _self,
73365         _uuid = prop.uuid,
73366         _protocol = prop.protocol,
73367         state = prop.state,
73368         _peer = prop.peer,
73369         _security = prop.metaData,
73370         _buf = [];
73371
73372     _self = {
73373         onmessage : null,
73374         onclose : null,
73375         onerror : null,
73376         writeData : function (data) {
73377             if (!_security.all && !_security.writeData) {
73378                 throw new WebAPIError(errorcode.SECURITY_ERR);
73379             }
73380             if (!tizen1_utils.isValidArray(data)) {
73381                 throw new WebAPIError(errorcode.TYPE_MISMATCH_ERR);
73382             }
73383             if (this.state === "CLOSED") {
73384                 return;
73385             }
73386
73387             event.trigger("bt-service-write-msg", [_peer.address, _uuid, data]);
73388             return data.length;
73389         },
73390         readData : function () {
73391             var data;
73392             if (!_security.all && !_security.readData) {
73393                 throw new WebAPIError(errorcode.SECURITY_ERR);
73394             }
73395             if (this.state === "CLOSED") {
73396                 return;
73397             }
73398
73399             data = utils.copy(_buf);
73400             _buf = [];
73401             return data;
73402         },
73403         close : function () {
73404             if (!_security.all && !_security.close) {
73405                 throw new WebAPIError(errorcode.SECURITY_ERR);
73406             }
73407
73408             Object.defineProperty(this, "state", {value: "CLOSED", writable: false});
73409             event.trigger("bt-service-state-changed", [_peer.address, _uuid, false]);
73410             event.trigger("bt-device-connected-update", [_peer.address, false]);
73411
73412             if (this.onclose) {
73413                 this.onclose();
73414             }
73415         }
73416     };
73417
73418     event.on("bt-service-state-update", function (addr, state) {
73419         var stateStr = "CLOSED";
73420         if (addr === _peer.address) {
73421             if (state) {
73422                 stateStr = "OPEN";
73423             }
73424             Object.defineProperty(this, "state", {value: stateStr, writable: false});
73425             event.trigger("bt-service-state-changed", [_peer.address, _uuid, state]);
73426             event.trigger("bt-device-connected-update", [_peer.address, state]);
73427         }
73428     });
73429
73430     event.on("bt-service-rawdata-received", function (addr, uuid, msg) {
73431         var i;
73432         if (addr === _peer.address && uuid === _uuid) {
73433             _buf = [];
73434             for (i = 0; i < msg.length; i++) {
73435                 _buf.push(msg.charCodeAt(i));
73436             }
73437             if (_self.onmessage) {
73438                 _self.onmessage();
73439             }
73440         }
73441     });
73442
73443     _self.__defineGetter__("uuid", function () {
73444         return _uuid;
73445     });
73446     _self.__defineGetter__("protocol", function () {
73447         return _protocol;
73448     });
73449     _self.__defineGetter__("state", function () {
73450         return state;
73451     });
73452     _self.__defineGetter__("peer", function () {
73453         return _peer;
73454     });
73455
73456     return _self;
73457 };
73458
73459 });
73460 define('ripple/platform/tizen/2.0/BookmarkFolder', function (require, exports, module) {
73461 /*
73462  *  Copyright 2013 Intel Corporation.
73463  *
73464  * Licensed under the Apache License, Version 2.0 (the "License");
73465  * you may not use this file except in compliance with the License.
73466  * You may obtain a copy of the License at
73467  *
73468  * http://www.apache.org/licenses/LICENSE-2.0
73469  *
73470  * Unless required by applicable law or agreed to in writing, software
73471  * distributed under the License is distributed on an "AS IS" BASIS,
73472  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
73473  * See the License for the specific language governing permissions and
73474  * limitations under the License.
73475  */
73476
73477 module.exports = function (title) {
73478     this.parent = undefined;
73479     this.__defineGetter__("title", function () {
73480         return title;
73481     });
73482
73483     title = title ? String(title).trim() : "";
73484 };
73485
73486 });
73487 define('ripple/platform/tizen/2.0/BookmarkItem', function (require, exports, module) {
73488 /*
73489  *  Copyright 2013 Intel Corporation.
73490  *
73491  * Licensed under the Apache License, Version 2.0 (the "License");
73492  * you may not use this file except in compliance with the License.
73493  * You may obtain a copy of the License at
73494  *
73495  * http://www.apache.org/licenses/LICENSE-2.0
73496  *
73497  * Unless required by applicable law or agreed to in writing, software
73498  * distributed under the License is distributed on an "AS IS" BASIS,
73499  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
73500  * See the License for the specific language governing permissions and
73501  * limitations under the License.
73502  */
73503
73504 module.exports = function (title, url) {
73505     this.parent = undefined;
73506     this.__defineGetter__("title", function () {
73507         return title;
73508     });
73509     this.__defineGetter__("url", function () {
73510         return url;
73511     });
73512
73513     title = title ? String(title).trim() : "";
73514     url = url ? String(url).trim() : "";
73515 };
73516
73517 });
73518 define('ripple/platform/tizen/2.0/CalendarAlarm', function (require, exports, module) {
73519 /*
73520  *  Copyright 2012 Intel Corporation.
73521  *
73522  * Licensed under the Apache License, Version 2.0 (the "License");
73523  * you may not use this file except in compliance with the License.
73524  * You may obtain a copy of the License at
73525  *
73526  * http://www.apache.org/licenses/LICENSE-2.0
73527  *
73528  * Unless required by applicable law or agreed to in writing, software
73529  * distributed under the License is distributed on an "AS IS" BASIS,
73530  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
73531  * See the License for the specific language governing permissions and
73532  * limitations under the License.
73533  */
73534
73535 var utils = require('ripple/utils'),
73536     TZDate = require('ripple/platform/tizen/2.0/TZDate'),
73537     TimeDuration = require('ripple/platform/tizen/2.0/TimeDuration'),
73538     errorcode = require('ripple/platform/tizen/2.0/errorcode'),
73539     WebAPIError = require('ripple/platform/tizen/2.0/WebAPIError'),
73540     _alarmMethods = ["SOUND", "DISPLAY"];
73541
73542 function CalendarAlarm (triggerTime, method, description) {
73543     var absoluteDate = null,
73544         before = null,
73545         isValid = false,
73546         _self = this;
73547
73548     if (triggerTime instanceof TZDate) {
73549         absoluteDate = triggerTime;
73550     } else if (triggerTime instanceof TimeDuration) {
73551         before = triggerTime;
73552     } else {
73553         throw (new WebAPIError(errorcode.TYPE_MISMATCH_ERR));
73554     }
73555
73556     isValid = utils.arrayContains(_alarmMethods, method);
73557     if (!isValid)
73558         throw (new WebAPIError(errorcode.TYPE_MISMATCH_ERR));
73559
73560     _self.absoluteDate = absoluteDate;
73561     _self.before       = before;
73562     _self.method       = method;
73563     _self.description  = description || "";
73564
73565     return _self;
73566 }
73567
73568 module.exports = CalendarAlarm;
73569
73570 });
73571 define('ripple/platform/tizen/2.0/CalendarAttendee', function (require, exports, module) {
73572 /*
73573  *  Copyright 2012 Intel Corporation.
73574  *
73575  * Licensed under the Apache License, Version 2.0 (the "License");
73576  * you may not use this file except in compliance with the License.
73577  * You may obtain a copy of the License at
73578  *
73579  * http://www.apache.org/licenses/LICENSE-2.0
73580  *
73581  * Unless required by applicable law or agreed to in writing, software
73582  * distributed under the License is distributed on an "AS IS" BASIS,
73583  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
73584  * See the License for the specific language governing permissions and
73585  * limitations under the License.
73586  */
73587
73588 module.exports = function (uri, attendeeInitDict) {
73589     var _self = this;
73590
73591     _self.uri = uri;
73592     if (attendeeInitDict) {
73593         _self.name         = (attendeeInitDict.name) ? attendeeInitDict.name : "";
73594         _self.role         = (attendeeInitDict.role) ? attendeeInitDict.role : "";
73595         _self.status       = (attendeeInitDict.status) ? attendeeInitDict.status : "";
73596         _self.RSVP         = (attendeeInitDict.RSVP) ? attendeeInitDict.RSVP : "";
73597         _self.type         = (attendeeInitDict.type) ? attendeeInitDict.type : "";
73598         _self.group        = (attendeeInitDict.group) ? attendeeInitDict.group : "";
73599         _self.delegatorURI = (attendeeInitDict.delegatorURI) ? attendeeInitDict.delegatorURI : "";
73600         _self.delegateURI  = (attendeeInitDict.delegateURI) ? attendeeInitDict.delegateURI : "";
73601         _self.contactRef   = (attendeeInitDict.contactRef) ? attendeeInitDict.contactRef : "";
73602     } else {
73603         _self.name         = "";
73604         _self.role         = "";
73605         _self.status       = "";
73606         _self.RSVP         = "";
73607         _self.type         = "";
73608         _self.group        = "";
73609         _self.delegatorURI = "";
73610         _self.delegateURI  = "";
73611         _self.contactRef   = "";
73612     }
73613
73614     return _self;
73615 };
73616
73617 });
73618 define('ripple/platform/tizen/2.0/CalendarEvent', function (require, exports, module) {
73619 /*
73620  *  Copyright 2012 Intel Corporation.
73621  *
73622  * Licensed under the Apache License, Version 2.0 (the "License");
73623  * you may not use this file except in compliance with the License.
73624  * You may obtain a copy of the License at
73625  *
73626  * http://www.apache.org/licenses/LICENSE-2.0
73627  *
73628  * Unless required by applicable law or agreed to in writing, software
73629  * distributed under the License is distributed on an "AS IS" BASIS,
73630  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
73631  * See the License for the specific language governing permissions and
73632  * limitations under the License.
73633  */
73634
73635 var utils = require('ripple/utils'),
73636     errorcode = require('ripple/platform/tizen/2.0/errorcode'),
73637     TZDate = require('ripple/platform/tizen/2.0/TZDate'),
73638     CalendarItem = require('ripple/platform/tizen/2.0/CalendarItem'),
73639     tizen1_utils = require('ripple/platform/tizen/2.0/tizen1_utils'),
73640     WebAPIError = require('ripple/platform/tizen/2.0/WebAPIError'),
73641     SimpleCoordinates = require('ripple/platform/tizen/2.0/SimpleCoordinates'),
73642     CalendarRecurrenceRule = require('ripple/platform/tizen/2.0/CalendarRecurrenceRule');
73643
73644 module.exports = function (eventInitDict) {
73645     var _self, isDetached = false, isInvalid = false;
73646
73647     _self = new CalendarItem("EVENT");
73648
73649     if ((eventInitDict !== undefined) && (eventInitDict !== null)) {
73650         _self.endDate        = tizen1_utils.isValidTZDate(eventInitDict.endDate) ? (new TZDate(new Date(eventInitDict.endDate))) : null;
73651         _self.availability   = (eventInitDict.availability) ? String(eventInitDict.availability) : "BUSY";
73652         _self.recurrenceRule = utils.copy(eventInitDict.recurrenceRule);
73653         if (eventInitDict.description) {
73654             _self.description = String(eventInitDict.description);
73655         }
73656         if (eventInitDict.summary) {
73657             _self.summary = String(eventInitDict.summary);
73658         }
73659         if (eventInitDict.isAllDay && (typeof eventInitDict.isAllDay === "boolean")) {
73660             _self.isAllDay = eventInitDict.isAllDay;
73661         }
73662         if (eventInitDict.startDate && tizen1_utils.isValidTZDate(eventInitDict.startDate)) {
73663             _self.startDate = eventInitDict.startDate;
73664         }
73665         if (eventInitDict.duration && (typeof eventInitDict.duration === "object")) {
73666             _self.duration = eventInitDict.duration;
73667         }
73668         if (eventInitDict.location) {
73669             _self.location = String(eventInitDict.location);
73670         }
73671         if (eventInitDict.geolocation && eventInitDict.geolocation.latitude && eventInitDict.geolocation.longitude) {
73672             _self.geolocation = new SimpleCoordinates(eventInitDict.geolocation.latitude, eventInitDict.geolocation.longitude);
73673         }
73674         if (eventInitDict.organizer) {
73675             _self.organizer = String(eventInitDict.organizer);
73676         }
73677         if (eventInitDict.visibility) {
73678             _self.visibility = String(eventInitDict.visibility);
73679         }
73680         if (eventInitDict.status) {
73681             _self.status = String(eventInitDict.status);
73682         }
73683         if (eventInitDict.priority) {
73684             _self.priority = String(eventInitDict.priority);
73685         }
73686         if (eventInitDict.alarms && tizen1_utils.isValidArray(eventInitDict.alarms)) {
73687             isInvalid = false;
73688             eventInitDict.alarms.some(function (alarm) {
73689                 if (!alarm || alarm.method === undefined) {// 'method' is CalendarAlarm's property.
73690                     isInvalid = true;
73691                     return;
73692                 }
73693             });
73694             if (!isInvalid) {
73695                 _self.alarms = eventInitDict.alarms;
73696             }
73697         }
73698         if (eventInitDict.categories && tizen1_utils.isValidArray(eventInitDict.categories)) {
73699             isInvalid = false;
73700             eventInitDict.categories.some(function (categorie) {
73701                 if (!categorie || typeof categorie !== "string") {
73702                     isInvalid = true;
73703                     return;
73704                 }
73705             });
73706             if (!isInvalid) {
73707                 _self.categories = eventInitDict.categories;
73708             }
73709         }
73710         if (eventInitDict.attendees && tizen1_utils.isValidArray(eventInitDict.attendees)) {
73711             isInvalid = false;
73712             eventInitDict.attendees.some(function (attendee) {
73713                 if (!attendee || attendee.uri === undefined) {// 'uri' is CalendarAttendee's property.
73714                     isInvalid = true;
73715                     return;
73716                 }
73717             });
73718             if (!isInvalid) {
73719                 _self.attendees = eventInitDict.attendees;
73720             }
73721         }
73722     } else {
73723         _self.endDate        = null;
73724         _self.availability   = "BUSY";
73725         _self.recurrenceRule = new CalendarRecurrenceRule();
73726     }
73727
73728     _self.expandRecurrence = function (startDate, endDate, successCallback, errorCallback) {
73729         _self.startDate = startDate;
73730         _self.endDate   = endDate;
73731         if (errorCallback) {
73732             window.setTimeout(function () {
73733                 errorCallback(new WebAPIError(errorcode.NOT_SUPPORTED_ERR));
73734             }, 1);
73735         }
73736     };
73737     _self.__defineGetter__("isDetached", function () {
73738         return isDetached;
73739     });
73740     return _self;
73741 };
73742
73743 });
73744 define('ripple/platform/tizen/2.0/CalendarEventId', function (require, exports, module) {
73745 /*
73746  *  Copyright 2012 Intel Corporation.
73747  *
73748  * Licensed under the Apache License, Version 2.0 (the "License");
73749  * you may not use this file except in compliance with the License.
73750  * You may obtain a copy of the License at
73751  *
73752  * http://www.apache.org/licenses/LICENSE-2.0
73753  *
73754  * Unless required by applicable law or agreed to in writing, software
73755  * distributed under the License is distributed on an "AS IS" BASIS,
73756  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
73757  * See the License for the specific language governing permissions and
73758  * limitations under the License.
73759  */
73760
73761 module.exports = function (uid, rid) {
73762     var _self = {};
73763
73764     _self.uid = (uid) ? String(uid) : "";
73765     _self.rid = (rid) ? String(rid) : "";
73766
73767     return _self;
73768 };
73769
73770 });
73771 define('ripple/platform/tizen/2.0/CalendarItem', function (require, exports, module) {
73772 /*
73773  *  Copyright 2012 Intel Corporation.
73774  *
73775  * Licensed under the Apache License, Version 2.0 (the "License");
73776  * you may not use this file except in compliance with the License.
73777  * You may obtain a copy of the License at
73778  *
73779  * http://www.apache.org/licenses/LICENSE-2.0
73780  *
73781  * Unless required by applicable law or agreed to in writing, software
73782  * distributed under the License is distributed on an "AS IS" BASIS,
73783  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
73784  * See the License for the specific language governing permissions and
73785  * limitations under the License.
73786  */
73787
73788 var utils = require('ripple/utils'),
73789     tizen1_utils = require('ripple/platform/tizen/2.0/tizen1_utils'),
73790     errorcode = require('ripple/platform/tizen/2.0/errorcode'),
73791     WebAPIError = require('ripple/platform/tizen/2.0/WebAPIError'),
73792     WebAPIException = require('ripple/platform/tizen/2.0/WebAPIException'),
73793     TZDate = require('ripple/platform/tizen/2.0/TZDate'),
73794     SimpleCoordinates = require('ripple/platform/tizen/2.0/SimpleCoordinates'),
73795     CalendarItemInit,
73796     CalendarEventInit,
73797     CalendarTaskInit,
73798     CalendarItem;
73799
73800 CalendarItem = function (type, id, lastModificationDate, _security) {
73801     var _self;
73802
73803     function _2digital(number) {
73804         return ((number >= 10) ? '' : '0') + number;
73805     }
73806
73807     if ((type !== "EVENT") && (type !== "TASK"))
73808         throw new WebAPIError(errorcode.NOT_FOUND_ERR);
73809
73810     if (type === "EVENT") {
73811         _self = new CalendarEventInit();
73812         id = {
73813             uid: id || Math.uuid(null, 16),
73814             rid: null
73815         };
73816     } else {
73817         _self = new CalendarTaskInit();
73818         id = id || Math.uuid(null, 16);
73819     }
73820
73821     lastModificationDate = (lastModificationDate) ? utils.copy(lastModificationDate) : null;
73822     _self.status = (type === "EVENT") ? "CONFIRMED" : "NEEDS_ACTION";
73823
73824     _self.__defineGetter__("calendarId", function () {
73825         return null;
73826     });
73827
73828     _self.__defineGetter__("id", function () {
73829         return id;
73830     });
73831
73832     _self.__defineGetter__("lastModificationDate", function () {
73833         return lastModificationDate;
73834     });
73835
73836     _self.clone = function () {
73837         var item = new CalendarItem(type);
73838
73839         if (_security instanceof Object && !_security.clone) {
73840             throw new WebAPIException(errorcode.SECURITY_ERR);
73841         }
73842
73843         item.id                   = Math.uuid(null, 16);
73844         item.calendarId           = _self.calendarId;
73845         item.lastModificationDate = new TZDate();
73846         item.description          = _self.description;
73847         item.summary              = _self.summary;
73848         item.isAllDay             = _self.isAllDay;
73849         item.startDate            = _self.startDate;
73850         item.duration             = _self.duration;
73851         item.location             = _self.location;
73852         item.geolocation          = _self.geolocation;
73853         item.organizer            = _self.organizer;
73854         item.visibility           = _self.visibility;
73855         item.status               = _self.status;
73856         item.priority             = _self.priority;
73857         item.alarms               = _self.alarms;
73858         item.categories           = _self.categories;
73859         item.attendees            = _self.attendees;
73860
73861         if (type === "EVENT") {
73862             item.endDate          = _self.endDate;
73863             item.availability     = _self.availability;
73864             item.recurrenceRule   = _self.recurrenceRule;
73865         } else {
73866             item.dueDate          = _self.dueDate;
73867             item.completedDate    = _self.completedDate;
73868             item.progress         = _self.progress;
73869         }
73870
73871         return item;
73872     };
73873
73874     _self.convertToString = function (format) {
73875         var str = "", pri, i, date, before, y, m, d, hh, mm, ss, dateStart = "", dateEnd = "",
73876             header = "BEGIN:VCALENDAR\r\nPRODID:-//Tizen.org//Tizen Calendar//EN\r\nVERSION:2.0\r\n",
73877             end = "END:VCALENDAR\r\n";
73878
73879         if (_security instanceof Object && !_security.convertToString) {
73880             throw new WebAPIException(errorcode.SECURITY_ERR);
73881         }
73882         if (format !== "ICALENDAR_20" && format !== "VCALENDAR_10") {
73883             throw new WebAPIError(errorcode.TYPE_MISMATCH_ERROR);
73884         }
73885
73886         //TODO: vcalendar 1.0 doesn't support yet
73887         if (format === "VCALENDAR_10") {
73888             return;
73889         }
73890
73891         str = header;
73892         if (type === "EVENT") {
73893             str += "BEGIN:VEVENT\r\n";
73894         } else if (type === "TASK") {
73895             str += "BEGIN:VTODO\r\n";
73896         }
73897
73898         if (this.isAllDay) {
73899             if (this.startDate) {
73900                 date = this.startDate;
73901                 y = date.getFullYear();
73902                 m = _2digital(date.getMonth() + 1);
73903                 d = _2digital(date.getDate());
73904                 str += "DTSTART;VALUE=DATE:" + y + m + d + "\r\n";
73905                 dateStart = "" + y + m + d + "T000000Z";
73906                 if (this.duration) {
73907                     date = date.addDuration(this.duration);
73908                     y = date.getFullYear();
73909                     m = _2digital(date.getMonth() + 1);
73910                     d = _2digital(date.getDate());
73911                     str += "DTEND;VALUE=DATE:" + y + m + d + "\r\n";
73912                     dateEnd = "" + y + m + d + "T000000Z";
73913                 }
73914             }
73915         } else {
73916             if (this.startDate) {
73917                 date = this.startDate;
73918                 y = date.getFullYear();
73919                 m = _2digital(date.getMonth() + 1);
73920                 d = _2digital(date.getDate());
73921                 hh = _2digital(date.getHours());
73922                 mm = _2digital(date.getMinutes());
73923                 ss = _2digital(date.getSeconds());
73924                 str += "DTSTART:" + y + m + d + "T" + hh + mm + ss + "Z" + "\r\n";
73925                 dateStart = "" + y + m + d + "T" + hh + mm + ss + "Z";
73926                 if (this.duration && this.duration.length && this.duration.unit) {
73927                     date = date.addDuration(this.duration);
73928                     y = date.getFullYear();
73929                     m = _2digital(date.getMonth() + 1);
73930                     d = _2digital(date.getDate());
73931                     hh = _2digital(date.getHours());
73932                     mm = _2digital(date.getMinutes());
73933                     ss = _2digital(date.getSeconds());
73934                     str += "DTEND:" + y + m + d + "T" + hh + mm + ss + "Z" + "\r\n";
73935                     dateEnd = "" + y + m + d + "T" + hh + mm + ss + "Z";
73936                 }
73937             }
73938         }
73939
73940         if (this.description) {
73941             str += "DESCRIPTION:" + this.description + "\r\n";
73942         }
73943         if (this.summary) {
73944             str += "SUMMARY:" + this.summary + "\r\n";
73945         }
73946         if (this.location) {
73947             str += "LOCATION:" + this.location + "\r\n";
73948         }
73949         if (this.geolocation) {
73950             // Don't need to check latitude and longitude due to they are mandatory attributes
73951             str += "GEO:" + this.geolocation.latitude + "," + this.geolocation.longitude + "\r\n";
73952         }
73953         if (this.organizer) {
73954             str += "ORGANIZER:" + this.organizer + "\r\n";
73955         }
73956         if (this.visibility) {
73957             str += "CLASS:" + this.visibility + "\r\n";
73958         }
73959         if (this.status) {
73960             str += "STATUS:" + this.status + "\r\n";
73961         }
73962         if (this.priority) {
73963             switch (this.priority) {
73964             case "HIGH":
73965                 pri = 2;
73966                 break;
73967             case "MEDIUM":
73968                 pri = 5;
73969                 break;
73970             case "LOW":
73971                 pri = 7;
73972                 break;
73973             }
73974             str += "PRIORITY:" + pri + "\r\n";
73975         }
73976         if (tizen1_utils.isValidArray(this.alarms)) {
73977             for (i = 0; i < this.alarms.length; i++) {
73978                 str += "BEGIN:VALARM\r\n";
73979                 // Don't need to check this.alarms[i].method due to it is a mandatory attribute
73980                 str += "ACTION:" + this.alarms[i].method + "\r\n";
73981                 if (this.alarms[i].description) {
73982                     str += "DESCRIPTION:" + this.alarms[i].description + "\r\n";
73983                 } else {
73984                     // description property MUST included if action is DISPLAY (RFC5545 3.6.6)
73985                     str += "DESCRIPTION:This is a reminder\r\n";
73986                 }
73987                 if (this.alarms[i].absoluteDate) {
73988                     date = this.alarms[i].absoluteDate;
73989                     y = date.getFullYear();
73990                     m = _2digital(date.getMonth() + 1);
73991                     d = _2digital(date.getDate());
73992                     hh = _2digital(date.getHours());
73993                     mm = _2digital(date.getMinutes());
73994                     ss = _2digital(date.getSeconds());
73995                     str += "TRIGGER;VALUE=DATE-TIME:" + y + m + d + "T" + hh + mm + ss + "Z" + "\r\n";
73996                 } else {
73997                     //it must be included before attribute
73998                     before = this.alarms[i].before;
73999                     switch (before.unit) {
74000                     case "DAYS":
74001                         str += "TRIGGER:-P" + before.length + "D" + "\r\n";
74002                         break;
74003                     case "HOURS":
74004                         str += "TRIGGER:-P0DT" + before.length + "H0M0S" + "\r\n";
74005                         break;
74006                     case "MINS":
74007                         str += "TRIGGER:-P0DT0H" + before.length + "M0S" + "\r\n";
74008                         break;
74009                     case "SECS":
74010                         str += "TRIGGER:-P0DT0H0M" + before.length + "S" + "\r\n";
74011                         break;
74012                     }
74013                 }
74014                 str += "END:VALARM\r\n";
74015             }
74016         }
74017         if (tizen1_utils.isValidArray(this.categories)) {
74018             str += "CATEGORIES:";
74019             for (i = 0; i < this.categories.length; i++) {
74020                 str += this.categories[i] + ",";
74021             }
74022             str = str.slice(0, -1);
74023             str += "\r\n";
74024         }
74025         if (tizen1_utils.isValidArray(this.attendees)) {
74026             for (i = 0; i < this.attendees.length; i++) {
74027                 //TODO: basic implementation
74028                 str += "ATTENDEE:mailto:" + this.attendees[i].uri + "\r\n";
74029             }
74030         }
74031
74032         if (type === "EVENT" && this.availability && dateStart !== "" && dateEnd !== "") {
74033             switch (this.availability) {
74034             case "BUSY":
74035                 str += "FREEBUSY;FBTYPE=BUSY:";
74036                 break;
74037             case "FREE":
74038                 str += "FREEBUSY;FBTYPE=FREE:";
74039                 break;
74040             }
74041             str += dateStart + "/" + dateEnd + "\r\n";
74042         }
74043         //TODO: endDate doesn't support (CalendarEvent specific property)
74044         //TODO: recurrenceRule doesn't support (CalendarEvent specific property)
74045         //TODO: dueDate doesn't support (CalendarTask specific property)
74046         //TODO: completeDate doesn't support (CalendarTask specific property)
74047         if (type === "TASK" && this.progress) {
74048             str += "PERCENT-COMPLETE:" + this.progress + "\r\n";
74049         }
74050
74051         if (type === "EVENT") {
74052             str += "END:VEVENT\r\n";
74053         } else if (type === "TASK") {
74054             str += "END:VTODO\r\n";
74055         }
74056         str += end;
74057
74058         return str;
74059     };
74060
74061     return _self;
74062 };
74063
74064 CalendarItemInit = function () {
74065     return {
74066         description: "",
74067         summary:     "",
74068         isAllDay:    false,
74069         startDate:   null,
74070         duration:    null,
74071         location:    "",
74072         geolocation: new SimpleCoordinates(),
74073         organizer:   "",
74074         visibility:  "PUBLIC",
74075         status:      "",
74076         priority:    "LOW",
74077         alarms:      [],
74078         categories:  [],
74079         attendees:   []
74080     };
74081 };
74082
74083 CalendarEventInit = function () {
74084     var _self = new CalendarItemInit();
74085
74086     _self.endDate        = undefined;
74087     _self.availability   = undefined;
74088     _self.recurrenceRule = undefined;
74089
74090     return _self;
74091 };
74092
74093 CalendarTaskInit = function () {
74094     var _self = new CalendarItemInit();
74095
74096     _self.dueDate       = undefined;
74097     _self.completedDate = undefined;
74098     _self.progress      = undefined;
74099
74100     return _self;
74101 };
74102
74103 module.exports = CalendarItem;
74104
74105 });
74106 define('ripple/platform/tizen/2.0/CalendarRecurrenceRule', function (require, exports, module) {
74107 /*
74108  *  Copyright 2012 Intel Corporation.
74109  *
74110  * Licensed under the Apache License, Version 2.0 (the "License");
74111  * you may not use this file except in compliance with the License.
74112  * You may obtain a copy of the License at
74113  *
74114  * http://www.apache.org/licenses/LICENSE-2.0
74115  *
74116  * Unless required by applicable law or agreed to in writing, software
74117  * distributed under the License is distributed on an "AS IS" BASIS,
74118  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
74119  * See the License for the specific language governing permissions and
74120  * limitations under the License.
74121  */
74122
74123 var utils = require('ripple/utils'),
74124     tizen1_utils = require('ripple/platform/tizen/2.0/tizen1_utils'),
74125     TZDate = require('ripple/platform/tizen/2.0/TZDate');
74126
74127 module.exports = function (frequency, ruleInitDict) {
74128     var _self = {};
74129
74130     _self.frequency = (frequency) ? frequency : 0;
74131
74132     if ((ruleInitDict !== undefined) && (ruleInitDict !== null)) {
74133         _self.interval        = ((ruleInitDict.interval > 0) && (ruleInitDict.interval === parseInt(ruleInitDict.interval, 10))) ? Number(ruleInitDict.interval) : 1;
74134         _self.untilDate       = tizen1_utils.isValidTZDate(ruleInitDict.untilDate) ? (new TZDate(new Date(ruleInitDict.untilDate))) : null;
74135         _self.occurrenceCount = (ruleInitDict.occurrenceCount === parseInt(ruleInitDict.occurrenceCount, 10)) ? Number(ruleInitDict.occurrenceCount) : -1;
74136         _self.daysOfTheWeek   = tizen1_utils.isValidArray(ruleInitDict.daysOfTheWeek) ? utils.copy(ruleInitDict.daysOfTheWeek) : [];
74137         _self.setPositions    = tizen1_utils.isValidArray(ruleInitDict.setPositions) ? utils.copy(ruleInitDict.setPositions) : [];
74138         _self.exceptions      = tizen1_utils.isValidArray(ruleInitDict.exceptions) ? utils.copy(ruleInitDict.exceptions) : [];
74139     } else {
74140         _self.interval        = 1;
74141         _self.untilDate       = null;
74142         _self.occurrenceCount = -1;
74143         _self.daysOfTheWeek   = [];
74144         _self.setPositions    = [];
74145         _self.exceptions      = [];
74146     }
74147
74148     return _self;
74149 };
74150
74151 });
74152 define('ripple/platform/tizen/2.0/CalendarTask', function (require, exports, module) {
74153 /*
74154  *  Copyright 2012 Intel Corporation.
74155  *
74156  * Licensed under the Apache License, Version 2.0 (the "License");
74157  * you may not use this file except in compliance with the License.
74158  * You may obtain a copy of the License at
74159  *
74160  * http://www.apache.org/licenses/LICENSE-2.0
74161  *
74162  * Unless required by applicable law or agreed to in writing, software
74163  * distributed under the License is distributed on an "AS IS" BASIS,
74164  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
74165  * See the License for the specific language governing permissions and
74166  * limitations under the License.
74167  */
74168
74169 var TZDate = require('ripple/platform/tizen/2.0/TZDate'),
74170     CalendarItem = require('ripple/platform/tizen/2.0/CalendarItem'),
74171     tizen1_utils = require('ripple/platform/tizen/2.0/tizen1_utils'),
74172     SimpleCoordinates = require('ripple/platform/tizen/2.0/SimpleCoordinates');
74173
74174 module.exports = function (taskInitDict) {
74175     var _self, isInvalid = false;
74176
74177     _self = new CalendarItem("TASK");
74178
74179     if ((taskInitDict !== undefined) && (taskInitDict !== null)) {
74180         _self.dueDate       = tizen1_utils.isValidTZDate(taskInitDict.dueDate) ? (new TZDate(new Date(taskInitDict.dueDate))) : undefined;
74181         _self.completedDate = tizen1_utils.isValidTZDate(taskInitDict.completedDate) ? (new TZDate(new Date(taskInitDict.completedDate))) : undefined;
74182         _self.progress      = ((0 <= taskInitDict.progress) && (taskInitDict.progress <= 100)) ? Number(taskInitDict.progress) : 0;
74183
74184         if (taskInitDict.description) {
74185             _self.description = String(taskInitDict.description);
74186         }
74187         if (taskInitDict.summary) {
74188             _self.summary = String(taskInitDict.summary);
74189         }
74190         if (taskInitDict.isAllDay && (typeof taskInitDict.isAllDay === "boolean")) {
74191             _self.isAllDay = taskInitDict.isAllDay;
74192         }
74193         if (taskInitDict.startDate && tizen1_utils.isValidTZDate(taskInitDict.startDate)) {
74194             _self.startDate = taskInitDict.startDate;
74195         }
74196         if (taskInitDict.duration instanceof tizen.TimeDuration) {
74197             _self.duration = taskInitDict.duration;
74198         }
74199         if (taskInitDict.location) {
74200             _self.location = String(taskInitDict.location);
74201         }
74202         if (taskInitDict.geolocation && taskInitDict.geolocation.latitude && taskInitDict.geolocation.longitude) {
74203             _self.geolocation = new SimpleCoordinates(taskInitDict.geolocation.latitude, taskInitDict.geolocation.longitude);
74204         }
74205         if (taskInitDict.organizer) {
74206             _self.organizer = String(taskInitDict.organizer);
74207         }
74208         if (taskInitDict.visibility) {
74209             _self.visibility = String(taskInitDict.visibility);
74210         }
74211         if (taskInitDict.status) {
74212             _self.status = String(taskInitDict.status);
74213         }
74214         if (taskInitDict.priority) {
74215             _self.priority = String(taskInitDict.priority);
74216         }
74217         if (taskInitDict.alarms && tizen1_utils.isValidArray(taskInitDict.alarms)) {
74218             isInvalid = false;
74219             taskInitDict.alarms.some(function (alarm) {
74220                 if (!alarm || alarm.method === undefined) {// 'method' is CalendarAlarm's property.
74221                     isInvalid = true;
74222                     return;
74223                 }
74224             });
74225             if (!isInvalid) {
74226                 _self.alarms = taskInitDict.alarms;
74227             }
74228         }
74229         if (taskInitDict.categories && tizen1_utils.isValidArray(taskInitDict.categories)) {
74230             isInvalid = false;
74231             taskInitDict.categories.every(function (categorie) {
74232                 if (!categorie || typeof categorie !== "string") {
74233                     isInvalid = true;
74234                     return;
74235                 }
74236             });
74237             if (!isInvalid) {
74238                 _self.categories = taskInitDict.categories;
74239             }
74240         }
74241         if (taskInitDict.attendees && tizen1_utils.isValidArray(taskInitDict.attendees)) {
74242             isInvalid = false;
74243             taskInitDict.attendees.some(function (attendee) {
74244                 if (!attendee || attendee.uri === undefined) {// 'uri' is CalendarAttendee's property.
74245                     isInvalid = true;
74246                     return;
74247                 }
74248             });
74249             if (!isInvalid) {
74250                 _self.attendees = taskInitDict.attendees;
74251             }
74252         }
74253     } else {
74254         _self.dueDate       = undefined;
74255         _self.completedDate = undefined;
74256         _self.progress      = 0;
74257     }
74258
74259     return _self;
74260 };
74261
74262 });
74263 define('ripple/platform/tizen/2.0/CompositeFilter', function (require, exports, module) {
74264 /*      
74265  *  Copyright 2012 Intel Corporation.
74266  *  
74267  * Licensed under the Apache License, Version 2.0 (the "License");
74268  * you may not use this file except in compliance with the License.
74269  * You may obtain a copy of the License at
74270  *  
74271  * http://www.apache.org/licenses/LICENSE-2.0
74272  *  
74273  * Unless required by applicable law or agreed to in writing, software
74274  * distributed under the License is distributed on an "AS IS" BASIS,
74275  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
74276  * See the License for the specific language governing permissions and
74277  * limitations under the License.
74278  */
74279
74280 module.exports = function (_type, _filters) {
74281     return {
74282         type: _type,
74283         filters: _filters
74284     };
74285 };
74286
74287
74288 });
74289 define('ripple/platform/tizen/2.0/ContactAccount', function (require, exports, module) {
74290 /*      
74291  *  Copyright 2012 Intel Corporation.
74292  *  
74293  * Licensed under the Apache License, Version 2.0 (the "License");
74294  * you may not use this file except in compliance with the License.
74295  * You may obtain a copy of the License at
74296  *  
74297  * http://www.apache.org/licenses/LICENSE-2.0
74298  *  
74299  * Unless required by applicable law or agreed to in writing, software
74300  * distributed under the License is distributed on an "AS IS" BASIS,
74301  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
74302  * See the License for the specific language governing permissions and
74303  * limitations under the License.
74304  */
74305
74306 module.exports = function (id, accountURI) {
74307     var _self, _id, _uri;
74308
74309     if (id) {
74310         _id = String(id);
74311     }
74312
74313     if (accountURI) {
74314         _uri = String(accountURI);
74315     }
74316
74317     _self = {
74318         accountServiceId : _id,
74319         contactURI : _uri
74320     };
74321
74322     return _self;
74323 };
74324
74325 });
74326 define('ripple/platform/tizen/2.0/ContactAddress', function (require, exports, module) {
74327 /*
74328  *  Copyright 2012 Intel Corporation.
74329  *
74330  * Licensed under the Apache License, Version 2.0 (the "License");
74331  * you may not use this file except in compliance with the License.
74332  * You may obtain a copy of the License at
74333  *
74334  * http://www.apache.org/licenses/LICENSE-2.0
74335  *
74336  * Unless required by applicable law or agreed to in writing, software
74337  * distributed under the License is distributed on an "AS IS" BASIS,
74338  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
74339  * See the License for the specific language governing permissions and
74340  * limitations under the License.
74341  */
74342
74343 var tizen1_utils = require('ripple/platform/tizen/2.0/tizen1_utils');
74344
74345 module.exports = function (addressInitDict) {
74346     var _self, type, i;
74347  
74348     _self = {
74349         country:               undefined,
74350         region:                undefined,
74351         city:                  undefined,
74352         streetAddress:         undefined,
74353         additionalInformation: undefined,
74354         postalCode:            undefined,
74355         isDefault:             false,
74356         types:                 undefined
74357     };
74358
74359     if (addressInitDict) {
74360         if (addressInitDict.country !== null && addressInitDict.country !== undefined) {
74361             _self.country = String(addressInitDict.country);
74362         }
74363         if (addressInitDict.region !== null && addressInitDict.region !== undefined) {
74364             _self.region = String(addressInitDict.region);
74365         }
74366         if (addressInitDict.city !== null && addressInitDict.city !== undefined) {
74367             _self.city = String(addressInitDict.city);
74368         }
74369         if (addressInitDict.streetAddress !== null && addressInitDict.streetAddress !== undefined) {
74370             _self.streetAddress = String(addressInitDict.streetAddress);
74371         }
74372         if (addressInitDict.additionalInformation !== null && addressInitDict.additionalInformation !== undefined) {
74373             _self.additionalInformation = String(addressInitDict.additionalInformation);
74374         }
74375         if (addressInitDict.postalCode !== null && addressInitDict.postalCode !== undefined) {
74376             _self.postalCode = String(addressInitDict.postalCode);
74377         }
74378         if (typeof addressInitDict.isDefault === "boolean") {
74379             _self.isDefault = addressInitDict.isDefault;
74380         }
74381         if (tizen1_utils.isValidArray(addressInitDict.types)) {
74382             _self.types = [];
74383
74384             for (i in addressInitDict.types) {
74385                 type = String(addressInitDict.types[i]).toUpperCase();
74386                 _self.types.push(type);
74387             }
74388         }
74389     }
74390
74391     return _self;
74392 };
74393
74394 });
74395 define('ripple/platform/tizen/2.0/ContactAnniversary', function (require, exports, module) {
74396 /*
74397  *  Copyright 2012 Intel Corporation.
74398  *
74399  * Licensed under the Apache License, Version 2.0 (the "License");
74400  * you may not use this file except in compliance with the License.
74401  * You may obtain a copy of the License at
74402  *
74403  * http://www.apache.org/licenses/LICENSE-2.0
74404  *
74405  * Unless required by applicable law or agreed to in writing, software
74406  * distributed under the License is distributed on an "AS IS" BASIS,
74407  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
74408  * See the License for the specific language governing permissions and
74409  * limitations under the License.
74410  */
74411
74412 var tizen1_utils = require('ripple/platform/tizen/2.0/tizen1_utils');
74413
74414 module.exports = function (date, label) {
74415     var _self;
74416
74417     _self = {
74418         date:  null,
74419         label: null
74420     };
74421
74422     _self.date = tizen1_utils.isValidDate(date) ? new Date(date) : new Date();
74423
74424     if (label) {
74425         _self.label = String(label);
74426     }
74427
74428     return _self;
74429 };
74430
74431 });
74432 define('ripple/platform/tizen/2.0/ContactBase', function (require, exports, module) {
74433 /*
74434  *  Copyright 2012 Intel Corporation.
74435  *
74436  * Licensed under the Apache License, Version 2.0 (the "License");
74437  * you may not use this file except in compliance with the License.
74438  * You may obtain a copy of the License at
74439  *
74440  * http://www.apache.org/licenses/LICENSE-2.0
74441  *
74442  * Unless required by applicable law or agreed to in writing, software
74443  * distributed under the License is distributed on an "AS IS" BASIS,
74444  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
74445  * See the License for the specific language governing permissions and
74446  * limitations under the License.
74447  */
74448
74449 var utils = require('ripple/utils'),
74450     errorcode = require('ripple/platform/tizen/2.0/errorcode'),
74451     WebAPIException = require('ripple/platform/tizen/2.0/WebAPIException'),
74452     tizen1_utils = require('ripple/platform/tizen/2.0/tizen1_utils'),
74453     ContactName = require('ripple/platform/tizen/2.0/ContactName'),
74454     ContactOrganization = require('ripple/platform/tizen/2.0/ContactOrganization'),
74455     ContactWebSite = require('ripple/platform/tizen/2.0/ContactWebSite'),
74456     ContactAnniversary = require('ripple/platform/tizen/2.0/ContactAnniversary'),
74457     ContactAddress = require('ripple/platform/tizen/2.0/ContactAddress'),
74458     ContactPhoneNumber = require('ripple/platform/tizen/2.0/ContactPhoneNumber'),
74459     ContactEmailAddress = require('ripple/platform/tizen/2.0/ContactEmailAddress');
74460
74461 function Contact(prop, _security) {
74462     var _self = this;
74463
74464     // constructor
74465     function init_ContactInitDict(contactInitDict) {
74466         var i;
74467
74468         if (contactInitDict.name) {
74469             _self.name = new ContactName(contactInitDict.name);
74470         }
74471         if (tizen1_utils.isValidArray(contactInitDict.addresses)) {
74472             for (i in contactInitDict.addresses) {
74473                 _self.addresses.push(new ContactAddress(contactInitDict.addresses[i]));
74474             }
74475         }
74476         if (contactInitDict.photoURI) {
74477             _self.photoURI = String(contactInitDict.photoURI);
74478         }
74479         if (tizen1_utils.isValidArray(contactInitDict.phoneNumbers)) {
74480             _self.phoneNumbers = [];
74481             for (i in contactInitDict.phoneNumbers) {
74482                 _self.phoneNumbers.push(new ContactPhoneNumber(
74483                             contactInitDict.phoneNumbers[i].number, contactInitDict.phoneNumbers[i].types));
74484             }
74485         }
74486         if (tizen1_utils.isValidArray(contactInitDict.emails)) {
74487             _self.emails = [];
74488             for (i in contactInitDict.emails) {
74489                 _self.emails.push(new ContactEmailAddress(
74490                             contactInitDict.emails[i].email, contactInitDict.emails[i].types));
74491             }
74492         }
74493         if (tizen1_utils.isValidDate(contactInitDict.birthday)) {
74494             _self.birthday = new Date(contactInitDict.birthday);
74495         }
74496         if (tizen1_utils.isValidArray(contactInitDict.anniversaries)) {
74497             _self.anniversaries = [];
74498             for (i in contactInitDict.anniversaries) {
74499                 _self.anniversaries.push(new ContactAnniversary(
74500                             contactInitDict.anniversaries[i].date, contactInitDict.anniversaries[i].label));
74501             }
74502         }
74503         if (tizen1_utils.isValidArray(contactInitDict.organizations)) {
74504             for (i in contactInitDict.organizations) {
74505                 _self.organizations.push(new ContactOrganization(
74506                             contactInitDict.organizations[i]));
74507             }
74508         }
74509         if (tizen1_utils.isValidArray(contactInitDict.notes)) {
74510             for (i in contactInitDict.notes) {
74511                 _self.notes.push(String(contactInitDict.notes[i]));
74512             }
74513         }
74514         if (tizen1_utils.isValidArray(contactInitDict.urls)) {
74515             for (i in contactInitDict.urls) {
74516                 _self.urls.push(new ContactWebSite(
74517                             contactInitDict.urls[i].url, contactInitDict.urls[i].type));
74518             }
74519         }
74520         if (contactInitDict.ringtoneURI) {
74521             _self.ringtoneURI = String(contactInitDict.ringtoneURI);
74522         }
74523         if (tizen1_utils.isValidArray(contactInitDict.groupIds)) {
74524             for (i in contactInitDict.groupIds) {
74525                 _self.groupIds.push(String(contactInitDict.groupIds[i]));
74526             }
74527         }
74528     }
74529
74530     function init_stringRepresentation(stringRepresentation) {
74531         //TODO: parse stringRepresentation
74532     }
74533
74534     // public
74535     function convertToString(format) {
74536         //TODO: convert content accord to Vcard protocal
74537         if (format !== 'VCARD_30') {
74538             throw new WebAPIException(errorcode.TYPE_MISMATCH_ERR);
74539         }
74540         return "";
74541     }
74542
74543     function clone(obj) {
74544         var copy = new Contact(), attr,
74545             ignoreProp = ["id", "personId", "addressBookId", "lastUpdated", "isFavorite"];
74546
74547         if (_security instanceof Object && !_security.clone) {
74548             throw new WebAPIException(errorcode.SECURITY_ERR);
74549         }
74550         for (attr in obj) {
74551             if ((ignoreProp.indexOf(attr) === -1) &&
74552                     obj.hasOwnProperty(attr) &&
74553                     (typeof obj[attr] !== "function")) {
74554                 copy[attr] = utils.copy(obj[attr]);
74555             }
74556         }
74557
74558         return copy;
74559     }
74560
74561     _self.name = null;
74562     _self.addresses = [];
74563     _self.photoURI = null;
74564     _self.phoneNumbers = [];
74565     _self.emails = [];
74566     _self.birthday = null;
74567     _self.anniversaries = [];
74568     _self.organizations = [];
74569     _self.notes = [];
74570     _self.urls = [];
74571     _self.ringtoneURI = null;
74572     _self.groupIds = [];
74573     _self.convertToString = convertToString;
74574     _self.clone = function () {
74575         return clone(_self);
74576     };
74577
74578     _self.__defineGetter__("id", function () {
74579         return null;
74580     });
74581
74582     _self.__defineGetter__("personId", function () {
74583         return null;
74584     });
74585
74586     _self.__defineGetter__("addressBookId", function () {
74587         return null;
74588     });
74589
74590     _self.__defineGetter__("lastUpdated", function () {
74591         return null;
74592     });
74593
74594     _self.__defineGetter__("isFavorite", function () {
74595         return false;
74596     });
74597
74598     if (typeof prop === "string") {
74599         init_stringRepresentation(String(prop));
74600     } else if (prop) {
74601         init_ContactInitDict(prop);
74602     }
74603
74604     return _self;
74605 }
74606
74607 module.exports = Contact;
74608
74609 });
74610 define('ripple/platform/tizen/2.0/ContactEmailAddress', function (require, exports, module) {
74611 /*
74612  *  Copyright 2012 Intel Corporation.
74613  *
74614  * Licensed under the Apache License, Version 2.0 (the "License");
74615  * you may not use this file except in compliance with the License.
74616  * You may obtain a copy of the License at
74617  *
74618  * http://www.apache.org/licenses/LICENSE-2.0
74619  *
74620  * Unless required by applicable law or agreed to in writing, software
74621  * distributed under the License is distributed on an "AS IS" BASIS,
74622  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
74623  * See the License for the specific language governing permissions and
74624  * limitations under the License.
74625  */
74626
74627 var tizen1_utils = require('ripple/platform/tizen/2.0/tizen1_utils');
74628
74629 module.exports = function (email, types, isDefault) {
74630     var _self, i, type;
74631
74632     _self = {
74633         email:     undefined,
74634         isDefault: false,
74635         types:     undefined
74636     };
74637
74638     _self.email = email ? String(email) : "";
74639
74640     if (tizen1_utils.isValidArray(types)) {
74641         _self.types = [];
74642
74643         for (i in types) {
74644             type = String(types[i]).toUpperCase();
74645             _self.types.push(type);
74646         }
74647     }
74648
74649     if (typeof isDefault === "boolean") {
74650         _self.isDefault = isDefault;
74651     }
74652
74653     return _self;
74654 };
74655
74656 });
74657 define('ripple/platform/tizen/2.0/ContactGroup', function (require, exports, module) {
74658 /*
74659  *  Copyright 2012 Intel Corporation.
74660  *
74661  * Licensed under the Apache License, Version 2.0 (the "License");
74662  * you may not use this file except in compliance with the License.
74663  * You may obtain a copy of the License at
74664  *
74665  * http://www.apache.org/licenses/LICENSE-2.0
74666  *
74667  * Unless required by applicable law or agreed to in writing, software
74668  * distributed under the License is distributed on an "AS IS" BASIS,
74669  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
74670  * See the License for the specific language governing permissions and
74671  * limitations under the License.
74672  */
74673
74674 module.exports = function (name, ringtoneURI, photoURI) {
74675     var _self = {};
74676
74677     _self.__defineGetter__("id", function () {
74678         return null;
74679     });
74680
74681     _self.__defineGetter__("addressBookId", function () {
74682         return null;
74683     });
74684
74685     _self.__defineGetter__("readOnly", function () {
74686         return false;
74687     });
74688
74689     _self.name          = name ? String(name) : "";
74690     _self.ringtoneURI   = ringtoneURI ? String(ringtoneURI) : null;
74691     _self.photoURI      = photoURI ? String(photoURI) : null;
74692
74693     return _self;
74694 };
74695
74696 });
74697 define('ripple/platform/tizen/2.0/ContactName', function (require, exports, module) {
74698 /*
74699  *  Copyright 2012 Intel Corporation.
74700  *
74701  * Licensed under the Apache License, Version 2.0 (the "License");
74702  * you may not use this file except in compliance with the License.
74703  * You may obtain a copy of the License at
74704  *
74705  * http://www.apache.org/licenses/LICENSE-2.0
74706  *
74707  * Unless required by applicable law or agreed to in writing, software
74708  * distributed under the License is distributed on an "AS IS" BASIS,
74709  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
74710  * See the License for the specific language governing permissions and
74711  * limitations under the License.
74712  */
74713
74714 var tizen1_utils = require('ripple/platform/tizen/2.0/tizen1_utils');
74715
74716 module.exports = function (nameInitDict) {
74717     var self, i;
74718
74719     self = {
74720         prefix:            null,
74721         suffix:            null,
74722         firstName:         null,
74723         middleName:        null,
74724         lastName:          null,
74725         nicknames:         [],
74726         phoneticFirstName: null,
74727         phoneticLastName:  null
74728     };
74729
74730     if (nameInitDict) {
74731         if (nameInitDict.prefix !== null && nameInitDict.prefix !== undefined) {
74732             self.prefix = String(nameInitDict.prefix);
74733         }
74734         if (nameInitDict.suffix !== null && nameInitDict.suffix !== undefined) {
74735             self.suffix = String(nameInitDict.suffix);
74736         }
74737         if (nameInitDict.firstName !== null && nameInitDict.firstName !== undefined) {
74738             self.firstName = String(nameInitDict.firstName);
74739         }
74740         if (nameInitDict.middleName !== null && nameInitDict.middleName !== undefined) {
74741             self.middleName = String(nameInitDict.middleName);
74742         }
74743         if (nameInitDict.lastName !== null && nameInitDict.lastName !== undefined) {
74744             self.lastName = String(nameInitDict.lastName);
74745         }
74746         if (tizen1_utils.isValidArray(nameInitDict.nicknames)) {
74747             for (i in nameInitDict.nicknames) {
74748                 self.nicknames.push(String(nameInitDict.nicknames[i]));
74749             }
74750         }
74751         if (nameInitDict.phoneticFirstName !== null && nameInitDict.phoneticFirstName !== undefined) {
74752             self.phoneticFirstName = String(nameInitDict.phoneticFirstName);
74753         }
74754         if (nameInitDict.phoneticLastName !== null && nameInitDict.phoneticLastName !== undefined) {
74755             self.phoneticLastName = String(nameInitDict.phoneticLastName);
74756         }
74757     }
74758
74759     self.__defineGetter__("displayName", function () {
74760         return null;
74761     });
74762
74763     return self;
74764 };
74765
74766 });
74767 define('ripple/platform/tizen/2.0/ContactOrganization', function (require, exports, module) {
74768 /*
74769  *  Copyright 2012 Intel Corporation.
74770  *
74771  * Licensed under the Apache License, Version 2.0 (the "License");
74772  * you may not use this file except in compliance with the License.
74773  * You may obtain a copy of the License at
74774  *
74775  * http://www.apache.org/licenses/LICENSE-2.0
74776  *
74777  * Unless required by applicable law or agreed to in writing, software
74778  * distributed under the License is distributed on an "AS IS" BASIS,
74779  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
74780  * See the License for the specific language governing permissions and
74781  * limitations under the License.
74782  */
74783
74784 module.exports = function (orgInitDict) {
74785     var _self;
74786
74787     _self = {
74788         name:       null,
74789         department: null,
74790         title:      null,
74791         role:       null,
74792         logoURI:    null
74793     };
74794
74795     if (orgInitDict) {
74796         if (orgInitDict.name !== null && orgInitDict.name !== undefined) {
74797             _self.name = String(orgInitDict.name);
74798         }
74799         if (orgInitDict.department !== null && orgInitDict.department !== undefined) {
74800             _self.department = String(orgInitDict.department);
74801         }
74802         if (orgInitDict.title !== null && orgInitDict.title !== undefined) {
74803             _self.title = String(orgInitDict.title);
74804         }
74805         if (orgInitDict.role !== null && orgInitDict.role !== undefined) {
74806             _self.role = String(orgInitDict.role);
74807         }
74808         if (orgInitDict.logoURI !== null && orgInitDict.logoURI !== undefined) {
74809             _self.logoURI = String(orgInitDict.logoURI);
74810         }
74811     }
74812
74813     return _self;
74814 };
74815
74816 });
74817 define('ripple/platform/tizen/2.0/ContactPhoneNumber', function (require, exports, module) {
74818 /*
74819  *  Copyright 2012 Intel Corporation.
74820  *
74821  * Licensed under the Apache License, Version 2.0 (the "License");
74822  * you may not use this file except in compliance with the License.
74823  * You may obtain a copy of the License at
74824  *
74825  * http://www.apache.org/licenses/LICENSE-2.0
74826  *
74827  * Unless required by applicable law or agreed to in writing, software
74828  * distributed under the License is distributed on an "AS IS" BASIS,
74829  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
74830  * See the License for the specific language governing permissions and
74831  * limitations under the License.
74832  */
74833
74834 var tizen1_utils = require('ripple/platform/tizen/2.0/tizen1_utils');
74835
74836 module.exports = function (number, types, isDefault) {
74837     var _self, i, type;
74838
74839     _self = {
74840         number:    undefined,
74841         isDefault: false,
74842         types:     undefined
74843     };
74844
74845     _self.number = number ? String(number) : "";
74846
74847     if (tizen1_utils.isValidArray(types)) {
74848         _self.types = [];
74849
74850         for (i in types) {
74851             type = String(types[i]).toUpperCase();
74852             _self.types.push(type);
74853         }
74854     } else {
74855         _self.types = ["VOICE"];
74856     }
74857
74858     if (typeof isDefault === "boolean") {
74859         _self.isDefault = isDefault;
74860     }
74861
74862     return _self;
74863 };
74864
74865 });
74866 define('ripple/platform/tizen/2.0/ContactRef', function (require, exports, module) {
74867 /*
74868  *  Copyright 2012 Intel Corporation.
74869  *
74870  * Licensed under the Apache License, Version 2.0 (the "License");
74871  * you may not use this file except in compliance with the License.
74872  * You may obtain a copy of the License at
74873  *
74874  * http://www.apache.org/licenses/LICENSE-2.0
74875  *
74876  * Unless required by applicable law or agreed to in writing, software
74877  * distributed under the License is distributed on an "AS IS" BASIS,
74878  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
74879  * See the License for the specific language governing permissions and
74880  * limitations under the License.
74881  */
74882
74883 var ContactRef = function (addressBookId, contactId) {
74884     if (!addressBookId || (typeof addressBookId !== "string") ||
74885         !contactId || (typeof contactId !== "string")) {
74886         return this;
74887     }
74888
74889     this.addressBookId = addressBookId;
74890     this.contactId     = contactId;
74891 };
74892
74893 module.exports = ContactRef;
74894
74895 });
74896 define('ripple/platform/tizen/2.0/ContactWebSite', function (require, exports, module) {
74897 /*
74898  *  Copyright 2012 Intel Corporation.
74899  *
74900  * Licensed under the Apache License, Version 2.0 (the "License");
74901  * you may not use this file except in compliance with the License.
74902  * You may obtain a copy of the License at
74903  *
74904  * http://www.apache.org/licenses/LICENSE-2.0
74905  *
74906  * Unless required by applicable law or agreed to in writing, software
74907  * distributed under the License is distributed on an "AS IS" BASIS,
74908  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
74909  * See the License for the specific language governing permissions and
74910  * limitations under the License.
74911  */
74912
74913 module.exports = function (url, type) {
74914     var _self;
74915
74916     _self = {
74917         url:  undefined,
74918         type: null
74919     };
74920
74921     if (url) {
74922         _self.url = String(url);
74923     }
74924     if (type) {
74925         _self.type = String(type).toUpperCase();
74926     }
74927
74928     return _self;
74929 };
74930
74931 });
74932 define('ripple/platform/tizen/2.0/Conversation', function (require, exports, module) {
74933 /*
74934  *  Copyright 2012 Intel Corporation.
74935  *
74936  * Licensed under the Apache License, Version 2.0 (the "License"),
74937  * you may not use this file except in compliance with the License.
74938  * You may obtain a copy of the License at
74939  *
74940  * http://www.apache.org/licenses/LICENSE-2.0
74941  *
74942  * Unless required by applicable law or agreed to in writing, software
74943  * distributed under the License is distributed on an "AS IS" BASIS,
74944  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
74945  * See the License for the specific language governing permissions and
74946  * limitations under the License.
74947  */
74948 var utils = require('ripple/utils');
74949
74950 module.exports = function (opt) {
74951     var conv = {}, priv = utils.copy(opt);
74952
74953     conv.__defineGetter__("id", function () {
74954         return priv.id;
74955     });
74956     conv.__defineGetter__("type", function () {
74957         return priv.type;
74958     });
74959     conv.__defineGetter__("timestamp", function () {
74960         return priv.timestamp;
74961     });
74962     conv.__defineGetter__("messageCount", function () {
74963         return priv.messageCount;
74964     });
74965     conv.__defineGetter__("unreadMessages", function () {
74966         return priv.unreadMessages;
74967     });
74968     conv.__defineGetter__("preview", function () {
74969         return priv.preview;
74970     });
74971     conv.__defineGetter__("subject", function () {
74972         return priv.subject;
74973     });
74974     conv.__defineGetter__("isRead", function () {
74975         return priv.isRead;
74976     });
74977     conv.__defineGetter__("from", function () {
74978         return priv.from;
74979     });
74980     conv.__defineGetter__("to", function () {
74981         return priv.to;
74982     });
74983     conv.__defineGetter__("cc", function () {
74984         return priv.cc;
74985     });
74986     conv.__defineGetter__("bcc", function () {
74987         return priv.bcc;
74988     });
74989     conv.__defineGetter__("lastMessageId", function () {
74990         return priv.lastMessageId;
74991     });
74992     return conv;
74993 };
74994
74995 });
74996 define('ripple/platform/tizen/2.0/DeviceMotionEvent', function (require, exports, module) {
74997 /*
74998  *  Copyright 2012 Intel Corporation.
74999  *
75000  * Licensed under the Apache License, Version 2.0 (the "License");
75001  * you may not use this file except in compliance with the License.
75002  * You may obtain a copy of the License at
75003  *
75004  * http://www.apache.org/licenses/LICENSE-2.0
75005  *
75006  * Unless required by applicable law or agreed to in writing, software
75007  * distributed under the License is distributed on an "AS IS" BASIS,
75008  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
75009  * See the License for the specific language governing permissions and
75010  * limitations under the License.
75011  */
75012
75013 var utils = require('ripple/utils'),
75014     Event = require('ripple/platform/tizen/2.0/EventBase');
75015
75016 module.exports = function () {
75017     var _self = {
75018             acceleration: {
75019                 x: null,
75020                 y: null,
75021                 z: null
75022             },
75023             accelerationIncludingGravity: {
75024                 x: null,
75025                 y: null,
75026                 z: null
75027             },
75028             rotationRate: {
75029                 alpha: null,
75030                 beta: null,
75031                 gamma: null
75032             },
75033             interval: 0
75034         };
75035
75036     Event.call(this);
75037
75038     this.__defineGetter__("acceleration", function () {
75039         return _self.acceleration;
75040     });
75041
75042     this.__defineGetter__("accelerationIncludingGravity", function () {
75043         return _self.accelerationIncludingGravity;
75044     });
75045
75046     this.__defineGetter__("rotationRate", function () {
75047         return _self.rotationRate;
75048     });
75049
75050     this.__defineGetter__("interval", function () {
75051         return _self.interval;
75052     });
75053
75054     this.initAccelerometerEvent = function (accelerometerType, accelerometerBubbles, accelerometerCancelable,
75055                                             accelerationData, accelerationGData, rotationRateData, intervalValue) {
75056         this.initEvent(accelerometerType, accelerometerBubbles, accelerometerCancelable);
75057
75058         _self.acceleration = utils.copy(accelerationData);
75059         _self.accelerationIncludingGravity = utils.copy(accelerationGData);
75060         _self.rotationRate = utils.copy(rotationRateData);
75061         _self.interval = intervalValue;
75062     };
75063 };
75064
75065
75066 });
75067 define('ripple/platform/tizen/2.0/DeviceOrientationEvent', function (require, exports, module) {
75068 /*
75069  *  Copyright 2012 Intel Corporation.
75070  *
75071  * Licensed under the Apache License, Version 2.0 (the "License");
75072  * you may not use this file except in compliance with the License.
75073  * You may obtain a copy of the License at
75074  *
75075  * http://www.apache.org/licenses/LICENSE-2.0
75076  *
75077  * Unless required by applicable law or agreed to in writing, software
75078  * distributed under the License is distributed on an "AS IS" BASIS,
75079  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
75080  * See the License for the specific language governing permissions and
75081  * limitations under the License.
75082  */
75083
75084 var Event = require('ripple/platform/tizen/2.0/EventBase');
75085
75086 module.exports = function () {
75087     var _self = {
75088             alpha: null,
75089             beta: null,
75090             gamma: null,
75091             absolute: false,
75092         };
75093
75094     Event.call(this);
75095
75096     this.__defineGetter__("alpha", function () {
75097         return _self.alpha;
75098     });
75099
75100     this.__defineGetter__("beta", function () {
75101         return _self.beta;
75102     });
75103
75104     this.__defineGetter__("gamma", function () {
75105         return _self.gamma;
75106     });
75107
75108     this.__defineGetter__("absolute", function () {
75109         return _self.absolute;
75110     });
75111
75112     this.initDeviceOrientationEvent = function (orientationType, orientationBubbles, orientationCancelable,
75113                                                alphaData, betaData, gammaData, isAbsolute) {
75114         this.initEvent(orientationType, orientationBubbles, orientationCancelable);
75115
75116         _self.alpha    = alphaData;
75117         _self.beta     = betaData;
75118         _self.gamma    = gammaData;
75119         _self.absolute = isAbsolute;
75120     };
75121 };
75122
75123
75124 });
75125 define('ripple/platform/tizen/2.0/DownloadRequest', function (require, exports, module) {
75126 /*
75127  *  Copyright 2012 Intel Corporation.
75128  *
75129  * Licensed under the Apache License, Version 2.0 (the "License");
75130  * you may not use this file except in compliance with the License.
75131  * You may obtain a copy of the License at
75132  *
75133  * http://www.apache.org/licenses/LICENSE-2.0
75134  *
75135  * Unless required by applicable law or agreed to in writing, software
75136  * distributed under the License is distributed on an "AS IS" BASIS,
75137  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
75138  * See the License for the specific language governing permissions and
75139  * limitations under the License.
75140  */
75141
75142 module.exports = function (url, destination, fileName) {
75143     var _self;
75144     _self = {
75145         url: url || null,
75146         destination: destination || null,
75147         fileName: fileName || null,
75148         networkType: null,
75149         httpHeader: null
75150     };
75151     return _self;
75152 };
75153
75154 });
75155 define('ripple/platform/tizen/2.0/EventBase', function (require, exports, module) {
75156 /*
75157  *  Copyright 2012 Intel Corporation.
75158  *
75159  * Licensed under the Apache License, Version 2.0 (the "License");
75160  * you may not use this file except in compliance with the License.
75161  * You may obtain a copy of the License at
75162  *
75163  * http://www.apache.org/licenses/LICENSE-2.0
75164  *
75165  * Unless required by applicable law or agreed to in writing, software
75166  * distributed under the License is distributed on an "AS IS" BASIS,
75167  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
75168  * See the License for the specific language governing permissions and
75169  * limitations under the License.
75170  */
75171
75172 module.exports = function () {
75173     var _self = {
75174         CAPTURING_PHASE: 1,
75175         AT_TARGET:  2,
75176         BUBBLING_PHASE: 3,
75177
75178         type: '',
75179         target: null, //new EventTarget(),
75180         currentTarget: null, //new EventTarget(),
75181         eventPhase: 0,
75182         bubbles: false,
75183         cancelable: false,
75184         timeStamp: 0
75185     };
75186
75187     this.__defineGetter__("type", function () {
75188         return _self.type;
75189     });
75190
75191     this.__defineGetter__("target", function () {
75192         return _self.target;
75193     });
75194
75195     this.__defineGetter__("currentTarget", function () {
75196         return _self.currentTarget;
75197     });
75198
75199     this.__defineGetter__("eventPhase", function () {
75200         return _self.eventPhase;
75201     });
75202
75203     this.__defineGetter__("bubbles", function () {
75204         return _self.bubbles;
75205     });
75206
75207     this.__defineGetter__("cancelable", function () {
75208         return _self.cancelable;
75209     });
75210
75211     this.__defineGetter__("timeStamp", function () {
75212         return _self.timeStamp;
75213     });
75214
75215     this.stopPropagation = function () {};
75216
75217     this.preventDefault = function () {};
75218
75219     this.initEvent = function (eventTypeArg, canBubbleArg, cancelableArg) {
75220         _self.type = eventTypeArg;
75221         _self.bubbles = canBubbleArg;
75222         _self.cancelable = cancelableArg;
75223
75224         _self.timeStamp = (new Date()).getTime();
75225     };
75226
75227     return _self;
75228 };
75229
75230
75231 });
75232 define('ripple/platform/tizen/2.0/GeoCircleBounds', function (require, exports, module) {
75233 /*
75234  *  Copyright 2012 Intel Corporation.
75235  *
75236  * Licensed under the Apache License, Version 2.0 (the "License");
75237  * you may not use this file except in compliance with the License.
75238  * You may obtain a copy of the License at
75239  *
75240  * http://www.apache.org/licenses/LICENSE-2.0
75241  *
75242  * Unless required by applicable law or agreed to in writing, software
75243  * distributed under the License is distributed on an "AS IS" BASIS,
75244  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
75245  * See the License for the specific language governing permissions and
75246  * limitations under the License.
75247  */
75248
75249 module.exports = function (_center, _radius) {
75250     var center, radius;
75251     center = _center || null;
75252     radius = _radius || 0;
75253
75254     this.__defineGetter__("center", function () {
75255         return center;
75256     });
75257
75258     this.__defineGetter__("radius", function () {
75259         return radius;
75260     });
75261 };
75262
75263 });
75264 define('ripple/platform/tizen/2.0/GeoPolyBounds', function (require, exports, module) {
75265 /*
75266  *  Copyright 2012 Intel Corporation.
75267  *
75268  * Licensed under the Apache License, Version 2.0 (the "License");
75269  * you may not use this file except in compliance with the License.
75270  * You may obtain a copy of the License at
75271  *
75272  * http://www.apache.org/licenses/LICENSE-2.0
75273  *
75274  * Unless required by applicable law or agreed to in writing, software
75275  * distributed under the License is distributed on an "AS IS" BASIS,
75276  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
75277  * See the License for the specific language governing permissions and
75278  * limitations under the License.
75279  */
75280
75281 module.exports = function (_points) {
75282     var points = _points || [];
75283
75284     this.__defineGetter__("points", function () {
75285         return points;
75286     });
75287 };
75288
75289 });
75290 define('ripple/platform/tizen/2.0/GeoRectBounds', function (require, exports, module) {
75291 /*
75292  *  Copyright 2012 Intel Corporation.
75293  *
75294  * Licensed under the Apache License, Version 2.0 (the "License");
75295  * you may not use this file except in compliance with the License.
75296  * You may obtain a copy of the License at
75297  *
75298  * http://www.apache.org/licenses/LICENSE-2.0
75299  *
75300  * Unless required by applicable law or agreed to in writing, software
75301  * distributed under the License is distributed on an "AS IS" BASIS,
75302  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
75303  * See the License for the specific language governing permissions and
75304  * limitations under the License.
75305  */
75306
75307 module.exports = function (_southWest, _northEast) {
75308     var southWest, northEast;
75309     southWest = _southWest || null;
75310     northEast = _northEast || null;
75311
75312     this.__defineGetter__("southWest", function () {
75313         return southWest;
75314     });
75315
75316     this.__defineGetter__("northEast", function () {
75317         return northEast;
75318     });
75319 };
75320
75321 });
75322 define('ripple/platform/tizen/2.0/GeocodeOptions', function (require, exports, module) {
75323 /*      
75324  *  Copyright 2012 Intel Corporation.
75325  *  
75326  * Licensed under the Apache License, Version 2.0 (the "License");
75327  * you may not use this file except in compliance with the License.
75328  * You may obtain a copy of the License at
75329  *  
75330  * http://www.apache.org/licenses/LICENSE-2.0
75331  *  
75332  * Unless required by applicable law or agreed to in writing, software
75333  * distributed under the License is distributed on an "AS IS" BASIS,
75334  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
75335  * See the License for the specific language governing permissions and
75336  * limitations under the License.
75337  */
75338
75339 var errorcode = require('ripple/platform/tizen/2.0/errorcode'),
75340     WebAPIError = require('ripple/platform/tizen/2.0/WebAPIError'),
75341     SortMode = require('ripple/platform/tizen/2.0/SortMode');
75342
75343 module.exports = function (_sortMode, _maxResults) {
75344     var _self;
75345     if (_sortMode !== null && _sortMode !== undefined) {
75346         if (typeof _sortMode !== "object") {
75347             throw (new WebAPIError(errorcode.TYPE_MISMATCH_ERR));
75348         }
75349         try {
75350             new SortMode(_sortMode.attributeName, _sortMode.order);
75351         } catch (e) {
75352             throw (new WebAPIError(errorcode.TYPE_MISMATCH_ERR));
75353         }
75354     }
75355     if (_maxResults !== null && _maxResults !== undefined) {
75356         if (typeof _maxResults !== "number") {
75357             throw (new WebAPIError(errorcode.TYPE_MISMATCH_ERR));
75358         }
75359     }
75360
75361     _self = {
75362         sortMode : _sortMode,
75363         maxResults : _maxResults || 0
75364     };
75365
75366     return _self;
75367 };
75368
75369
75370 });
75371 define('ripple/platform/tizen/2.0/GeocodeResult', function (require, exports, module) {
75372 /*      
75373  *  Copyright 2012 Intel Corporation.
75374  *  
75375  * Licensed under the Apache License, Version 2.0 (the "License");
75376  * you may not use this file except in compliance with the License.
75377  * You may obtain a copy of the License at
75378  *  
75379  * http://www.apache.org/licenses/LICENSE-2.0
75380  *  
75381  * Unless required by applicable law or agreed to in writing, software
75382  * distributed under the License is distributed on an "AS IS" BASIS,
75383  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
75384  * See the License for the specific language governing permissions and
75385  * limitations under the License.
75386  */
75387
75388 var SimpleCoordinates = require('ripple/platform/tizen/2.0/SimpleCoordinates');
75389
75390 module.exports = function (lat, lon) {
75391     var _self, _coordinates, jsonStr, jsonObj;
75392
75393     _coordinates = new SimpleCoordinates(lat, lon);
75394
75395     jsonObj = {
75396         "type" : "Point",
75397         "coordinates" : [lat, lon]
75398     };
75399
75400     jsonStr = JSON.stringify(jsonObj);
75401
75402     _self = {
75403         coordinates : _coordinates,
75404         toGeoJSON : function () {
75405             return jsonStr;
75406         }
75407     };
75408     return _self;
75409 };
75410
75411
75412 });
75413 define('ripple/platform/tizen/2.0/GeometryFilter', function (require, exports, module) {
75414 /*
75415  *  Copyright 2012 Intel Corporation.
75416  *
75417  * Licensed under the Apache License, Version 2.0 (the "License");
75418  * you may not use this file except in compliance with the License.
75419  * You may obtain a copy of the License at
75420  *
75421  * http://www.apache.org/licenses/LICENSE-2.0
75422  *
75423  * Unless required by applicable law or agreed to in writing, software
75424  * distributed under the License is distributed on an "AS IS" BASIS,
75425  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
75426  * See the License for the specific language governing permissions and
75427  * limitations under the License.
75428  */
75429
75430 module.exports = function (criteria, geometry) {
75431     var _self;
75432
75433     _self = {
75434         criteria: criteria,
75435         geometry: geometry
75436     };
75437
75438     return _self;
75439 };
75440
75441 });
75442 define('ripple/platform/tizen/2.0/Message', function (require, exports, module) {
75443 /*
75444  *  Copyright 2012 Intel Corporation.
75445  *
75446  * Licensed under the Apache License, Version 2.0 (the "License");
75447  * you may not use this file except in compliance with the License.
75448  * You may obtain a copy of the License at
75449  *
75450  * http://www.apache.org/licenses/LICENSE-2.0
75451  *
75452  * Unless required by applicable law or agreed to in writing, software
75453  * distributed under the License is distributed on an "AS IS" BASIS,
75454  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
75455  * See the License for the specific language governing permissions and
75456  * limitations under the License.
75457  */
75458
75459 var msg_utils = require('ripple/platform/tizen/2.0/msg_utils'),
75460     MessageBody = require('ripple/platform/tizen/2.0/MessageBody'),
75461     errorcode = require('ripple/platform/tizen/2.0/errorcode'),
75462     WebAPIException = require('ripple/platform/tizen/2.0/WebAPIException');
75463
75464 module.exports = function (type, messageInit) {
75465     var _id = null, _serviceId = null, _conversationId = null,
75466         _folderId = null, _type = type, _timestamp = null,
75467         _from = null, _hasAttachment = false, _messageStatus = null,
75468         msg = {};
75469
75470     if (messageInit !== undefined && messageInit !== null) {
75471         if (msg_utils.setMsg(messageInit, msg) === false) {
75472             throw (new WebAPIException(errorcode.TYPE_MISMATCH_ERR));
75473         }
75474         if (messageInit.priv !== undefined) {
75475             /* secret constructor for PrivateMessage */
75476             _id = messageInit.priv.id;
75477             _serviceId = messageInit.priv.serviceId;
75478             _conversationId = messageInit.priv.conversationId;
75479             _folderId = messageInit.priv.folderId;
75480             _type = messageInit.priv.type;
75481             _timestamp = new Date(messageInit.priv.timestamp);
75482             _from = messageInit.priv.from;
75483             _hasAttachment = messageInit.priv.hasAttachment;
75484             _messageStatus = messageInit.priv.messageStatus;
75485         }
75486         msg.body = new MessageBody(_id, msg.body.loaded, msg.body.plainBody, msg.body.htmlBody, []);
75487     }
75488
75489     msg.__defineGetter__("id", function () {
75490         return _id;
75491     });
75492     msg.__defineGetter__("conversationId", function () {
75493         return _conversationId;
75494     });
75495     msg.__defineGetter__("folderId", function () {
75496         return _folderId;
75497     });
75498     msg.__defineGetter__("type", function () {
75499         return _type;
75500     });
75501     msg.__defineGetter__("timestamp", function () {
75502         return _timestamp;
75503     });
75504     msg.__defineGetter__("from", function () {
75505         return _from;
75506     });
75507     msg.__defineGetter__("hasAttachment", function () {
75508         return _hasAttachment;
75509     });
75510     msg.__defineGetter__("messageStatus", function () {
75511         return _messageStatus;
75512     });
75513     return msg;
75514 };
75515
75516 });
75517 define('ripple/platform/tizen/2.0/MessageBody', function (require, exports, module) {
75518 /*
75519  *  Copyright 2012 Intel Corporation.
75520  *
75521  * Licensed under the Apache License, Version 2.0 (the "License");
75522  * you may not use this file except in compliance with the License.
75523  * You may obtain a copy of the License at
75524  *
75525  * http://www.apache.org/licenses/LICENSE-2.0
75526  *
75527  * Unless required by applicable law or agreed to in writing, software
75528  * distributed under the License is distributed on an "AS IS" BASIS,
75529  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
75530  * See the License for the specific language governing permissions and
75531  * limitations under the License.
75532  */
75533
75534 module.exports = function (id, isloaded, _plainbody, _htmlbody, inlineattachments) {
75535     var msgbody, _id = id, _loaded = isloaded;
75536     msgbody = {
75537         plainBody: _plainbody,
75538         htmlBody: _htmlbody,
75539         inlineAttachments: [] // TODO: not support attachment yet
75540     };
75541     msgbody.__defineGetter__("messageId", function () {
75542         return _id;
75543     });
75544     msgbody.__defineGetter__("loaded", function () {
75545         return _loaded;
75546     });
75547     return msgbody;
75548 };
75549
75550 });
75551 define('ripple/platform/tizen/2.0/MessageFolder', function (require, exports, module) {
75552 /*
75553  *  Copyright 2012 Intel Corporation.
75554  *
75555  * Licensed under the Apache License, Version 2.0 (the "License");
75556  * you may not use this file except in compliance with the License.
75557  * You may obtain a copy of the License at
75558  *
75559  * http://www.apache.org/licenses/LICENSE-2.0
75560  *
75561  * Unless required by applicable law or agreed to in writing, software
75562  * distributed under the License is distributed on an "AS IS" BASIS,
75563  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
75564  * See the License for the specific language governing permissions and
75565  * limitations under the License.
75566  */
75567
75568 module.exports = function (opt) {
75569     var folder = {}, _id = opt.id, _parentId = null, _serviceId = opt.serviceId,
75570         _contentType = opt.contentType, _name = opt.id, _path = opt.path,
75571         _type = opt.type, _synchronizable = opt.synchronizable;
75572
75573     folder.name = _name;
75574     folder.synchronizable = _synchronizable;
75575     
75576     folder.__defineGetter__("id", function () {
75577         return _id;
75578     });
75579     folder.__defineGetter__("parentId", function () {
75580         return _parentId;
75581     });
75582     folder.__defineGetter__("serviceId", function () {
75583         return _serviceId;
75584     });
75585     folder.__defineGetter__("contentType", function () {
75586         return _contentType;
75587     });
75588     folder.__defineGetter__("path", function () {
75589         return _path;
75590     });
75591     folder.__defineGetter__("type", function () {
75592         return _type;
75593     });
75594     return folder;
75595 };
75596
75597 });
75598 define('ripple/platform/tizen/2.0/MessageStorage', function (require, exports, module) {
75599 /*
75600  *  Copyright 2012 Intel Corporation.
75601  *
75602  * Licensed under the Apache License, Version 2.0 (the "License");
75603  * you may not use this file except in compliance with the License.
75604  * You may obtain a copy of the License at
75605  *
75606  * http://www.apache.org/licenses/LICENSE-2.0
75607  *
75608  * Unless required by applicable law or agreed to in writing, software
75609  * distributed under the License is distributed on an "AS IS" BASIS,
75610  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
75611  * See the License for the specific language governing permissions and
75612  * limitations under the License.
75613  */
75614 var _self,
75615     utils = require('ripple/utils'),
75616     event = require('ripple/event'),
75617     Message = require('ripple/platform/tizen/2.0/Message'),
75618     Conversation = require('ripple/platform/tizen/2.0/Conversation'),
75619     errorcode = require('ripple/platform/tizen/2.0/errorcode'),
75620     WebAPIException = require('ripple/platform/tizen/2.0/WebAPIException'),
75621     WebAPIError = require('ripple/platform/tizen/2.0/WebAPIError'),
75622     PrivMessage = require('ripple/platform/tizen/2.0/PrivMessage'),
75623     MessageFolder = require('ripple/platform/tizen/2.0/MessageFolder'),
75624     msg_utils = require('ripple/platform/tizen/2.0/msg_utils'),
75625     tizen1_utils = require('ripple/platform/tizen/2.0/tizen1_utils'),
75626     t = require('ripple/platform/tizen/2.0/typedef'),
75627     TypeCoerce = require('ripple/platform/tizen/2.0/typecoerce'),
75628     TIZEN_DEFAULT_MSG_FROM = {"messaging.sms": "13572468",
75629                               "messaging.mms": "13572468",
75630                               "messaging.email": "tizen.simulator@tizen.org"};
75631
75632 _self = function (messages, security_check) {
75633     var message_storage = {},
75634         _findMessage, _findConversation,
75635         _processMessageChange, _processConversationChange,
75636         _folders = {}, folderOpt = {},
75637         _msgListeners = {},
75638         _convListeners = {},
75639         _folderListeners = {},
75640         _security_check = security_check,
75641         _messages = messages;
75642
75643     // init folders
75644     folderOpt = {id: "INBOX", serviceId: _messages.id, contentType: _messages.type,
75645                  path: "inbox", type: "INBOX", synchronizable: true};
75646     _folders.INBOX = new MessageFolder(folderOpt);
75647     folderOpt = {id: "OUTBOX", serviceId: _messages.id, contentType: _messages.type,
75648                  path: "outbox", type: "OUTBOX", synchronizable: false};
75649     _folders.OUTBOX = new MessageFolder(folderOpt);
75650     folderOpt = {id: "DRAFT", serviceId: _messages.id, contentType: _messages.type,
75651                  path: "draft", type: "DRAFTS", synchronizable: false};
75652     _folders.DRAFT = new MessageFolder(folderOpt);
75653     folderOpt = {id: "SENTBOX", serviceId: _messages.id, contentType: _messages.type,
75654                  path: "sentbox", type: "SENTBOX", synchronizable: false};
75655     _folders.SENTBOX = new MessageFolder(folderOpt);
75656
75657     event.on("MsgRecv", function (msg) {
75658         // msg sent from panel to module
75659         if (msg.priv.type !== _messages.type ||
75660             msg.priv.serviceId !== _messages.id) {
75661             return;
75662         }
75663         // trigger Message add
75664         _processMessageChange([msg], "add");
75665         _messages.conv = msg_utils.loadConv(_messages.type, _messages.id);
75666
75667         if (_messages.conv[msg.priv.conversationId].messageCount === 1) {
75668             _processConversationChange([_messages.conv[msg.priv.conversationId]], "add");
75669         } else {
75670             _processConversationChange([_messages.conv[msg.priv.conversationId]], "update");
75671         }
75672     });
75673
75674     event.on("OutsideMessageReceived", function (msg) {
75675         // msg sent from module to panel
75676         if (msg.msg.priv.type !== _messages.type ||
75677             msg.msg.priv.serviceId !== _messages.id) {
75678             return;
75679         }
75680         // trigger conversation/Message add
75681         _processMessageChange([msg.msg], "add");
75682         _messages.conv = msg_utils.loadConv(_messages.type, _messages.id);
75683
75684         if (_messages.conv[msg.msg.priv.conversationId].messageCount === 1) {
75685             _processConversationChange([_messages.conv[msg.msg.priv.conversationId]], "add");
75686         } else {
75687             _processConversationChange([_messages.conv[msg.msg.priv.conversationId]], "update");
75688         }
75689     });
75690
75691     event.on("MsgSentRst", function (rst) {
75692         // ACK from panel when module sent a msg to panel
75693         if (rst.priv.type !== _messages.type ||
75694             rst.priv.serviceId !== _messages.id) {
75695             return;
75696         }
75697         // trigger conversation/Message Update
75698         _processMessageChange([rst], "update");
75699         _messages.conv = msg_utils.loadConv(_messages.type, _messages.id);
75700         _processConversationChange([_messages.conv[rst.priv.conversationId]], "update");
75701     });
75702
75703     _findMessage = function (src, filter) {
75704         var ret, foo = {};
75705         switch (filter.attributeName) {
75706         case "type":
75707             foo[filter.attributeName] = _messages.type;
75708             ret = tizen1_utils.matchAttributeFilter([foo],
75709                       filter.attributeName, filter.matchFlag, filter.matchValue);
75710             if (ret.length === 0) {
75711                 ret = [];
75712             } else {
75713                 // make an array
75714                 ret = utils.filter(src, function () { return true; });
75715             }
75716             break;
75717         case "id":
75718         case "conversationId":
75719         case "folderId":
75720         case "from":
75721         case "messageStatus":
75722             ret = tizen1_utils.matchAttributeFilter(src,
75723                       "priv." + filter.attributeName,
75724                       filter.matchFlag, filter.matchValue);
75725             break;
75726         case "hasAttachment":
75727             if (filter.matchFlag !== "EXACTLY" || typeof filter.matchValue !== "boolean") {
75728                 throw (new WebAPIException(errorcode.INVALID_VALUES_ERR,
75729                               "Support only matchFlag === 'EXACTLY' and typeof matchValue === 'boolean'"));
75730             }
75731             ret = tizen1_utils.matchAttributeBooleanFilter(src,
75732                       "priv." + filter.attributeName, filter.matchValue);
75733             break;
75734         case "to":
75735         case "cc":
75736         case "bcc":
75737             ret = tizen1_utils.matchAttributeArrayFilter(src,
75738                       filter.attributeName, filter.matchFlag, filter.matchValue);
75739             break;
75740         case "body":
75741             ret = tizen1_utils.matchAttributeFilter(src,
75742                       filter.attributeName + ".plainBody",
75743                       filter.matchFlag, filter.matchValue);
75744             break;
75745         case "subject":
75746         case "inResponseTo":
75747             ret = tizen1_utils.matchAttributeFilter(src, filter.attributeName,
75748                       filter.matchFlag, filter.matchValue);
75749             break;
75750         case "isRead":
75751         case "isHighPriority":
75752             if (filter.matchFlag !== "EXACTLY" || typeof filter.matchValue !== "boolean") {
75753                 throw (new WebAPIException(errorcode.INVALID_VALUES_ERR,
75754                               "Support only matchFlag === 'EXACTLY' and typeof matchValue === 'boolean'"));
75755             }
75756             ret = tizen1_utils.matchAttributeBooleanFilter(src,
75757                       filter.attributeName, filter.matchValue);
75758             break;
75759         case "timestamp":
75760             ret = tizen1_utils.matchAttributeRangeFilter(src,
75761                       "priv." + filter.attributeName,
75762                       filter.initialValue, filter.endValue);
75763             break;
75764
75765         case "attachments":
75766             throw (new WebAPIException(errorcode.NOT_SUPPORTED_ERR,
75767                                   "not support find by " + filter.attributeName));
75768         default:
75769             throw (new WebAPIException(errorcode.INVALID_VALUES_ERR,
75770                                    "invalid attributeName"));
75771         }
75772         return ret;
75773     };
75774
75775     _processMessageChange = function (messages, type) {
75776         var i, j, ret = [], tmp,
75777             operation = {"add": "messagesadded",
75778                          "remove": "messagesremoved",
75779                          "update": "messagesupdated"};
75780
75781         for (i in _msgListeners) {
75782             ret = [];
75783             if (_msgListeners[i].filter !== null) {
75784                 tmp = _findMessage(messages, _msgListeners[i].filter);
75785             } else {
75786                 tmp = messages;
75787             }
75788             if (tmp.length !== 0) {
75789                 for (j = 0; j < tmp.length; j++) {
75790                     ret.push(new Message(tmp[j].priv.type, tmp[j]));
75791                 }
75792                 _msgListeners[i].callback[operation[type]](ret);
75793             }
75794         }
75795     };
75796
75797     _findConversation = function (src, filter) {
75798         var ret, foo = {};
75799         switch (filter.attributeName) {
75800         case "type":
75801             foo[filter.attributeName] = _messages.type;
75802             ret = tizen1_utils.matchAttributeFilter([foo], filter.attributeName, filter.matchFlag, filter.matchValue);
75803             if (ret.length === 0) {
75804                 ret = [];
75805             } else {
75806                 // make an array
75807                 ret = utils.filter(_messages.conv, function () { return true; });
75808             }
75809             break;
75810         case "id":
75811         case "preview":
75812         case "subject":
75813         case "from":
75814         case "lastMessageId":
75815             ret = tizen1_utils.matchAttributeFilter(src, filter.attributeName, filter.matchFlag, filter.matchValue);
75816             break;
75817         case "to":
75818         case "cc":
75819         case "bcc":
75820             ret = tizen1_utils.matchAttributeArrayFilter(src,
75821                       filter.attributeName, filter.matchFlag, filter.matchValue);
75822             break;
75823         case "isRead":
75824             if (filter.matchFlag !== "EXACTLY" || typeof filter.matchValue !== "boolean") {
75825                 throw (new WebAPIException(errorcode.INVALID_VALUES_ERR,
75826                               "Support only matchFlag === 'EXACTLY' and typeof matchValue === 'boolean'"));
75827             }
75828             ret = tizen1_utils.matchAttributeBooleanFilter(src,
75829                       filter.attributeName, filter.matchValue);
75830             break;
75831         case "timestamp":
75832         case "messageCount":
75833         case "unreadMessages":
75834             ret = tizen1_utils.matchAttributeRangeFilter(src,
75835                       filter.attributeName,
75836                       filter.initialValue, filter.endValue);
75837             break;
75838         default:
75839             throw (new WebAPIException(errorcode.INVALID_VALUES_ERR,
75840                                    "invalid attributeName"));
75841         }
75842         return ret;
75843     };
75844
75845     _processConversationChange = function (conversations, type) {
75846         var i, j, ret = [], tmp,
75847             operation = {"add": "conversationsadded",
75848                          "remove": "conversationsremoved",
75849                          "update": "conversationsupdated"};
75850
75851         for (i in _convListeners) {
75852             ret = [];
75853             if (_convListeners[i].filter !== null) {
75854                 tmp = _findConversation(conversations, _convListeners[i].filter);
75855             } else {
75856                 tmp = conversations;
75857             }
75858             if (tmp.length !== 0) {
75859                 for (j = 0; j < tmp.length; j++) {
75860                     ret.push(new Conversation(tmp[j]));
75861                 }
75862                 _convListeners[i].callback[operation[type]](ret);
75863             }
75864         }
75865     };
75866
75867     message_storage = {
75868         addDraftMessage: function (_msg, onSuccess, onError) {
75869             var m, msg = {}, opt = {};
75870
75871             if (_security_check.write === false) {
75872                 throw (new WebAPIException(errorcode.SECURITY_ERR));
75873             }
75874             if (msg_utils.setMsg(_msg, msg) === false) {
75875                 throw (new WebAPIException(errorcode.TYPE_MISMATCH_ERR));
75876             }
75877             if (onSuccess && !(new TypeCoerce(t.SuccessCallback)).match(onSuccess)) {
75878                 throw new WebAPIException(errorcode.TYPE_MISMATCH_ERR);
75879             }
75880             if (onError && !(new TypeCoerce(t.ErrorCallback)).match(onError)) {
75881                 throw new WebAPIException(errorcode.TYPE_MISMATCH_ERR);
75882             }
75883             opt.id = Math.uuid(8, 16);
75884             opt.serviceId = _messages.id;
75885             if ((msg.inResponseTo !== null) &&
75886                 (_messages.msg[msg.inResponseTo] !== undefined)) {
75887                 opt.conversationId = _messages.msg[msg.inResponseTo].conversationId;
75888             } else {
75889                 opt.conversationId = opt.id;
75890             }
75891             opt.folderId = "DRAFTS";
75892             opt.type = _messages.type;
75893             opt.timestamp = new Date();
75894             opt.from = TIZEN_DEFAULT_MSG_FROM[_messages.type];
75895             if (msg.attachments.length === 0) {
75896                 opt.hasAttachment = false;
75897             } else {
75898                 opt.hasAttachment = true;
75899             }
75900             opt.messageStatus = "DRAFT";
75901
75902             m = new PrivMessage(msg, opt);
75903             _messages.msg[m.priv.id] = m;  // local
75904             msg_utils.saveMsg(_messages.msg[m.priv.id]);  // remote
75905             // trigger message add
75906             _processMessageChange([m], "add");
75907             if (onSuccess) {
75908                 setTimeout(function () {
75909                     onSuccess(new Message(m.priv.type, m));
75910                 }, 1);
75911             }
75912         },
75913
75914         removeMessages: function (messages, onSuccess, onError) {
75915             var i, c, na_msg = "", msgToDel = [], convToDel = {}, delConv = [], updateConv = [];
75916
75917             if (_security_check.write === false) {
75918                 throw (new WebAPIException(errorcode.SECURITY_ERR));
75919             }
75920             if (tizen1_utils.isValidArray(messages) === false) {
75921                 throw (new WebAPIException(errorcode.TYPE_MISMATCH_ERR));
75922             }
75923             if (messages.length === 0) {
75924                 throw (new WebAPIException(errorcode.INVALID_VALUES_ERR));
75925             }
75926             if (onSuccess && !(new TypeCoerce(t.SuccessCallback)).match(onSuccess)) {
75927                 throw new WebAPIException(errorcode.TYPE_MISMATCH_ERR);
75928             }
75929             if (onError && !(new TypeCoerce(t.ErrorCallback)).match(onError)) {
75930                 throw new WebAPIException(errorcode.TYPE_MISMATCH_ERR);
75931             }
75932
75933             _messages.conv = msg_utils.loadConv(_messages.type, _messages.id);
75934             for (i = 0; i < messages.length; i++) {
75935                 if (_messages.msg[messages[i].id] === undefined) {
75936                     na_msg += messages[i].id + ", ";
75937                 } else {
75938                     msgToDel.push(utils.copy(_messages.msg[messages[i].id]));
75939                 }
75940                 if (_messages.conv[messages[i].conversationId] !== undefined) {
75941                     convToDel[messages[i].conversationId] = _messages.conv[messages[i].conversationId];
75942                 }
75943             }
75944             if (na_msg === "") {
75945                 for (i = 0; i < messages.length; i++) {
75946                     // conversation updated at remote when msg is deleted
75947                     msg_utils.delMsg(_messages.msg[messages[i].id]); // remote
75948                     delete _messages.msg[messages[i].id]; // local
75949                 }
75950                 // update conversation
75951                 _messages.conv = msg_utils.loadConv(_messages.type, _messages.id);
75952                 for (c in convToDel) {
75953                     if (_messages.conv[c] === undefined) {
75954                         delConv.push(convToDel[c]);
75955                     } else {
75956                         updateConv.push(convToDel[c]);
75957                     }
75958                 }
75959                 if (onSuccess) {
75960                     setTimeout(function () {
75961                         onSuccess();
75962                     }, 1);
75963                 }
75964                 // trigger messages remove
75965                 _processMessageChange(msgToDel, "remove");
75966                 if (delConv.length > 0) {
75967                     _processConversationChange(delConv, "remove");
75968                 }
75969                 if (updateConv.length > 0) {
75970                     _processConversationChange(updateConv, "update");
75971                 }
75972             } else {
75973                 if (onError) {
75974                     setTimeout(function () {
75975                         onError(new WebAPIError(errorcode.NOT_FOUND_ERR,
75976                                 na_msg + "not found !!"));
75977                     }, 1);
75978                 }
75979             }
75980         },
75981
75982         updateMessages: function (messages, onSuccess, onError) {
75983             var i, m, updateConv = {}, updateMsg = [], tmp,
75984                 na_msg = "", invalid_msg = "";
75985
75986             if (_security_check.write === false) {
75987                 throw (new WebAPIException(errorcode.SECURITY_ERR));
75988             }
75989             if (onSuccess && !(new TypeCoerce(t.SuccessCallback)).match(onSuccess)) {
75990                 throw new WebAPIException(errorcode.TYPE_MISMATCH_ERR);
75991             }
75992             if (onError && !(new TypeCoerce(t.ErrorCallback)).match(onError)) {
75993                 throw new WebAPIException(errorcode.TYPE_MISMATCH_ERR);
75994             }
75995             if (tizen1_utils.isValidArray(messages) === false) {
75996                 throw (new WebAPIException(errorcode.TYPE_MISMATCH_ERR));
75997             }
75998             if (messages.length === 0) {
75999                 throw (new WebAPIException(errorcode.INVALID_VALUES_ERR));
76000             }
76001             // update conversation
76002             _messages.conv = msg_utils.loadConv(_messages.type, _messages.id);
76003             for (i = 0; i < messages.length; i++) {
76004                 m = _messages.msg[messages[i].id];
76005                 if (m === undefined) {
76006                     // msg not found
76007                     na_msg += messages[i].id + ", ";
76008                 } else {
76009                     if (m.priv.messageStatus === "DRAFT") {
76010                         tmp = {};
76011                         // allow update all writeable attr in draft
76012                         if (msg_utils.setMsg(messages[i], tmp) === false) {
76013                             invalid_msg += messages[i].id + ", ";
76014                         }
76015                     }
76016                 }
76017             }
76018             if (invalid_msg !== "") {
76019                 if (onError) {
76020                     setTimeout(function () {
76021                         onError(new WebAPIError(errorcode.INVALID_VALUES_ERR,
76022                                 invalid_msg + "invalid values"));
76023                     }, 1);
76024                 }
76025                 return;
76026             }
76027             if (na_msg !== "") {
76028                 if (onError) {
76029                     setTimeout(function () {
76030                         onError(new WebAPIError(errorcode.NOT_FOUND_ERR,
76031                                 na_msg + "not found !!"));
76032                     }, 1);
76033                 }
76034                 return;
76035             }
76036
76037             for (i = 0; i < messages.length; i++) {
76038                 m = _messages.msg[messages[i].id];
76039                 if (m.priv.messageStatus === "DRAFT") {
76040                     msg_utils.setMsg(messages[i], m);
76041                     updateMsg.push(m);
76042                 } else {
76043                     // only allow update isRead in other folders
76044                     if (typeof messages[i].isRead === 'boolean') {
76045                         m.isRead = messages[i].isRead;
76046                         updateMsg.push(m);
76047                         updateConv[m.priv.conversationId] = _messages.conv[m.priv.conversationId];
76048                     }
76049                 }
76050                 msg_utils.saveMsg(m);
76051             }
76052             if (onSuccess) {
76053                 setTimeout(function () {
76054                     onSuccess();
76055                 }, 1);
76056             }
76057
76058             // trigger Message update
76059             _processMessageChange(updateMsg, "update");
76060
76061             _messages.conv = msg_utils.loadConv(_messages.type, _messages.id);
76062             // trigger conversation update
76063             _processConversationChange(updateConv, "update");
76064         },
76065
76066         findMessages: function (filter, onSuccess, onError, sort, _limit, _offset) {
76067             var i, tmp, offset, limit, ret = [];
76068
76069             if (_security_check.read === false) {
76070                 throw (new WebAPIException(errorcode.SECURITY_ERR));
76071             }
76072             if (!(new TypeCoerce(t.MessageArraySuccessCallback)).match(onSuccess)) {
76073                 throw new WebAPIException(errorcode.TYPE_MISMATCH_ERR);
76074             }
76075             if (onError && !(new TypeCoerce(t.ErrorCallback)).match(onError)) {
76076                 throw new WebAPIException(errorcode.TYPE_MISMATCH_ERR);
76077             }
76078             if (sort && !(new TypeCoerce(t.SortMode)).match(sort)) {
76079                 throw new WebAPIException(errorcode.TYPE_MISMATCH_ERR);
76080             }
76081             if (_limit && !(new TypeCoerce(t.long)).match(_limit)) {
76082                 throw new WebAPIException(errorcode.TYPE_MISMATCH_ERR);
76083             }
76084             if (_offset && !(new TypeCoerce(t.long)).match(_offset)) {
76085                 throw new WebAPIException(errorcode.TYPE_MISMATCH_ERR);
76086             }
76087             tmp = _findMessage(_messages.msg, filter);
76088
76089             if (_offset) {
76090                 offset = _offset;
76091             } else {
76092                 offset = 0;
76093             }
76094             if (_limit) {
76095                 limit = Math.min(_limit + offset, tmp.length);
76096             } else {
76097                 limit = tmp.length;
76098             }
76099             for (i = offset; i < limit; i++) {
76100                 ret.push(new Message(tmp[i].priv.type, tmp[i]));
76101             }
76102             setTimeout(function () {
76103                 onSuccess(ret);
76104             }, 1);
76105         },
76106
76107         findConversations: function (filter, onSuccess, onError, sort, _limit, _offset) {
76108             var i, tmp, offset, limit, ret = [];
76109
76110             if (_security_check.read === false) {
76111                 throw (new WebAPIException(errorcode.SECURITY_ERR));
76112             }
76113             if (!(new TypeCoerce(t.MessageConversationArraySuccessCallback)).match(onSuccess)) {
76114                 throw new WebAPIException(errorcode.TYPE_MISMATCH_ERR);
76115             }
76116             if (onError && !(new TypeCoerce(t.ErrorCallback)).match(onError)) {
76117                 throw new WebAPIException(errorcode.TYPE_MISMATCH_ERR);
76118             }
76119             if (sort && !(new TypeCoerce(t.SortMode)).match(sort)) {
76120                 throw new WebAPIException(errorcode.TYPE_MISMATCH_ERR);
76121             }
76122             if (_limit && !(new TypeCoerce(t.long)).match(_limit)) {
76123                 throw new WebAPIException(errorcode.TYPE_MISMATCH_ERR);
76124             }
76125             if (_offset && !(new TypeCoerce(t.long)).match(_offset)) {
76126                 throw new WebAPIException(errorcode.TYPE_MISMATCH_ERR);
76127             }
76128             // download conversation
76129             _messages.conv = msg_utils.loadConv(_messages.type, _messages.id);
76130
76131             tmp = _findConversation(_messages.conv, filter);
76132
76133             if (_offset) {
76134                 offset = _offset;
76135             } else {
76136                 offset = 0;
76137             }
76138             if (_limit) {
76139                 limit = Math.min(_limit + offset, tmp.length);
76140             } else {
76141                 limit = tmp.length;
76142             }
76143             for (i = offset; i < limit; i++) {
76144                 ret.push(new Conversation(tmp[i]));
76145             }
76146             setTimeout(function () {
76147                 onSuccess(ret);
76148             }, 1);
76149         },
76150
76151         removeConversations: function (conversations, onSuccess, onError) {
76152             var i, m, na_msg = "", retConv = [], removeMsg = [];
76153
76154             if (_security_check.write === false) {
76155                 throw (new WebAPIException(errorcode.SECURITY_ERR));
76156             }
76157             if (onSuccess && !(new TypeCoerce(t.SuccessCallback)).match(onSuccess)) {
76158                 throw new WebAPIException(errorcode.TYPE_MISMATCH_ERR);
76159             }
76160             if (onError && !(new TypeCoerce(t.ErrorCallback)).match(onError)) {
76161                 throw new WebAPIException(errorcode.TYPE_MISMATCH_ERR);
76162             }
76163             // download conversation
76164             _messages.conv = msg_utils.loadConv(_messages.type, _messages.id);
76165
76166             if (tizen1_utils.isValidArray(conversations) === false) {
76167                 throw (new WebAPIException(errorcode.TYPE_MISMATCH_ERR));
76168             }
76169             if (conversations.length === 0) {
76170                 throw (new WebAPIException(errorcode.INVALID_VALUES_ERR));
76171             }
76172             if ((onSuccess && typeof onSuccess !== "function") ||
76173                 (onError && typeof onError !== "function")) {
76174                 throw new WebAPIException(errorcode.TYPE_MISMATCH_ERR);
76175             }
76176
76177             for (i = 0; i < conversations.length; i++) {
76178                 if (_messages.conv[conversations[i].id] === undefined) {
76179                     na_msg += conversations[i].id + ", ";
76180                 } else {
76181                     retConv.push(_messages.conv[conversations[i].id]);
76182                     for (m in _messages.msg) {
76183                         if (_messages.msg[m].priv.conversationId === conversations[i].id) {
76184                             removeMsg.push(_messages.msg[m]);
76185                         }
76186                     }
76187                 }
76188             }
76189             if (na_msg === "") {
76190                 for (i = 0; i < removeMsg.length; i++) {
76191                     // conversation updated at remote
76192                     msg_utils.delMsg(removeMsg[i]);  // remote
76193                     delete _messages.msg[removeMsg[i].priv.id]; // local
76194                 }
76195                 // trigger msg(retMsg)/conv(retConv) delete update
76196                 _processMessageChange(removeMsg, "remove");
76197                 _processConversationChange(retConv, "remove");
76198                 if (onSuccess) {
76199                     setTimeout(function () {
76200                         onSuccess();
76201                     }, 1);
76202                 }
76203             } else {
76204                 if (onError) {
76205                     setTimeout(function () {
76206                         onError(new WebAPIError(errorcode.NOT_FOUND_ERR,
76207                                 na_msg + "not found !!"));
76208                     }, 1);
76209                 }
76210             }
76211         },
76212
76213         findFolders: function (filter, onSuccess, onError) {
76214             var ret = [], tmp, i;
76215
76216             if (_security_check.read === false) {
76217                 throw (new WebAPIException(errorcode.SECURITY_ERR));
76218             }
76219             if (!(new TypeCoerce(t.MessageFolderArraySuccessCallback)).match(onSuccess)) {
76220                 throw new WebAPIException(errorcode.TYPE_MISMATCH_ERR);
76221             }
76222             if (onError && !(new TypeCoerce(t.ErrorCallback)).match(onError)) {
76223                 throw new WebAPIException(errorcode.TYPE_MISMATCH_ERR);
76224             }
76225             switch (filter.attributeName) {
76226             case "id":
76227             case "serviceId":
76228             case "contentType":
76229             case "name":
76230             case "path":
76231             case "type":
76232                 tmp = tizen1_utils.matchAttributeFilter(_folders,
76233                           filter.attributeName, filter.matchFlag,
76234                           filter.matchValue);
76235                 break;
76236             case "synchronizable":
76237                 if (filter.matchFlag !== "EXACTLY" ||
76238                     typeof filter.matchValue !== "boolean") {
76239                     throw (new WebAPIException(errorcode.INVALID_VALUES_ERR,
76240                                   "Support only matchFlag === 'EXACTLY' and typeof matchValue === 'boolean'"));
76241                 }
76242                 tmp = tizen1_utils.matchAttributeBooleanFilter(_folders,
76243                           filter.attributeName, filter.matchValue);
76244                 break;
76245             case "parentId":
76246                 if (filter.matchValue === null) {
76247                     tmp = utils.filter(_folders, function (o) { return o.parentId === null; });
76248                 } else {
76249                     tmp = tizen1_utils.matchAttributeFilter(_folders,
76250                               filter.attributeName, filter.matchValue);
76251                 }
76252                 break;
76253             default:
76254                 throw (new WebAPIException(errorcode.INVALID_VALUES_ERR,
76255                                        "invalid attributeName"));
76256             }
76257             for (i = 0; i < tmp.length; i++) {
76258                 ret.push(new MessageFolder(tmp[i]));
76259             }
76260             setTimeout(function () {
76261                 onSuccess(ret);
76262             }, 1);
76263         },
76264
76265         addMessagesChangeListener: function (msgCallback, filter) {
76266             var watchId, msgListener = {};
76267
76268             if (_security_check.read === false) {
76269                 throw (new WebAPIException(errorcode.SECURITY_ERR));
76270             }
76271             if (!(new TypeCoerce(t.MessagesChangeCallback)).match(msgCallback)) {
76272                 throw new WebAPIException(errorcode.TYPE_MISMATCH_ERR);
76273             }
76274             if (filter && !(new TypeCoerce(t.AbstractFilter)).match(filter)) {
76275                 throw new WebAPIException(errorcode.TYPE_MISMATCH_ERR);
76276             }
76277
76278             watchId = Number(Math.uuid(8, 10));
76279             msgListener.callback = msgCallback;
76280             msgListener.filter = filter || null;
76281             _msgListeners[watchId] = msgListener;
76282             return watchId;
76283         },
76284
76285         addConversationsChangeListener: function (convCallback, filter) {
76286             var watchId, convListener = {};
76287
76288             if (_security_check.read === false) {
76289                 throw (new WebAPIException(errorcode.SECURITY_ERR));
76290             }
76291             if (!(new TypeCoerce(t.MessageConversationsChangeCallback)).match(convCallback)) {
76292                 throw new WebAPIException(errorcode.TYPE_MISMATCH_ERR);
76293             }
76294             if (filter && !(new TypeCoerce(t.AbstractFilter)).match(filter)) {
76295                 throw new WebAPIException(errorcode.TYPE_MISMATCH_ERR);
76296             }
76297
76298             watchId = Number(Math.uuid(8, 10));
76299             convListener.callback = convCallback;
76300             convListener.filter = filter || null;
76301             _convListeners[watchId] = convListener;
76302             return watchId;
76303         },
76304
76305         addFoldersChangeListener: function (callback, filter) {
76306             var watchId, folderListener = {};
76307
76308             if (_security_check.read === false) {
76309                 throw (new WebAPIException(errorcode.SECURITY_ERR));
76310             }
76311             if (!(new TypeCoerce(t.MessageFoldersChangeCallback)).match(callback)) {
76312                 throw new WebAPIException(errorcode.TYPE_MISMATCH_ERR);
76313             }
76314             if (filter && !(new TypeCoerce(t.AbstractFilter)).match(filter)) {
76315                 throw new WebAPIException(errorcode.TYPE_MISMATCH_ERR);
76316             }
76317
76318             watchId = Number(Math.uuid(8, 10));
76319             folderListener.callback = callback;
76320             folderListener.filter = filter || null;
76321             _folderListeners[watchId] = folderListener;
76322             return watchId;
76323         },
76324
76325         removeChangeListener: function (watchid) {
76326             if (_security_check.read === false) {
76327                 throw (new WebAPIException(errorcode.SECURITY_ERR));
76328             }
76329             if (!(new TypeCoerce(t.long)).match(watchid)) {
76330                 throw (new WebAPIException(errorcode.TYPE_MISMATCH_ERR));
76331             }
76332             if (_msgListeners[watchid] !== undefined) {
76333                 delete _msgListeners[watchid];
76334                 return;
76335             }
76336             if (_convListeners[watchid] !== undefined) {
76337                 delete _convListeners[watchid];
76338                 return;
76339             }
76340             if (_folderListeners[watchid] !== undefined) {
76341                 delete _folderListeners[watchid];
76342                 return;
76343             }
76344             throw (new WebAPIException(errorcode.NOT_FOUND_ERR));
76345         }
76346
76347     };
76348     return message_storage;
76349 };
76350
76351 module.exports = _self;
76352
76353 });
76354 define('ripple/platform/tizen/2.0/MessagingService', function (require, exports, module) {
76355 /*
76356  *  Copyright 2012 Intel Corporation.
76357  *
76358  * Licensed under the Apache License, Version 2.0 (the "License");
76359  * you may not use this file except in compliance with the License.
76360  * You may obtain a copy of the License at
76361  *
76362  * http://www.apache.org/licenses/LICENSE-2.0
76363  *
76364  * Unless required by applicable law or agreed to in writing, software
76365  * distributed under the License is distributed on an "AS IS" BASIS,
76366  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
76367  * See the License for the specific language governing permissions and
76368  * limitations under the License.
76369  */
76370
76371 var event = require('ripple/event'),
76372     errorcode = require('ripple/platform/tizen/2.0/errorcode'),
76373     deviceSettings = require('ripple/deviceSettings'),
76374     WebAPIError = require('ripple/platform/tizen/2.0/WebAPIError'),
76375     WebAPIException = require('ripple/platform/tizen/2.0/WebAPIException'),
76376     PrivMessage = require('ripple/platform/tizen/2.0/PrivMessage'),
76377     MessageStorage = require('ripple/platform/tizen/2.0/MessageStorage'),
76378     msg_utils = require('ripple/platform/tizen/2.0/msg_utils'),
76379     t = require('ripple/platform/tizen/2.0/typedef'),
76380     TypeCoerce = require('ripple/platform/tizen/2.0/typecoerce'),
76381     _self,
76382     TIZEN_DEFAULT_MSG_FROM = {"messaging.sms": "13572468",
76383                               "messaging.mms": "13572468",
76384                               "messaging.email": "tizen.simulator@tizen.org"},
76385     INCOMING_TYPE = {"messaging.sms": "sms",
76386                      "messaging.mms": "mms",
76387                      "messaging.email": "email"};
76388
76389 _self = function (id, type, security_check) {
76390     var msg_service = {},
76391         pendingOperations = {},
76392         _msgSending = {},
76393         _receivedEmails = [],
76394         _id = id,
76395         _type = type,
76396         _security_check = security_check,
76397         _from = TIZEN_DEFAULT_MSG_FROM[_type],
76398         _incomingType = INCOMING_TYPE[_type],
76399         _messages = msg_utils.loadMsg(_type, _id),
76400         _messageStorage = new MessageStorage(_messages, _security_check);
76401
76402     event.on("MessageSent", function (rst) {
76403         var i, rsp_ok = [], rsp_fail = [];
76404         // rst.msg is the real msg in module
76405         if (rst.msg.priv.type !== _type ||
76406             rst.msg.priv.serviceId !== _id) {
76407             // not my msg
76408             return;
76409         }
76410         if (_msgSending[rst.id] !== undefined) {
76411             for (i in rst) {
76412                 if ((i !== "id") && (i !== "msg")) {
76413                     if (rst[i] === true) {
76414                         rsp_ok.push(i);
76415                     } else {
76416                         rsp_fail.push(i);
76417                     }
76418                 }
76419             }
76420             rst.msg.priv.folderId = "SENTBOX";
76421             if (rsp_fail.length === 0) {
76422                 rst.msg.priv.messageStatus = "SENT";
76423                 _msgSending[rst.id].onsuccess(rsp_ok);
76424             } else {
76425                 rst.msg.priv.messageStatus = "FAILED";
76426                 _msgSending[rst.id].onerror(rsp_fail);
76427             }
76428             msg_utils.saveMsg(rst.msg);  // sync to remote
76429             event.trigger("MsgSentRst", [rst.msg]);
76430             delete _msgSending[rst.id];
76431         }
76432     });
76433
76434     event.on("MessageReceived", function (rst) {
76435         var m, opt = {}, msgInit = {}, msg = {};
76436
76437         if (rst.type !== _incomingType) {
76438             // not my msg
76439             return;
76440         }
76441         msgInit.plainBody = rst.body;
76442         msgInit.to = [_from];
76443         // TODO: handle attachment
76444         if (msg_utils.setMsg(msgInit, msg) === false) {
76445             throw (new WebAPIException(errorcode.TYPE_MISMATCH_ERR, "received message error"));
76446         }
76447         opt.id = Math.uuid(8, 16);
76448         opt.serviceId = _id;
76449         opt.conversationId = opt.id;
76450         opt.folderId = "INBOX";
76451         opt.type = _type;
76452         opt.timestamp = new Date();
76453         opt.from = rst.from;
76454         if (msg.attachments.length === 0) {
76455             opt.hasAttachment = false;
76456         } else {
76457             opt.hasAttachment = true;
76458         }
76459         opt.messageStatus = "RECEIVED";
76460         m = new PrivMessage(msg, opt);
76461         msg_utils.saveMsg(m);   // save in server
76462         if (_type !== "messaging.email") {
76463             _messages.msg[m.priv.id] = m;  // sync to local
76464             event.trigger("MsgRecv", [m]);
76465         } else {
76466             _receivedEmails.push(m);  // don't sync to local yet
76467         }
76468     });
76469
76470     msg_service = {
76471         sendMessage: function (_msg, onSuccess, onError) {
76472             var m, msg = {}, opt = {}, shortMsg = {}, rst = {};
76473             if (_security_check.write === false) {
76474                 throw (new WebAPIException(errorcode.SECURITY_ERR));
76475             }
76476             if (_msg === null || _msg === undefined || _msg.id === undefined) {
76477                 throw (new WebAPIException(errorcode.TYPE_MISMATCH_ERR));
76478             }
76479
76480             if (msg_utils.setMsg(_msg, msg) === false) {
76481                 throw (new WebAPIException(errorcode.TYPE_MISMATCH_ERR));
76482             }
76483             if ((arguments.length > 1) && onSuccess !== null && !(new TypeCoerce(t.SuccessCallback)).match(onSuccess)) {
76484                 throw new WebAPIException(errorcode.TYPE_MISMATCH_ERR);
76485             }
76486             if ((arguments.length > 2) && onError !== null && !(new TypeCoerce(t.ErrorCallback)).match(onError)) {
76487                 throw new WebAPIException(errorcode.TYPE_MISMATCH_ERR);
76488             }
76489             if (deviceSettings.retrieve("CELLULAR_NETWORK.status") === false &&
76490                 (_incomingType === 'sms' || _incomingType === 'mms')) {
76491                 if (onError) {
76492                     setTimeout(function () {
76493                         onError(new WebAPIError(errorcode.NETWORK_ERR));
76494                     }, 1);
76495                 }
76496                 return;
76497             }
76498             if (deviceSettings.retrieve("WIFI_NETWORK.status") === false &&
76499                 _incomingType === 'email') {
76500                 if (onError) {
76501                     setTimeout(function () {
76502                         onError(new WebAPIError(errorcode.NETWORK_ERR));
76503                     }, 1);
76504                 }
76505                 return;
76506             }
76507             if (typeof _msg.id === 'string') {
76508                 if (_messages.msg[_msg.id] === undefined) {
76509                     if (onError) {
76510                         setTimeout(function () {
76511                             onError(new WebAPIError(errorcode.INVALID_VALUES_ERR));
76512                         }, 1);
76513                     }
76514                     return;
76515                 }
76516                 if (_messages.msg[_msg.id].priv.messageStatus === "DRAFT") {
76517                     msg_utils.delMsg(_messages.msg[_msg.id]);
76518                     delete _messages.msg[_msg.id];
76519                 } else {
76520                     // if msg found in storage, it can only be a draft.
76521                     if (onError) {
76522                         setTimeout(function () {
76523                             onError(new WebAPIError(errorcode.UNKNOWN_ERR));
76524                         }, 1);
76525                     }
76526                     return;
76527                 }
76528             }
76529             opt.id = Math.uuid(8, 16);
76530             opt.serviceId = _id;
76531             if ((msg.inResponseTo !== null) &&
76532                 (_messages.msg[msg.inResponseTo] !== undefined) &&
76533                 (_messages.msg[msg.inResponseTo].priv.messageStatus !== "DRAFT")) {
76534                 opt.conversationId = _messages.msg[msg.inResponseTo].priv.conversationId;
76535             } else {
76536                 opt.conversationId = opt.id;
76537             }
76538             opt.folderId = "OUTBOX";
76539             opt.type = _type;
76540             opt.timestamp = new Date();
76541             opt.from = _from;
76542             if (msg.attachments.length === 0) {
76543                 opt.hasAttachment = false;
76544             } else {
76545                 opt.hasAttachment = true;
76546             }
76547             opt.messageStatus = "SENDING";
76548
76549             m = new PrivMessage(msg, opt);
76550             _messages.msg[m.priv.id] = m;
76551             msg_utils.saveMsg(m);  // sync to remote
76552             shortMsg.msg = m;   // pass by ref
76553             shortMsg.id = m.priv.id;
76554             shortMsg.body = m.body.plainBody;
76555             shortMsg.to = m.to.slice(0);
76556             shortMsg.cc = m.cc.slice(0);
76557             shortMsg.bcc = m.bcc.slice(0);
76558             event.trigger("OutsideMessageReceived", [shortMsg]);
76559             rst.onsuccess = onSuccess;
76560             rst.onerror = onError;
76561             _msgSending[m.priv.id] = rst;
76562         },
76563
76564         loadMessageBody: function (msg, onSuccess, onError) {
76565             var pendingID;
76566             if (_security_check.write === false) {
76567                 throw (new WebAPIException(errorcode.SECURITY_ERR));
76568             }
76569             if (_messages.msg[msg.id] === undefined) {
76570                 throw (new WebAPIException(errorcode.NOT_FOUND_ERR));
76571             }
76572             if (!(new TypeCoerce(t.MessageBodySuccessCallback)).match(onSuccess)) {
76573                 throw new WebAPIException(errorcode.TYPE_MISMATCH_ERR);
76574             }
76575             if ((arguments.length > 2) && onError !== null && !(new TypeCoerce(t.ErrorCallback)).match(onError)) {
76576                 throw new WebAPIException(errorcode.TYPE_MISMATCH_ERR);
76577             }
76578             pendingID = setTimeout(function () {
76579                 if (pendingOperations.hasOwnProperty(pendingID) === false) {
76580                     // has been cancelled/expired
76581                     return;
76582                 }
76583                 delete pendingOperations[pendingID];
76584                 onSuccess(_messages.msg[msg.id].body);
76585             }, 1);
76586             pendingOperations[pendingID] = onError;
76587             return pendingID;
76588         },
76589         loadMessageAttachment: function (msg, onSuccess, onError) {
76590             var pendingID;
76591
76592             if (_security_check.write === false) {
76593                 throw (new WebAPIException(errorcode.SECURITY_ERR));
76594             }
76595             if (_messages.msg[msg.id] === undefined) {
76596                 throw (new WebAPIException(errorcode.NOT_FOUND_ERR));
76597             }
76598             if (!(new TypeCoerce(t.MessageAttachmentSuccessCallback)).match(onSuccess)) {
76599                 throw new WebAPIException(errorcode.TYPE_MISMATCH_ERR);
76600             }
76601             if ((arguments.length > 2) && onError !== null && !(new TypeCoerce(t.ErrorCallback)).match(onError)) {
76602                 throw new WebAPIException(errorcode.TYPE_MISMATCH_ERR);
76603             }
76604             pendingID = setTimeout(function () {
76605                 if (pendingOperations.hasOwnProperty(pendingID) === false) {
76606                     // has been cancelled/expired
76607                     return;
76608                 }
76609                 delete pendingOperations[pendingID];
76610                 onSuccess(_messages.msg[msg.id].attachments);
76611             }, 1);
76612             pendingOperations[pendingID] = onError;
76613             return pendingID;
76614         },
76615         sync: function (successCallback, errorCallback, limit) {
76616             var i, m, pendingID;
76617
76618             if (_security_check.write === false) {
76619                 throw (new WebAPIException(errorcode.SECURITY_ERR));
76620             }
76621             if ((arguments.length > 0) && successCallback !== null && !(new TypeCoerce(t.SuccessCallback)).match(successCallback)) {
76622                 throw new WebAPIException(errorcode.TYPE_MISMATCH_ERR);
76623             }
76624             if ((arguments.length > 1) && errorCallback !== null && !(new TypeCoerce(t.ErrorCallback)).match(errorCallback)) {
76625                 throw new WebAPIException(errorcode.TYPE_MISMATCH_ERR);
76626             }
76627             if ((arguments.length > 2) && limit !== null && !(new TypeCoerce(t.long)).match(limit)) {
76628                 throw new WebAPIException(errorcode.TYPE_MISMATCH_ERR);
76629             }
76630             pendingID = setTimeout(function () {
76631                 if (pendingOperations.hasOwnProperty(pendingID) === false) {
76632                     // has been cancelled/expired
76633                     return;
76634                 }
76635                 delete pendingOperations[pendingID];
76636                 for (i = 0; i < _receivedEmails.length; i++) {
76637                     m = _receivedEmails[i];
76638                     _messages.msg[m.priv.id] = m;  // sync to local
76639                     event.trigger("MsgRecv", [m]);
76640                 }
76641                 _receivedEmails = [];
76642                 if (successCallback) {
76643                     successCallback();
76644                 }
76645             }, 1);
76646             pendingOperations[pendingID] = errorCallback;
76647             return pendingID;
76648         },
76649
76650         syncFolder: function (folder, onSuccess, onError, limit) {
76651             var i, m, pendingID;
76652
76653             if (_security_check.write === false) {
76654                 throw (new WebAPIException(errorcode.SECURITY_ERR));
76655             }
76656             if (!(new TypeCoerce(t.MessageFolder)).match(folder)) {
76657                 throw new WebAPIException(errorcode.TYPE_MISMATCH_ERR);
76658             }
76659             if ((arguments.length > 1) && onSuccess !== null && !(new TypeCoerce(t.SuccessCallback)).match(onSuccess)) {
76660                 throw new WebAPIException(errorcode.TYPE_MISMATCH_ERR);
76661             }
76662             if ((arguments.length > 2) && onError !== null && !(new TypeCoerce(t.ErrorCallback)).match(onError)) {
76663                 throw new WebAPIException(errorcode.TYPE_MISMATCH_ERR);
76664             }
76665             if ((arguments.length > 3) && limit !== null && !(new TypeCoerce(t.long)).match(limit)) {
76666                 throw new WebAPIException(errorcode.TYPE_MISMATCH_ERR);
76667             }
76668             pendingID = setTimeout(function () {
76669                 if (pendingOperations.hasOwnProperty(pendingID) === false) {
76670                     // has been cancelled/expired
76671                     return;
76672                 }
76673                 delete pendingOperations[pendingID];
76674                 if (folder.id === "INBOX") {
76675                     for (i = 0; i < _receivedEmails.length; i++) {
76676                         m = _receivedEmails[i];
76677                         _messages.msg[m.priv.id] = m;  // sync to local
76678                         event.trigger("MsgRecv", [m]);
76679                     }
76680                     _receivedEmails = [];
76681                 }
76682                 onSuccess();
76683             }, 1);
76684             pendingOperations[pendingID] = onError;
76685             return pendingID;
76686         },
76687
76688         stopSync: function (pendingID) {
76689             if (!(new TypeCoerce(t.long)).match(pendingID)) {
76690                 throw new WebAPIException(errorcode.TYPE_MISMATCH_ERR);
76691             }
76692             if (pendingOperations[pendingID] !== undefined) {
76693                 clearTimeout(pendingID);
76694                 pendingOperations[pendingID](new WebAPIError(errorcode.ABORT_ERR));
76695             }
76696             delete pendingOperations[pendingID];
76697         }
76698     };
76699     msg_service.__defineGetter__("type", function () {
76700         return _type;
76701     });
76702     msg_service.__defineGetter__("messageStorage", function () {
76703         return _messageStorage;
76704     });
76705     return msg_service;
76706 };
76707
76708 module.exports = _self;
76709
76710 });
76711 define('ripple/platform/tizen/2.0/NDEFMessage', function (require, exports, module) {
76712 /*
76713  *  Copyright 2012 Intel Corporation
76714  *
76715  * Licensed under the Apache License, Version 2.0 (the "License");
76716  * you may not use _self file except in compliance with the License.
76717  * You may obtain a copy of the License at
76718  *
76719  * http://www.apache.org/licenses/LICENSE-2.0
76720  *
76721  * Unless required by applicable law or agreed to in writing, software
76722  * distributed under the License is distributed on an "AS IS" BASIS,
76723  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
76724  * See the License for the specific language governing permissions and
76725  * limitations under the License.
76726  */
76727
76728 module.exports = function (ndefRecords) {
76729     //TODO: NDEFMessage doesn't support rawData constructor
76730     var _self,
76731         _ndefRecords = ndefRecords || [],
76732         space = " ",
76733         _recordCount;
76734
76735     _recordCount = _ndefRecords.length;
76736
76737     _self = {
76738         records : _ndefRecords,
76739         toByte : function () {
76740             var result = [], i, j;
76741             for (i in this.records) {
76742                 for (j = 0; j < this.records[i].payload.length; j++) {
76743                     result.push(this.records[i].payload.charCodeAt(j));
76744                 }
76745                 if (i < this.records.length - 1) {
76746                     result.push(space.charCodeAt(0));
76747                 }
76748             }
76749             return result;
76750         }
76751     };
76752
76753     _self.__defineGetter__("recordCount", function () {
76754         return _recordCount;
76755     });
76756
76757     return _self;
76758 };
76759
76760 });
76761 define('ripple/platform/tizen/2.0/NDEFRecord', function (require, exports, module) {
76762 /*
76763  *  Copyright 2012 Intel Corporation
76764  *
76765  * Licensed under the Apache License, Version 2.0 (the "License");
76766  * you may not use _self file except in compliance with the License.
76767  * You may obtain a copy of the License at
76768  *
76769  * http://www.apache.org/licenses/LICENSE-2.0
76770  *
76771  * Unless required by applicable law or agreed to in writing, software
76772  * distributed under the License is distributed on an "AS IS" BASIS,
76773  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
76774  * See the License for the specific language governing permissions and
76775  * limitations under the License.
76776  */
76777 var errorcode = require('ripple/platform/tizen/2.0/errorcode'),
76778     WebAPIException = require('ripple/platform/tizen/2.0/WebAPIException');
76779
76780 module.exports = function (tnf, type, payload, id) {
76781     var _self = {},
76782         _tnf = tnf,
76783         _type = type,
76784         _id = id || [],
76785         _payload = payload;
76786
76787     if (arguments.length < 3) {
76788         throw new WebAPIException(errorcode.TYPE_MISMATCH_ERR);
76789     }
76790     _self.__defineGetter__("tnf", function () {
76791         return _tnf;
76792     });
76793
76794     _self.__defineGetter__("type", function () {
76795         return _type;
76796     });
76797
76798     _self.__defineGetter__("id", function () {
76799         return _id;
76800     });
76801
76802     _self.__defineGetter__("payload", function () {
76803         return _payload;
76804     });
76805     return _self;
76806 };
76807
76808 });
76809 define('ripple/platform/tizen/2.0/NDEFRecordMedia', function (require, exports, module) {
76810 /*
76811  *  Copyright 2012 Intel Corporation
76812  *
76813  * Licensed under the Apache License, Version 2.0 (the "License");
76814  * you may not use _self file except in compliance with the License.
76815  * You may obtain a copy of the License at
76816  *
76817  * http://www.apache.org/licenses/LICENSE-2.0
76818  *
76819  * Unless required by applicable law or agreed to in writing, software
76820  * distributed under the License is distributed on an "AS IS" BASIS,
76821  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
76822  * See the License for the specific language governing permissions and
76823  * limitations under the License.
76824  */
76825
76826 var NDEFRecord = require('ripple/platform/tizen/2.0/NDEFRecord'),
76827     errorcode = require('ripple/platform/tizen/2.0/errorcode'),
76828     WebAPIException = require('ripple/platform/tizen/2.0/WebAPIException');
76829
76830 module.exports = function (mimeType, data) {
76831     var _self = {},
76832         _mimeType = mimeType,
76833         _data = data;
76834
76835     if (arguments.length < 2) {
76836         throw new WebAPIException(errorcode.TYPE_MISMATCH_ERR);
76837     }
76838
76839     _self = new NDEFRecord(2, [], [], []);
76840
76841     _self.__defineGetter__("mimeType", function () {
76842         return _mimeType;
76843     });
76844
76845     _self.__defineGetter__("data", function () {
76846         return _data;
76847     });
76848     return _self;
76849 };
76850
76851 });
76852 define('ripple/platform/tizen/2.0/NDEFRecordText', function (require, exports, module) {
76853 /*
76854  *  Copyright 2012 Intel Corporation
76855  *
76856  * Licensed under the Apache License, Version 2.0 (the "License");
76857  * you may not use _self file except in compliance with the License.
76858  * You may obtain a copy of the License at
76859  *
76860  * http://www.apache.org/licenses/LICENSE-2.0
76861  *
76862  * Unless required by applicable law or agreed to in writing, software
76863  * distributed under the License is distributed on an "AS IS" BASIS,
76864  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
76865  * See the License for the specific language governing permissions and
76866  * limitations under the License.
76867  */
76868
76869 var NDEFRecord = require('ripple/platform/tizen/2.0/NDEFRecord');
76870
76871 module.exports = function (text, languageCode, encoding) {
76872     var _self = {},
76873         _text = text,
76874         _languageCode = languageCode,
76875         _encoding = encoding;
76876
76877     _self = new NDEFRecord(1, [], [], []);
76878
76879     _self.__defineGetter__("text", function () {
76880         return _text;
76881     });
76882
76883     _self.__defineGetter__("languageCode", function () {
76884         return _languageCode;
76885     });
76886
76887     _self.__defineGetter__("encoding", function () {
76888         return _encoding;
76889     });
76890
76891     return _self;
76892 };
76893
76894 });
76895 define('ripple/platform/tizen/2.0/NDEFRecordURI', function (require, exports, module) {
76896 /*
76897  *  Copyright 2012 Intel Corporation
76898  *
76899  * Licensed under the Apache License, Version 2.0 (the "License");
76900  * you may not use _self file except in compliance with the License.
76901  * You may obtain a copy of the License at
76902  *
76903  * http://www.apache.org/licenses/LICENSE-2.0
76904  *
76905  * Unless required by applicable law or agreed to in writing, software
76906  * distributed under the License is distributed on an "AS IS" BASIS,
76907  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
76908  * See the License for the specific language governing permissions and
76909  * limitations under the License.
76910  */
76911
76912 var NDEFRecord = require('ripple/platform/tizen/2.0/NDEFRecord');
76913
76914 module.exports = function (uri) {
76915     var _self = {},
76916         _uri = uri;
76917
76918     _self = new NDEFRecord(3, [], [], []);
76919
76920     _self.__defineGetter__("uri", function () {
76921         return _uri;
76922     });
76923
76924     return _self;
76925 };
76926
76927 });
76928 define('ripple/platform/tizen/2.0/NotificationBase', function (require, exports, module) {
76929 /*
76930  *  Copyright 2012 Intel Corporation.
76931  *
76932  * Licensed under the Apache License, Version 2.0 (the "License");
76933  * you may not use this file except in compliance with the License.
76934  * You may obtain a copy of the License at
76935  *
76936  * http://www.apache.org/licenses/LICENSE-2.0
76937  *
76938  * Unless required by applicable law or agreed to in writing, software
76939  * distributed under the License is distributed on an "AS IS" BASIS,
76940  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
76941  * See the License for the specific language governing permissions and
76942  * limitations under the License.
76943  */
76944
76945 module.exports = function (_title) {
76946     var id = Math.uuid(null, 16),
76947         type = "STATUS",
76948         postedTime,
76949         title = _title,
76950         content,
76951         _self = {};
76952
76953     _self.__defineGetter__("id", function () {
76954         return id;
76955     });
76956     _self.__defineGetter__("type", function () {
76957         return type;
76958     });
76959     _self.__defineGetter__("postedTime", function () {
76960         return postedTime;
76961     });
76962     _self.__defineGetter__("title", function () {
76963         return title;
76964     });
76965     _self.__defineSetter__("title", function (_title) {
76966         title = _title;
76967     });
76968     _self.__defineGetter__("content", function () {
76969         return content;
76970     });
76971     _self.__defineSetter__("content", function (_content) {
76972         content = _content;
76973     });
76974
76975     return _self;
76976 };
76977 });
76978 define('ripple/platform/tizen/2.0/NotificationDetailInfo', function (require, exports, module) {
76979 /*
76980  *  Copyright 2012 Intel Corporation.
76981  *
76982  * Licensed under the Apache License, Version 2.0 (the "License");
76983  * you may not use this file except in compliance with the License.
76984  * You may obtain a copy of the License at
76985  *
76986  * http://www.apache.org/licenses/LICENSE-2.0
76987  *
76988  * Unless required by applicable law or agreed to in writing, software
76989  * distributed under the License is distributed on an "AS IS" BASIS,
76990  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
76991  * See the License for the specific language governing permissions and
76992  * limitations under the License.
76993  */
76994
76995 module.exports = function (mainText, subText) {
76996     var _self;
76997     _self = {
76998         mainText: mainText,
76999         subText: subText || null
77000     };
77001
77002     return _self;
77003 };
77004
77005 });
77006 define('ripple/platform/tizen/2.0/POIBase', function (require, exports, module) {
77007 /*
77008  *  Copyright 2012 Intel Corporation.
77009  *
77010  * Licensed under the Apache License, Version 2.0 (the "License");
77011  * you may not use this file except in compliance with the License.
77012  * You may obtain a copy of the License at
77013  *
77014  * http://www.apache.org/licenses/LICENSE-2.0
77015  *
77016  * Unless required by applicable law or agreed to in writing, software
77017  * distributed under the License is distributed on an "AS IS" BASIS,
77018  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
77019  * See the License for the specific language governing permissions and
77020  * limitations under the License.
77021  */
77022
77023 var tizen1_utils = require('ripple/platform/tizen/2.0/tizen1_utils'),
77024     POIGeometry = require('ripple/platform/tizen/2.0/POIGeometry'),
77025     errorcode = require('ripple/platform/tizen/2.0/errorcode'),
77026     WebAPIError = require('ripple/platform/tizen/2.0/WebAPIError');
77027
77028
77029 module.exports = function (prop) {
77030     var _self, i, copy, attr;
77031     _self = {
77032         name : null,
77033         categories : [],
77034         address : null,
77035         phoneNumbers : [],
77036         geometry : null,
77037         urls : [],
77038         rating : null,
77039         tags : null,
77040         toGeoJSON : function () {
77041             throw new WebAPIError(errorcode.NOT_SUPPORTED_ERR);
77042         }
77043     };
77044
77045     _self.__defineGetter__("id", function () {
77046         return null;
77047     });
77048
77049     _self.__defineGetter__("providerName", function () {
77050         return null;
77051     });
77052
77053     if (prop) {
77054         if (prop.name) {
77055             _self.name = String(prop.name);
77056         }
77057         if (tizen1_utils.isValidArray(prop.categories)) {
77058             _self.categories = [];
77059             for (i in prop.categories) {
77060                 _self.categories.push(String(prop.categories[i]));
77061             }
77062         }
77063         if (prop.address) {
77064             if (typeof prop.address === "string") {
77065                 _self.address = String(prop.address);
77066             } else if (Object.prototype.toString.call(prop.address) === "[object Object]") {
77067                 copy = prop.address.constructor();
77068                 for (attr in prop.address) {
77069                     if (prop.address.hasOwnProperty(attr)) {
77070                         copy[attr] = prop.address[attr];
77071                     }
77072                 }
77073                 _self.address = copy;
77074             }
77075         }
77076         if (tizen1_utils.isValidArray(prop.phoneNumbers)) {
77077             _self.phoneNumbers = [];
77078             for (i in prop.phoneNumbers) {
77079                 _self.phoneNumbers.push(String(prop.phoneNumbers[i]));
77080             }
77081         }
77082         if (prop.geometry) {
77083             _self.geometry = new POIGeometry(prop.geometry.position, prop.geometry.viewport, prop.geometry.wkt);
77084         }
77085         if (tizen1_utils.isValidArray(prop.urls)) {
77086             _self.urls = [];
77087             for (i in prop.urls) {
77088                 _self.urls.push(String(prop.urls[i]));
77089             }
77090         }
77091         if (typeof prop.rating === "number") {
77092             _self.rating = prop.rating;
77093         }
77094         if (Object.prototype.toString.call(prop.tags) === "[object Object]") {
77095             copy = prop.tags.constructor();
77096             for (attr in prop.tags) {
77097                 if (prop.tags.hasOwnProperty(attr)) {
77098                     copy[attr] = prop.tags[attr];
77099                 }
77100             }
77101             _self.tags = copy;
77102         }
77103     }
77104
77105     return _self;
77106 };
77107
77108 });
77109 define('ripple/platform/tizen/2.0/POIFilter', function (require, exports, module) {
77110 /*
77111  *  Copyright 2012 Intel Corporation.
77112  *
77113  * Licensed under the Apache License, Version 2.0 (the "License");
77114  * you may not use this file except in compliance with the License.
77115  * You may obtain a copy of the License at
77116  *
77117  * http://www.apache.org/licenses/LICENSE-2.0
77118  *
77119  * Unless required by applicable law or agreed to in writing, software
77120  * distributed under the License is distributed on an "AS IS" BASIS,
77121  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
77122  * See the License for the specific language governing permissions and
77123  * limitations under the License.
77124  */
77125
77126 module.exports = function (attributeName, value) {
77127     var _self;
77128
77129     _self = {
77130         attributeName: attributeName,
77131         value: value
77132     };
77133
77134     return _self;
77135 };
77136
77137 });
77138 define('ripple/platform/tizen/2.0/POIGeometry', function (require, exports, module) {
77139 /*
77140  *  Copyright 2012 Intel Corporation.
77141  *
77142  * Licensed under the Apache License, Version 2.0 (the "License");
77143  * you may not use this file except in compliance with the License.
77144  * You may obtain a copy of the License at
77145  *
77146  * http://www.apache.org/licenses/LICENSE-2.0
77147  *
77148  * Unless required by applicable law or agreed to in writing, software
77149  * distributed under the License is distributed on an "AS IS" BASIS,
77150  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
77151  * See the License for the specific language governing permissions and
77152  * limitations under the License.
77153  */
77154
77155 var SimpleCoordinates = require('ripple/platform/tizen/2.0/SimpleCoordinates'),
77156     GeoRectBounds = require('ripple/platform/tizen/2.0/GeoRectBounds');
77157
77158 module.exports = function (position, viewport, wkt) {
77159     var _self, _position = null, _viewport = null, _wkt = "";
77160
77161     if (position) {
77162         _position = new SimpleCoordinates(position.latitude, position.longitude);
77163     }
77164
77165     if (viewport) {
77166         _viewport = new GeoRectBounds(viewport.southWest, viewport.northEast);
77167     }
77168
77169     if (wkt) {
77170         _wkt = String(wkt);
77171     }
77172
77173     _self = {
77174         position : _position,
77175         viewport: _viewport,
77176         wkt: _wkt
77177     };
77178
77179     return _self;
77180 };
77181
77182 });
77183 define('ripple/platform/tizen/2.0/PackageInformation', function (require, exports, module) {
77184 /*
77185  *  Copyright 2013 Intel Corporation.
77186  *
77187  * Licensed under the Apache License, Version 2.0 (the "License");
77188  * you may not use this file except in compliance with the License.
77189  * You may obtain a copy of the License at
77190  *
77191  * http://www.apache.org/licenses/LICENSE-2.0
77192  *
77193  * Unless required by applicable law or agreed to in writing, software
77194  * distributed under the License is distributed on an "AS IS" BASIS,
77195  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
77196  * See the License for the specific language governing permissions and
77197  * limitations under the License.
77198  */
77199 module.exports = function (id, name, iconPath, version, totalSize,
77200         dataSize, lastModified, author, description, appIds) {
77201     var packageInformation = {}, _date = new Date(lastModified);
77202
77203     packageInformation.__defineGetter__("id", function () {
77204         return id;
77205     });
77206     packageInformation.__defineGetter__("name", function () {
77207         return name;
77208     });
77209     packageInformation.__defineGetter__("iconPath", function () {
77210         return iconPath;
77211     });
77212     packageInformation.__defineGetter__("version", function () {
77213         return version;
77214     });
77215     packageInformation.__defineGetter__("totalSize", function () {
77216         return totalSize;
77217     });
77218     packageInformation.__defineGetter__("dataSize", function () {
77219         return dataSize;
77220     });
77221     packageInformation.__defineGetter__("lastModified", function () {
77222         return _date;
77223     });
77224     packageInformation.__defineGetter__("author", function () {
77225         return author;
77226     });
77227     packageInformation.__defineGetter__("description", function () {
77228         return description;
77229     });
77230     packageInformation.__defineGetter__("appIds", function () {
77231         return appIds;
77232     });
77233
77234     return packageInformation;
77235 };
77236
77237 });
77238 define('ripple/platform/tizen/2.0/PrivMessage', function (require, exports, module) {
77239 /*
77240  *  Copyright 2012 Intel Corporation.
77241  *
77242  * Licensed under the Apache License, Version 2.0 (the "License"),
77243  * you may not use this file except in compliance with the License.
77244  * You may obtain a copy of the License at
77245  *
77246  * http://www.apache.org/licenses/LICENSE-2.0
77247  *
77248  * Unless required by applicable law or agreed to in writing, software
77249  * distributed under the License is distributed on an "AS IS" BASIS,
77250  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
77251  * See the License for the specific language governing permissions and
77252  * limitations under the License.
77253  */
77254 var utils = require('ripple/utils');
77255
77256 module.exports = function (m, opt) {
77257     return {
77258 // readonly begin
77259         priv: {id: opt.id,
77260                serviceId: opt.serviceId,
77261                conversationId: opt.conversationId,
77262                folderId: opt.folderId,
77263                type: opt.type,
77264                timestamp: new Date(opt.timestamp),
77265                from: opt.from,
77266                hasAttachment: opt.hasAttachment,
77267                messageStatus: opt.messageStatus
77268         },
77269 // readonly end
77270         to: m.to.slice(0),
77271         cc: m.cc.slice(0),
77272         bcc: m.bcc.slice(0),
77273         body: utils.copy(m.body),
77274         isRead: m.isRead,
77275         isHighPriority: m.isHighPriority,
77276         subject: m.subject,
77277         inResponseTo: m.inResponseTo,
77278         attachments: utils.copy(m.attachments)
77279     };
77280 };
77281
77282 });
77283 define('ripple/platform/tizen/2.0/RequestedApplicationControl', function (require, exports, module) {
77284 /*
77285  *  Copyright 2012 Intel Corporation.
77286  *
77287  * Licensed under the Apache License, Version 2.0 (the "License");
77288  * you may not use this file except in compliance with the License.
77289  * You may obtain a copy of the License at
77290  *
77291  * http://www.apache.org/licenses/LICENSE-2.0
77292  *
77293  * Unless required by applicable law or agreed to in writing, software
77294  * distributed under the License is distributed on an "AS IS" BASIS,
77295  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
77296  * See the License for the specific language governing permissions and
77297  * limitations under the License.
77298  */
77299
77300 var event = require('ripple/event');
77301
77302 module.exports = function (appControl) {
77303     var _self, _appControl = appControl;
77304
77305     _self = {
77306         replyResult: function (data) {
77307             event.trigger("appServiceReplied", "Result: " + data);
77308         },
77309         replyFailure: function () {
77310             event.trigger("appServiceReplied", "Failure");
77311         }
77312     };
77313
77314     _self.__defineGetter__("appControl", function () {
77315         return _appControl;
77316     });
77317
77318     return _self;
77319 };
77320
77321 });
77322 define('ripple/platform/tizen/2.0/ReverseGeocodeOptions', function (require, exports, module) {
77323 /*      
77324  *  Copyright 2012 Intel Corporation.
77325  *  
77326  * Licensed under the Apache License, Version 2.0 (the "License");
77327  * you may not use this file except in compliance with the License.
77328  * You may obtain a copy of the License at
77329  *  
77330  * http://www.apache.org/licenses/LICENSE-2.0
77331  *  
77332  * Unless required by applicable law or agreed to in writing, software
77333  * distributed under the License is distributed on an "AS IS" BASIS,
77334  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
77335  * See the License for the specific language governing permissions and
77336  * limitations under the License.
77337  */
77338 var errorcode = require('ripple/platform/tizen/2.0/errorcode'),
77339     WebAPIError = require('ripple/platform/tizen/2.0/WebAPIError'),
77340     SortMode = require('ripple/platform/tizen/2.0/SortMode');
77341
77342 module.exports = function (_sortMode, _resultType, _maxResults) {
77343     var _self;
77344     if (_sortMode !== null && _sortMode !== undefined) {
77345         if (typeof _sortMode !== "object") {
77346             throw (new WebAPIError(errorcode.TYPE_MISMATCH_ERR));
77347         }
77348         try {
77349             new SortMode(_sortMode.attributeName, _sortMode.order);
77350         } catch (e) {
77351             throw (new WebAPIError(errorcode.TYPE_MISMATCH_ERR));
77352         }
77353     }
77354     if (_resultType !== null && _resultType !== undefined) {
77355         if (_resultType !== "FORMATTED" && _resultType !== "STRUCTURED") {
77356             throw (new WebAPIError(errorcode.TYPE_MISMATCH_ERR));
77357         }
77358     }
77359     if (_maxResults !== null && _maxResults !== undefined) {
77360         if (typeof _maxResults !== "number") {
77361             throw (new WebAPIError(errorcode.TYPE_MISMATCH_ERR));
77362         }
77363     }
77364     _self = {
77365         sortMode : _sortMode,
77366         resultType : _resultType || "FORMATTED",
77367         maxResults : _maxResults || 0
77368     };
77369
77370     return _self;
77371 };
77372
77373
77374 });
77375 define('ripple/platform/tizen/2.0/SimpleCoordinates', function (require, exports, module) {
77376 /*      
77377  *  Copyright 2012 Intel Corporation.
77378  *  
77379  * Licensed under the Apache License, Version 2.0 (the "License");
77380  * you may not use this file except in compliance with the License.
77381  * You may obtain a copy of the License at
77382  *  
77383  * http://www.apache.org/licenses/LICENSE-2.0
77384  *  
77385  * Unless required by applicable law or agreed to in writing, software
77386  * distributed under the License is distributed on an "AS IS" BASIS,
77387  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
77388  * See the License for the specific language governing permissions and
77389  * limitations under the License.
77390  */
77391
77392 function SimpleCoordinates (_latitude, _longitude) {
77393     this.latitude = _latitude || 0;
77394     this.longitude = _longitude || 0;
77395     return this;
77396 };
77397
77398 module.exports = SimpleCoordinates;
77399
77400 });
77401 define('ripple/platform/tizen/2.0/SortMode', function (require, exports, module) {
77402 /*      
77403  *  Copyright 2012 Intel Corporation.
77404  *  
77405  * Licensed under the Apache License, Version 2.0 (the "License");
77406  * you may not use this file except in compliance with the License.
77407  * You may obtain a copy of the License at
77408  *  
77409  * http://www.apache.org/licenses/LICENSE-2.0
77410  *  
77411  * Unless required by applicable law or agreed to in writing, software
77412  * distributed under the License is distributed on an "AS IS" BASIS,
77413  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
77414  * See the License for the specific language governing permissions and
77415  * limitations under the License.
77416  */
77417
77418 var errorcode = require('ripple/platform/tizen/2.0/errorcode'),
77419     WebAPIError = require('ripple/platform/tizen/2.0/WebAPIError');
77420
77421 module.exports = function (_attributeName, _order) {
77422     var _self;
77423     if (_attributeName !== null && _attributeName !== undefined) {
77424         if (typeof _attributeName !== "string") {
77425             throw (new WebAPIError(errorcode.TYPE_MISMATCH_ERR));
77426         }
77427     }
77428     if (_order !== null && _order !== undefined) {
77429         if (_order !== "ASC" && _order !== "DESC") {
77430             throw (new WebAPIError(errorcode.TYPE_MISMATCH_ERR));
77431         }
77432     }
77433     _self = {
77434         attributeName: _attributeName,
77435         order: _order,
77436     };
77437
77438     return _self;
77439 };
77440
77441
77442 });
77443 define('ripple/platform/tizen/2.0/StatusNotification', function (require, exports, module) {
77444 /*
77445  *  Copyright 2012 Intel Corporation.
77446  *
77447  * Licensed under the Apache License, Version 2.0 (the "License");
77448  * you may not use this file except in compliance with the License.
77449  * You may obtain a copy of the License at
77450  *
77451  * http://www.apache.org/licenses/LICENSE-2.0
77452  *
77453  * Unless required by applicable law or agreed to in writing, software
77454  * distributed under the License is distributed on an "AS IS" BASIS,
77455  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
77456  * See the License for the specific language governing permissions and
77457  * limitations under the License.
77458  */
77459
77460 var utils = require('ripple/utils'),
77461     NotificationBase = require('ripple/platform/tizen/2.0/NotificationBase'),
77462     errorcode = require('ripple/platform/tizen/2.0/errorcode'),
77463     WebAPIError = require('ripple/platform/tizen/2.0/WebAPIError'),
77464     tizen1_utils = require('ripple/platform/tizen/2.0/tizen1_utils'),
77465     _self;
77466
77467 function _checkServiceProperties(service) {
77468     if (typeof service !== "object") {
77469         return false;
77470     }
77471
77472     if (typeof service.operation !== "string") {
77473         return false;
77474     }
77475
77476     if (service.uri && typeof service.uri !== "string") {
77477         return false;
77478     }
77479
77480     if (service.mime && typeof service.mime !== "string") {
77481         return false;
77482     }
77483
77484     if (service.data && !tizen1_utils.isValidArray(service.data)) {
77485         return false;
77486     }
77487
77488     return true;
77489 }
77490
77491 function _checkNotificationDetailInfo(info) {
77492     if (typeof info !== "object") {
77493         return false;
77494     }
77495
77496     if (typeof info.mainText !== "string") {
77497         return false;
77498     }
77499
77500     if (info.subText && typeof info.subText !== "string") {
77501         return false;
77502     }
77503
77504     return true;
77505 }
77506
77507 function _checkDictProperties(dict) {
77508     var flag = false;
77509     if (dict) {
77510         if (typeof dict !== "object") {
77511             return false;
77512         }
77513
77514         if (dict.content && typeof dict.content !== "string") {
77515             return false;
77516         }
77517
77518         if (dict.iconPath && typeof dict.iconPath !== "string") {
77519             return false;
77520         }
77521
77522         if (dict.soundPath && typeof dict.soundPath !== "string") {
77523             return false;
77524         }
77525
77526         if (dict.vibration && typeof dict.vibration !== "boolean") {
77527             return false;
77528         }
77529
77530         if (dict.appControl && !_checkServiceProperties(dict.appControl)) {
77531             return false;
77532         }
77533
77534         if (dict.appId && typeof dict.appId !== "string") {
77535             return false;
77536         }
77537
77538         if (dict.progressType && !(dict.progressType === "PERCENTAGE" || dict.progressType === "BYTE")) {
77539             return false;
77540         }
77541
77542         if (dict.progressValue && typeof dict.progressValue !== "number") {
77543             return false;
77544         }
77545
77546         if (dict.number && typeof dict.number !== "number") {
77547             return false;
77548         }
77549
77550         if (dict.subIconPath && typeof dict.subIconPath !== "string") {
77551             return false;
77552         }
77553
77554         if (dict.detailInfo) {
77555             if (!tizen1_utils.isValidArray(dict.detailInfo)) {
77556                 return false;
77557             }
77558             flag = false;
77559             utils.forEach(dict.detailInfo, function (info) {
77560                 if (!_checkNotificationDetailInfo(info)) {
77561                     flag = true;
77562                 }
77563             });
77564             if (flag === true) {
77565                 return false;
77566             }
77567         }
77568
77569         if (dict.backgroundImagePath && typeof dict.backgroundImagePath !== "string") {
77570             return false;
77571         }
77572
77573         if (dict.thumbnails) {
77574             if (!tizen1_utils.isValidArray(dict.thumbnails)) {
77575                 return false;
77576             }
77577
77578             flag = false;
77579             utils.forEach(dict.thumbnails, function (thumbnail) {
77580                 if (typeof thumbnail !== "string") {
77581                     flag = true;
77582                 }
77583             });
77584             if (flag === true) {
77585                 return false;
77586             }
77587         }
77588     }
77589     return true;
77590 }
77591
77592 _self = function (_statusType, title, notificationInitDict) {
77593     var statusType,
77594         notification;
77595
77596     if (typeof _statusType !== "string" || !(_statusType === "SIMPLE" || _statusType === "THUMBNAIL" || _statusType === "ONGOING" || _statusType === "PROGRESS")        || typeof title !== "string" || !_checkDictProperties(notificationInitDict)) {
77597         throw (new WebAPIError(errorcode.TYPE_MISMATCH_ERR));
77598     }
77599
77600     if (notificationInitDict && _statusType === "PROGRESS" && notificationInitDict.progressValue &&
77601         (notificationInitDict.progressValue < 1 || notificationInitDict.progressValue > 100)) {
77602         throw (new WebAPIError(errorcode.INVALID_VALUES_ERR));
77603     }
77604
77605     statusType = _statusType;
77606     notification = new NotificationBase(title);
77607     notification.__defineGetter__("statusType", function () {
77608         return statusType;
77609     });
77610
77611     if (notificationInitDict) {
77612         notification.content = notificationInitDict.content ? notificationInitDict.content : undefined;
77613         notification.iconPath = notificationInitDict.iconPath ? notificationInitDict.iconPath : undefined;
77614         notification.number = notificationInitDict.number ? notificationInitDict.number: undefined;
77615         notification.detailInfo = notificationInitDict.detailInfo ? notificationInitDict.detailInfo : undefined;
77616         notification.backgroundImagePath = notificationInitDict.backgroundImagePath ? notificationInitDict.backgroundImagePath : undefined;
77617         notification.thumbnails = notificationInitDict.thumbnails ? notificationInitDict.thumbnails : undefined;
77618         notification.soundPath = notificationInitDict.soundPath ? notificationInitDict.soundPath : undefined;
77619         notification.vibration = notificationInitDict.vibration !== undefined ? notificationInitDict.vibration : false;
77620         notification.appControl = notificationInitDict.appControl ? notificationInitDict.appControl : undefined;
77621         notification.appId = notificationInitDict.appId ? notificationInitDict.appId : undefined;
77622         if (statusType === "PROGRESS") {
77623             notification.progressType = notificationInitDict.progressType ? notificationInitDict.progressType : "PERCENTAGE";
77624             notification.progressValue = notificationInitDict.progressValue ? notificationInitDict.progressValue : undefined;
77625         }
77626     }
77627
77628     return notification;
77629 };
77630
77631 module.exports = _self;
77632
77633 });
77634 define('ripple/platform/tizen/2.0/SyncInfo', function (require, exports, module) {
77635 /*      
77636  *  Copyright 2013 Intel Corporation.
77637  *  
77638  * Licensed under the Apache License, Version 2.0 (the "License");
77639  * you may not use this file except in compliance with the License.
77640  * You may obtain a copy of the License at
77641  *  
77642  * http://www.apache.org/licenses/LICENSE-2.0
77643  *  
77644  * Unless required by applicable law or agreed to in writing, software
77645  * distributed under the License is distributed on an "AS IS" BASIS,
77646  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
77647  * See the License for the specific language governing permissions and
77648  * limitations under the License.
77649  */
77650
77651 var db = require('ripple/db'),
77652     t = require('ripple/platform/tizen/2.0/typecast'),
77653     _counter = 0,
77654     _accounts = {};
77655
77656 function SyncInfo(url, id, password, mode, arg) {
77657     var syncInfo, _id, _password, _internal_id;
77658     syncInfo = this;
77659
77660     function save() {
77661         _accounts[_internal_id] = {id: _id, password: _password};
77662         db.saveObject("save-syncinfo", _accounts);
77663     }
77664
77665     _id = id;
77666     _password = password;
77667     _internal_id = _counter++;
77668
77669     t.SyncMode(mode);
77670
77671     syncInfo.url    = url;
77672     syncInfo.mode   = mode;
77673
77674     syncInfo.__defineSetter__("id", function (id) {
77675         _id = id;
77676         save();
77677     });
77678     syncInfo.__defineGetter__("id", function () {
77679         return null;
77680     });
77681     syncInfo.__defineSetter__("password", function (password) {
77682         _password = password;
77683         save();
77684     });
77685     syncInfo.__defineGetter__("password", function () {
77686         return null;
77687     });
77688
77689     Object.defineProperty(syncInfo, "__syncInfoID__", {
77690         "configurable": false,
77691         "enumerable":   false,
77692         "get": (function (_id_) {
77693             return function () { return _id_; };
77694         })(_internal_id)
77695     });
77696
77697     switch (mode) {
77698     case "MANUAL":
77699         if (arguments.length >= 5) {
77700             t.SyncType(arg);
77701         }
77702         syncInfo.type = arg;
77703         break;
77704     case "PERIODIC":
77705         t.SyncInterval(arg);
77706         syncInfo.interval = arg;
77707         break;
77708     }
77709     save();
77710
77711     return syncInfo;
77712 }
77713
77714 module.exports = SyncInfo;
77715
77716 });
77717 define('ripple/platform/tizen/2.0/SyncProfileInfo', function (require, exports, module) {
77718 /*      
77719  *  Copyright 2013 Intel Corporation.
77720  *  
77721  * Licensed under the Apache License, Version 2.0 (the "License");
77722  * you may not use this file except in compliance with the License.
77723  * You may obtain a copy of the License at
77724  *  
77725  * http://www.apache.org/licenses/LICENSE-2.0
77726  *  
77727  * Unless required by applicable law or agreed to in writing, software
77728  * distributed under the License is distributed on an "AS IS" BASIS,
77729  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
77730  * See the License for the specific language governing permissions and
77731  * limitations under the License.
77732  */
77733
77734 function SyncProfileInfo(profileName, syncInfo, serviceInfo) {
77735     var profile = this;
77736
77737     profile.profileName =   profileName;
77738     profile.syncInfo =      syncInfo;
77739     profile.serviceInfo =   serviceInfo;
77740
77741     return profile;
77742 }
77743
77744 module.exports = SyncProfileInfo;
77745
77746 });
77747 define('ripple/platform/tizen/2.0/SyncServiceInfo', function (require, exports, module) {
77748 /*      
77749  *  Copyright 2013 Intel Corporation.
77750  *  
77751  * Licensed under the Apache License, Version 2.0 (the "License");
77752  * you may not use this file except in compliance with the License.
77753  * You may obtain a copy of the License at
77754  *  
77755  * http://www.apache.org/licenses/LICENSE-2.0
77756  *  
77757  * Unless required by applicable law or agreed to in writing, software
77758  * distributed under the License is distributed on an "AS IS" BASIS,
77759  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
77760  * See the License for the specific language governing permissions and
77761  * limitations under the License.
77762  */
77763
77764 var db = require('ripple/db'),
77765     t = require('ripple/platform/tizen/2.0/typecast'),
77766     _counter = 0,
77767     _accounts = {};
77768
77769 function SyncServiceInfo(enable, serviceType, serverDatabaseUri, id, password) {
77770     var _id, _password, syncServiceInfo, _internal_id;
77771     syncServiceInfo = this;
77772
77773     function save() {
77774         _accounts[_internal_id] = {id: _id, password: _password};
77775         db.saveObject("save-syncserviceinfo", _accounts);
77776     }
77777
77778     t.SyncServiceType(serviceType);
77779
77780     if (id) {
77781         _id = id;
77782     }
77783
77784     if (password) {
77785         _password = password;
77786     }
77787
77788     _internal_id = _counter++;
77789
77790     syncServiceInfo.enable =            enable;
77791     syncServiceInfo.serviceType =       serviceType;
77792     syncServiceInfo.serverDatabaseUri = serverDatabaseUri;
77793
77794     syncServiceInfo.__defineSetter__("id", function (id) {
77795         _id = id;
77796         save();
77797     });
77798
77799     syncServiceInfo.__defineSetter__("password", function (password) {
77800         _password = password;
77801         save();
77802     });
77803
77804     syncServiceInfo.__defineGetter__("id", function () {
77805         return null;
77806     });
77807
77808     syncServiceInfo.__defineGetter__("password", function () {
77809         return null;
77810     });
77811
77812     Object.defineProperty(syncServiceInfo, "__syncServiceInfoID__", {
77813         "configurable": false,
77814         "enumerable":   false,
77815         "get": (function (_id_) {
77816             return function () { return _id_; };
77817         })(_internal_id)
77818     });
77819
77820     save();
77821
77822     return syncServiceInfo;
77823 }
77824
77825 module.exports = SyncServiceInfo;
77826
77827 });
77828 define('ripple/platform/tizen/2.0/SyncStatistics', function (require, exports, module) {
77829 /*      
77830  *  Copyright 2013 Intel Corporation.
77831  *  
77832  * Licensed under the Apache License, Version 2.0 (the "License");
77833  * you may not use this file except in compliance with the License.
77834  * You may obtain a copy of the License at
77835  *  
77836  * http://www.apache.org/licenses/LICENSE-2.0
77837  *  
77838  * Unless required by applicable law or agreed to in writing, software
77839  * distributed under the License is distributed on an "AS IS" BASIS,
77840  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
77841  * See the License for the specific language governing permissions and
77842  * limitations under the License.
77843  */
77844
77845 module.exports = function (syncStatus, serviceType, lastSyncTime,
77846         serverToClientTotal, serverToClientAdded, serverToClientUpdated, serverToClientRemoved,
77847         clientToServerTotal, clientToServerAdded, clientToServerUpdated, clientToServerRemoved) {
77848
77849     var statistics = {};
77850
77851     statistics.__defineGetter__("syncStatus", function () {
77852         return syncStatus;
77853     });
77854
77855     statistics.__defineGetter__("serviceType", function () {
77856         return serviceType;
77857     });
77858
77859     statistics.__defineGetter__("lastSyncTime", function () {
77860         return lastSyncTime;
77861     });
77862
77863     statistics.__defineGetter__("serverToClientTotal", function () {
77864         return serverToClientTotal;
77865     });
77866
77867     statistics.__defineGetter__("serverToClientAdded", function () {
77868         return serverToClientAdded;
77869     });
77870
77871     statistics.__defineGetter__("serverToClientUpdated", function () {
77872         return serverToClientUpdated;
77873     });
77874
77875     statistics.__defineGetter__("serverToClientRemoved", function () {
77876         return serverToClientRemoved;
77877     });
77878
77879     statistics.__defineGetter__("clientToServerTotal", function () {
77880         return clientToServerTotal;
77881     });
77882
77883     statistics.__defineGetter__("clientToServerAdded", function () {
77884         return clientToServerAdded;
77885     });
77886
77887     statistics.__defineGetter__("clientToServerUpdated", function () {
77888         return clientToServerUpdated;
77889     });
77890
77891     statistics.__defineGetter__("clientToServerRemoved", function () {
77892         return clientToServerRemoved;
77893     });
77894
77895     return statistics;
77896 };
77897
77898
77899 });
77900 define('ripple/platform/tizen/2.0/TZDate', function (require, exports, module) {
77901 /*
77902  *  Copyright 2012 Intel Corporation.
77903  *
77904  * Licensed under the Apache License, Version 2.0 (the "License");
77905  * you may not use this file except in compliance with the License.
77906  * You may obtain a copy of the License at
77907  *
77908  * http://www.apache.org/licenses/LICENSE-2.0
77909  *
77910  * Unless required by applicable law or agreed to in writing, software
77911  * distributed under the License is distributed on an "AS IS" BASIS,
77912  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
77913  * See the License for the specific language governing permissions and
77914  * limitations under the License.
77915  */
77916
77917 var errorcode = require('ripple/platform/tizen/2.0/errorcode'),
77918     WebAPIException = require('ripple/platform/tizen/2.0/WebAPIException'),
77919     tz = require('ripple/platform/tizen/2.0/timezone_info'),
77920     tizen1_utils = require('ripple/platform/tizen/2.0/tizen1_utils'),
77921     _Month = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"],
77922     _Day = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"];
77923
77924 function TZDate (dt) {
77925     var d, UTCd, UTC_diff, tzid = "", target_diff, temp_date,
77926     time = require('ripple/platform/tizen/2.0/time'),
77927         hour = arguments[3] || 0, min = arguments[4] || 0,
77928         sec = arguments[5] || 0, msec = arguments[6] || 0,
77929
77930     _checkTZDate = function (dat) {
77931         var Tzdate = require('ripple/platform/tizen/2.0/TZDate'),
77932             i, tzd;
77933         if (typeof dat !== 'object' || dat === undefined || dat === null) {
77934             return false;
77935         }
77936         tzd = new Tzdate();
77937         for (i in tzd) {
77938             if (dat.hasOwnProperty(i) === false) {
77939                 return false;
77940             }
77941         }
77942         return true;
77943     },
77944     _d2UTCd_sync = function () {
77945         UTCd = new Date(d.valueOf() - (UTC_diff * 1000 * 60 * 60));
77946     },
77947     _UTCd2d_sync = function () {
77948         d = new Date(UTCd.valueOf() + (UTC_diff * 1000 * 60 * 60));
77949     },
77950     _getValue = function (o) {
77951         var other;
77952         other = new Date(o.getUTCFullYear(), o.getUTCMonth(), o.getUTCDate(),
77953                     o.getUTCHours(), o.getUTCMinutes(), o.getUTCSeconds(), o.getUTCMilliseconds());
77954         return other.valueOf();
77955     },
77956     _int_range_check = function (val, _min, _max) {
77957         var v = Number(val);
77958
77959         if (v > _max || v < _min) {
77960             return false;
77961         }
77962         return true;
77963     };
77964
77965     if (arguments[7] !== undefined) {
77966         tzid = arguments[7];
77967     }
77968
77969     if (dt === null || dt === undefined) {
77970         temp_date = new Date();
77971         tzid = time.getLocalTimezone();
77972         target_diff = tz.getTimezoneDiff(tzid);
77973         d = new Date(temp_date.valueOf() + (target_diff + temp_date.getTimezoneOffset() / 60) * 1000 * 60 * 60);
77974     } else {
77975         if (tizen1_utils.isValidDate(dt)) {
77976             d = new Date(dt);
77977             if (arguments[1] !== undefined) {
77978                 tzid = arguments[1];
77979             }
77980         } else {
77981             if (arguments.length === 1) {
77982                 throw new WebAPIException(errorcode.TYPE_MISMATCH_ERR);
77983             } else {
77984                 d = new Date(arguments[0], arguments[1], arguments[2], hour, min, sec, msec);
77985             }
77986         }
77987     }
77988
77989     if (tz.isValidTimezone(tzid) === false) {
77990         tzid = 'UTC';
77991     }
77992     UTC_diff = tz.getTimezoneDiff(tzid);
77993     _d2UTCd_sync();
77994
77995     this.getDate = function () {
77996         return d.getDate();
77997     };
77998     this.setDate = function (dt) {
77999         if (_int_range_check(dt, 1, 31)) {
78000             d.setDate(dt);
78001             _d2UTCd_sync();
78002         }
78003     };
78004     this.getDay = function () {
78005         return d.getDay();
78006     };
78007     this.getFullYear = function () {
78008         return d.getFullYear();
78009     };
78010     this.setFullYear = function (yr) {
78011         if (_int_range_check(yr, 1000, 9999)) {
78012             d.setFullYear(yr);
78013             _d2UTCd_sync();
78014         }
78015     };
78016     this.getHours = function () {
78017         return d.getHours();
78018     };
78019     this.setHours = function (hr) {
78020         if (_int_range_check(hr, 0, 23)) {
78021             d.setHours(hr);
78022             _d2UTCd_sync();
78023         }
78024     };
78025     this.getMilliseconds = function () {
78026         return d.getMilliseconds();
78027     };
78028     this.setMilliseconds = function (msec) {
78029         if (_int_range_check(msec, 0, 999)) {
78030             d.setMilliseconds(msec);
78031             _d2UTCd_sync();
78032         }
78033     };
78034     this.getMinutes = function () {
78035         return d.getMinutes();
78036     };
78037     this.setMinutes = function (min) {
78038         if (_int_range_check(min, 0, 59)) {
78039             d.setMinutes(min);
78040             _d2UTCd_sync();
78041         }
78042     };
78043     this.getMonth = function () {
78044         return d.getMonth();
78045     };
78046     this.setMonth = function (m) {
78047         if (_int_range_check(m, 0, 11)) {
78048             d.setMonth(m);
78049             _d2UTCd_sync();
78050         }
78051     };
78052     this.getSeconds = function () {
78053         return d.getSeconds();
78054     };
78055     this.setSeconds = function (s) {
78056         if (_int_range_check(s, 0, 59)) {
78057             d.setSeconds(s);
78058             _d2UTCd_sync();
78059         }
78060     };
78061     this.getUTCDate = function () {
78062         return UTCd.getDate();
78063     };
78064     this.setUTCDate = function (dt) {
78065         if (_int_range_check(dt, 1, 31)) {
78066             UTCd.setDate(dt);
78067             _UTCd2d_sync();
78068         }
78069     };
78070     this.getUTCDay = function () {
78071         return UTCd.getDay();
78072     };
78073     this.getUTCFullYear = function () {
78074         return UTCd.getFullYear();
78075     };
78076     this.setUTCFullYear = function (yr) {
78077         if (_int_range_check(yr, 1000, 9999)) {
78078             UTCd.setFullYear(yr);
78079             _UTCd2d_sync();
78080         }
78081     };
78082     this.getUTCHours = function () {
78083         return UTCd.getHours();
78084     };
78085     this.setUTCHours = function (hr) {
78086         if (_int_range_check(hr, 0, 23)) {
78087             UTCd.setHours(hr);
78088             _UTCd2d_sync();
78089         }
78090     };
78091     this.getUTCMilliseconds = function () {
78092         return UTCd.getMilliseconds();
78093     };
78094     this.setUTCMilliseconds = function (msec) {
78095         if (_int_range_check(msec, 0, 999)) {
78096             UTCd.setMilliseconds(msec);
78097             _UTCd2d_sync();
78098         }
78099     };
78100     this.getUTCMinutes = function () {
78101         return UTCd.getMinutes();
78102     };
78103     this.setUTCMinutes = function (min) {
78104         if (_int_range_check(min, 0, 59)) {
78105             UTCd.setMinutes(min);
78106             _UTCd2d_sync();
78107         }
78108     };
78109     this.getUTCMonth = function () {
78110         return UTCd.getMonth();
78111     };
78112     this.setUTCMonth = function (m) {
78113         if (_int_range_check(m, 0, 11)) {
78114             UTCd.setMonth(m);
78115             _UTCd2d_sync();
78116         }
78117     };
78118     this.getUTCSeconds = function () {
78119         return UTCd.getSeconds();
78120     };
78121     this.setUTCSeconds = function (s) {
78122         if (_int_range_check(s, 0, 59)) {
78123             UTCd.setSeconds(s);
78124             _UTCd2d_sync();
78125         }
78126     };
78127     this.getTimezone = function () {
78128         return tzid;
78129     };
78130     this.toTimezone = function (new_tzid) {
78131         var diff,
78132             Tzdate = require('ripple/platform/tizen/2.0/TZDate');
78133         if (typeof new_tzid !== 'string') {
78134             throw new WebAPIException(errorcode.TYPE_MISMATCH_ERR);
78135         }
78136         if (tz.isValidTimezone(new_tzid) === true) {
78137             diff = tz.getTimezoneDiff(new_tzid) - UTC_diff;
78138             return new Tzdate(new Date(d.valueOf() + (diff * 1000 * 60 * 60)), new_tzid);
78139         } else {
78140             throw new WebAPIException(errorcode.INVALID_VALUES_ERR);
78141         }
78142     };
78143     this.toLocalTimezone = function () {
78144         var diff,
78145             localTzid,
78146             Tzdate = require('ripple/platform/tizen/2.0/TZDate');
78147         localTzid = time.getLocalTimezone();
78148
78149         diff = tz.getTimezoneDiff(localTzid) - UTC_diff;
78150         return new Tzdate(new Date(d.valueOf() + (diff * 1000 * 60 * 60)), localTzid);
78151     };
78152     this.toUTC = function () {
78153         var Tzdate = require('ripple/platform/tizen/2.0/TZDate');
78154         return new Tzdate(UTCd, "UTC");
78155     };
78156     this.difference = function (other) {
78157         var diff,
78158             TDur = require('ripple/platform/tizen/2.0/TimeDuration');
78159         if (_checkTZDate(other) === false) {
78160             throw new WebAPIException(errorcode.TYPE_MISMATCH_ERR);
78161         }
78162         diff = (UTCd.valueOf() - _getValue(other));
78163         if (diff % 86400000 === 0) {
78164             return new TDur(diff/86400000, 'DAYS');
78165         } else {
78166             return new TDur(diff);
78167         }
78168     };
78169     this.equalsTo = function (other) {
78170         if (_checkTZDate(other) === false) {
78171             throw new WebAPIException(errorcode.TYPE_MISMATCH_ERR);
78172         }
78173         return (UTCd.valueOf() === _getValue(other));
78174     };
78175     this.earlierThan = function (other) {
78176         if (_checkTZDate(other) === false) {
78177             throw new WebAPIException(errorcode.TYPE_MISMATCH_ERR);
78178         }
78179         return (UTCd.valueOf() < _getValue(other));
78180     };
78181     this.laterThan = function (other) {
78182         if (_checkTZDate(other) === false) {
78183             throw new WebAPIException(errorcode.TYPE_MISMATCH_ERR);
78184         }
78185         return (UTCd.valueOf() > _getValue(other));
78186     };
78187     this.addDuration = function (dur) {
78188         var Tzdate = require('ripple/platform/tizen/2.0/TZDate'),
78189             Tunit = {"MSECS": 1,
78190                 "SECS": 1000,
78191                 "MINS": 60 * 1000,
78192                 "HOURS": 60 * 60 * 1000,
78193                 "DAYS": 24 * 60 * 60 * 1000
78194             };
78195         if (typeof dur !== 'object' || dur === undefined || dur === null) {
78196             throw new WebAPIException(errorcode.TYPE_MISMATCH_ERR);
78197         }
78198         if (dur.length === undefined || dur.length === null ||
78199                 dur.unit === undefined || dur.unit === null) {
78200             throw new WebAPIException(errorcode.TYPE_MISMATCH_ERR);
78201         }
78202         if ((typeof dur.length) !== 'number') {
78203             throw new WebAPIException(errorcode.TYPE_MISMATCH_ERR);
78204         }
78205         if (Tunit[dur.unit] === undefined) {
78206             throw new WebAPIException(errorcode.TYPE_MISMATCH_ERR);
78207         }
78208         return new Tzdate(new Date(d.valueOf() + (parseInt(dur.length, 10) * Tunit[dur.unit])), tzid);
78209     };
78210     this.toLocaleDateString = function () {
78211         if (d.toString() === "Invalid Date") {
78212             return d.toString();
78213         } else {
78214             return this.toDateString() + " (" + tz.getTimezoneAbbr(tzid) + ")";
78215         }
78216     };
78217     this.toLocaleTimeString = function () {
78218         if (d.toString() === "Invalid Date") {
78219             return d.toString();
78220         } else {
78221             return this.toTimeString() + " (" + tz.getTimezoneAbbr(tzid) + ")";
78222         }
78223     };
78224     this.toLocaleString = function () {
78225         if (d.toString() === "Invalid Date") {
78226             return d.toString();
78227         } else {
78228             return this.toString() + " (" + tz.getTimezoneAbbr(tzid) + ")";
78229         }
78230     };
78231     this.toDateString = function () {
78232         var i, ret = "", fmt = time.getDateFormat();
78233         if (d.toString() === "Invalid Date") {
78234             return d.toString();
78235         }
78236         for (i = 0; i < fmt.length; i++) {
78237             switch (fmt.charAt(i)) {
78238             case 'd':
78239                 ret = ret + d.getDate();
78240                 break;
78241             case 'y':
78242                 ret = ret + d.getFullYear();
78243                 break;
78244             case 'm':
78245                 ret = ret + (d.getMonth() + 1);
78246                 break;
78247             case 'M':
78248                 ret = ret + _Month[d.getMonth()];
78249                 break;
78250             case 'D':
78251                 ret = ret + _Day[d.getDay()];
78252                 break;
78253             default:
78254                 ret = ret + fmt.charAt(i);
78255             }
78256         }
78257         return ret;
78258     };
78259     this.toTimeString = function () {
78260         var i, hh, mm, ss, AP,
78261             ret = "", fmt = time.getTimeFormat();
78262
78263         if (d.toString() === "Invalid Date") {
78264             return d.toString();
78265         }
78266
78267         if (fmt.search(/ap/) === -1) {
78268             AP = false;
78269         } else {
78270             AP = true;
78271             if (d.getHours() > 11) {
78272                 fmt = fmt.replace("ap", "PM");
78273             } else {
78274                 fmt = fmt.replace("ap", "AM");
78275             }
78276         }
78277         for (i = 0; i < fmt.length; i++) {
78278             switch (fmt.charAt(i)) {
78279             case 'h':
78280                 hh = d.getHours();
78281                 if (AP) {
78282                     hh = (hh > 12) ? hh - 12 : hh;
78283                 }
78284                 hh = (hh < 10 ? "0" : "") + hh;
78285                 ret = ret + hh;
78286                 break;
78287             case 'm':
78288                 mm = d.getMinutes();
78289                 mm = (mm < 10 ? "0" : "") + mm;
78290                 ret = ret + mm;
78291                 break;
78292             case 's':
78293                 ss = d.getSeconds();
78294                 ss = (ss < 10 ? "0" : "") + ss;
78295                 ret = ret + ss;
78296                 break;
78297             default:
78298                 ret = ret + fmt.charAt(i);
78299             }
78300         }
78301         return ret;
78302     };
78303     this.toString = function () {
78304         if (d.toString() === "Invalid Date") {
78305             return d.toString();
78306         } else {
78307             return (this.toDateString() + " " + this.toTimeString());
78308         }
78309     };
78310     this.getTimezoneAbbreviation = function () {
78311         return tz.getTimezoneAbbr(tzid);
78312     };
78313     this.secondsFromUTC = function () {
78314         return (-1 * UTC_diff * 60 * 60);
78315     };
78316     this.isDST = function () {
78317         throw (new WebAPIException(errorcode.NOT_SUPPORTED_ERR));
78318     };
78319     this.getPreviousDSTTransition = function () {
78320         throw (new WebAPIException(errorcode.NOT_SUPPORTED_ERR));
78321     };
78322     this.getNextDSTTransition = function () {
78323         throw (new WebAPIException(errorcode.NOT_SUPPORTED_ERR));
78324     };
78325     return this;
78326 }
78327
78328 module.exports = TZDate;
78329
78330 });
78331 define('ripple/platform/tizen/2.0/TimeDuration', function (require, exports, module) {
78332 /*
78333  *  Copyright 2012 Intel Corporation.
78334  *
78335  * Licensed under the Apache License, Version 2.0 (the "License");
78336  * you may not use this file except in compliance with the License.
78337  * You may obtain a copy of the License at
78338  *
78339  * http://www.apache.org/licenses/LICENSE-2.0
78340  *
78341  * Unless required by applicable law or agreed to in writing, software
78342  * distributed under the License is distributed on an "AS IS" BASIS,
78343  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
78344  * See the License for the specific language governing permissions and
78345  * limitations under the License.
78346  */
78347
78348 var errorcode = require('ripple/platform/tizen/2.0/errorcode'),
78349     WebAPIException = require('ripple/platform/tizen/2.0/WebAPIException');
78350
78351 function TimeDuration(l, u) {
78352     var _length, _unit,
78353         TimeDurationUnit = {"MSECS": 1,
78354                             "SECS": 1000,
78355                             "MINS": 60 * 1000,
78356                             "HOURS": 60 * 60 * 1000,
78357                             "DAYS": 24 * 60 * 60 * 1000
78358                            },
78359         _simplifyDuration = function (ms) {
78360             var TDur = require('ripple/platform/tizen/2.0/TimeDuration'),
78361                 uni = "MSECS";
78362             if ((ms % 1000) === 0) {
78363                 ms = ms / 1000;
78364                 uni = "SECS";
78365                 if ((ms % 60) === 0) {
78366                     ms = ms / 60;
78367                     uni = "MINS";
78368                     if ((ms % 60) === 0) {
78369                         ms = ms / 60;
78370                         uni = "HOURS";
78371                         if ((ms % 24) === 0) {
78372                             ms = ms / 24;
78373                             uni = "DAYS";
78374                         }
78375                     }
78376                 }
78377             }
78378             return (new TDur(ms, uni));
78379         },
78380         _toMSECS = function (unit) {
78381             if (TimeDurationUnit[unit] === undefined) {
78382                 throw new WebAPIException(errorcode.TYPE_MISMATCH_ERR);
78383             } else {
78384                 return TimeDurationUnit[unit];
78385             }
78386         };
78387
78388     _length = l || 0;
78389     if ((u !== undefined) && (u !== null)) {
78390         if (TimeDurationUnit[u] === undefined) {
78391             throw new WebAPIException(errorcode.TYPE_MISMATCH_ERR);
78392         } else {
78393             _unit = u;
78394         }
78395     } else {
78396         _unit = "MSECS";
78397     }
78398
78399     this.length = _length;
78400     this.unit = _unit;
78401     this.difference = function (o) {
78402         if (typeof o !== 'object' || o === null || o === undefined) {
78403             throw new WebAPIException(errorcode.TYPE_MISMATCH_ERR);
78404         }
78405         if (o.length === undefined || o.length === null ||
78406                 o.unit === undefined || o.unit === null) {
78407             throw new WebAPIException(errorcode.TYPE_MISMATCH_ERR);
78408         }
78409         if ((typeof o.length) !== 'number') {
78410             throw new WebAPIException(errorcode.TYPE_MISMATCH_ERR);
78411         }
78412         if (TimeDurationUnit[o.unit] === undefined) {
78413             throw new WebAPIException(errorcode.TYPE_MISMATCH_ERR);
78414         }
78415
78416         var thisMS = _length * _toMSECS(_unit),
78417             otherMS = o.length * _toMSECS(o.unit);
78418         return _simplifyDuration(thisMS - otherMS);
78419     };
78420     this.equalsTo = function (o) {
78421         if (typeof o !== 'object' || o === null || o === undefined) {
78422             throw new WebAPIException(errorcode.TYPE_MISMATCH_ERR);
78423         }
78424         if (o.length === undefined || o.length === null ||
78425                 o.unit === undefined || o.unit === null) {
78426             throw new WebAPIException(errorcode.TYPE_MISMATCH_ERR);
78427         }
78428         if ((typeof o.length) !== 'number') {
78429             throw new WebAPIException(errorcode.TYPE_MISMATCH_ERR);
78430         }
78431         if (TimeDurationUnit[o.unit] === undefined) {
78432             throw new WebAPIException(errorcode.TYPE_MISMATCH_ERR);
78433         }
78434
78435         var thisMS = _length * _toMSECS(_unit),
78436             otherMS = o.length * _toMSECS(o.unit);
78437         return (thisMS === otherMS);
78438     };
78439     this.lessThan = function (o) {
78440         if (typeof o !== 'object' || o === null || o === undefined) {
78441             throw new WebAPIException(errorcode.TYPE_MISMATCH_ERR);
78442         }
78443         if (o.length === undefined || o.length === null ||
78444                 o.unit === undefined || o.unit === null) {
78445             throw new WebAPIException(errorcode.TYPE_MISMATCH_ERR);
78446         }
78447         if ((typeof o.length) !== 'number') {
78448             throw new WebAPIException(errorcode.TYPE_MISMATCH_ERR);
78449         }
78450         if (TimeDurationUnit[o.unit] === undefined) {
78451             throw new WebAPIException(errorcode.TYPE_MISMATCH_ERR);
78452         }
78453
78454         var thisMS = _length * _toMSECS(_unit),
78455             otherMS = o.length * _toMSECS(o.unit);
78456         return (thisMS < otherMS);
78457     };
78458     this.greaterThan = function (o) {
78459         if (typeof o !== 'object' || o === null || o === undefined) {
78460             throw new WebAPIException(errorcode.TYPE_MISMATCH_ERR);
78461         }
78462         if (o.length === undefined || o.length === null ||
78463                 o.unit === undefined || o.unit === null) {
78464             throw new WebAPIException(errorcode.TYPE_MISMATCH_ERR);
78465         }
78466         if ((typeof o.length) !== 'number') {
78467             throw new WebAPIException(errorcode.TYPE_MISMATCH_ERR);
78468         }
78469         if (TimeDurationUnit[o.unit] === undefined) {
78470             throw new WebAPIException(errorcode.TYPE_MISMATCH_ERR);
78471         }
78472
78473         var thisMS = _length * _toMSECS(_unit),
78474             otherMS = o.length * _toMSECS(o.unit);
78475         return (thisMS > otherMS);
78476     };
78477     return this;
78478 }
78479
78480 module.exports = TimeDuration;
78481
78482 });
78483 define('ripple/platform/tizen/2.0/WebAPIError', function (require, exports, module) {
78484 /*
78485  *  Copyright 2012 Intel Corporation.
78486  *
78487  * Licensed under the Apache License, Version 2.0 (the "License");
78488  * you may not use this file except in compliance with the License.
78489  * You may obtain a copy of the License at
78490  *
78491  * http://www.apache.org/licenses/LICENSE-2.0
78492  *
78493  * Unless required by applicable law or agreed to in writing, software
78494  * distributed under the License is distributed on an "AS IS" BASIS,
78495  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
78496  * See the License for the specific language governing permissions and
78497  * limitations under the License.
78498  */
78499
78500 var errorcode = require('ripple/platform/tizen/2.0/errorcode');
78501
78502 var msg = {
78503     0: "Generic Error",
78504     1: "Index or size is negative, or greater than the allowed value.",
78505     2: "Specified range of text does not fit into a DOMString.",
78506     3: "Node is inserted somewhere it doesn't belong.",
78507     4: "Node is used in a different document than the one that created it (that doesn't support it).",
78508     5: "An invalid or illegal character is specified.",
78509     6: "Data is specified for a Node which does not support data.",
78510     7: "An attempt is made to modify an object where modifications are not allowed.",
78511     8: "An attempt is made to reference a Node in a context where it does not exist.",
78512     9: "The implementation does not support the requested type of object or operation.",
78513     10: "An attempt is made to add an attribute that is already in use elsewhere.",
78514     11: "An attempt is made to use an object that is not, or is no longer, usable.",
78515     12: "An invalid or illegal string is specified.",
78516     13: "An attempt is made to modify the type of the underlying object.",
78517     14: "An attempt is made to create or change an object in a way which is incorrect with regard to namespaces.",
78518     15: "A parameter or an operation is not supported by the underlying object.",
78519     16: "A call to a method such as insertBefore or removeChild would make the Node invalid with respect to \"partial validity\", this exception would be raised and the operation would not be done.",
78520     17: "The type of an object is incompatible with the expected type of the parameter associated to the object.",
78521     18: "An attempt is made to perform an operation or access some data in a way that would be a security risk or a violation of the user agent's security policy.",
78522     19: "A network error occurs in synchronous requests.",
78523     20: "The abort error occurs in asynchronous requests by user prompt.",
78524     21: "The operation could not be completed because the URL does not match.",
78525     22: "The quota has been exceeded.",
78526     23: "The operation timed out.",
78527     24: "The supplied node is incorrect or has an incorrect ancestor for this operation.",
78528     25: "The object can not be cloned.",
78529     99: "The content of an object does not include valid values.",
78530     100: "Error occurred in communication with the underlying implementation that meant the requested method could not complete.",
78531     111: "Requested service is not available."
78532 },
78533     errType = {
78534     0: "UnknownError",
78535     1: "IndexSizeError",
78536     2: "DOMStringSizeError",
78537     3: "HierarchyRequestError",
78538     4: "WrongDocumentError",
78539     5: "InvalidCharacterError",
78540     6: "NoDataAllowedError",
78541     7: "NoModificationAllowedError",
78542     8: "NotFoundError",
78543     9: "NotSupportedError",
78544     10: "InuseAttributeError",
78545     11: "InvalidStateError",
78546     12: "SyntaxError",
78547     13: "InvalidModificationError",
78548     14: "NamespaceError",
78549     15: "InvalidAccessError",
78550     16: "ValidationError",
78551     17: "TypeMismatchError",
78552     18: "SecurityError",
78553     19: "NetworkError",
78554     20: "AbortError",
78555     21: "URLMismatchError",
78556     22: "QuotaExceededError",
78557     23: "TimeoutError",
78558     24: "InvalidNodeTypeError",
78559     25: "DataCloneError",
78560     99: "InvalidValuesError",
78561     100: "IOError",
78562     111: "ServiceNotAvailableError"
78563 };
78564
78565 /*
78566   support 3 types of error:
78567   - WebAPIError()
78568       code = errorcode.UNKNOWN_ERR
78569       message = errorcode.message[UNKNOWN_ERR]
78570   - WebAPIError(errorcode."TYPE_MISMATCH_ERR")
78571       code = 17
78572       message = errorcode.message[17]
78573   - WebAPIError(my_own_error_code, "This is my error message.")
78574       code = my_own_error_code(number)
78575       message = "This is my error message."
78576 */
78577
78578 module.exports = function (code, message, name) {
78579     var _code, _message, _name;
78580
78581     if (typeof code !== 'number') {
78582         _code = errorcode.UNKNOWN_ERR;
78583         _message = msg[_code];
78584         _name = errType[_code];
78585     } else {
78586         _code = code;
78587         if (typeof message === 'string') {
78588             _message = message;
78589         } else {
78590             _message = msg[_code];
78591         }
78592         if (typeof name === 'string') {
78593             _name = name;
78594         } else {
78595             _name = errType[_code];
78596         }
78597     }
78598
78599     this.__defineGetter__("code", function () {
78600         return _code;
78601     });
78602     this.__defineGetter__("message", function () {
78603         return _message;
78604     });
78605     this.__defineGetter__("name", function () {
78606         return _name;
78607     });
78608 };
78609
78610 });
78611 define('ripple/platform/tizen/2.0/WebAPIException', function (require, exports, module) {
78612 /*
78613  *  Copyright 2012 Intel Corporation.
78614  *
78615  * Licensed under the Apache License, Version 2.0 (the "License");
78616  * you may not use this file except in compliance with the License.
78617  * You may obtain a copy of the License at
78618  *
78619  * http://www.apache.org/licenses/LICENSE-2.0
78620  *
78621  * Unless required by applicable law or agreed to in writing, software
78622  * distributed under the License is distributed on an "AS IS" BASIS,
78623  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
78624  * See the License for the specific language governing permissions and
78625  * limitations under the License.
78626  */
78627
78628 var errorcode = require('ripple/platform/tizen/2.0/errorcode');
78629
78630 var msg = {
78631     0: "Generic Error",
78632     1: "Index or size is negative, or greater than the allowed value.",
78633     2: "Specified range of text does not fit into a DOMString.",
78634     3: "Node is inserted somewhere it doesn't belong.",
78635     4: "Node is used in a different document than the one that created it (that doesn't support it).",
78636     5: "An invalid or illegal character is specified.",
78637     6: "Data is specified for a Node which does not support data.",
78638     7: "An attempt is made to modify an object where modifications are not allowed.",
78639     8: "An attempt is made to reference a Node in a context where it does not exist.",
78640     9: "The implementation does not support the requested type of object or operation.",
78641     10: "An attempt is made to add an attribute that is already in use elsewhere.",
78642     11: "An attempt is made to use an object that is not, or is no longer, usable.",
78643     12: "An invalid or illegal string is specified.",
78644     13: "An attempt is made to modify the type of the underlying object.",
78645     14: "An attempt is made to create or change an object in a way which is incorrect with regard to namespaces.",
78646     15: "A parameter or an operation is not supported by the underlying object.",
78647     16: "A call to a method such as insertBefore or removeChild would make the Node invalid with respect to \"partial validity\", this exception would be raised and the operation would not be done.",
78648     17: "The type of an object is incompatible with the expected type of the parameter associated to the object.",
78649     18: "An attempt is made to perform an operation or access some data in a way that would be a security risk or a violation of the user agent's security policy.",
78650     19: "A network error occurs in synchronous requests.",
78651     20: "The abort error occurs in asynchronous requests by user prompt.",
78652     21: "The operation could not be completed because the URL does not match.",
78653     22: "The quota has been exceeded.",
78654     23: "The operation timed out.",
78655     24: "The supplied node is incorrect or has an incorrect ancestor for this operation.",
78656     25: "The object can not be cloned.",
78657     99: "The content of an object does not include valid values.",
78658     100: "Error occurred in communication with the underlying implementation that meant the requested method could not complete.",
78659     111: "Requested service is not available."
78660 },
78661     errType = {
78662     0: "UnknownError",
78663     1: "IndexSizeError",
78664     2: "DOMStringSizeError",
78665     3: "HierarchyRequestError",
78666     4: "WrongDocumentError",
78667     5: "InvalidCharacterError",
78668     6: "NoDataAllowedError",
78669     7: "NoModificationAllowedError",
78670     8: "NotFoundError",
78671     9: "NotSupportedError",
78672     10: "InuseAttributeError",
78673     11: "InvalidStateError",
78674     12: "SyntaxError",
78675     13: "InvalidModificationError",
78676     14: "NamespaceError",
78677     15: "InvalidAccessError",
78678     16: "ValidationError",
78679     17: "TypeMismatchError",
78680     18: "SecurityError",
78681     19: "NetworkError",
78682     20: "AbortError",
78683     21: "URLMismatchError",
78684     22: "QuotaExceededError",
78685     23: "TimeoutError",
78686     24: "InvalidNodeTypeError",
78687     25: "DataCloneError",
78688     99: "InvalidValuesError",
78689     100: "IOError",
78690     111: "ServiceNotAvailableError"
78691 };
78692
78693 /*
78694   support 3 types of error:
78695   - WebAPIError()
78696       code = errorcode.UNKNOWN_ERR
78697       message = errorcode.message[UNKNOWN_ERR]
78698   - WebAPIError(errorcode."TYPE_MISMATCH_ERR")
78699       code = 17
78700       message = errorcode.message[17]
78701   - WebAPIError(my_own_error_code, "This is my error message.")
78702       code = my_own_error_code(number)
78703       message = "This is my error message."
78704 */
78705
78706 module.exports = function (code, message, name) {
78707     var g, c, _code, _message, _name;
78708
78709     for (c in errorcode) {
78710         g = errorcode.__lookupGetter__(c);
78711         if (g) {
78712             this.__defineGetter__(c, g);
78713         }
78714     }
78715
78716     if (typeof code !== 'number') {
78717         _code = errorcode.UNKNOWN_ERR;
78718         _message = msg[_code];
78719         _name = errType[_code];
78720     } else {
78721         _code = code;
78722         if (typeof message === 'string') {
78723             _message = message;
78724         } else {
78725             _message = msg[_code];
78726         }
78727         if (typeof name === 'string') {
78728             _name = name;
78729         } else {
78730             _name = errType[_code];
78731         }
78732     }
78733
78734     this.__defineGetter__("code", function () {
78735         return _code;
78736     });
78737     this.__defineGetter__("message", function () {
78738         return _message;
78739     });
78740     this.__defineGetter__("name", function () {
78741         return _name;
78742     });
78743 };
78744
78745 });
78746 define('ripple/platform/tizen/2.0/account', function (require, exports, module) {
78747 /*
78748  *  Copyright 2012 Intel Corporation.
78749  *
78750  * Licensed under the Apache License, Version 2.0 (the "License");
78751  * you may not use this file except in compliance with the License.
78752  * You may obtain a copy of the License at
78753  *
78754  * http://www.apache.org/licenses/LICENSE-2.0
78755  *
78756  * Unless required by applicable law or agreed to in writing, software
78757  * distributed under the License is distributed on an "AS IS" BASIS,
78758  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
78759  * See the License for the specific language governing permissions and
78760  * limitations under the License.
78761  */
78762
78763 var db = require('ripple/db'),
78764     utils = require('ripple/utils'),
78765     tizen1_utils = require('ripple/platform/tizen/2.0/tizen1_utils'),
78766     errorcode = require('ripple/platform/tizen/2.0/errorcode'),
78767     WebAPIError = require('ripple/platform/tizen/2.0/WebAPIError'),
78768     _data = {
78769         DB_ACCOUNT_KEY : "tizen1-db-accounts",
78770         accounts : {}
78771     },
78772     _self;
78773
78774 function _checkAccount(account) {
78775     if (typeof account !== "object" ||
78776         typeof account.id !== "string" ||
78777         typeof account.appid !== "string" ||
78778         typeof account.userName !== "string" ||
78779         typeof account.displayName !== "string" ||
78780         typeof account.service !== "object") {
78781         return false;
78782     }
78783
78784     return true;
78785 }
78786
78787 function _checkCallback(successCallback, errorCallback) {
78788     tizen1_utils.validateArgumentType(successCallback, "function",
78789                                         new WebAPIError(errorcode.TYPE_MISMATCH_ERR));
78790     if (errorCallback) {
78791         tizen1_utils.validateArgumentType(errorCallback, "function",
78792                                             new WebAPIError(errorcode.TYPE_MISMATCH_ERR));
78793     }
78794 }
78795
78796 _self = {
78797     getAccounts : function () {
78798         var results = [];
78799         utils.forEach(_data.accounts, function (account) {
78800             results.push(utils.copy(account));
78801         });
78802
78803         return results;
78804     },
78805
78806     getAccountById : function (id) {
78807         var acccount = null;
78808
78809         if (typeof id !== "string") {
78810             throw new WebAPIError(errorcode.TYPE_MISMATCH_ERR);
78811         }
78812
78813         if (_data.accounts[id]) {
78814             account = utils.copy(_data.accounts[id]);
78815         }
78816
78817         return account;
78818     },
78819
78820     getAccountByUserName : function (userName) {
78821         var result = null;
78822
78823         if (typeof userName !== "string") {
78824             throw new WebAPIError(errorcode.TYPE_MISMATCH_ERR);
78825         }
78826
78827         utils.forEach(_data.accounts, function (account) {
78828             if (userName === account.userName) {
78829                 result = utils.copy(account);
78830             }
78831         });
78832
78833         return result;
78834     },
78835
78836     getAccountByappId : function (appId) {
78837         var result = null;
78838
78839         if (typeof appId !== "string") {
78840             throw new WebAPIError(errorcode.TYPE_MISMATCH_ERR);
78841         }
78842
78843         utils.forEach(_data.accounts, function (account) {
78844             if (appId === account.appId) {
78845                 result = utils.copy(account);
78846             }
78847         });
78848
78849         return result;
78850     },
78851
78852     getAccountByServiceId : function (serviceId) {
78853         var result = null;
78854
78855         if (typeof serviceId !== "string") {
78856             throw new WebAPIError(errorcode.TYPE_MISMATCH_ERR);
78857         }
78858
78859         utils.forEach(_data.accounts, function (account) {
78860             if (serviceId === account.service.id) {
78861                 result = utils.copy(account);
78862             }
78863         });
78864
78865         return result;
78866     },
78867
78868     getAccountByTag : function (tag) {
78869         var results = [], i;
78870
78871         if (typeof tag !== "string") {
78872             throw new WebAPIError(errorcode.TYPE_MISMATCH_ERR);
78873         }
78874
78875         utils.forEach(_data.accounts, function (account) {
78876             for (i in account.service.tag) {
78877                 if (tag === account.service.tag[i]) {
78878                     results.push(utils.copy(account));
78879                     break;
78880                 }
78881             }
78882         });
78883
78884         return results;
78885     },
78886
78887     add : function (account, successCallback, errorCallback) {
78888         if (!_checkAccount(account)) {
78889             throw new WebAPIError(errorcode.TYPE_MISMATCH_ERR);
78890         }
78891
78892         _checkCallback(successCallback, errorCallback);
78893
78894         if (!_data.accounts[account.id]) {
78895             _data.accounts[account.id] = utils.copy(account);
78896         }
78897
78898         successCallback();
78899     },
78900
78901     update : function (account, successCallback, errorCallback) {
78902         if (!_checkAccount(account)) {
78903             throw new WebAPIError(errorcode.TYPE_MISMATCH_ERR);
78904         }
78905
78906         _checkCallback(successCallback, errorCallback);
78907
78908         if (!_data.accounts[account.id]) {
78909             errorCallback(new WebAPIError(errorcode.NOT_FOUND_ERR));
78910             return;
78911         }
78912
78913         _data.accounts[account.id] = utils.copy(account);
78914         successCallback();
78915     },
78916
78917     remove : function (id, successCallback, errorCallback) {
78918         if (typeof id !== "string") {
78919             throw new WebAPIError(errorcode.TYPE_MISMATCH_ERR);
78920         }
78921
78922         _checkCallback(successCallback, errorCallback);
78923
78924         if (!_data.accounts[id]) {
78925             errorCallback(new WebAPIError(errorcode.NOT_FOUND_ERR));
78926             return;
78927         }
78928
78929         delete _data.accounts[id];
78930         successCallback();
78931     },
78932
78933     getAccountApplications : function () {
78934         var results = [];
78935         /* FIXME: wait for API update */
78936         return results;
78937     }
78938 };
78939
78940 function _initialize() {
78941     _data.accounts = db.retrieveObject(_data.DB_ACCOUNT_KEY) || {};
78942 }
78943
78944 _initialize();
78945
78946 module.exports = _self;
78947
78948 });
78949 define('ripple/platform/tizen/2.0/alarm', function (require, exports, module) {
78950 /*
78951  *  Copyright 2012 Intel Corporation.
78952  *
78953  * Licensed under the Apache License, Version 2.0 (the "License");
78954  * you may not use this file except in compliance with the License.
78955  * You may obtain a copy of the License at
78956  *
78957  * http://www.apache.org/licenses/LICENSE-2.0
78958  *
78959  * Unless required by applicable law or agreed to in writing, software
78960  * distributed under the License is distributed on an "AS IS" BASIS,
78961  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
78962  * See the License for the specific language governing permissions and
78963  * limitations under the License.
78964  */
78965
78966 var db = require('ripple/db'),
78967     errorcode = require('ripple/platform/tizen/2.0/errorcode'),
78968     event = require('ripple/event'),
78969     utils = require('ripple/utils'),
78970     t = require('ripple/platform/tizen/2.0/typecast'),
78971     WebAPIException = require('ripple/platform/tizen/2.0/WebAPIException'),
78972     AlarmRelative = require('ripple/platform/tizen/2.0/AlarmRelative'),
78973     AlarmAbsolute = require('ripple/platform/tizen/2.0/AlarmAbsolute'),
78974     AlarmStore,
78975     _DB_ALARMS_KEY = "tizen1.0-db-alarms",
78976     PERIOD_MINUTE = 60,
78977     PERIOD_HOUR   = 60 * PERIOD_MINUTE,
78978     PERIOD_DAY    = 24 * PERIOD_HOUR,
78979     PERIOD_WEEK   = 7 * PERIOD_DAY,
78980     _alarms = {}, _alarmStack = [],
78981     _security = {
78982         "http://tizen.org/privilege/alarm": ["add", "remove", "removeAll"]
78983     },
78984     _isInitialized = false, _self;
78985
78986 function _initialize() {
78987     _alarms = db.retrieveObject(_DB_ALARMS_KEY);
78988     utils.forEach(_alarms, function (alarmStore) {
78989         _alarmStack.push(alarmStore);
78990     });
78991     _isInitialized = true;
78992 }
78993
78994 function _get() {
78995     if (!_isInitialized) {
78996         _initialize();
78997     }
78998 }
78999
79000 function _save() {
79001     db.saveObject(_DB_ALARMS_KEY, _alarmStack);
79002 }
79003
79004 function _updateDB(alarmStore) {
79005     _alarmStack.push(alarmStore);
79006     _save();
79007 }
79008
79009 function _getCurrentAppId() {
79010     return db.retrieve("current-url");
79011 }
79012
79013 function _checkTriggerAlarm(alarm) {
79014     var remainingTime, nextTriggerDate;
79015
79016     if (alarm.delay !== undefined) { // Alarm is relative
79017         if (alarm.period !== null)
79018             return false;
79019
79020         remainingTime = alarm.getRemainingSeconds();
79021         if (remainingTime === null)
79022             return true; // This alarm is triggered, remove it
79023     } else if (alarm.period !== undefined) { // Alarm is absolute,no repeat
79024         nextTriggerDate = alarm.getNextScheduledDate();
79025         if (nextTriggerDate === null)
79026             return true; // Already triggered
79027     }
79028
79029     return false; // Alarm is repeat, not expired
79030 }
79031
79032 function _convertToAlarm(alarmStore) {
79033     var alarm, frequency;
79034
79035     if (alarmStore.delay !== null) { // AlarmRelative
79036         alarm = new AlarmRelative(alarmStore.delay, alarmStore.period);
79037         alarm.date = alarmStore.date;
79038     } else { // AlarmAbsolute
79039         if (alarmStore.period !== null && alarmStore.period !== PERIOD_WEEK) {
79040             frequency = alarmStore.period;
79041         } else if (alarmStore.period === PERIOD_WEEK) {
79042             frequency = alarmStore.daysOfTheWeek;
79043         }
79044         alarm = new AlarmAbsolute(alarmStore.date, frequency);
79045     }
79046
79047     alarm.__defineGetter__("id", function () {
79048         return alarmStore.id;
79049     });
79050
79051     return alarm;
79052 }
79053
79054 function _eventCheckAlarm(id) {
79055     var alarm, diff;
79056
79057     _get();
79058     utils.forEach(_alarmStack, function (alarmStore) {
79059         if (alarmStore.id !== id)
79060             return;
79061
79062         alarm = _convertToAlarm(alarmStore);
79063         if (alarm.delay !== undefined) {
79064             diff = alarm.getRemainingSeconds();
79065             if (0 < diff && diff < 2) {
79066                 event.trigger("SendTriggerAppId", [alarmStore.applicationId]);
79067             }
79068         } else {
79069             diff = (new Date()) - alarm.getNextScheduledDate();
79070             if (-2000 < diff && diff < 2000) {
79071                 event.trigger("SendTriggerAppId", [alarmStore.applicationId]);
79072             }
79073         }
79074     });
79075 }
79076
79077
79078 _self = function () {
79079     var currentAppId, alarm;
79080
79081     alarm = {
79082         add: function (alarm, applicationId, appControl) {
79083             var alarmStore, external = alarm;
79084
79085             if (!_security.add) {
79086                 throw new WebAPIException(errorcode.SECURITY_ERR);
79087             }
79088
79089             alarm         = t.Alarm(alarm);
79090             applicationId = t.ApplicationId(applicationId);
79091             appControl    = t.ApplicationControl(appControl, "?");
79092
79093             alarm.id = Math.uuid(null, 16);
79094             currentAppId = _getCurrentAppId(); // Update The Current URL.
79095             alarmStore = new AlarmStore(alarm, applicationId, currentAppId, appControl);
79096             _updateDB(alarmStore);
79097
79098             external.__defineGetter__("id", function () {
79099                 return alarm.id;
79100             });
79101         },
79102
79103         remove: function (id) {
79104             var isFound = false, i;
79105
79106             if (!_security.remove) {
79107                 throw new WebAPIException(errorcode.SECURITY_ERR);
79108             }
79109
79110             id = t.AlarmId(id);
79111
79112             for (i in _alarmStack) {
79113                 if (_alarmStack[i].id !== id)
79114                     continue;
79115
79116                 _alarmStack.splice(i, 1);
79117                 _save();
79118                 isFound = true;
79119             }
79120
79121             if (!isFound) {
79122                 throw new WebAPIException(errorcode.NOT_FOUND_ERR);
79123             }
79124         },
79125
79126         removeAll: function () {
79127             var availableStack = [], i;
79128
79129             if (!_security.removeAll)
79130                 throw new WebAPIException(errorcode.SECURITY_ERR);
79131
79132             for (i in _alarmStack) {
79133                 if (_alarmStack[i].currentAppId === currentAppId)
79134                     continue;
79135
79136                 availableStack.push(_alarmStack[i]);
79137             }
79138             _alarmStack = availableStack;
79139             _save();
79140         },
79141
79142         get: function (id) {
79143             var isFound = false, item, isExpired, alarm;
79144
79145             id = t.AlarmId(id);
79146
79147             for (item in _alarmStack) {
79148                 if (_alarmStack[item].id === id) {
79149                     alarm = _convertToAlarm(_alarmStack[item]);
79150                     isExpired = _checkTriggerAlarm(alarm);
79151                     if (isExpired) {
79152                         _alarmStack.splice(item, 1);
79153                         _save();
79154                     } else {
79155                         isFound = true;
79156                     }
79157                     break;
79158                 }
79159             }
79160             if (!isFound) {
79161                 throw new WebAPIException(errorcode.NOT_FOUND_ERR);
79162             }
79163
79164             return alarm;
79165         },
79166
79167         getAll: function () {
79168             var availableStack = [], backAlarms = [], isExpired, alarm, i;
79169
79170             for (i in _alarmStack) {
79171                 alarm = _convertToAlarm(_alarmStack[i]); // alarmStore --> alarm
79172                 isExpired = _checkTriggerAlarm(alarm); // Check if the alarm is expired
79173                 if (isExpired)
79174                     continue;
79175
79176                 availableStack.push(_alarmStack[i]);
79177                 if (_alarmStack[i].currentAppId === currentAppId)
79178                     backAlarms.push(alarm);
79179             }
79180             _alarmStack = availableStack;
79181             _save();
79182             return backAlarms;
79183         },
79184
79185         handleSubFeatures: function (subFeatures) {
79186             var i, subFeature;
79187
79188             for (subFeature in subFeatures) {
79189                 for (i in _security[subFeature]) {
79190                     _security[_security[subFeature][i]] = true;
79191                 }
79192             }
79193         }
79194     };
79195
79196     currentAppId = _getCurrentAppId();
79197     _get();
79198
79199     alarm.__defineGetter__("PERIOD_MINUTE", function () {
79200         return PERIOD_MINUTE;
79201     });
79202
79203     alarm.__defineGetter__("PERIOD_HOUR", function () {
79204         return PERIOD_HOUR;
79205     });
79206
79207     alarm.__defineGetter__("PERIOD_DAY", function () {
79208         return PERIOD_DAY;
79209     });
79210
79211     alarm.__defineGetter__("PERIOD_WEEK", function () {
79212         return PERIOD_WEEK;
79213     });
79214
79215     return alarm;
79216 };
79217
79218 AlarmStore = function (alarmObject, applicationId, currentAppId, appControl) {
79219     var _self;
79220     _self = {
79221         id: alarmObject.id,
79222         delay: alarmObject.delay || null,
79223         date: alarmObject.date || null,
79224         period: alarmObject.period || null,
79225         daysOfTheWeek: alarmObject.daysOfTheWeek || null,
79226         applicationId: applicationId,
79227         currentAppId: currentAppId,
79228         appControl: appControl || null
79229     };
79230     return _self;
79231 };
79232
79233 event.on("CheckAlarm", function (id) {
79234     _eventCheckAlarm(id);
79235 });
79236
79237 module.exports = _self;
79238
79239 });
79240 define('ripple/platform/tizen/2.0/application', function (require, exports, module) {
79241 /*
79242  *  Copyright 2012 Intel Corporation.
79243  *
79244  * Licensed under the Apache License, Version 2.0 (the "License");
79245  * you may not use this file except in compliance with the License.
79246  * You may obtain a copy of the License at
79247  *
79248  * http://www.apache.org/licenses/LICENSE-2.0
79249  *
79250  * Unless required by applicable law or agreed to in writing, software
79251  * distributed under the License is distributed on an "AS IS" BASIS,
79252  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
79253  * See the License for the specific language governing permissions and
79254  * limitations under the License.
79255  */
79256
79257 var utils = require('ripple/utils'),
79258     event = require('ripple/event'),
79259     app = require('ripple/app'),
79260     db = require('ripple/db'),
79261     errorcode = require('ripple/platform/tizen/2.0/errorcode'),
79262     tizen1_utils = require('ripple/platform/tizen/2.0/tizen1_utils'),
79263     WebAPIError = require('ripple/platform/tizen/2.0/WebAPIError'),
79264     Application = require('ripple/platform/tizen/2.0/ApplicationBase'),
79265     ApplicationInformation = require('ripple/platform/tizen/2.0/ApplicationInformation'),
79266     ApplicationContext = require('ripple/platform/tizen/2.0/ApplicationContext'),
79267     ApplicationCertificate = require('ripple/platform/tizen/2.0/ApplicationCertificate'),
79268     _DB_APPLICATION_KEY = "tizen1-db-application",
79269     _security = {
79270         "http://tizen.org/privilege/application.launch": ["launch", "launchAppControl"],
79271         "http://tizen.org/privilege/appmanager.kill": ["kill"],
79272         "http://tizen.org/privilege/appmanager.certificate": ["getAppCerts"]
79273     },
79274     _data = {
79275         applications : {},
79276         applicationContexts : {},
79277         activeApp : null,
79278         listeners : {}
79279     },
79280     _appDialogTemplate = jQuery("#app-dialog-template").html(),
79281     _appDialogTemplate_short = jQuery("#app-dialog2-template").html(),
79282     _appDialogTemplate_exit_hide = jQuery("#app-dialog3-template").html(),
79283     _self;
79284
79285 function _setupCurrentApp() {
79286     var info, contextId;
79287     info = app.getInfo();
79288     contextId = Math.uuid(null, 16);
79289     _data.applications[info.id] = {
79290         id: info.id,
79291         name: info.name,
79292         iconPath: info.icon,
79293         version: info.version,
79294         show: true,
79295         categories: [],
79296         installDate: new Date(),
79297         size: 1024,
79298         packageId: "sample0123",
79299         sharedURI: "/usr/local/share/",
79300         operation: "",
79301         appControl: {
79302             uri: "",
79303             mime: "",
79304             category: "",
79305             data: ""
79306         },
79307         type: "AUTHOR_ROOT",
79308         value: []
79309     };
79310     _data.applicationContexts[contextId] = {id: contextId, appId: info.id};
79311     _data.activeApp = _data.applicationContexts[contextId];
79312 }
79313
79314 function _translate(apps) {
79315     // translate string to Date after retrieving from DB,
79316     // it is a temporary sulusion
79317     var i;
79318     for (i in apps) {
79319         if (typeof apps[i].installDate === 'string') {
79320             apps[i].installDate = new Date(apps[i].installDate);
79321         }
79322     }
79323     return apps;
79324 }
79325
79326 function _initialize() {
79327     _data = {
79328         applications : {},
79329         applicationContexts : {},
79330         activeApp : null,
79331         listeners : {}
79332     };
79333     _data.applications = _translate(db.retrieveObject(_DB_APPLICATION_KEY).installedAppList);
79334     _setupCurrentApp();
79335     $("#app-dialog").dialog({
79336         resizable: false,
79337         draggable: false,
79338         modal: true,
79339         autoOpen: false,
79340         position: 'center',
79341         minWidth: '500',
79342         minHeight: '262',
79343         open: function () { $(".ui-dialog-titlebar-close", $(this).parent()).hide(); }
79344     });
79345 }
79346
79347 _initialize();
79348
79349 _self = function () {
79350     // private
79351     function getHandle() {
79352         var handle;
79353         do {
79354             handle = Math.uuid(10, 10);
79355         } while (handle.toString().indexOf('0') === 0);
79356
79357         return parseInt(handle, 10);
79358     }
79359
79360     // public
79361     function getCurrentApplication() {
79362         var application, innerApp;
79363         /* activeApp update (by WidgetInformationUpdate event) sometime will late after user calling getCurrentApplication()
79364            for example: load other application by omnibar */
79365         if (app.getInfo().id !== _data.activeApp.appId) {
79366             _data.applications = db.retrieveObject(_DB_APPLICATION_KEY).installedAppList;
79367             _setupCurrentApp();
79368         }
79369         innerApp = _data.applications[_data.activeApp.appId];
79370         application = new Application(
79371                 new ApplicationInformation(
79372                     innerApp.id,
79373                     innerApp.name,
79374                     innerApp.iconPath,
79375                     innerApp.version,
79376                     innerApp.show,
79377                     innerApp.categories,
79378                     innerApp.installDate,
79379                     innerApp.size,
79380                     innerApp.packageId),
79381                 _data.activeApp.id, innerApp);
79382         return application;
79383     }
79384
79385     function kill(contextId, successCallback, errorCallback) {
79386         if (!_security.kill) {
79387             throw new WebAPIError(errorcode.SECURITY_ERR);
79388         }
79389
79390         if (typeof contextId !== "string") {
79391             throw new WebAPIError(errorcode.TYPE_MISMATCH_ERR);
79392         }
79393
79394         tizen1_utils.validateCallbackType(successCallback, errorCallback);
79395
79396         if (!_data.applicationContexts[contextId]) {
79397             if (errorCallback) {
79398                 errorCallback(new WebAPIError(errorcode.NOT_FOUND_ERR));
79399             }
79400             return;
79401         }
79402
79403         if (_data.activeApp && _data.activeApp.id === contextId) {
79404             if (errorCallback) {
79405                 errorCallback(new WebAPIError(errorcode.INVALID_VALUES_ERR));
79406             }
79407             return;
79408         }
79409
79410         delete _data.applicationContexts[contextId];
79411         if (successCallback) {
79412             successCallback();
79413         }
79414     }
79415
79416     function launch(id, successCallback, errorCallback) {
79417         var htmlContent;
79418
79419         if (!_security.launch) {
79420             throw new WebAPIError(errorcode.SECURITY_ERR);
79421         }
79422
79423         if (typeof id !== "string") {
79424             throw new WebAPIError(errorcode.TYPE_MISMATCH_ERR);
79425         }
79426
79427         tizen1_utils.validateCallbackType(successCallback, errorCallback);
79428
79429         if (!_data.applications[id]) {
79430             if (errorCallback) {
79431                 errorCallback(new WebAPIError(errorcode.NOT_FOUND_ERR));
79432             }
79433             return;
79434         }
79435         htmlContent = _appDialogTemplate_short.replace(/#application-name/, _data.applications[id].name)
79436             .replace(/#application-id/, id);
79437         jQuery("#app-dialog-box").html(htmlContent);
79438         $("#app-dialog").dialog("open");
79439
79440         if (successCallback) {
79441             successCallback();
79442         }
79443     }
79444
79445     function launchAppControl(appControl, id, successCallback, errorCallback, replyCallback) {
79446         var isFound, appId, htmlContent;
79447
79448         if (!_security.launchAppControl) {
79449             throw new WebAPIError(errorcode.SECURITY_ERR);
79450         }
79451
79452         if ((typeof appControl !== "object") ||
79453             (typeof appControl.operation !== "string") ||
79454             (appControl.uri && (typeof appControl.uri !== "string")) ||
79455             (appControl.mime && (typeof appControl.mime !== "string")) ||
79456             (appControl.category && (typeof appControl.category !== "string")) ||
79457             (!appControl.data instanceof Array)) {
79458             throw new WebAPIError(errorcode.TYPE_MISMATCH_ERR);
79459         }
79460
79461         if (id && (typeof id !== "string")) {
79462             throw new WebAPIError(errorcode.TYPE_MISMATCH_ERR);
79463         }
79464
79465         tizen1_utils.validateCallbackType(successCallback, errorCallback);
79466
79467         if (replyCallback && ((typeof replyCallback !== "object") ||
79468             (replyCallback.onsuccess && (typeof replyCallback.onsuccess !== "function")) ||
79469             (replyCallback.onfailure && (typeof replyCallback.onfailure !== "function")))) {
79470             throw new WebAPIError(errorcode.TYPE_MISMATCH_ERR);
79471         }
79472
79473         if (id) {
79474             if (!_data.applications[id]) {
79475                 if (errorCallback) {
79476                     errorCallback(new WebAPIError(errorcode.NOT_FOUND_ERR));
79477                 }
79478                 return;
79479             }
79480             htmlContent = _appDialogTemplate.replace(/#application-name/, _data.applications[appId].name)
79481                 .replace(/#appControl-operation/, _data.applications[appId].operation)
79482                 .replace(/#appControl-uri/, _data.applications[appId].appControl.uri)
79483                 .replace(/#appControl-mime/, _data.applications[appId].appControl.mime)
79484                 .replace(/#appControl-category/, _data.applications[appId].appControl.category)
79485                 .replace(/#appControl-data/, JSON.stringify(_data.applications[appId].appControl.data));
79486             jQuery("#app-dialog-box").html(htmlContent);
79487             $("#app-dialog").dialog("open");
79488
79489             _data.activeApp.replyCallback = replyCallback;
79490
79491             if (successCallback) {
79492                 successCallback();
79493             }
79494         } else {
79495             isFound = false;
79496             utils.forEach(_data.applications, function (application) {
79497                 if (application.operation === appControl.operation) {
79498                     appId = application.id;
79499                     isFound = true;
79500                 }
79501             });
79502             if (isFound) {
79503                 htmlContent = _appDialogTemplate.replace(/#application-name/, _data.applications[appId].name)
79504                     .replace(/#appControl-operation/, _data.applications[appId].operation)
79505                     .replace(/#appControl-uri/, _data.applications[appId].appControl.uri)
79506                     .replace(/#appControl-mime/, _data.applications[appId].appControl.mime)
79507                     .replace(/#appControl-category/, _data.applications[appId].appControl.category)
79508                     .replace(/#appControl-data/, JSON.stringify(_data.applications[appId].appControl.data));
79509                 jQuery("#app-dialog-box").html(htmlContent);
79510                 $("#app-dialog").dialog("open");
79511
79512                 _data.activeApp.replyCallback = replyCallback;
79513
79514                 if (successCallback) {
79515                     successCallback();
79516                 }
79517             } else {
79518                 if (errorCallback) {
79519                     errorCallback(new WebAPIError(errorcode.NOT_FOUND_ERR));
79520                 }
79521             }
79522         }
79523     }
79524
79525     function findAppControl(appControl, successCallback, errorCallback) {
79526         var informationArray = [];
79527
79528         if ((typeof appControl !== "object") ||
79529             (typeof appControl.operation !== "string") ||
79530             (appControl.uri && (typeof appControl.uri !== "string")) ||
79531             (appControl.mime && (typeof appControl.mime !== "string")) ||
79532             (appControl.category && (typeof appControl.category !== "string")) ||
79533             (!appControl.data instanceof Array)) {
79534             throw new WebAPIError(errorcode.TYPE_MISMATCH_ERR);
79535         }
79536
79537         tizen1_utils.validateArgumentType(successCallback, "function",
79538                 new WebAPIError(errorcode.TYPE_MISMATCH_ERR));
79539
79540         if (errorCallback) {
79541             tizen1_utils.validateArgumentType(errorCallback, "function",
79542                     new WebAPIError(errorcode.TYPE_MISMATCH_ERR));
79543         }
79544         utils.forEach(_data.applications, function (application) {
79545             if (application.operation === appControl.operation) {
79546                 informationArray.push(new ApplicationInformation(
79547                         application.id,
79548                         application.name,
79549                         application.iconPath,
79550                         application.version,
79551                         application.show,
79552                         application.categories,
79553                         application.installDate,
79554                         application.size,
79555                         application.packageId));
79556             }
79557         });
79558         if (informationArray.length === 0) {
79559             if (errorCallback) {
79560                 setTimeout(errorCallback(new WebAPIError(errorcode.NOT_FOUND_ERR)), 1);
79561             }
79562         } else {
79563             setTimeout(successCallback(informationArray, appControl), 1);
79564         }
79565     }
79566
79567     function getAppsContext(successCallback, errorCallback) {
79568         var array = [];
79569
79570         tizen1_utils.validateArgumentType(successCallback, "function",
79571                 new WebAPIError(errorcode.TYPE_MISMATCH_ERR));
79572
79573         if (errorCallback) {
79574             tizen1_utils.validateArgumentType(errorCallback, "function",
79575                     new WebAPIError(errorcode.TYPE_MISMATCH_ERR));
79576         }
79577
79578         utils.forEach(_data.applicationContexts, function (context) {
79579             array.push(new ApplicationContext(context.id, context.appId));
79580         });
79581
79582         setTimeout(successCallback(array), 1);
79583     }
79584
79585     function getAppContext(contextId) {
79586         var  appContext;
79587
79588         if (contextId === null || contextId === undefined) {
79589             appContext = new ApplicationContext(_data.activeApp.id, _data.activeApp.appId);
79590             return (appContext);
79591         }
79592         if (contextId && (typeof contextId !== "string")) {
79593             throw new WebAPIError(errorcode.TYPE_MISMATCH_ERR);
79594         }
79595         if (_data.applicationContexts[contextId]) {
79596             appContext = new ApplicationContext(contextId, _data.applicationContexts[contextId].appId);
79597             return (appContext);
79598         }
79599         throw new WebAPIError(errorcode.NOT_FOUND_ERR);
79600     }
79601
79602     function getAppsInfo(successCallback, errorCallback) {
79603         var appsInfo = [];
79604
79605         tizen1_utils.validateArgumentType(successCallback, "function",
79606                 new WebAPIError(errorcode.TYPE_MISMATCH_ERR));
79607
79608         if (errorCallback) {
79609             tizen1_utils.validateArgumentType(errorCallback, "function",
79610                     new WebAPIError(errorcode.TYPE_MISMATCH_ERR));
79611         }
79612
79613         utils.forEach(_data.applications, function (application) {
79614             appsInfo.push(new ApplicationInformation(
79615                     application.id,
79616                     application.name,
79617                     application.iconPath,
79618                     application.version,
79619                     application.show,
79620                     application.categories,
79621                     application.installDate,
79622                     application.size,
79623                     application.packageId));
79624         });
79625         setTimeout(successCallback(appsInfo), 1);
79626     }
79627
79628     function getAppInfo(id) {
79629         var appId, appInfo, theApp;
79630
79631         if (arguments.length === 0) {
79632             appId = _data.activeApp.appId;
79633             theApp = _data.applications[appId];
79634
79635             appInfo = new ApplicationInformation(
79636                     theApp.id,
79637                     theApp.name,
79638                     theApp.iconPath,
79639                     theApp.version,
79640                     theApp.show,
79641                     theApp.categories,
79642                     theApp.installDate,
79643                     theApp.size,
79644                     theApp.packageId);
79645             return appInfo;
79646         }
79647
79648         if (id && (typeof id !== "string")) {
79649             throw new WebAPIError(errorcode.TYPE_MISMATCH_ERR);
79650         }
79651
79652         if (!_data.applications[id]) {
79653             throw new WebAPIError(errorcode.NOT_FOUND_ERR);
79654         }
79655
79656         theApp = _data.applications[id];
79657         appInfo = new ApplicationInformation(
79658                     theApp.id,
79659                     theApp.name,
79660                     theApp.iconPath,
79661                     theApp.version,
79662                     theApp.show,
79663                     theApp.categories,
79664                     theApp.installDate,
79665                     theApp.size,
79666                     theApp.packageId);
79667         return appInfo;
79668     }
79669
79670     function getAppCerts(id) {
79671         var certs = [];
79672
79673         if (!_security.getAppCerts) {
79674             throw new WebAPIError(errorcode.SECURITY_ERR);
79675         }
79676
79677         if (id === null) {
79678             id = _data.activeApp.appId;
79679             certs.push(new ApplicationCertificate(_data.applications[id].type, _data.applications[id].value));
79680             return certs;
79681         }
79682
79683         if (id && typeof id !== "string") {
79684             throw new WebAPIError(errorcode.TYPE_MISMATCH_ERR);
79685         }
79686
79687         if (!_data.applications[id]) {
79688             throw new WebAPIError(errorcode.NOT_FOUND_ERR);
79689         }
79690         certs.push(new ApplicationCertificate(_data.applications[id].type, _data.applications[id].value));
79691         return certs;
79692     }
79693
79694     function getAppSharedURI(id) {
79695         var appId;
79696
79697         if (id === null || id === undefined) {
79698             appId = _data.activeApp.appId;
79699             return _data.applications[appId].sharedURI;
79700         }
79701
79702         if (id && (typeof id !== "string")) {
79703             throw new WebAPIError(errorcode.TYPE_MISMATCH_ERR);
79704         }
79705
79706         if (!_data.applications[id]) {
79707             throw new WebAPIError(errorcode.NOT_FOUND_ERR);
79708         }
79709
79710         return _data.applications[id].sharedURI;
79711     }
79712
79713     function addAppInfoEventListener(eventCallback) {
79714         var handle;
79715
79716         if (!eventCallback ||
79717             (typeof eventCallback.oninstalled !== "function") ||
79718             (typeof eventCallback.onupdated !== "function") ||
79719             (typeof eventCallback.onuninstalled !== "function")) {
79720             throw new WebAPIError(errorcode.TYPE_MISMATCH_ERR);
79721         }
79722
79723         handle = getHandle();
79724         _data.listeners[handle] = eventCallback;
79725
79726         return handle;
79727     }
79728
79729     function removeAppInfoEventListener(listenerID) {
79730         if (typeof listenerID !== "number") {
79731             throw new WebAPIError(errorcode.TYPE_MISMATCH_ERR);
79732         }
79733
79734         if (!_data.listeners[listenerID]) {
79735             throw new WebAPIError(errorcode.NOT_FOUND_ERR);
79736         }
79737
79738         delete _data.listeners[listenerID];
79739     }
79740
79741     function handleSubFeatures(subFeatures) {
79742         var i, subFeature;
79743
79744         for (subFeature in subFeatures) {
79745             for (i in _security[subFeature]) {
79746                 _security[_security[subFeature][i]] = true;
79747             }
79748         }
79749     }
79750
79751     var application = {
79752         getCurrentApplication : getCurrentApplication,
79753         kill : kill,
79754         launch : launch,
79755         launchAppControl : launchAppControl,
79756         findAppControl : findAppControl,
79757         getAppsContext : getAppsContext,
79758         getAppContext : getAppContext,
79759         getAppsInfo : getAppsInfo,
79760         getAppInfo : getAppInfo,
79761         getAppCerts : getAppCerts,
79762         getAppSharedURI: getAppSharedURI,
79763         addAppInfoEventListener : addAppInfoEventListener,
79764         removeAppInfoEventListener : removeAppInfoEventListener,
79765         handleSubFeatures : handleSubFeatures
79766     };
79767
79768     return application;
79769 };
79770
79771 event.on("tizen-application-exit", function () {
79772     var htmlContent;
79773     htmlContent = _appDialogTemplate_exit_hide.replace(/#application-name/, _data.applications[_data.activeApp.appId].name)
79774         .replace(/#application-id/, _data.applications[_data.activeApp.appId].id)
79775         .replace(/#application-operation/g, "exit")
79776         .replace(/#application-verb/, "launch")
79777         .replace(/#next-command/, "Launch")
79778         .replace(/#application-btn/, "app-dialog-reload-btn");
79779     jQuery("#app-dialog-box").html(htmlContent);
79780     $("#app-dialog").dialog("open");
79781 });
79782
79783 event.on("tizen-application-hide", function () {
79784     var htmlContent;
79785     htmlContent = _appDialogTemplate_exit_hide.replace(/#application-name/, _data.applications[_data.activeApp.appId].name)
79786         .replace(/#application-id/, _data.applications[_data.activeApp.appId].id)
79787         .replace(/#application-operation/g, "hide")
79788         .replace(/#application-verb/, "show")
79789         .replace(/#next-command/, "Show")
79790         .replace(/#application-btn/, "app-dialog-return-btn");
79791     jQuery("#app-dialog-box").html(htmlContent);
79792     $("#app-dialog").dialog("open");
79793 });
79794
79795 event.on("programChanged", function (status, id) {
79796     var callback, data, innerApp;
79797     _data.applications = db.retrieveObject(_DB_APPLICATION_KEY).installedAppList;
79798     _setupCurrentApp();
79799     switch (status) {
79800     case "installed":
79801     case "updated":
79802         innerApp = _data.applications[id];
79803         data = new ApplicationInformation(
79804                         innerApp.id,
79805                         innerApp.name,
79806                         innerApp.iconPath,
79807                         innerApp.version,
79808                         innerApp.show,
79809                         innerApp.categories,
79810                         innerApp.installDate,
79811                         innerApp.size,
79812                         innerApp.packageId);
79813         break;
79814     case "uninstalled":
79815         data = id;
79816         break;
79817
79818     default:
79819         return;
79820     }
79821     callback = "on" + status;
79822     utils.forEach(_data.listeners, function (listener) {
79823         listener[callback](data);
79824     });
79825 });
79826
79827 jQuery("#app-dialog-return-btn").live("click", function () {
79828     $("#app-dialog").dialog("close");
79829 });
79830
79831 jQuery("#app-dialog-reload-btn").live("click", function () {
79832     $("#app-dialog").dialog("close");
79833     window.tinyHipposReload = true;
79834     location.reload();
79835 });
79836
79837 jQuery("#app-dialog-generate-reply").live("click", function () {
79838     var type, data, ret = [];
79839     type = jQuery('input:radio[name="app-dialog-reply-type"]:checked').val();
79840     data = jQuery("#app-dialog-reply-json").val();
79841     $("#app-dialog").dialog("close");
79842     if (_data.activeApp.replyCallback) {
79843         switch (type) {
79844         case "replyResult":
79845             if (_data.activeApp.replyCallback.onsuccess) {
79846                 if (data === "") {
79847                     _data.activeApp.replyCallback.onsuccess();
79848                 } else {
79849                     try {
79850                         ret = JSON.parse(data);
79851                         _data.activeApp.replyCallback.onsuccess(ret);
79852                     } catch (e) {
79853                         console.log("replyResult: JSON parsing error: " + e.message);
79854                         _data.activeApp.replyCallback.onsuccess();
79855                     }
79856                 }
79857             }
79858             break;
79859         case "replyFailure":
79860             if (_data.activeApp.replyCallback.onfailure) {
79861                 _data.activeApp.replyCallback.onfailure();
79862             }
79863             break;
79864         }
79865     }
79866 });
79867
79868 event.on("ApplicationLoad", function () {
79869     _initialize();
79870 });
79871
79872 module.exports = _self;
79873
79874 });
79875 define('ripple/platform/tizen/2.0/battery', function (require, exports, module) {
79876 /*
79877  *  Copyright 2012 Intel Corporation
79878  *
79879  * Licensed under the Apache License, Version 2.0 (the "License");
79880  * you may not use this file except in compliance with the License.
79881  * You may obtain a copy of the License at
79882  *
79883  * http://www.apache.org/licenses/LICENSE-2.0
79884  *
79885  * Unless required by applicable law or agreed to in writing, software
79886  * distributed under the License is distributed on an "AS IS" BASIS,
79887  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
79888  * See the License for the specific language governing permissions and
79889  * limitations under the License.
79890  */
79891
79892 var event = require('ripple/event'),
79893     utils = require('ripple/utils'),
79894     errorcode = require('ripple/platform/tizen/2.0/errorcode'),
79895     WebAPIError = require('ripple/platform/tizen/2.0/WebAPIError'),
79896     _data = {
79897         charging: true,
79898         chargingTime: 0,
79899         level: 1.0,
79900         dischargingTime: Infinity,
79901         chargingchange: {},
79902         chargingtimechange: {},
79903         levelchange: {},
79904         dischargingtimechange: {}
79905     },
79906     _self;
79907
79908 _self = {
79909     addEventListener: function (event, callback, capture) {
79910         if (typeof callback !== "function" || event === undefined) {
79911             throw (new WebAPIError(errorcode.TYPE_MISMATCH_ERR));
79912         }
79913         switch (event) {
79914         case "chargingchange":
79915         case "chargingtimechange":
79916         case "levelchange":
79917         case "dischargingtimechange":
79918             var isExist = false, item;
79919             for (item in _data[event]) {
79920                 if (callback === item) {
79921                     isExist = true;
79922                     break;
79923                 }
79924             }
79925             if (!isExist) {
79926                 _data[event].add(callback);
79927             }
79928             break;
79929
79930         default:
79931             break;
79932         }
79933     },
79934
79935     removeEventListener: function (event, callback, capture) {
79936         if (typeof callback !== "function" || event === undefined) {
79937             throw (new WebAPIError(errorcode.TYPE_MISMATCH_ERR));
79938         }
79939         _data[event].unbind(callback);
79940     },
79941
79942     dispatchEvent: function (event) {
79943         if (event === undefined) {
79944             throw (new WebAPIError(errorcode.TYPE_MISMATCH_ERR));
79945         }
79946         return _data[event].exec(event);
79947     }
79948 };
79949
79950 _self.__defineGetter__("charging", function () {
79951     return _data.charging;
79952 });
79953
79954 _self.__defineGetter__("chargingTime", function () {
79955     return _data.chargingTime;
79956 });
79957
79958 _self.__defineGetter__("level", function () {
79959     return _data.level;
79960 });
79961
79962 _self.__defineGetter__("dischargingTime", function () {
79963     return _data.dischargingTime;
79964 });
79965
79966 function _initialize() {
79967     var callback = [];
79968
79969     function bind(name) {
79970         _self.__defineGetter__(name, function () {
79971             return callback;
79972         });
79973
79974         _self.__defineSetter__(name, function (cb) {
79975             callback = cb;
79976         });
79977
79978         return {
79979             get: function () {
79980                 return callback;
79981             },
79982
79983             set: function (value) {
79984                 callback = value;
79985             },
79986
79987             add: function (value) {
79988                 callback.push(value);
79989             },
79990
79991             exec: function (arg) {
79992                 callback.forEach(function (callback) {
79993                     return !callback || callback(arg);
79994                 });
79995             },
79996
79997             unbind: function (value) {
79998                 if (value === undefined) {
79999                     callback = [];
80000                 } else {
80001                     utils.forEach(callback, function (callback, index) {
80002                         if (callback === value) {
80003                             callback.splice(index, 1);
80004                         }
80005                     });
80006                 }
80007             }
80008         };
80009     }
80010
80011     _data.chargingchange        = bind("onchargingchange");
80012     _data.chargingtimechange    = bind("onchargingtimechange");
80013     _data.levelchange           = bind("onlevelchange");
80014     _data.dischargingtimechange = bind("ondischargingtimechange");
80015
80016     event.on("BatteryEvent", function (status) {
80017         for (var ev in status) {
80018             if ((status[ev] !== undefined) && (status[ev] !== _data[ev])) {
80019                 _data[ev] = status[ev];
80020             }
80021         }
80022         _data[status.type].exec();
80023     });
80024 }
80025
80026 _initialize();
80027
80028 module.exports = _self;
80029
80030 });
80031 define('ripple/platform/tizen/2.0/bluetooth', function (require, exports, module) {
80032 /*
80033  *  Copyright 2012 Intel Corporation
80034  *
80035  * Licensed under the Apache License, Version 2.0 (the "License");
80036  * you may not use this file except in compliance with the License.
80037  * You may obtain a copy of the License at
80038  *
80039  * http://www.apache.org/licenses/LICENSE-2.0
80040  *
80041  * Unless required by applicable law or agreed to in writing, software
80042  * distributed under the License is distributed on an "AS IS" BASIS,
80043  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
80044  * See the License for the specific language governing permissions and
80045  * limitations under the License.
80046  */
80047
80048 var utils = require('ripple/utils'),
80049     db = require('ripple/db'),
80050     event = require('ripple/event'),
80051     errorcode = require('ripple/platform/tizen/2.0/errorcode'),
80052     WebAPIError = require('ripple/platform/tizen/2.0/WebAPIError'),
80053     tizen1_utils = require('ripple/platform/tizen/2.0/tizen1_utils'),
80054     BluetoothDevice = require('ripple/platform/tizen/2.0/BluetoothDevice'),
80055     BluetoothClassDeviceMajor = require('ripple/platform/tizen/2.0/BluetoothClassDeviceMajor'),
80056     BluetoothClassDeviceMinor = require('ripple/platform/tizen/2.0/BluetoothClassDeviceMinor'),
80057     BluetoothClassDeviceService = require('ripple/platform/tizen/2.0/BluetoothClassDeviceService'),
80058     BluetoothServiceHandler = require('ripple/platform/tizen/2.0/BluetoothServiceHandler'),
80059     BluetoothAdapter,
80060     _data = {
80061         DB_BLUETOOTH_KEY : "tizen1-db-bluetooth_adapter-name",
80062         DEFAULT_ADAPTER_NAME: "Tizen BT Adapter",
80063         DEFAULT_ADAPTER_ADDRESS: "12:34:56:78:90:AB",
80064         availableDevsChanging : false,
80065         DEFAULT_VISIBLE_TIME : 180000,
80066         DISCOVER_TIME : 10000,
80067         DISCOVER_INTERVAL : 1000,
80068         bluetoothClassDeviceMajor : {},
80069         bluetoothClassDeviceMinor : {},
80070         bluetoothClassDeviceService : {},
80071         adapter : {},
80072         historyDevs : {},
80073         availableDevs : {},
80074         localServices : {},
80075     },
80076     _security = {
80077         "http://tizen.org/privilege/bluetoothmanager": ["setVisible"],
80078         "http://tizen.org/privilege/bluetooth.admin": ["setName", "setPowered"],
80079         "http://tizen.org/privilege/bluetooth.gap": ["getDefaultAdapter", "discoverDevices", "stopDiscovery", "getKnownDevices", "getDevice", "createBonding", "destroyBonding", "hasService"],
80080         "http://tizen.org/privilege/bluetooth.spp": ["registerRFCOMMServiceByUUID", "connectToServiceByUUID", "writeData", "readData", "close", "unregister"]
80081     },
80082     _self;
80083
80084 function _initialize() {
80085     var adapterName;
80086
80087     _data.bluetoothClassDeviceMajor = new BluetoothClassDeviceMajor();
80088     _data.bluetoothClassDeviceMinor = new BluetoothClassDeviceMinor();
80089     _data.bluetoothClassDeviceService = new BluetoothClassDeviceService();
80090     adapterName = db.retrieveObject(_data.DB_BLUETOOTH_KEY) || _data.DEFAULT_ADAPTER_NAME;
80091     _data.adapter = new BluetoothAdapter(adapterName, _data.DEFAULT_ADAPTER_ADDRESS);
80092 }
80093
80094 function _validateDiscoverDevicesType(onSuccess, onError) {
80095     if (typeof onSuccess !== "object") {
80096         throw new WebAPIError(errorcode.TYPE_MISMATCH_ERR);
80097     }
80098     if (onError) {
80099         tizen1_utils.validateArgumentType(onError, "function",
80100                 new WebAPIError(errorcode.TYPE_MISMATCH_ERR));
80101     }
80102     tizen1_utils.validateArgumentType(onSuccess.onstarted, "function",
80103             new WebAPIError(errorcode.TYPE_MISMATCH_ERR));
80104     tizen1_utils.validateArgumentType(onSuccess.ondevicefound, "function",
80105             new WebAPIError(errorcode.TYPE_MISMATCH_ERR));
80106     tizen1_utils.validateArgumentType(onSuccess.ondevicedisappeared, "function",
80107             new WebAPIError(errorcode.TYPE_MISMATCH_ERR));
80108     tizen1_utils.validateArgumentType(onSuccess.onfinished, "function",
80109             new WebAPIError(errorcode.TYPE_MISMATCH_ERR));
80110 }
80111
80112 BluetoothAdapter = function (devName, devAddress) {
80113     var adapter,
80114         timeoutVar,
80115         _devName = devName,
80116         _devAddress = devAddress,
80117         _devPowered = false,
80118         _devVisible = false,
80119         _isDiscovering = false,
80120         discoverInterval;
80121
80122     // private
80123     function _updatePowerStatus(status) {
80124         if (_devPowered === status) {
80125             return;
80126         }
80127         if (!status) {
80128             _updateVisibleStatus(false);
80129             utils.forEach(_data.historyDevs, function (dev) {
80130                 event.trigger("bt-service-state-update", [dev.address, false]);
80131                 Object.defineProperty(dev, "isBonded", {value: false, writable: false});
80132                 event.trigger("bt-device-bonded-changed", [dev.address, false]);
80133                 jQuery("#service-transfer-textarea-" + dev.address.replace(/:/g, "")).val("");
80134                 jQuery("#service-receive-textarea-" + dev.address.replace(/:/g, "")).html("");
80135             });
80136         }
80137         _devPowered = status;
80138         event.trigger("bt-adapter-power-changed", [_devPowered]);
80139     }
80140
80141     function _updateVisibleStatus(status, time) {
80142         if (!_devPowered)
80143             return;
80144         _devVisible = status;
80145         event.trigger("bt-adapter-visible-changed", [_devVisible]);
80146         if (_devVisible) {
80147             if (time > 0) {
80148                 timeoutVar = setTimeout(function () {
80149                     _devVisible = false;
80150                     event.trigger("bt-adapter-visible-changed", [_devVisible]);
80151                 }, time);
80152             }
80153         } else {
80154             clearTimeout(timeoutVar);
80155         }
80156     }
80157
80158     // public
80159     function setName(name, successCallback, errorCallback) {
80160         if (!_security.setName) {
80161             throw new WebAPIError(errorcode.SECURITY_ERR);
80162         }
80163
80164         tizen1_utils.validateCallbackType(successCallback, errorCallback);
80165
80166         if (typeof name !== "string") {
80167             throw new WebAPIError(errorcode.TYPE_MISMATCH_ERR);
80168         }
80169
80170         if (!_devPowered) {
80171             if (errorCallback) {
80172                 errorCallback(new WebAPIError(errorcode.SERVICE_NOT_AVAILABLE_ERR));
80173             }
80174             return;
80175         }
80176
80177         _devName = name;
80178         db.saveObject(_data.DB_BLUETOOTH_KEY, _devName);
80179         event.trigger("bt-adapter-name-changed", [_devName]);
80180         if (successCallback) {
80181             successCallback();
80182         }
80183     }
80184
80185     function setPowered(state, successCallback, errorCallback) {
80186         if (!_security.setPowered) {
80187             throw new WebAPIError(errorcode.SECURITY_ERR);
80188         }
80189
80190         tizen1_utils.validateCallbackType(successCallback, errorCallback);
80191
80192         if (typeof state !== "boolean") {
80193             throw new WebAPIError(errorcode.TYPE_MISMATCH_ERR);
80194         }
80195
80196         _updatePowerStatus(state);
80197         if (successCallback) {
80198             successCallback();
80199         }
80200     }
80201
80202     function setVisible(mode, successCallback, errorCallback, timeout) {
80203         var time;
80204
80205         if (!_security.setVisible) {
80206             throw new WebAPIError(errorcode.SECURITY_ERR);
80207         }
80208
80209         tizen1_utils.validateCallbackType(successCallback, errorCallback);
80210
80211         if (typeof mode !== "boolean") {
80212             throw new WebAPIError(errorcode.TYPE_MISMATCH_ERR);
80213         }
80214
80215         if (!_devPowered) {
80216             if (errorCallback) {
80217                 errorCallback(new WebAPIError(errorcode.SERVICE_NOT_AVAILABLE_ERR));
80218             }
80219             return;
80220         }
80221
80222         if (typeof timeout === "number") {
80223             if (timeout < 0) {
80224                 time = _data.DEFAULT_VISIBLE_TIME;
80225             } else {
80226                 time = timeout * 1000;
80227             }
80228         } else {
80229             time = _data.DEFAULT_VISIBLE_TIME;
80230         }
80231         _updateVisibleStatus(mode, time);
80232         if (successCallback) {
80233             successCallback();
80234         }
80235     }
80236
80237     function discoverDevices(successCallback, errorCallback) {
80238         var interval;
80239
80240         if (!_security.discoverDevices) {
80241             throw new WebAPIError(errorcode.SECURITY_ERR);
80242         }
80243
80244         _validateDiscoverDevicesType(successCallback, errorCallback);
80245
80246         if (!_devPowered) {
80247             if (errorCallback) {
80248                 errorCallback(new WebAPIError(errorcode.SERVICE_NOT_AVAILABLE_ERR));
80249             }
80250             return;
80251         }
80252
80253         // already discovering
80254         if (_isDiscovering) {
80255             return;
80256         }
80257         _isDiscovering = true;
80258         _data.historyDevs = {};
80259
80260         successCallback.onstarted();
80261         _data.availableDevsChanging = false;
80262         utils.forEach(_data.availableDevs, function (item) {
80263             _data.historyDevs[item.address] = item;
80264             successCallback.ondevicefound(utils.copy(item));
80265         });
80266
80267         discoverInterval = setTimeout(function () {
80268             var devs = [];
80269             clearInterval(interval);
80270             utils.forEach(_data.historyDevs, function (item) {
80271                 devs.push(utils.copy(item));
80272             });
80273             successCallback.onfinished(devs);
80274             _isDiscovering = false;
80275         }, _data.DISCOVER_TIME);
80276
80277         interval = setInterval(function () {
80278             var removeList = [], i;
80279             if (!_isDiscovering) {
80280                 clearInterval(interval);
80281                 return;
80282             }
80283
80284             if (_data.availableDevsChanging === true) {
80285                 _data.availableDevsChanging = false;
80286                 utils.forEach(_data.historyDevs, function (item) {
80287                     if (!_data.availableDevs[item.address]) {
80288                         removeList.push(item.address);
80289                     }
80290                 });
80291                 for (i in removeList) {
80292                     successCallback.ondevicedisappeared(removeList[i]);
80293                     delete _data.historyDevs[removeList[i]];
80294                 }
80295                 utils.forEach(_data.availableDevs, function (item) {
80296                     if (!_data.historyDevs[item.address]) {
80297                         _data.historyDevs[item.address] = item;
80298                         successCallback.ondevicefound(utils.copy(item));
80299                     }
80300                 });
80301             }
80302         }, _data.DISCOVER_INTERVAL);
80303     }
80304
80305     function stopDiscovery(successCallback, errorCallback) {
80306         if (!_security.stopDiscovery) {
80307             throw new WebAPIError(errorcode.SECURITY_ERR);
80308         }
80309
80310         tizen1_utils.validateCallbackType(successCallback, errorCallback);
80311
80312         if (!_devPowered) {
80313             if (errorCallback) {
80314                 errorCallback(new WebAPIError(errorcode.SERVICE_NOT_AVAILABLE_ERR));
80315             }
80316             return;
80317         }
80318
80319         if (_isDiscovering) {
80320             clearTimeout(discoverInterval);
80321         }
80322         _isDiscovering = false;
80323         if (successCallback) {
80324             successCallback();
80325         }
80326     }
80327
80328     function getKnownDevices(successCallback, errorCallback) {
80329         var devs = [];
80330
80331         if (!_security.getKnownDevices) {
80332             throw new WebAPIError(errorcode.SECURITY_ERR);
80333         }
80334
80335         tizen1_utils.validateArgumentType(successCallback, "function",
80336                 new WebAPIError(errorcode.TYPE_MISMATCH_ERR));
80337
80338         if (errorCallback) {
80339             tizen1_utils.validateArgumentType(errorCallback, "function",
80340                     new WebAPIError(errorcode.TYPE_MISMATCH_ERR));
80341         }
80342
80343         if (!_devPowered) {
80344             if (errorCallback) {
80345                 errorCallback(new WebAPIError(errorcode.SERVICE_NOT_AVAILABLE_ERR));
80346             }
80347             return;
80348         }
80349         utils.forEach(_data.historyDevs, function (item) {
80350             devs.push(utils.copy(item));
80351         });
80352         successCallback(devs);
80353     }
80354
80355     function getDevice(address, successCallback, errorCallback) {
80356         if (!_security.getDevice) {
80357             throw new WebAPIError(errorcode.SECURITY_ERR);
80358         }
80359
80360         if (typeof address !== "string") {
80361             throw new WebAPIError(errorcode.TYPE_MISMATCH_ERR);
80362         }
80363
80364         tizen1_utils.validateArgumentType(successCallback, "function",
80365                 new WebAPIError(errorcode.TYPE_MISMATCH_ERR));
80366
80367         if (errorCallback) {
80368             tizen1_utils.validateArgumentType(errorCallback, "function",
80369                     new WebAPIError(errorcode.TYPE_MISMATCH_ERR));
80370         }
80371
80372         if (!_devPowered) {
80373             if (errorCallback) {
80374                 errorCallback(new WebAPIError(errorcode.SERVICE_NOT_AVAILABLE_ERR));
80375             }
80376             return;
80377         }
80378
80379         if (_data.historyDevs[address]) {
80380             successCallback(utils.copy(_data.historyDevs[address]));
80381         } else {
80382             errorCallback(new WebAPIError(errorcode.NOT_FOUND_ERR));
80383         }
80384     }
80385
80386     function createBonding(address, successCallback, errorCallback) {
80387         if (!_security.createBonding) {
80388             throw new WebAPIError(errorcode.SECURITY_ERR);
80389         }
80390
80391         if (typeof address !== "string") {
80392             throw new WebAPIError(errorcode.TYPE_MISMATCH_ERR);
80393         }
80394
80395         tizen1_utils.validateArgumentType(successCallback, "function",
80396                 new WebAPIError(errorcode.TYPE_MISMATCH_ERR));
80397
80398         if (errorCallback) {
80399             tizen1_utils.validateArgumentType(errorCallback, "function",
80400                     new WebAPIError(errorcode.TYPE_MISMATCH_ERR));
80401         }
80402
80403         if (!_devPowered) {
80404             if (errorCallback) {
80405                 errorCallback(new WebAPIError(errorcode.SERVICE_NOT_AVAILABLE_ERR));
80406             }
80407             return;
80408         }
80409
80410         if (_data.historyDevs[address]) {
80411             Object.defineProperty(_data.historyDevs[address], "isBonded", {value: true, writable: false});
80412             event.trigger("bt-device-bonded-changed", [address, true]);
80413             successCallback(utils.copy(_data.historyDevs[address]));
80414         } else if (errorCallback) {
80415             errorCallback(new WebAPIError(errorcode.NOT_FOUND_ERR));
80416         }
80417     }
80418
80419     function destroyBonding(address, successCallback, errorCallback) {
80420         if (!_security.destroyBonding) {
80421             throw new WebAPIError(errorcode.SECURITY_ERR);
80422         }
80423
80424         if (typeof address !== "string") {
80425             throw new WebAPIError(errorcode.TYPE_MISMATCH_ERR);
80426         }
80427
80428         tizen1_utils.validateCallbackType(successCallback, errorCallback);
80429
80430         if (!_devPowered) {
80431             if (errorCallback) {
80432                 errorCallback(new WebAPIError(errorcode.SERVICE_NOT_AVAILABLE_ERR));
80433             }
80434             return;
80435         }
80436
80437         if (_data.historyDevs[address]) {
80438             event.trigger("bt-service-state-update", [address, false]);
80439             Object.defineProperty(_data.historyDevs[address], "isBonded", {value: false, writable: false});
80440             event.trigger("bt-device-bonded-changed", [address, false]);
80441             if (successCallback) {
80442                 successCallback();
80443             }
80444         } else if (errorCallback) {
80445             errorCallback(new WebAPIError(errorcode.NOT_FOUND_ERR));
80446         }
80447     }
80448
80449     function registerRFCOMMServiceByUUID(uuid, name, successCallback, errorCallback, securityLevel) {
80450         if (!_security.registerRFCOMMServiceByUUID) {
80451             throw new WebAPIError(errorcode.SECURITY_ERR);
80452         }
80453
80454         if (typeof name !== "string" || typeof uuid !== "string") {
80455             throw new WebAPIError(errorcode.TYPE_MISMATCH_ERR);
80456         }
80457
80458         tizen1_utils.validateArgumentType(successCallback, "function",
80459                 new WebAPIError(errorcode.TYPE_MISMATCH_ERR));
80460
80461         if (errorCallback) {
80462             tizen1_utils.validateArgumentType(errorCallback, "function",
80463                     new WebAPIError(errorcode.TYPE_MISMATCH_ERR));
80464         }
80465
80466         if (securityLevel) {
80467             if (securityLevel !== "LOW" && securityLevel !== "MEDIUM" && securityLevel !== "HIGH") {
80468                 throw new WebAPIError(errorcode.TYPE_MISMATCH_ERR);
80469             }
80470         }
80471
80472         if (!_devPowered) {
80473             if (errorCallback) {
80474                 errorCallback(new WebAPIError(errorcode.SERVICE_NOT_AVAILABLE_ERR));
80475             }
80476             return;
80477         }
80478
80479         _data.localServices[uuid] = new BluetoothServiceHandler({uuid: uuid, name: name, isConnected: false, metaData: _security});
80480         successCallback(_data.localServices[uuid]);
80481     }
80482
80483     event.on("bt-simulated-devices-changed", function () {
80484         var devs = db.retrieveObject("bt-simulated-devices");
80485         utils.forEach(_data.availableDevs, function (item) {
80486             if (!devs[item.address]) {
80487                 delete _data.availableDevs[item.address];
80488             }
80489         });
80490         utils.forEach(devs, function (item) {
80491             if (!_data.availableDevs[item.address]) {
80492
80493                 _data.availableDevs[item.address] = new BluetoothDevice({
80494                     name: item.name,
80495                     address: item.address,
80496                     deviceClass: item.deviceClass,
80497                     isBonded: false,
80498                     isTrusted: item.isTrusted,
80499                     isConnected: false,
80500                     services: item.services,
80501                     metaData: _security
80502                 });
80503             }
80504         });
80505         _data.availableDevsChanging = true;
80506     });
80507
80508     event.on("bt-unregister-service", function (uuid, successCallback, errorCallback) {
80509         if (!_data.localServices[uuid]) {
80510             if (errorCallback) {
80511                 errorCallback(new WebAPIError(errorcode.UNKNOWN_ERR));
80512             }
80513             return;
80514         }
80515         delete _data.localServices[uuid];
80516         if (successCallback) {
80517             successCallback();
80518         }
80519     });
80520
80521     event.on("bt-power-setting", function (status) {
80522         _updatePowerStatus(status);
80523     });
80524
80525     adapter = {
80526         setName : setName,
80527         setPowered : setPowered,
80528         setVisible : setVisible,
80529         discoverDevices : discoverDevices,
80530         stopDiscovery : stopDiscovery,
80531         getKnownDevices : getKnownDevices,
80532         getDevice : getDevice,
80533         createBonding : createBonding,
80534         destroyBonding : destroyBonding,
80535         registerRFCOMMServiceByUUID : registerRFCOMMServiceByUUID
80536     };
80537
80538     adapter.__defineGetter__("name", function () {
80539         return _devName;
80540     });
80541     adapter.__defineGetter__("address", function () {
80542         return _devAddress;
80543     });
80544     adapter.__defineGetter__("powered", function () {
80545         return _devPowered;
80546     });
80547     adapter.__defineGetter__("visible", function () {
80548         return _devVisible;
80549     });
80550
80551     return adapter;
80552 };
80553
80554 _initialize();
80555
80556 _self = function () {
80557     function getDefaultAdapter() {
80558         if (!_security.getDefaultAdapter) {
80559             throw new WebAPIError(errorcode.SECURITY_ERR);
80560         }
80561
80562         if (arguments.length > 0) {
80563             throw new WebAPIError(errorcode.TYPE_MISMATCH_ERR);
80564         }
80565
80566         if (!_data.adapter) {
80567             throw new WebAPIError(errorcode.UNKNOWN_ERR);
80568         }
80569
80570         return _data.adapter;
80571     }
80572
80573     function handleSubFeatures(subFeatures) {
80574         var i, subFeature;
80575
80576         for (subFeature in subFeatures) {
80577             for (i in _security[subFeature]) {
80578                 _security[_security[subFeature][i]] = true;
80579             }
80580         }
80581     }
80582
80583     var bluetooth = {
80584         getDefaultAdapter : getDefaultAdapter,
80585         handleSubFeatures : handleSubFeatures
80586     };
80587
80588     bluetooth.__defineGetter__("deviceMajor", function () {
80589         return _data.bluetoothClassDeviceMajor;
80590     });
80591     bluetooth.__defineGetter__("deviceMinor", function () {
80592         return _data.bluetoothClassDeviceMinor;
80593     });
80594     bluetooth.__defineGetter__("deviceService", function () {
80595         return _data.bluetoothClassDeviceService;
80596     });
80597
80598     return bluetooth;
80599 };
80600
80601 module.exports = _self;
80602
80603 });
80604 define('ripple/platform/tizen/2.0/bookmark', function (require, exports, module) {
80605 /*
80606  *  Copyright 2013 Intel Corporation.
80607  *
80608  * Licensed under the Apache License, Version 2.0 (the "License");
80609  * you may not use this file except in compliance with the License.
80610  * You may obtain a copy of the License at
80611  *
80612  * http://www.apache.org/licenses/LICENSE-2.0
80613  *
80614  * Unless required by applicable law or agreed to in writing, software
80615  * distributed under the License is distributed on an "AS IS" BASIS,
80616  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
80617  * See the License for the specific language governing permissions and
80618  * limitations under the License.
80619  */
80620
80621 var db = require('ripple/db'),
80622     utils = require('ripple/utils'),
80623     t = require('ripple/platform/tizen/2.0/typecast'),
80624     errorcode = require('ripple/platform/tizen/2.0/errorcode'),
80625     WebAPIException = require('ripple/platform/tizen/2.0/WebAPIException'),
80626     BookmarkFolder = require('ripple/platform/tizen/2.0/BookmarkFolder'),
80627     BookmarkItem = require('ripple/platform/tizen/2.0/BookmarkItem'),
80628     BookmarkExternal,
80629     BookmarkInternal,
80630     BookmarkStorage,
80631     _data = {
80632         DB_BOOKMARK_KEY: "tizen1-bookmark",
80633         bookmarks:       [],
80634         dbStorage:       []
80635     },
80636     _security = {
80637         "http://tizen.org/privilege/bookmark.read": ["get"],
80638         "http://tizen.org/privilege/bookmark.write": ["add", "remove"]
80639     },
80640     _self;
80641
80642 function _get() {
80643     _data.dbStorage = db.retrieveObject(_data.DB_BOOKMARK_KEY) || [];
80644 }
80645
80646 function _save() {
80647     db.saveObject(_data.DB_BOOKMARK_KEY, _data.dbStorage);
80648 }
80649
80650 function _initialize() {
80651     _get();
80652
80653     utils.forEach(_data.dbStorage, function (bookmark) {
80654         _data.bookmarks.push(new BookmarkInternal(bookmark, null));
80655     });
80656 }
80657
80658 function _persist() {
80659     _data.dbStorage = [];
80660
80661     utils.forEach(_data.bookmarks, function (bookmark) {
80662         _data.dbStorage.push(new BookmarkStorage(bookmark));
80663     });
80664
80665     _save();
80666 }
80667
80668 function _isFolder(bookmark) {
80669     return !bookmark.url;
80670 }
80671
80672 function _isExternal(bookmark) {
80673     return !("children" in bookmark);
80674 }
80675
80676 function _getChildren(bookmark, BookmarkType, parent) {
80677     var i, children = [];
80678
80679     if (!_isExternal(bookmark)) {
80680         for (i in bookmark.children) {
80681             children.push(new BookmarkType(bookmark.children[i], parent));
80682         }
80683     }
80684
80685     return children;
80686 }
80687
80688 _self = function () {
80689     var bookmark;
80690
80691     // private
80692     /*
80693      * map
80694      *    Map the external bookmark to the internal one in the tree
80695      *
80696      * bookmarkExternal
80697      *    External bookmark Object
80698      *
80699      * callback
80700      *    callback(index, peers). Optional.
80701      *
80702      *          Root    Bookmark        Not Found
80703      * ------------------------------------------
80704      *  index   0       index           -1
80705      *  peers   null    peers           null
80706      *
80707      * Return   null    peers[index]    undefined
80708      */
80709
80710     function map(bookmarkExternal, callback) {
80711         var trace = [], it, i, peers = null;
80712
80713         if (!bookmarkExternal) {
80714             if (callback) {
80715                 callback(0, null);
80716             }
80717             return null;
80718         }
80719
80720         for (it = bookmarkExternal; it; it = it.parent) {
80721             trace.push(it);
80722         }
80723
80724         for (it = _data.bookmarks; trace.length !== 0; it = it[i].children) {
80725             bookmarkExternal = trace.pop();
80726             peers = null;
80727
80728             for (i in it) {
80729                 if (it[i].external === bookmarkExternal) {
80730                     peers = it;
80731                     break;
80732                 }
80733             }
80734         }
80735
80736         if (callback) {
80737             return callback((peers !== null) ? i : -1, peers);
80738         }
80739
80740         return (peers !== null) ? peers[i] : undefined;
80741     }
80742
80743     function traverse(bookmarks, trace, level) {
80744         for (var i in bookmarks) {
80745             trace.push(bookmarks[i].external);
80746             if ((level !== 0) && bookmarks[i].children) {
80747                 traverse(bookmarks[i].children, trace, --level);
80748             }
80749         }
80750     }
80751
80752     function isExisting(bookmark, peers) {
80753         var i;
80754
80755         for (i in peers) {
80756             if ((peers[i].title === bookmark.title) &&
80757                 (_isFolder(peers[i]) === _isFolder(bookmark))) {
80758                 return true;
80759             }
80760         }
80761
80762         return false;
80763     }
80764
80765     // public
80766     function get(parentFolder, recursive) {
80767         var bookmarks = [], parent, peers;
80768
80769         if (!_security.get) {
80770             throw new WebAPIException(errorcode.SECURITY_ERR);
80771         }
80772
80773         parentFolder = t.BookmarkFolder(parentFolder, "?");
80774         recursive = t.boolean(recursive, "?");
80775
80776         parent = map(parentFolder);
80777         if ((parent === undefined) || (parent && !_isFolder(parent))) {
80778             throw new WebAPIException(errorcode.NOT_FOUND_ERR);
80779         }
80780         peers = parent ? parent.children : _data.bookmarks;
80781         traverse(peers, bookmarks, recursive ? -1 : 0);
80782
80783         return bookmarks;
80784     }
80785
80786     function add(bookmark, parentFolder) {
80787         var parent, peers;
80788
80789         if (!_security.add) {
80790             throw new WebAPIException(errorcode.SECURITY_ERR);
80791         }
80792
80793         bookmark = t.Bookmark(bookmark);
80794         parentFolder = t.BookmarkFolder(parentFolder, "?");
80795
80796         parent = map(parentFolder);
80797         if ((parent === undefined) || (parent && !_isFolder(parent))) {
80798             throw new WebAPIException(errorcode.NOT_FOUND_ERR);
80799         }
80800         peers = parent ? parent.children : _data.bookmarks;
80801         if (isExisting(bookmark, peers)) {
80802             throw new WebAPIException(errorcode.UNKNOWN_ERR);
80803         }
80804
80805         peers.push(new BookmarkInternal(bookmark));
80806
80807         _persist();
80808
80809         bookmark.__defineGetter__("parent", function () {
80810             return parent ? parent.external : null;
80811         });
80812     }
80813
80814     function remove(bookmark) {
80815         if (!_security.remove) {
80816             throw new WebAPIException(errorcode.SECURITY_ERR);
80817         }
80818
80819         bookmark = t.Bookmark(bookmark, "?");
80820
80821         if (!bookmark) {
80822             _data.bookmarks = [];
80823         } else {
80824             map(bookmark, function (index, peers) {
80825                 if (index === -1) {
80826                     throw new WebAPIException(errorcode.NOT_FOUND_ERR);
80827                 }
80828                 peers.splice(index, 1);
80829             });
80830         }
80831
80832         _persist();
80833     }
80834
80835     function handleSubFeatures(subFeatures) {
80836         var i, subFeature;
80837
80838         for (subFeature in subFeatures) {
80839             for (i in _security[subFeature]) {
80840                 _security[_security[subFeature][i]] = true;
80841             }
80842         }
80843     }
80844
80845     bookmark = {
80846         get:               get,
80847         add:               add,
80848         remove:            remove,
80849         handleSubFeatures: handleSubFeatures
80850     };
80851
80852     return bookmark;
80853 };
80854
80855 /*
80856  * BookmarkInternal     BookmarkStorage     BookmarkExternal
80857  * ---------------------------------------------------------
80858  * title                title               title
80859  * url                  url                 url/-
80860  * children             children            -
80861  * external             -                   -
80862  * -                    -                   parent
80863  */
80864
80865 BookmarkInternal = function (bookmark, parent) {
80866     this.title    = bookmark.title;
80867     this.url      = _isFolder(bookmark) ? null : bookmark.url;
80868     this.children = _isFolder(bookmark) ?
80869         _getChildren(bookmark, BookmarkInternal, this) : null;
80870     this.external = _isExternal(bookmark) ? bookmark :
80871         new BookmarkExternal(bookmark, parent);
80872 };
80873
80874 BookmarkStorage = function (bookmark) {
80875     this.title    = bookmark.title;
80876     this.url      = _isFolder(bookmark) ? null : bookmark.url;
80877     this.children = _isFolder(bookmark) ?
80878         _getChildren(bookmark, BookmarkStorage) : null;
80879 };
80880
80881 BookmarkExternal = function (bookmark, parent) {
80882     var self;
80883
80884     if (_isFolder(bookmark)) {
80885         self = new BookmarkFolder(bookmark.title);
80886     } else {
80887         self = new BookmarkItem(bookmark.title, bookmark.url);
80888     }
80889
80890     self.__defineGetter__("parent", function () {
80891         return parent ? parent.external : null;
80892     });
80893
80894     return self;
80895 };
80896
80897 _initialize();
80898
80899 module.exports = _self;
80900
80901 });
80902 define('ripple/platform/tizen/2.0/calendar', function (require, exports, module) {
80903 /*
80904  *  Copyright 2012 Intel Corporation.
80905  *
80906  * Licensed under the Apache License, Version 2.0 (the "License");
80907  * you may not use this file except in compliance with the License.
80908  * You may obtain a copy of the License at
80909  *
80910  * http://www.apache.org/licenses/LICENSE-2.0
80911  *
80912  * Unless required by applicable law or agreed to in writing, software
80913  * distributed under the License is distributed on an "AS IS" BASIS,
80914  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
80915  * See the License for the specific language governing permissions and
80916  * limitations under the License.
80917  */
80918
80919 var utils = require('ripple/utils'),
80920     db = require('ripple/db'),
80921     tizen1_utils = require('ripple/platform/tizen/2.0/tizen1_utils'),
80922     errorcode = require('ripple/platform/tizen/2.0/errorcode'),
80923     WebAPIError = require('ripple/platform/tizen/2.0/WebAPIError'),
80924     WebAPIException = require('ripple/platform/tizen/2.0/WebAPIException'),
80925     TZDate = require('ripple/platform/tizen/2.0/TZDate'),
80926     CalendarItem = require('ripple/platform/tizen/2.0/CalendarItem'),
80927     CalendarEvent = require('ripple/platform/tizen/2.0/CalendarEvent'),
80928     CalendarTask = require('ripple/platform/tizen/2.0/CalendarTask'),
80929     Calendar,
80930     CalendarStorage,
80931     CalendarItemsStorage,
80932     _DB_CALENDARS_KEY = "tizen1-db-calendars",
80933     _watchers = [],
80934     _calendars = {
80935         EVENT: {},
80936         TASK: {}
80937     },
80938     _calendarsStorage,
80939     _security = {
80940         "http://tizen.org/privilege/calendar.read": ["getCalendars", "getDefaultCalendar", "getCalendar", "get", "find",
80941             "addChangeListener", "removeChangeListener", "expandRecurrence", "convertToString", "clone"],
80942         "http://tizen.org/privilege/calendar.write": ["add", "addBatch", "update", "updateBatch", "remove", "removeBatch"]
80943     },
80944     _self;
80945
80946 function _isValidId(id) {
80947     return (/[a-z]|[A-Z]|[0-9]|[\-]/).test(id);
80948 }
80949
80950 function retrieveCalendars() {
80951     _calendarsStorage = db.retrieveObject(_DB_CALENDARS_KEY) || {EVENT: {}, TASK: {}};
80952 }
80953
80954 function saveCalendars() {
80955     db.saveObject(_DB_CALENDARS_KEY, _calendarsStorage);
80956 }
80957
80958 _self = function () {
80959     var calendarManager;
80960
80961     // private
80962     function isValidType(type) {
80963         for (var t in _calendars) {
80964             if (type === t)
80965                 return true;
80966         }
80967         return false;
80968     }
80969
80970     function loadCalendars(type) {
80971         var calsStorage, defCalendar, id, i, item;
80972
80973         retrieveCalendars();
80974         calsStorage = _calendarsStorage[type];
80975
80976         if (tizen1_utils.isEmptyObject(calsStorage)) {
80977             defCalendar = new Calendar(type, "DEF_CAL_" + type);
80978
80979             _calendars[type][defCalendar.id] = defCalendar;
80980             calsStorage[defCalendar.id] = new CalendarStorage(defCalendar);
80981         } else {
80982             for (id in calsStorage) {
80983                 for (i in calsStorage[id].items) {
80984                     item = calsStorage[id].items[i];
80985                 }
80986                 _calendars[type][id] = new Calendar(type, calsStorage[id].name, calsStorage[id].items, id);
80987             }
80988         }
80989     }
80990
80991     // public
80992     function getCalendars(type, successCallback, errorCallback) {
80993         if (!_security.getCalendars) {
80994             throw new WebAPIException(errorcode.SECURITY_ERR);
80995         }
80996
80997         function _getCalendars() {
80998             var i, result = [];
80999
81000             if (!isValidType(type))
81001                 throw new WebAPIException(errorcode.TYPE_MISMATCH_ERR);
81002
81003             if (tizen1_utils.isEmptyObject(_calendars[type])) {
81004                 loadCalendars(type);
81005             }
81006
81007             if (_calendars.length !== 0) {
81008                 for (i in _calendars[type]) {
81009                     result.push(_calendars[type][i]);
81010                 }
81011                 window.setTimeout(function () {
81012                     successCallback(result);
81013                 }, 1);
81014             } else if (errorCallback) {
81015                 window.setTimeout(function () {
81016                     errorCallback(new WebAPIError(errorcode.UNKNOWN_ERR));
81017                 }, 1);
81018             }
81019         }
81020
81021         return tizen1_utils.validateTypeMismatch(successCallback, errorCallback, "calendar:getCalendars", _getCalendars);
81022     }
81023
81024     function getDefaultCalendar(type) {
81025         var id, calendar;
81026
81027         if (!_security.getDefaultCalendar) {
81028             throw new WebAPIException(errorcode.SECURITY_ERR);
81029         }
81030         if (!isValidType(type))
81031             throw new WebAPIException(errorcode.TYPE_MISMATCH_ERR);
81032
81033         if (tizen1_utils.isEmptyObject(_calendars[type])) {
81034             loadCalendars(type);
81035         }
81036
81037         for (id in _calendars[type]) {
81038             calendar = _calendars[type][id];
81039             break;
81040         }
81041
81042         if (calendar === undefined)
81043             throw new WebAPIException(errorcode.NOT_FOUND_ERR);
81044
81045         return calendar;
81046     }
81047
81048     function getCalendar(type, id) {
81049         var calendar;
81050
81051         if (!_security.getCalendar) {
81052             throw new WebAPIException(errorcode.SECURITY_ERR);
81053         }
81054         if (!isValidType(type) || !_isValidId(id))
81055             throw new WebAPIException(errorcode.TYPE_MISMATCH_ERR);
81056
81057         if (tizen1_utils.isEmptyObject(_calendars[type])) {
81058             loadCalendars(type);
81059         }
81060
81061         calendar = _calendars[type][id];
81062         if (calendar === undefined)
81063             throw new WebAPIException(errorcode.NOT_FOUND_ERR);
81064
81065         return calendar;
81066     }
81067
81068     function handleSubFeatures(subFeatures) {
81069         var i, subFeature;
81070
81071         for (subFeature in subFeatures) {
81072             for (i in _security[subFeature]) {
81073                 _security[_security[subFeature][i]] = true;
81074             }
81075         }
81076     }
81077
81078     calendarManager = {
81079         getCalendars:       getCalendars,
81080         getDefaultCalendar: getDefaultCalendar,
81081         getCalendar:        getCalendar,
81082         handleSubFeatures:  handleSubFeatures
81083     };
81084
81085     return calendarManager;
81086 };
81087
81088 Calendar = function (type, name, storageItems, id) {
81089     var privateItems = {},
81090         defaultWatchId = 0;
81091     id = id || Math.uuid(null, 16);
81092
81093     // private
81094     function createCalendarItem() {
81095         var calendarItem = null;
81096
81097         switch (type) {
81098         case "EVENT":
81099             calendarItem = new CalendarEvent();
81100             break;
81101
81102         case "TASK":
81103             calendarItem = new CalendarTask();
81104             break;
81105
81106         default:
81107             break;
81108         }
81109
81110         return calendarItem;
81111     }
81112
81113     function isValidCalendarItemId(itemId) {
81114         var i;
81115
81116         if (!_isValidId(itemId))
81117             return false;
81118
81119         for (i in privateItems) {
81120             if (i === itemId)
81121                 return true;
81122         }
81123
81124         return false;
81125     }
81126
81127     function loadCalendarItemInit(calendarItem, storageItem) {
81128         calendarItem.description    = utils.copy(storageItem.description);
81129         calendarItem.summary        = utils.copy(storageItem.summary);
81130         calendarItem.isAllDay       = utils.copy(storageItem.isAllDay);
81131         calendarItem.startDate      = new TZDate(new Date(storageItem.startDate));
81132         calendarItem.duration       = utils.copy(storageItem.duration);
81133         calendarItem.location       = utils.copy(storageItem.location);
81134         calendarItem.geolocation    = utils.copy(storageItem.geolocation);
81135         calendarItem.organizer      = utils.copy(storageItem.organizer);
81136         calendarItem.visibility     = utils.copy(storageItem.visibility);
81137         calendarItem.status         = utils.copy(storageItem.status);
81138         calendarItem.priority       = utils.copy(storageItem.priority);
81139         calendarItem.alarms         = utils.copy(storageItem.alarms);
81140         calendarItem.categories     = utils.copy(storageItem.categories);
81141         calendarItem.attendees      = utils.copy(storageItem.attendees);
81142     }
81143
81144     function loadCalendarEventInit(calendarItem, storageItem) {
81145         loadCalendarItemInit(calendarItem, storageItem);
81146
81147         calendarItem.endDate = new TZDate(new Date(storageItem.endDate));
81148         calendarItem.availability = utils.copy(storageItem.availability);
81149         calendarItem.recurrenceRule = utils.copy(storageItem.recurrenceRule);
81150         calendarItem.expandRecurrence = function (startDate, endDate, successCallback, errorCallback) {
81151             if (!_security.expandRecurrence) {
81152                 throw new WebAPIException(errorcode.SECURITY_ERR);
81153             }
81154
81155             calendarItem.startDate = startDate;
81156             calendarItem.endDate   = endDate;
81157
81158             if (errorCallback) {
81159                 window.setTimeout(function () {
81160                     errorCallback(new WebAPIError(errorcode.NOT_SUPPORTED_ERR));
81161                 }, 1);
81162             }
81163         };
81164         calendarItem.frequency       = utils.copy(storageItem.frequency);
81165         calendarItem.interval        = utils.copy(storageItem.interval);
81166         calendarItem.untilDate       = storageItem.untilDate ? new TZDate(new Date(storageItem.untilDate)):storageItem.untilDate;
81167         calendarItem.occurrenceCount = utils.copy(storageItem.occurrenceCount);
81168         calendarItem.daysOfTheWeek   = utils.copy(storageItem.daysOfTheWeek);
81169         calendarItem.setPositions    = utils.copy(storageItem.setPositions);
81170         calendarItem.exceptions      = utils.copy(storageItem.exceptions);
81171     }
81172
81173     function loadCalendarTaskInit(calendarItem, storageItem) {
81174         loadCalendarItemInit(calendarItem, storageItem);
81175
81176         calendarItem.dueDate       = new TZDate(new Date(storageItem.dueDate));
81177         calendarItem.completedDate = storageItem.completedDate ? new TZDate(new Date(storageItem.completedDate)):storageItem.completedDate;
81178         calendarItem.progress      = utils.copy(storageItem.progress);
81179     }
81180
81181     function loadCalendarItems() {
81182         var i, calendarItem;
81183
81184         if (storageItems === undefined)
81185             return;
81186
81187         for (i in storageItems) {
81188             calendarItem = new CalendarItem(type, i, new TZDate(new Date(storageItems[i].lastModificationDate)), _security);
81189
81190             if (type === "EVENT") {
81191                 loadCalendarEventInit(calendarItem, storageItems[i]);
81192             } else {
81193                 loadCalendarTaskInit(calendarItem, storageItems[i]);
81194             }
81195
81196             privateItems[i] = calendarItem;
81197         }
81198     }
81199
81200     function saveCalendarItems() {
81201         _calendarsStorage[type][id] ||  (_calendarsStorage[type][id] = {});
81202         _calendarsStorage[type][id].items = new CalendarItemsStorage(privateItems);
81203         saveCalendars();
81204     }
81205
81206     // public
81207     function get(id) {
81208         var uid;
81209
81210         if (!_security.get) {
81211             throw new WebAPIException(errorcode.SECURITY_ERR);
81212         }
81213         uid = (type === "EVENT") ? id.uid : id;
81214         if (!isValidCalendarItemId(uid))
81215             throw new WebAPIException(errorcode.NOT_FOUND_ERR);
81216
81217
81218         return privateItems[uid];
81219     }
81220
81221     function add(item) {
81222         var uid;
81223
81224         if (!_security.add) {
81225             throw new WebAPIException(errorcode.SECURITY_ERR);
81226         }
81227         // set the calendarId of the item
81228         item.__defineGetter__("calendarId", function () {
81229             return id;
81230         });
81231
81232         // typecoerce
81233         uid = (type === "EVENT") ? item.id.uid : item.id;
81234         privateItems[uid] = utils.copy(item);
81235
81236         saveCalendarItems();
81237
81238         window.setTimeout(function () {
81239             for (var i in _watchers) {
81240                 _watchers[i].onitemsadded([utils.copy(item)]);
81241             }
81242         }, 1);
81243     }
81244
81245     function addBatch(items, successCallback, errorCallback) {
81246         if (!_security.addBatch) {
81247             throw new WebAPIException(errorcode.SECURITY_ERR);
81248         }
81249         tizen1_utils.validateCallbackType(successCallback, errorCallback);
81250
81251         // typecoerce items
81252
81253         window.setTimeout(function () {
81254             var i, uid;
81255
81256             for (i in items) {
81257                 uid = (type === "EVENT") ? items[i].id.uid : items[i].id;
81258                 privateItems[uid] = utils.copy(items[i]);
81259             }
81260
81261             saveCalendarItems();
81262
81263             if (successCallback) {
81264                 successCallback(utils.copy(items));
81265             }
81266             for (i in _watchers) {
81267                 _watchers[i].onitemsadded(utils.copy(items));
81268             }
81269         }, 1);
81270     }
81271
81272     function update(item, updateAllInstances) {
81273         var calendarItem, attr, uid;
81274
81275         if (!_security.update) {
81276             throw new WebAPIException(errorcode.SECURITY_ERR);
81277         }
81278         // typecoerce item, updateAllInstances
81279
81280         uid = (type === "EVENT") ? item.id.uid : item.id;
81281         if (!isValidCalendarItemId(uid))
81282             throw new WebAPIException(errorcode.NOT_FOUND_ERR);
81283
81284         if (updateAllInstances === undefined || updateAllInstances === null) {
81285             updateAllInstances = true;
81286         }
81287
81288         if ((type === "EVENT") && !updateAllInstances) {
81289             calendarItem = createCalendarItem();
81290
81291             for (attr in privateItems[uid]) {
81292                 if (attr !== "id" && attr !== "lastModificationDate") {
81293                     if (item[attr] !== undefined)
81294                         calendarItem[attr] = utils.copy(item[attr]);
81295                     else
81296                         calendarItem[attr] = utils.copy(privateItems[uid][attr]);
81297                 }
81298             }
81299
81300             add(calendarItem);
81301         } else {
81302             for (attr in privateItems[uid]) {
81303                 if ((attr !== "id") && (attr !== "lastModificationDate") && (item[attr] !== undefined))
81304                     privateItems[uid][attr] = utils.copy(item[attr]);
81305             }
81306             window.setTimeout(function () {
81307                 var i;
81308
81309                 for (i in _watchers) {
81310                     _watchers[i].onitemsupdated([utils.copy(privateItems[uid])]);
81311                 }
81312             }, 1);
81313         }
81314         saveCalendarItems();
81315     }
81316
81317     function updateBatch(items, successCallback, errorCallback, updateAllInstances) {
81318         if (!_security.updateBatch) {
81319             throw new WebAPIException(errorcode.SECURITY_ERR);
81320         }
81321         tizen1_utils.validateCallbackType(successCallback, errorCallback);
81322
81323         // typecoerce items updateAllInstances
81324         if (!tizen1_utils.isValidArray(items) ||
81325             (items.length === 0)) {
81326             throw new WebAPIException(errorcode.TYPE_MISMATCH_ERR);
81327         }
81328
81329         window.setTimeout(function () {
81330             var i, j, attr, calendarItem, updatedItems = [], uid;
81331
81332             for (i in items) {
81333                 uid = (type === "EVENT") ? items[i].id.uid : items[i].id;
81334                 if (!uid || !privateItems[uid]) {
81335                     if (errorCallback) {
81336                         errorCallback(new WebAPIError(errorcode.NOT_FOUND_ERR));
81337                     }
81338                     return;
81339                 }
81340             }
81341
81342             if (updateAllInstances) {
81343                 for (i in privateItems) {
81344                     for (j in items) {
81345                         uid = (type === "EVENT") ? items[j].id.uid : items[j].id;
81346                         if (i === uid) {
81347                             for (attr in privateItems[i]) {
81348                                 if (attr !== "id" && attr !== "lastModificationDate" && items[j][attr] !== undefined)
81349                                     privateItems[i][attr] = utils.copy(items[j][attr]);
81350                             }
81351                             saveCalendarItems();
81352                             updatedItems.push(utils.copy(privateItems[i]));
81353                         }
81354                     }
81355                 }
81356             } else {
81357                 for (i in items) {
81358                     calendarItem = createCalendarItem();
81359
81360                     uid = (type === "EVENT") ? items[i].id.uid : items[i].id;
81361                     for (attr in privateItems[uid]) {
81362                         if (attr !== "id" && attr !== "lastModificationDate") {
81363                             if (items[i][attr] !== undefined)
81364                                 calendarItem[attr] = utils.copy(items[i][attr]);
81365                             else
81366                                 calendarItem[attr] = utils.copy(privateItems[uid][attr]);
81367                         }
81368                     }
81369
81370                     add(calendarItem);
81371                     updatedItems.push(utils.copy(calendarItem));
81372                 }
81373             }
81374
81375             saveCalendarItems();
81376             if (successCallback) {
81377                 successCallback();
81378             }
81379             for (i in _watchers) {
81380                 _watchers[i].onitemsupdated(utils.copy(updatedItems));
81381             }
81382         }, 1);
81383     }
81384
81385     function remove(id) {
81386         var isFound = false, i, uid;
81387
81388         if (!_security.remove) {
81389             throw new WebAPIException(errorcode.SECURITY_ERR);
81390         }
81391
81392         uid = (type === "EVENT") ? id.uid : id;
81393         for (i in privateItems) {
81394             if (i === uid) {
81395                 delete privateItems[i];
81396                 isFound = true;
81397                 break;
81398             }
81399         }
81400
81401         if (!isFound)
81402             throw new WebAPIException(errorcode.NOT_FOUND_ERR);
81403
81404         saveCalendarItems();
81405
81406         window.setTimeout(function () {
81407             var i;
81408
81409             for (i in _watchers) {
81410                 _watchers[i].onitemsremoved([id]);
81411             }
81412         }, 1);
81413     }
81414
81415     function removeBatch(ids, successCallback, errorCallback) {
81416         if (!_security.removeBatch) {
81417             throw new WebAPIException(errorcode.SECURITY_ERR);
81418         }
81419         tizen1_utils.validateCallbackType(successCallback, errorCallback);
81420
81421         if (!tizen1_utils.isValidArray(ids) || (ids.length === 0)) {
81422             throw new WebAPIException(errorcode.TYPE_MISMATCH_ERR);
81423         }
81424
81425         window.setTimeout(function () {
81426             var i, uid;
81427
81428             for (i in ids) {
81429                 uid = (type === "EVENT") ? ids[i].uid : ids[i];
81430
81431                 if (!privateItems[uid]) {
81432                     if (errorCallback) {
81433                         errorCallback(new WebAPIError(errorcode.NOT_FOUND_ERR));
81434                     }
81435                     return;
81436                 }
81437             }
81438
81439             for (i in ids) {
81440                 uid = (type === "EVENT") ? ids[i].uid : ids[i];
81441                 delete privateItems[uid];
81442             }
81443             saveCalendarItems();
81444             if (successCallback) {
81445                 successCallback();
81446             }
81447
81448             for (i in _watchers) {
81449                 _watchers[i].onitemsremoved(utils.copy(ids));
81450             }
81451         }, 1);
81452     }
81453
81454     function find(successCallback, errorCallback, filter, sortMode) {
81455         if (!_security.find) {
81456             throw new WebAPIException(errorcode.SECURITY_ERR);
81457         }
81458
81459         function _find() {
81460             var i, calendarItems = [], result = [];
81461
81462             for (i in privateItems) {
81463                 calendarItems.push(privateItems[i]);
81464             }
81465             if (calendarItems.length > 0) {
81466                 result = tizen1_utils.query(calendarItems, filter, sortMode);
81467             }
81468             window.setTimeout(function () {
81469                 successCallback(result);
81470             }, 1);
81471         }
81472
81473         tizen1_utils.validateTypeMismatch(successCallback, errorCallback, "calendar:find", _find);
81474     }
81475
81476     function addChangeListener(successCallback) {
81477         var watchId;
81478
81479         if (!_security.addChangeListener) {
81480             throw new WebAPIException(errorcode.SECURITY_ERR);
81481         }
81482         if ((typeof successCallback !== "object") ||
81483             (typeof successCallback.onitemsadded   !== "function") ||
81484             (typeof successCallback.onitemsupdated !== "function") ||
81485             (typeof successCallback.onitemsremoved !== "function"))
81486             throw new WebAPIException(errorcode.TYPE_MISMATCH_ERR);
81487
81488         watchId = ++defaultWatchId;
81489         _watchers[watchId] = successCallback;
81490
81491         return watchId;
81492     }
81493
81494     function removeChangeListener(watchId) {
81495         if (!_security.removeChangeListener) {
81496             throw new WebAPIException(errorcode.SECURITY_ERR);
81497         }
81498         if (!_isValidId(watchId))
81499             throw new WebAPIException(errorcode.TYPE_MISMATCH_ERR);
81500
81501         if (!_watchers[watchId])
81502             throw new WebAPIException(errorcode.NOT_FOUND_ERR);
81503
81504         delete _watchers[watchId];
81505     }
81506
81507     loadCalendarItems(type, privateItems, storageItems);
81508
81509     this.__defineGetter__("id", function () {
81510         return id;
81511     });
81512     this.__defineGetter__("name", function () {
81513         return name;
81514     });
81515
81516     this.get                  = get;
81517     this.add                  = add;
81518     this.addBatch             = addBatch;
81519     this.update               = update;
81520     this.updateBatch          = updateBatch;
81521     this.remove               = remove;
81522     this.removeBatch          = removeBatch;
81523     this.find                 = find;
81524     this.addChangeListener    = addChangeListener;
81525     this.removeChangeListener = removeChangeListener;
81526 };
81527
81528 CalendarStorage = function (calendar) {
81529     this.id   = calendar.id;
81530     this.name = calendar.name;
81531 };
81532
81533 CalendarItemsStorage = function (privateItems) {
81534     var itemsStorage = {}, i, attr;
81535
81536     for (i in privateItems) {
81537         itemsStorage[i] = {};
81538         for (attr in privateItems[i]) {
81539             //TODO: should be
81540             //      if (privateItems[i][attr] instanceof TZDate) {
81541             //But, we used "utils.copy" before store the item to privateItems list.
81542             //So the constructor information all lost
81543             if ((attr === "startDate" || attr === "endDate" || attr === "dueDate" || attr === "completedDate" || attr === "lastModificationDate") &&
81544                 (privateItems[i][attr])) {
81545
81546                 itemsStorage[i][attr] = privateItems[i][attr].toString();
81547             } else if (typeof privateItems[i] !== "function") {
81548                 itemsStorage[i][attr] = privateItems[i][attr];
81549             }
81550         }
81551     }
81552
81553     return itemsStorage;
81554 };
81555
81556 module.exports = _self;
81557
81558 });
81559 define('ripple/platform/tizen/2.0/callHistory', function (require, exports, module) {
81560 /*
81561  *  Copyright 2012 Intel Corporation.
81562  *
81563  * Licensed under the Apache License, Version 2.0 (the "License");
81564  * you may not use this file except in compliance with the License.
81565  * You may obtain a copy of the License at
81566  *
81567  * http://www.apache.org/licenses/LICENSE-2.0
81568  *
81569  * Unless required by applicable law or agreed to in writing, software
81570  * distributed under the License is distributed on an "AS IS" BASIS,
81571  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
81572  * See the License for the specific language governing permissions and
81573  * limitations under the License.
81574  */
81575
81576 var utils = require('ripple/utils'),
81577     db = require('ripple/db'),
81578     event = require('ripple/event'),
81579     errorcode = require('ripple/platform/tizen/2.0/errorcode'),
81580     WebAPIError = require('ripple/platform/tizen/2.0/WebAPIError'),
81581     WebAPIException = require('ripple/platform/tizen/2.0/WebAPIException'),
81582     t = require('ripple/platform/tizen/2.0/typedef'),
81583     TypeCoerce = require('ripple/platform/tizen/2.0/typecoerce'),
81584     tizen1_utils = require('ripple/platform/tizen/2.0/tizen1_utils'),
81585     _DB_CALL_KEY = "tizen1-db-callhistory",
81586     _data = {
81587         observers: {},
81588         callHistory: []
81589     },
81590     _security = {
81591         "http://tizen.org/privilege/callhistory.read": ["find", "addChangeListener", "removeChangeListener"],
81592         "http://tizen.org/privilege/callhistory.write": ["remove", "removeBatch", "removeAll"]
81593     },
81594     _self;
81595
81596 function _getValue(inputValue, key) {
81597     var keys = key.split("."),
81598         value = inputValue[keys[0]],
81599         index;
81600
81601     for (index = 1; index < keys.length; index++) {
81602         if (value[keys[index]]) {
81603             value = value[keys[index]];
81604         }
81605     }
81606
81607     return value;
81608 }
81609
81610 function _filter(inputArray, filter) {
81611     var index, filterResults = [], compositeResultArray;
81612
81613     if (filter === null || filter === undefined) {
81614         return inputArray;
81615     }
81616
81617     if (filter.type && filter.filters) {
81618         filterResults = _filter(inputArray, filter.filters[0]);
81619         for (index = 1; index < filter.filters.length; index++) {
81620             compositeResultArray = _filter(inputArray, filter.filters[index]);
81621
81622             filterResults = tizen1_utils.arrayComposite(filter.type, filterResults, compositeResultArray);
81623         }
81624         return filterResults;
81625     }
81626
81627     if (filter.attributeName === null || filter.attributeName === undefined) {
81628         throw new WebAPIException(errorcode.TYPE_MISMATCH_ERR);
81629     }
81630
81631     if (filter.matchFlag) {
81632         if (filter.attributeName === 'features') {
81633             filterResults = tizen1_utils.matchAttributeArrayFilter(inputArray, filter.attributeName, filter.matchFlag, filter.matchValue);
81634         } else {
81635             filterResults = tizen1_utils.matchAttributeFilter(inputArray, filter.attributeName, filter.matchFlag, filter.matchValue);
81636         }
81637     }
81638     else if (filter.initialValue || filter.endValue) {
81639         filterResults = tizen1_utils.matchAttributeRangeFilter(inputArray, filter.attributeName, filter.initialValue, filter.endValue);
81640     }
81641
81642     return filterResults;
81643 }
81644
81645 function _sort(inputArray, sortMode) {
81646     if (sortMode.attributeName === null || sortMode.attributeName === undefined) {
81647         throw new WebAPIException(errorcode.TYPE_MISMATCH_ERR);
81648     }
81649
81650     inputArray.sort(function (a, b) {
81651         return sortMode.order === "ASC" ? _getValue(a, sortMode.attributeName) - _getValue(b, sortMode.attributeName) :
81652                _getValue(b, sortMode.attributeName) - _getValue(a, sortMode.attributeName);
81653     });
81654
81655     return inputArray;
81656 }
81657
81658 function _save() {
81659     db.saveObject(_DB_CALL_KEY, _data.callHistory);
81660 }
81661
81662 function _retrieve() {
81663     var index;
81664
81665     _data.callHistory = db.retrieveObject(_DB_CALL_KEY) || [];
81666
81667     for (index = 0; index < _data.callHistory.length; index++) {
81668         _data.callHistory[index].startTime = new Date(_data.callHistory[index].startTime);
81669     }
81670 }
81671
81672 function _isValidCallHistoryEntry(arg) {
81673     return arg && arg.hasOwnProperty("uid") && arg.hasOwnProperty("type") &&
81674            arg.hasOwnProperty("features") && arg.hasOwnProperty("remoteParties") &&
81675            arg.hasOwnProperty("startTime") && arg.hasOwnProperty("duration") &&
81676            arg.hasOwnProperty("direction");
81677 }
81678
81679 function _rtnRmtPty(pty) {
81680     var _remoteParty = pty.remoteParty,
81681         _personId = pty.personId,
81682         _self = {};
81683     _self.__defineGetter__("remoteParty", function () {
81684         return _remoteParty;
81685     });
81686     _self.__defineGetter__("personId", function () {
81687         return _personId;
81688     });
81689     return _self;
81690 }
81691
81692 function _rtnEntry(entry) {
81693     var _uid = entry.uid,
81694         _type = entry.type,
81695         _features = tizen1_utils.copy(entry.features),
81696         _remoteParties = [],
81697         _startTime = new Date(entry.startTime),
81698         _duration = entry.duration,
81699         _direction = entry.direction,
81700         _self = {}, i;
81701
81702     for (i = 0; i < entry.remoteParties.length; i++) {
81703         _remoteParties.push(_rtnRmtPty(entry.remoteParties[i]));
81704     }
81705     _self.__defineGetter__("uid", function () {
81706         return _uid;
81707     });
81708     _self.__defineGetter__("type", function () {
81709         return _type;
81710     });
81711     _self.__defineGetter__("features", function () {
81712         return _features;
81713     });
81714     _self.__defineGetter__("remoteParties", function () {
81715         return _remoteParties;
81716     });
81717     _self.__defineGetter__("startTime", function () {
81718         return _startTime;
81719     });
81720     _self.__defineGetter__("duration", function () {
81721         return _duration;
81722     });
81723     _self.direction = _direction;
81724
81725     return _self;
81726 }
81727
81728 function _initialize() {
81729     _retrieve();
81730
81731     event.on("CallInProgress", function () {
81732     });
81733
81734     event.on("CallRecorded", function (record) {
81735         var historyEntry = tizen1_utils.copy(record);
81736         historyEntry.uid = Math.uuid(8, 16);
81737
81738         _data.callHistory.push(historyEntry);
81739         _save();
81740
81741         utils.forEach(_data.observers, function (observer) {
81742             observer.onadded([historyEntry]);
81743         });
81744     });
81745 }
81746
81747 _self = function () {
81748     this.find = function (successCallback, errorCallback, filter, sortMode, limit, offset) {
81749         var i, rtn = [],
81750             filterResults,
81751             limitValue = limit | 0,
81752             offsetValue = offset | 0;
81753
81754         if (!_security.find) {
81755             throw new WebAPIException(errorcode.SECURITY_ERR);
81756         }
81757
81758         if (!(new TypeCoerce(t.SuccessCallback)).match(successCallback)) {
81759             throw new WebAPIException(errorcode.TYPE_MISMATCH_ERR);
81760         }
81761         if ((arguments.length > 1) && errorCallback !== null && !(new TypeCoerce(t.ErrorCallback)).match(errorCallback)) {
81762             throw new WebAPIException(errorcode.TYPE_MISMATCH_ERR);
81763         }
81764         if ((arguments.length > 2) && filter !== null && !(new TypeCoerce(t.AbstractFilter)).match(filter)) {
81765             throw new WebAPIException(errorcode.TYPE_MISMATCH_ERR);
81766         }
81767         if ((arguments.length > 3) && sortMode !== null && !(new TypeCoerce(t.SortMode)).match(sortMode)) {
81768             throw new WebAPIException(errorcode.TYPE_MISMATCH_ERR);
81769         }
81770
81771         if ((arguments.length > 4) && limit !== null && !(new TypeCoerce(t['unsigned long'])).match(limit)) {
81772             throw new WebAPIException(errorcode.TYPE_MISMATCH_ERR);
81773         }
81774         if ((arguments.length > 5) && offset !== null && !(new TypeCoerce(t['unsigned long'])).match(offset)) {
81775             throw new WebAPIException(errorcode.TYPE_MISMATCH_ERR);
81776         }
81777
81778         filterResults = tizen1_utils.copy(_data.callHistory);
81779         if (filter !== null && filter !== undefined) {
81780             filterResults = _filter(filterResults, filter);
81781         }
81782
81783         if (sortMode !== null && sortMode !== undefined) {
81784             _sort(filterResults, sortMode);
81785         }
81786
81787         setTimeout(function () {
81788             if (limitValue > 0) {
81789                 offsetValue = offsetValue > 0 ? offsetValue : 0;
81790                 filterResults = filterResults.slice(offsetValue, limitValue);
81791             }
81792
81793             for (i = 0; i < filterResults.length; i++) {
81794                 rtn.push(_rtnEntry(filterResults[i]));
81795             }
81796             successCallback(rtn);
81797         }, 1);
81798     };
81799     this.remove = function (entry) {
81800         var isFound = false, rtn = [];
81801
81802         if (!_security.remove) {
81803             throw new WebAPIException(errorcode.SECURITY_ERR);
81804         }
81805
81806         if (!_isValidCallHistoryEntry(entry)) {
81807             throw new WebAPIException(errorcode.TYPE_MISMATCH_ERR);
81808         }
81809
81810         _data.callHistory = _data.callHistory.filter(function (element) {
81811             return utils.some(element, function (value, key) {
81812                 if (tizen1_utils.isEqual(entry[key], value)) {
81813                     isFound = true;
81814                     return false;
81815                 }
81816                 return true;
81817             });
81818         });
81819
81820         if (!isFound) {
81821             throw new WebAPIException(errorcode.NOT_FOUND_ERR);
81822         }
81823
81824         _save();
81825         rtn.push(_rtnEntry(entry));
81826         utils.forEach(_data.observers, function (observer) {
81827             observer.onchanged(rtn);
81828         });
81829
81830     };
81831     this.removeBatch = function (entries, successCallback, errorCallback) {
81832         var isFound = false, i, rtn = [];
81833
81834         if (!_security.removeBatch) {
81835             throw new WebAPIException(errorcode.SECURITY_ERR);
81836         }
81837
81838         if (tizen1_utils.isValidArray(entries) === false) {
81839             throw new WebAPIException(errorcode.TYPE_MISMATCH_ERR);
81840         }
81841         if ((arguments.length > 1) && successCallback !== null && !(new TypeCoerce(t.SuccessCallback)).match(successCallback)) {
81842             throw new WebAPIException(errorcode.TYPE_MISMATCH_ERR);
81843         }
81844         if ((arguments.length > 2) && errorCallback !== null && !(new TypeCoerce(t.ErrorCallback)).match(errorCallback)) {
81845             throw new WebAPIException(errorcode.TYPE_MISMATCH_ERR);
81846         }
81847         for (i = 0; i < entries.length; i++) {
81848             if (!_isValidCallHistoryEntry(entries[i])) {
81849                 throw new WebAPIException(errorcode.TYPE_MISMATCH_ERR);
81850             }
81851         }
81852
81853         setTimeout(function () {
81854             isFound = entries.every(function (element) {
81855                 return _data.callHistory.some(function (callHistory) {
81856                     return element.uid === callHistory.uid;
81857                 });
81858             });
81859
81860             if (!isFound) {
81861                 if (errorCallback) {
81862                     errorCallback(new WebAPIError(errorcode.NOT_FOUND_ERR));
81863                 }
81864                 return;
81865             }
81866
81867             _data.callHistory = _data.callHistory.filter(function (element) {
81868                 return !entries.some(function (entryValue, entryIndex) {
81869                     return tizen1_utils.isEqual(element, entryValue);
81870                 });
81871             });
81872
81873             _save();
81874
81875             if (successCallback) {
81876                 successCallback();
81877             }
81878             for (i = 0; i < entries.length; i++) {
81879                 rtn.push(_rtnEntry(entries[i]));
81880             }
81881             utils.forEach(_data.observers, function (observer) {
81882                 observer.onchanged(rtn);
81883             });
81884         }, 1);
81885     };
81886     this.removeAll = function (successCallback, errorCallback) {
81887         var i, rtn = [];
81888
81889         if (!_security.removeAll) {
81890             throw new WebAPIException(errorcode.SECURITY_ERR);
81891         }
81892
81893         if ((arguments.length > 0) && successCallback !== null && !(new TypeCoerce(t.SuccessCallback)).match(successCallback)) {
81894             throw new WebAPIException(errorcode.TYPE_MISMATCH_ERR);
81895         }
81896         if ((arguments.length > 1) && errorCallback !== null && !(new TypeCoerce(t.ErrorCallback)).match(errorCallback)) {
81897             throw new WebAPIException(errorcode.TYPE_MISMATCH_ERR);
81898         }
81899
81900         for (i = 0; i < _data.callHistory.length; i++) {
81901             rtn.push(_rtnEntry(_data.callHistory[i]));
81902         }
81903
81904         _data.callHistory = [];
81905         _save();
81906
81907         if (successCallback) {
81908             successCallback();
81909         }
81910         utils.forEach(_data.observers, function (observer) {
81911             observer.onchanged(rtn);
81912         });
81913
81914     };
81915     this.addChangeListener = function (observerObj) {
81916         var handle = Number(Math.uuid(8, 10));
81917
81918         if (!_security.addChangeListener) {
81919             throw new WebAPIException(errorcode.SECURITY_ERR);
81920         }
81921
81922         if (observerObj === null || typeof observerObj !== 'object' ||
81923             (observerObj.hasOwnProperty("onadded") && typeof observerObj.onadded !== 'function') ||
81924             (observerObj.hasOwnProperty("onremoved") && typeof observerObj.onremoved !== 'function') ||
81925             (observerObj.hasOwnProperty("onchanged") && typeof observerObj.onchanged !== 'function')) {
81926             throw new WebAPIException(errorcode.TYPE_MISMATCH_ERR);
81927         }
81928
81929         _data.observers[handle] = observerObj;
81930
81931         return handle;
81932     };
81933     this.removeChangeListener = function (handle) {
81934         if (!_security.removeChangeListener) {
81935             throw new WebAPIException(errorcode.SECURITY_ERR);
81936         }
81937         if (typeof handle !== 'number') {
81938             throw new WebAPIException(errorcode.TYPE_MISMATCH_ERR);
81939         }
81940
81941         if (_data.observers[handle]) {
81942             delete _data.observers[handle];
81943         }
81944         else {
81945             throw new WebAPIException(errorcode.INVALID_VALUES_ERR);
81946         }
81947     };
81948     this.handleSubFeatures = function (subFeatures) {
81949         function setSecurity(method) {
81950             _security[method] = true;
81951         }
81952
81953         for (var subFeature in subFeatures) {
81954             utils.forEach(_security[subFeature], setSecurity);
81955         }
81956     };
81957 };
81958
81959 _initialize();
81960
81961 module.exports = _self;
81962
81963 });
81964 define('ripple/platform/tizen/2.0/contact', function (require, exports, module) {
81965 /*
81966  *  Copyright 2012 Intel Corporation.
81967  *
81968  * Licensed under the Apache License, Version 2.0 (the "License");
81969  * you may not use this file except in compliance with the License.
81970  * You may obtain a copy of the License at
81971  *
81972  * http://www.apache.org/licenses/LICENSE-2.0
81973  *
81974  * Unless required by applicable law or agreed to in writing, software
81975  * distributed under the License is distributed on an "AS IS" BASIS,
81976  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
81977  * See the License for the specific language governing permissions and
81978  * limitations under the License.
81979  */
81980
81981 var db = require('ripple/db'),
81982     utils = require('ripple/utils'),
81983     tizen1_utils = require('ripple/platform/tizen/2.0/tizen1_utils'),
81984     t = require('ripple/platform/tizen/2.0/typecast'),
81985     errorcode = require('ripple/platform/tizen/2.0/errorcode'),
81986     WebAPIError = require('ripple/platform/tizen/2.0/WebAPIError'),
81987     WebAPIException = require('ripple/platform/tizen/2.0/WebAPIException'),
81988     Contact = require('ripple/platform/tizen/2.0/ContactBase'),
81989     AddressBook,
81990     AddressBookData,
81991     AddressBookStorage,
81992     ContactPublic,
81993     ContactData,
81994     ContactPrivate,
81995     ContactGroup,
81996     Person,
81997     PersonBuilder,
81998     _data = {
81999         DB_CONTACT_KEY: "tizen1-contact",
82000         addressBooks:   [],
82001         contacts:       {},
82002         persons:        {},
82003         contactData:    {},
82004         dbStorage:      {}
82005     },
82006     _security = {
82007         "http://tizen.org/privilege/contact.read": ["getAddressBooks", "getDefaultAddressBook",
82008                 "getAddressBook", "get", "find", "addChangeListener", "removeChangeListener",
82009                 "getGroup", "getGroups", "clone"],
82010         "http://tizen.org/privilege/contact.write": ["add", "addBatch",
82011                 "update", "updateBatch", "remove", "removeBatch", "addGroup",
82012                 "updateGroup", "removeGroup", "link", "unlink"]
82013     },
82014     _self;
82015
82016 function _get() {
82017     _data.dbStorage = db.retrieveObject(_data.DB_CONTACT_KEY) || {addressBooks: [], persons: {}};
82018 }
82019
82020 function _save() {
82021     db.saveObject(_data.DB_CONTACT_KEY, _data.dbStorage);
82022 }
82023
82024 function _serialize(obj) {
82025     var i, dbObj = {};
82026
82027     for (i in obj) {
82028         if (typeof obj[i] !== "function")
82029             dbObj[i] = utils.copy(obj[i]);
82030     }
82031
82032     return dbObj;
82033 }
82034
82035 /* check filter type (it's a recursive function)
82036    0: It is not a filter
82037    1: CompositeFilter
82038    2: AttributeFilter
82039    3: AttributeRangeFilter
82040  */
82041 function _filterType(filter) {
82042     var i = 0, ret;
82043
82044     if (Object.prototype.toString.call(filter) !== "[object Object]") {
82045         return 0; // 0: it is not a filter
82046     }
82047
82048     /* check if it is CompositFilter or not */
82049     if (filter.type !== null && filter.type !== undefined) {
82050         /* attribute 'type' of CompositeFilter must be "UNION" or "INTERSECTION" */
82051         if (filter.type === "UNION" || filter.type === "INTERSECTION") {
82052             /*attribute 'filters' of CompositeFilter must be AbstractFilter array */
82053             if (tizen1_utils.isValidArray(filter.filters)) {
82054                 for (i = 0; i < filter.filters.length; i++) {
82055                     /* recursive call */
82056                     if (_filterType(filter.filters[i]) === 0) {
82057                         return 0; // 0: it is not a filter
82058                     }
82059                 }
82060             } else {
82061                 return 0; // 0: it is not a filter
82062             }
82063         } else {
82064             return 0; // 0: it is not a filter
82065         }
82066         return 1; // CompositeFilter
82067     }
82068
82069     /* AttributeFilter or AttributeRangeFilter must have attributeName */
82070     if (filter.attributeName === null || filter.attributeName === undefined) {
82071         return 0; // 0: it is not a filter
82072     } else {
82073         ret = 2; // assume it is an AttributeFilter
82074         if ((filter.initialValue !== null && filter.initialValue !== undefined) ||
82075             (filter.endValue !== null && filter.endValue !== undefined)) {
82076             ret = 3; // AttributeRangeFilter
82077         }
82078         return ret;
82079     }
82080 }
82081
82082 function _sort(objects, sortMode) {
82083     function getValue(obj, key) {
82084         var keys = key.split("."),
82085             value = obj[keys[0]],
82086             i;
82087
82088         for (i = 1; i < keys.length; i++) {
82089             if (value[keys[i]]) {
82090                 value = value[keys[i]];
82091             }
82092         }
82093
82094         return value;
82095     }
82096
82097     objects.sort(function (a, b) {
82098         return (sortMode.order === "ASC") ?
82099             (getValue(a, sortMode.attributeName) < getValue(b, sortMode.attributeName) ? -1 : 1):
82100             (getValue(a, sortMode.attributeName) > getValue(b, sortMode.attributeName) ? -1 : 1);
82101     });
82102
82103     return objects;
82104 }
82105
82106 function _replacePerson(oldId, newId) {
82107     var contact, dbAddressBook, idab, idc, i;
82108
82109     for (idab in _data.contacts) {
82110         for (idc in _data.contacts[idab]) {
82111             contact = _data.contacts[idab][idc];
82112             if (contact.personId === oldId) {
82113                 if (newId === null) {
82114                     delete _data.contacts[idab][idc];
82115                 } else {
82116                     contact.personId = newId;
82117                 }
82118             }
82119         }
82120     }
82121
82122     if (_data.persons[oldId]) {
82123         delete _data.persons[oldId];
82124     }
82125
82126     for (i in _data.dbStorage.addressBooks) {
82127         dbAddressBook = _data.dbStorage.addressBooks[i];
82128         for (idc in dbAddressBook.contacts) {
82129             contact = dbAddressBook.contacts[idc];
82130             if (contact.personId === oldId) {
82131                 if (newId === null) {
82132                     delete dbAddressBook.contacts[idc];
82133                 } else {
82134                     contact.personId = newId;
82135                 }
82136             }
82137         }
82138     }
82139
82140     if (_data.dbStorage.persons[oldId]) {
82141         delete _data.dbStorage.persons[oldId];
82142     }
82143 }
82144
82145 _self = function () {
82146     var contact;
82147
82148     // private
82149     function loadAddressBooks() {
82150         var i;
82151
82152         _get();
82153
82154         if (_data.dbStorage.addressBooks.length === 0) {
82155             // Initialize default address books if database is empty
82156             _data.dbStorage.addressBooks = [
82157                 new AddressBookStorage(Math.uuid(null, 16), "Phone address book", false, {}, []),
82158                 new AddressBookStorage(Math.uuid(null, 16), "SIM address book", false, {}, [])
82159             ];
82160         }
82161
82162         utils.forEach(_data.dbStorage.addressBooks, function (addressBook) {
82163             _data.addressBooks.push(new AddressBook(addressBook.id, addressBook.name,
82164                 addressBook.readOnly, addressBook.contacts, addressBook.groups));
82165         });
82166
82167         for (i in _data.dbStorage.persons) {
82168             _data.persons[i] = new Person(_data.dbStorage.persons[i]);
82169         }
82170     }
82171
82172     // public
82173     // Address Book Methods
82174     function getAddressBooks(successCallback, errorCallback) {
82175         if (!_security.getAddressBooks) {
82176             throw new WebAPIException(errorcode.SECURITY_ERR);
82177         }
82178
82179         t.ContactManager("getAddressBooks", arguments);
82180
82181         if (_data.addressBooks.length === 0) {
82182             loadAddressBooks();
82183         }
82184         successCallback(_data.addressBooks);
82185     }
82186
82187     function getDefaultAddressBook() {
82188         if (!_security.getDefaultAddressBook) {
82189             throw new WebAPIException(errorcode.SECURITY_ERR);
82190         }
82191         if (_data.addressBooks.length === 0) {
82192             loadAddressBooks();
82193         }
82194         return _data.addressBooks[0];
82195     }
82196
82197     function getAddressBook(addressBookId) {
82198         var i;
82199
82200         if (!_security.getAddressBook) {
82201             throw new WebAPIException(errorcode.SECURITY_ERR);
82202         }
82203
82204         t.ContactManager("getAddressBook", arguments);
82205
82206         if (_data.addressBooks.length === 0) {
82207             loadAddressBooks();
82208         }
82209         for (i in _data.addressBooks) {
82210             if (_data.addressBooks[i].id === addressBookId) {
82211                 return _data.addressBooks[i];
82212             }
82213         }
82214
82215         /* Cannot found */
82216         throw new WebAPIException(errorcode.NOT_FOUND_ERR);
82217     }
82218
82219     // Person Methods
82220     function get(personId) {
82221         if (!_security.get) {
82222             throw new WebAPIException(errorcode.SECURITY_ERR);
82223         }
82224
82225         t.ContactManager("get", arguments);
82226
82227         if (_data.persons[personId] === undefined) {
82228             throw new WebAPIException(errorcode.NOT_FOUND_ERR);
82229         }
82230
82231         return new Person(_data.persons[personId]);
82232     }
82233
82234     function update(person) {
82235         var updated;
82236
82237         if (!_security.update) {
82238             throw new WebAPIException(errorcode.SECURITY_ERR);
82239         }
82240
82241         t.ContactManager("update", arguments);
82242
82243         if (!person.id) {
82244             throw new WebAPIException(errorcode.INVALID_VALUES_ERR);
82245         }
82246         if (_data.persons[person.id] === undefined) {
82247             throw new WebAPIException(errorcode.NOT_FOUND_ERR);
82248         }
82249
82250         updated = new Person(person);
82251
82252         _data.persons[updated.id] = updated;
82253         _data.dbStorage.persons[updated.id] = _serialize(updated);
82254         _save();
82255
82256         window.setTimeout(function () {
82257             utils.forEach(_data.contactData.listeners, function (listener) {
82258                 listener.onpersonsupdated([new Person(updated)]);
82259             });
82260         }, 1);
82261     }
82262
82263     function updateBatch(persons, successCallback, errorCallback) {
82264         if (!_security.updateBatch) {
82265             throw new WebAPIException(errorcode.SECURITY_ERR);
82266         }
82267
82268         t.ContactManager("updateBatch", arguments);
82269
82270         window.setTimeout(function () {
82271             var i, updated;
82272
82273             if (persons.length === 0) {
82274                 if (errorCallback) {
82275                     errorCallback(new WebAPIError(errorcode.INVALID_VALUES_ERR));
82276                 }
82277                 return;
82278             }
82279
82280             for (i in persons) {
82281                 if (!persons[i].id) {
82282                     if (errorCallback) {
82283                         errorCallback(new WebAPIError(errorcode.INVALID_VALUES_ERR));
82284                     }
82285                     return;
82286                 }
82287                 if (_data.persons[persons[i].id] === undefined) {
82288                     if (errorCallback) {
82289                         errorCallback(new WebAPIError(errorcode.NOT_FOUND_ERR));
82290                     }
82291                     return;
82292                 }
82293             }
82294             for (i in persons) {
82295                 updated = new Person(persons[i]);
82296
82297                 _data.persons[updated.id] = updated;
82298                 _data.dbStorage.persons[updated.id] = _serialize(updated);
82299             }
82300             _save();
82301             if (successCallback) {
82302                 successCallback();
82303             }
82304
82305             utils.forEach(_data.contactData.listeners, function (listener) {
82306                 var i, watched = [];
82307
82308                 for (i in persons) {
82309                     watched.push(new Person(_data.persons[persons[i].id]));
82310                 }
82311                 listener.onpersonsupdated(watched);
82312             });
82313         }, 1);
82314     }
82315
82316     function remove(personId) {
82317         if (!_security.remove) {
82318             throw new WebAPIException(errorcode.SECURITY_ERR);
82319         }
82320
82321         t.ContactManager("remove", arguments);
82322
82323         if (_data.persons[personId] === undefined) {
82324             throw new WebAPIException(errorcode.NOT_FOUND_ERR);
82325         }
82326         _replacePerson(personId, null);
82327         _save();
82328
82329         window.setTimeout(function () {
82330             utils.forEach(_data.contactData.listeners, function (listener) {
82331                 listener.onpersonsremoved([personId]);
82332             });
82333         }, 1);
82334     }
82335
82336     function removeBatch(personIds, successCallback, errorCallback) {
82337         if (!_security.removeBatch) {
82338             throw new WebAPIException(errorcode.SECURITY_ERR);
82339         }
82340
82341         t.ContactManager("removeBatch", arguments);
82342
82343         window.setTimeout(function () {
82344             var i;
82345
82346             if (personIds.length === 0) {
82347                 if (errorCallback) {
82348                     errorCallback(new WebAPIError(errorcode.INVALID_VALUES_ERR));
82349                 }
82350                 return;
82351             }
82352
82353             for (i in personIds) {
82354                 if (!personIds[i]) {
82355                     if (errorCallback) {
82356                         errorCallback(new WebAPIError(errorcode.INVALID_VALUES_ERR));
82357                     }
82358                     return;
82359                 }
82360                 if (_data.persons[personIds[i]] === undefined) {
82361                     if (errorCallback) {
82362                         errorCallback(new WebAPIError(errorcode.NOT_FOUND_ERR));
82363                     }
82364                     return;
82365                 }
82366             }
82367             for (i in personIds) {
82368                 _replacePerson(personIds[i], null);
82369             }
82370             _save();
82371             if (successCallback) {
82372                 successCallback();
82373             }
82374
82375             utils.forEach(_data.contactData.listeners, function (listener) {
82376                 listener.onpersonsremoved(utils.copy(personIds));
82377             });
82378         }, 1);
82379     }
82380
82381     function find(successCallback, errorCallback, filter, sortMode) {
82382         var i, matched = [], result = [];
82383
82384         if (!_security.find) {
82385             throw new WebAPIException(errorcode.SECURITY_ERR);
82386         }
82387
82388         t.ContactManager("find", arguments);
82389
82390         if (filter) {
82391             switch (_filterType(filter)) {
82392             case 0:
82393                 throw new WebAPIException(errorcode.TYPE_MISMATCH_ERR);
82394
82395             case 1:
82396                 //TODO:
82397                 //"compositeFilter doesn't support"
82398                 throw new WebAPIException(errorcode.NOT_SUPPORTED_ERR);
82399
82400             case 2:
82401             case 3:
82402                 break;
82403             }
82404         }
82405
82406         if (filter === null || filter === undefined) {
82407             utils.forEach(_data.persons, function (person) {
82408                 matched.push(person);
82409             });
82410         } else {
82411             switch (filter.attributeName) {
82412             case "id":
82413             case "displayName":
82414             case "photoURI":
82415             case "ringtoneURI":
82416             case "displayContactId":
82417                 matched = tizen1_utils.matchAttributeFilter(_data.persons,
82418                         filter.attributeName, filter.matchFlag, filter.matchValue);
82419                 break;
82420
82421             case "contactCount":
82422                 if (filter.matchFlag !== "EXACTLY" || typeof filter.matchValue !== "number") {
82423                     throw new WebAPIException(errorcode.TYPE_MISMATCH_ERR);
82424                 }
82425                 matched = tizen1_utils.matchAttributeFilter(_data.persons,
82426                         filter.attributeName, filter.matchFlag, filter.matchValue);
82427                 break;
82428
82429             case "hasPhoneNumber":
82430             case "hasEmail":
82431             case "isFavorite":
82432                 if (filter.matchFlag !== "EXACTLY" || typeof filter.matchValue !== "boolean") {
82433                     throw new WebAPIException(errorcode.TYPE_MISMATCH_ERR);
82434                 }
82435                 matched = tizen1_utils.matchAttributeBooleanFilter(_data.persons,
82436                         filter.attributeName, filter.matchValue);
82437                 break;
82438
82439             default:
82440                 break;
82441             }
82442         }
82443
82444         if (sortMode) {
82445             _sort(matched, sortMode);
82446         }
82447
82448         for (i in matched) {
82449             result.push(new Person(matched[i]));
82450         }
82451         successCallback(result);
82452     }
82453
82454     function addChangeListener(successCallback) {
82455         var id;
82456
82457         if (!_security.addChangeListener) {
82458             throw new WebAPIException(errorcode.SECURITY_ERR);
82459         }
82460
82461         t.ContactManager("addChangeListener", arguments);
82462
82463         id = ++_data.contactData.nListener;
82464         _data.contactData.listeners[id] = successCallback;
82465
82466         return id;
82467     }
82468
82469     function removeChangeListener(watchId) {
82470         if (!_security.removeChangeListener) {
82471             throw new WebAPIException(errorcode.SECURITY_ERR);
82472         }
82473
82474         t.ContactManager("removeChangeListener", arguments);
82475
82476         if (_data.contactData.listeners[watchId] === undefined) {
82477             throw new WebAPIException(errorcode.NOT_FOUND_ERR);
82478         }
82479         delete _data.contactData.listeners[watchId];
82480     }
82481
82482     function handleSubFeatures(subFeatures) {
82483         var i, subFeature;
82484
82485         for (subFeature in subFeatures) {
82486             for (i in _security[subFeature]) {
82487                 _security[_security[subFeature][i]] = true;
82488             }
82489         }
82490     }
82491
82492     _data.contactData = new ContactData();
82493
82494     contact = {
82495         getAddressBooks:       getAddressBooks,
82496         getDefaultAddressBook: getDefaultAddressBook,
82497         getAddressBook:        getAddressBook,
82498
82499         get:                   get,
82500         update:                update,
82501         updateBatch:           updateBatch,
82502         remove:                remove,
82503         removeBatch:           removeBatch,
82504         find:                  find,
82505         addChangeListener:     addChangeListener,
82506         removeChangeListener:  removeChangeListener,
82507         handleSubFeatures:     handleSubFeatures
82508     };
82509
82510     return contact;
82511 };
82512
82513 AddressBook = function (id, name, readOnly, dbContacts, dbGroups) {
82514     var addressBook,
82515         privateData = new AddressBookData(dbContacts, dbGroups);
82516
82517     // private
82518     function addNewContact(contact, external) {
82519         var added, person;
82520         added = new ContactPrivate(contact, true);
82521         privateData.contacts[added.id] = added;
82522
82523         person = new PersonBuilder(added);
82524         _data.persons[person.id] = person;
82525
82526         added.personId = person.id;
82527         added.addressBookId = id;
82528
82529         dbContacts[added.id] = _serialize(added);
82530         _data.dbStorage.persons[person.id] = _serialize(_data.persons[person.id]);
82531
82532         external.__defineGetter__("id", function () {
82533             return added.id;
82534         });
82535         external.__defineGetter__("personId", function () {
82536             return added.personId;
82537         });
82538         external.__defineGetter__("addressBookId", function () {
82539             return added.addressBookId;
82540         });
82541         external.__defineGetter__("lastUpdated", function () {
82542             return added.lastUpdated;
82543         });
82544         if (external.name !== null) {
82545             external.name.__defineGetter__("displayName", function () {
82546                 return added.name.displayName;
82547             });
82548         }
82549     }
82550
82551     // public
82552     function get(id) {
82553         if (!_security.get) {
82554             throw new WebAPIException(errorcode.SECURITY_ERR);
82555         }
82556
82557         t.AddressBook("get", arguments);
82558
82559         if (privateData.contacts[id] === undefined) {
82560             throw new WebAPIException(errorcode.NOT_FOUND_ERR);
82561         }
82562         return new ContactPublic(privateData.contacts[id]);
82563     }
82564
82565     function add(contact) {
82566         var added, external = contact;
82567
82568         if (!_security.add) {
82569             throw new WebAPIException(errorcode.SECURITY_ERR);
82570         }
82571         if (addressBook.readOnly) {
82572             throw new WebAPIException(errorcode.SECURITY_ERR);
82573         }
82574
82575         t.AddressBook("add", arguments);
82576
82577         addNewContact(contact, external);
82578         _save();
82579
82580         window.setTimeout(function () {
82581             utils.forEach(privateData.listeners, function (listener) {
82582                 listener.oncontactsadded([new ContactPublic(added)]);
82583             });
82584             utils.forEach(_data.contactData.listeners, function (listener) {
82585                 listener.onpersonsadded([new Person(_data.persons[external.personId])]);
82586             });
82587         }, 1);
82588     }
82589
82590     function addBatch(contacts, successCallback, errorCallback) {
82591         var external = contacts;
82592         if (!_security.addBatch) {
82593             throw new WebAPIException(errorcode.SECURITY_ERR);
82594         }
82595         if (addressBook.readOnly) {
82596             throw new WebAPIException(errorcode.SECURITY_ERR);
82597         }
82598
82599         t.AddressBook("addBatch", arguments);
82600
82601         window.setTimeout(function () {
82602             var i, personIds = [];
82603
82604             if (contacts.length === 0) {
82605                 if (errorCallback) {
82606                     errorCallback(new WebAPIError(errorcode.INVALID_VALUES_ERR));
82607                 }
82608                 return;
82609             }
82610
82611             for (i in contacts) {
82612                 addNewContact(contacts[i], external[i]);
82613                 personIds.push(external[i].personId);
82614             }
82615             _save();
82616             if (successCallback) {
82617                 successCallback(external);
82618             }
82619
82620             utils.forEach(privateData.listeners, function (listener) {
82621                 var i, watched = [];
82622
82623                 for (i in contacts) {
82624                     watched.push(new ContactPublic(external[i]));
82625                 }
82626                 listener.oncontactsadded(watched);
82627             });
82628             utils.forEach(_data.contactData.listeners, function (listener) {
82629                 var i, watched = [];
82630
82631                 for (i in personIds) {
82632                     watched.push(new Person(_data.persons[personIds[i]]));
82633                 }
82634                 listener.onpersonsadded(watched);
82635             });
82636         }, 1);
82637     }
82638
82639     function update(contact) {
82640         var updated;
82641
82642         if (!_security.update) {
82643             throw new WebAPIException(errorcode.SECURITY_ERR);
82644         }
82645         if (addressBook.readOnly) {
82646             throw new WebAPIException(errorcode.SECURITY_ERR);
82647         }
82648
82649         t.AddressBook("update", arguments);
82650
82651         if (!contact.id) {
82652             throw new WebAPIException(errorcode.INVALID_VALUES_ERR);
82653         }
82654         if (privateData.contacts[contact.id] === undefined) {
82655             throw new WebAPIException(errorcode.NOT_FOUND_ERR);
82656         }
82657
82658         updated = new ContactPrivate(contact, false);
82659
82660         privateData.contacts[updated.id] = updated;
82661         dbContacts[updated.id] = _serialize(updated);
82662         _save();
82663
82664         window.setTimeout(function () {
82665             utils.forEach(privateData.listeners, function (listener) {
82666                 listener.oncontactsupdated([new ContactPublic(updated)]);
82667             });
82668         }, 1);
82669     }
82670
82671     function updateBatch(contacts, successCallback, errorCallback) {
82672         if (!_security.updateBatch) {
82673             throw new WebAPIException(errorcode.SECURITY_ERR);
82674         }
82675         if (addressBook.readOnly) {
82676             throw new WebAPIException(errorcode.SECURITY_ERR);
82677         }
82678
82679         t.AddressBook("updateBatch", arguments);
82680
82681         window.setTimeout(function () {
82682             var i, updated;
82683
82684             if (contacts.length === 0) {
82685                 if (errorCallback) {
82686                     errorCallback(new WebAPIError(errorcode.INVALID_VALUES_ERR));
82687                 }
82688                 return;
82689             }
82690
82691             for (i in contacts) {
82692                 if (!contacts[i].id) {
82693                     if (errorCallback) {
82694                         errorCallback(new WebAPIError(errorcode.INVALID_VALUES_ERR));
82695                     }
82696                     return;
82697                 }
82698                 if (privateData.contacts[contacts[i].id] === undefined) {
82699                     if (errorCallback) {
82700                         errorCallback(new WebAPIError(errorcode.NOT_FOUND_ERR));
82701                     }
82702                     return;
82703                 }
82704             }
82705             for (i in contacts) {
82706                 updated = new ContactPrivate(contacts[i], false);
82707
82708                 privateData.contacts[updated.id] = updated;
82709                 dbContacts[updated.id] = _serialize(updated);
82710             }
82711             _save();
82712             if (successCallback) {
82713                 successCallback();
82714             }
82715
82716             utils.forEach(privateData.listeners, function (listener) {
82717                 var i, watched = [];
82718
82719                 for (i in contacts) {
82720                     watched.push(new ContactPublic(
82721                         privateData.contacts[contacts[i].id]));
82722                 }
82723                 listener.oncontactsupdated(watched);
82724             });
82725         }, 1);
82726     }
82727
82728     function remove(id) {
82729         if (!_security.remove) {
82730             throw new WebAPIException(errorcode.SECURITY_ERR);
82731         }
82732         if (addressBook.readOnly) {
82733             throw new WebAPIException(errorcode.SECURITY_ERR);
82734         }
82735
82736         t.AddressBook("remove", arguments);
82737
82738         if (privateData.contacts[id] === undefined) {
82739             throw new WebAPIException(errorcode.NOT_FOUND_ERR);
82740         }
82741
82742         delete privateData.contacts[id];
82743         if (dbContacts[id]) {
82744             delete dbContacts[id];
82745         }
82746         _save();
82747
82748         window.setTimeout(function () {
82749             utils.forEach(privateData.listeners, function (listener) {
82750                 listener.oncontactsremoved([id]);
82751             });
82752         }, 1);
82753     }
82754
82755     function removeBatch(ids, successCallback, errorCallback) {
82756         if (!_security.removeBatch) {
82757             throw new WebAPIException(errorcode.SECURITY_ERR);
82758         }
82759         if (addressBook.readOnly) {
82760             throw new WebAPIException(errorcode.SECURITY_ERR);
82761         }
82762
82763         t.AddressBook("removeBatch", arguments);
82764
82765         window.setTimeout(function () {
82766             var i;
82767
82768             if (ids.length === 0) {
82769                 if (errorCallback) {
82770                     errorCallback(new WebAPIError(errorcode.INVALID_VALUES_ERR));
82771                 }
82772                 return;
82773             }
82774
82775             for (i in ids) {
82776                 if (!ids[i]) {
82777                     if (errorCallback) {
82778                         errorCallback(new WebAPIError(errorcode.INVALID_VALUES_ERR));
82779                     }
82780                     return;
82781                 }
82782                 if (privateData.contacts[ids[i]] === undefined) {
82783                     if (errorCallback) {
82784                         errorCallback(new WebAPIError(errorcode.NOT_FOUND_ERR));
82785                     }
82786                     return;
82787                 }
82788             }
82789             for (i in ids) {
82790                 delete privateData.contacts[ids[i]];
82791                 if (dbContacts[ids[i]]) {
82792                     delete dbContacts[ids[i]];
82793                 }
82794             }
82795             _save();
82796             if (successCallback) {
82797                 successCallback();
82798             }
82799
82800             utils.forEach(privateData.listeners, function (listener) {
82801                 listener.oncontactsremoved(utils.copy(ids));
82802             });
82803         }, 1);
82804     }
82805
82806     function find(successCallback, errorCallback, filter, sortMode) {
82807         var result = [], begin, end, i,
82808             atr, _re, errFlag = false, _rangeMatch, low, high, matched,
82809             _existMatch, _arrayMatch;
82810
82811         if (!_security.find) {
82812             throw new WebAPIException(errorcode.SECURITY_ERR);
82813         }
82814
82815         t.AddressBook("find", arguments);
82816
82817         if (filter) {
82818             switch (_filterType(filter)) {
82819             case 0:
82820                 throw new WebAPIException(errorcode.TYPE_MISMATCH_ERR);
82821             case 1:
82822                 //TODO:
82823                 //"compositeFilter doesn't support"
82824                 throw new WebAPIException(errorcode.NOT_SUPPORTED_ERR);
82825             case 2:
82826             case 3:
82827                 break;
82828             }
82829         }
82830
82831         /* return all contacts if no filter argument */
82832         if (filter === null || filter === undefined) {
82833             utils.forEach(privateData.contacts, function (contact) {
82834                 result.push(new ContactPublic(contact));
82835             });
82836             successCallback(result);
82837             return;
82838         }
82839
82840         /* check composition of filter.attributeName */
82841         switch (filter.attributeName) {
82842         case "id" :
82843         case "personId" :
82844         case "addressBookId" :
82845         case "name.prefix" :
82846         case "name.suffix" :
82847         case "name.firstName" :
82848         case "name.middleName" :
82849         case "name.lastName" :
82850         case "name.phoneticFirstName" :
82851         case "name.phoneticLastName" :
82852         case "name.displayName" :
82853         case "account.accountServiceId" :
82854         case "account.contactURI" :
82855         case "photoURI" :
82856         case "ringtoneURI" :
82857             matched = tizen1_utils.matchAttributeFilter(privateData.contacts,
82858                     filter.attributeName, filter.matchFlag, filter.matchValue);
82859             break;
82860
82861         case "name.nicknames" :
82862         case "notes" :
82863         case "groupIds" :
82864             matched = tizen1_utils.matchAttributeArrayFilter(privateData.contacts,
82865                     filter.attributeName, filter.matchFlag, filter.matchValue);
82866             break;
82867
82868         case "addresses.country" :
82869         case "addresses.region" :
82870         case "addresses.city" :
82871         case "addresses.streetAddress" :
82872         case "addresses.additionalInformation" :
82873         case "addresses.postalCode" :
82874         case "phoneNumbers.number" :
82875         case "emails.email" :
82876         case "anniversaries.label" :
82877         case "organizations.name" :
82878         case "organizations.department" :
82879         case "organizations.title" :
82880         case "organizations.role" :
82881         case "organizations.logoURI" :
82882         case "urls.url" :
82883         case "urls.type" :
82884             atr = filter.attributeName.split(".");
82885             _existMatch = function (obj) {
82886                 return (obj[atr[0]] !== undefined);
82887             };
82888
82889             if (filter.matchValue === undefined || filter.matchFlag === "EXISTS") {
82890                 matched = utils.filter(privateData.contacts, _existMatch);
82891                 break;
82892             }
82893
82894             errFlag = false;
82895
82896             switch (filter.matchFlag)
82897             {
82898             case "EXACTLY":
82899                 _re = new RegExp("^" + filter.matchValue + "$");
82900                 break;
82901             case "FULLSTRING":
82902                 _re = new RegExp("^" + filter.matchValue + "$", "i");
82903                 break;
82904             case "CONTAINS":
82905                 _re = new RegExp(filter.matchValue, "i");
82906                 break;
82907             case "STARTSWITH":
82908                 _re = new RegExp("^" + filter.matchValue, "i");
82909                 break;
82910             case "ENDSWITH":
82911                 _re = new RegExp(filter.matchValue + "$", "i");
82912                 break;
82913             default:
82914                 errFlag = true;
82915             }
82916
82917             if (errFlag) {
82918                 matched = [];
82919                 break;
82920             }
82921
82922             _arrayMatch = function (obj) {
82923                 return (obj[atr[0]].some(function (o) {
82924                     if (typeof o[atr[1]] !== "string") {
82925                         return false;
82926                     } else {
82927                         return (o[atr[1]].search(_re) !== -1);
82928                     }
82929                 }));
82930             };
82931
82932             matched = utils.filter(privateData.contacts, _arrayMatch);
82933             break;
82934
82935         case "addresses.types" :
82936         case "phoneNumbers.types" :
82937         case "emails.types" :
82938             atr = filter.attributeName.split(".");
82939             _existMatch = function (obj) {
82940                 return (obj[atr[0]].some(function (o) {
82941                     return (o[atr[1]] !== undefined);
82942                 }));
82943             };
82944
82945             if (filter.matchValue === undefined || filter.matchFlag === "EXISTS") {
82946                 matched = utils.filter(privateData.contacts, _existMatch);
82947                 break;
82948             }
82949
82950             errFlag = false;
82951
82952             switch (filter.matchFlag) {
82953             case "EXACTLY":
82954                 _re = new RegExp("^" + filter.matchValue + "$");
82955                 break;
82956             case "FULLSTRING":
82957                 _re = new RegExp("^" + filter.matchValue + "$", "i");
82958                 break;
82959             case "CONTAINS":
82960                 _re = new RegExp(filter.matchValue, "i");
82961                 break;
82962             case "STARTSWITH":
82963                 _re = new RegExp("^" + filter.matchValue, "i");
82964                 break;
82965             case "ENDSWITH":
82966                 _re = new RegExp(filter.matchValue + "$", "i");
82967                 break;
82968             default:
82969                 errFlag = true;
82970             }
82971
82972             if (errFlag) {
82973                 matched = [];
82974                 break;
82975             }
82976
82977             _arrayMatch = function (obj) {
82978                 return (obj[atr[0]].some(function (o) {
82979                     if (!tizen1_utils.isValidArray(o[atr[1]])) {
82980                         return false;
82981                     } else {
82982                         return (o[atr[1]].some(function (t) {
82983                             return (t.search(_re) !== -1);
82984                         }));
82985                     }
82986                 }));
82987             };
82988
82989             matched = utils.filter(privateData.contacts, _arrayMatch);
82990             break;
82991
82992         case "anniversaries.date" :
82993             low = filter.initialValue;
82994             high = filter.endValue;
82995             atr = filter.attributeName.split(".");
82996
82997             if (low !== undefined && low !== null) {
82998                 if (!tizen1_utils.isValidDate(low)) {
82999                     throw new WebAPIException(errorcode.TYPE_MISMATCH_ERR);
83000                 }
83001             }
83002             if (high !== undefined && high !== null) {
83003                 if (!tizen1_utils.isValidDate(high)) {
83004                     throw new WebAPIException(errorcode.TYPE_MISMATCH_ERR);
83005                 }
83006             }
83007
83008             _rangeMatch = function (obj) {
83009                 var isMatched = true;
83010                 if (low !== null && low !== undefined) {
83011                     if (!tizen1_utils.isValidArray(obj[atr[0]])) {
83012                         isMatched = false;
83013                     } else {
83014                         isMatched = (obj[atr[0]].some(function (o) {
83015                             return (o[atr[1]] >= low);
83016                         }));
83017                     }
83018                 }
83019                 if (isMatched && (high !== null && high !== undefined)) {
83020                     if (!tizen1_utils.isValidArray(obj[atr[0]])) {
83021                         isMatched = false;
83022                     } else {
83023                         isMatched = (obj[atr[0]].some(function (o) {
83024                             return (o[atr[1]] <= high);
83025                         }));
83026                     }
83027                 }
83028                 return isMatched;
83029             };
83030
83031             matched = utils.filter(privateData.contacts, _rangeMatch);
83032             break;
83033
83034         case "addresses.isDefault" :
83035         case "phoneNumbers.isDefault" :
83036         case "emails.isDefault" :
83037             break;
83038
83039         case "isFavorite" :
83040             if (filter.matchFlag !== "EXACTLY" || typeof filter.matchValue !== "boolean") {
83041                 throw new WebAPIException(errorcode.TYPE_MISMATCH_ERR);
83042             } else {
83043                 matched = tizen1_utils.matchAttributeBooleanFilter(privateData.contacts,
83044                         filter.attributeName, filter.matchValue);
83045             }
83046             break;
83047
83048         case "birthday" :
83049             begin = filter.initialValue;
83050             end = filter.endValue;
83051
83052             if (begin !== null && begin !== undefined) {
83053                 if (!tizen1_utils.isValidDate(begin)) {
83054                     throw new WebAPIException(errorcode.TYPE_MISMATCH_ERR);
83055                 }
83056             }
83057
83058             if (end !== null && end !== undefined) {
83059                 if (!tizen1_utils.isValidDate(end)) {
83060                     throw new WebAPIException(errorcode.TYPE_MISMATCH_ERR);
83061                 }
83062             }
83063
83064             matched = tizen1_utils.matchAttributeRangeFilter(privateData.contacts,
83065                     filter.attributeName, begin, end);
83066             break;
83067
83068         default:
83069             throw new WebAPIException(errorcode.INVALID_VALUES_ERR);
83070         }
83071
83072         if (sortMode) {
83073             _sort(matched, sortMode);
83074         }
83075
83076         for (i in matched) {
83077             result.push(new ContactPublic(matched[i]));
83078         }
83079         successCallback(result);
83080     }
83081
83082     function addChangeListener(successCallback, errorCallback) {
83083         var id;
83084
83085         if (!_security.addChangeListener) {
83086             throw new WebAPIException(errorcode.SECURITY_ERR);
83087         }
83088
83089         t.AddressBook("addChangeListener", arguments);
83090
83091         id = ++privateData.nListener;
83092         privateData.listeners[id] = successCallback;
83093
83094         return id;
83095     }
83096
83097     function removeChangeListener(watchId) {
83098         if (!_security.removeChangeListener) {
83099             throw new WebAPIException(errorcode.SECURITY_ERR);
83100         }
83101
83102         t.AddressBook("removeChangeListener", arguments);
83103
83104         if (privateData.listeners[watchId] === undefined) {
83105             throw new WebAPIException(errorcode.NOT_FOUND_ERR);
83106         }
83107         delete privateData.listeners[watchId];
83108     }
83109
83110     function getGroup(groupId) {
83111         var i;
83112
83113         if (!_security.getGroup) {
83114             throw new WebAPIException(errorcode.SECURITY_ERR);
83115         }
83116
83117         t.AddressBook("getGroup", arguments);
83118
83119         for (i in privateData.groups) {
83120             if (privateData.groups[i].id === groupId)
83121                 break;
83122         }
83123         if (privateData.groups[i] === undefined) {
83124             throw new WebAPIException(errorcode.NOT_FOUND_ERR);
83125         }
83126
83127         return new ContactGroup(privateData.groups[i]);
83128     }
83129
83130     function addGroup(group) {
83131         var external = group;
83132
83133         if (!_security.addGroup) {
83134             throw new WebAPIException(errorcode.SECURITY_ERR);
83135         }
83136
83137         t.AddressBook("addGroup", arguments);
83138
83139         group.id            = Math.uuid(null, 16);
83140         group.addressBookId = id;
83141
83142         external.__defineGetter__("id", function () {
83143             return group.id;
83144         });
83145
83146         external.__defineGetter__("addressBookId", function () {
83147             return group.addressBookId;
83148         });
83149
83150         privateData.groups.push(group);
83151         _save();
83152     }
83153
83154     function updateGroup(group) {
83155         var i;
83156
83157         if (!_security.updateGroup) {
83158             throw new WebAPIException(errorcode.SECURITY_ERR);
83159         }
83160
83161         t.AddressBook("updateGroup", arguments);
83162
83163         if (!group.id) {
83164             throw new WebAPIException(errorcode.INVALID_VALUES_ERR);
83165         }
83166         for (i in privateData.groups) {
83167             if (privateData.groups[i].id === group.id)
83168                 break;
83169         }
83170         if (privateData.groups[i].id === undefined) {
83171             throw new WebAPIException(errorcode.NOT_FOUND_ERR);
83172         }
83173         if (privateData.groups[i].readOnly) {
83174             throw new WebAPIException(errorcode.SECURITY_ERR);
83175         }
83176         privateData.groups[i] = utils.copy(group);
83177         _save();
83178     }
83179
83180     function removeGroup(groupId) {
83181         var i;
83182
83183         if (!_security.removeGroup) {
83184             throw new WebAPIException(errorcode.SECURITY_ERR);
83185         }
83186
83187         t.AddressBook("removeGroup", arguments);
83188
83189         for (i in privateData.groups) {
83190             if (privateData.groups[i].id === groupId)
83191                 break;
83192         }
83193         if (privateData.groups[i].id === undefined) {
83194             throw new WebAPIException(errorcode.NOT_FOUND_ERR);
83195         }
83196         if (privateData.groups[i].readOnly) {
83197             throw new WebAPIException(errorcode.SECURITY_ERR);
83198         }
83199
83200         privateData.groups.splice(i, 1);
83201         _save();
83202     }
83203
83204     function getGroups() {
83205         var groups = [], i;
83206
83207         if (!_security.getGroups) {
83208             throw new WebAPIException(errorcode.SECURITY_ERR);
83209         }
83210
83211         for (i in privateData.groups) {
83212             groups.push(new ContactGroup(privateData.groups[i]));
83213         }
83214         return groups;
83215     }
83216
83217     privateData.load();
83218     // Make private contacts accessible for Person methods
83219     _data.contacts[id] = privateData.contacts;
83220
83221     addressBook = {
83222         get:                  get,
83223         add:                  add,
83224         addBatch:             addBatch,
83225         update:               update,
83226         updateBatch:          updateBatch,
83227         remove:               remove,
83228         removeBatch:          removeBatch,
83229         find:                 find,
83230         addChangeListener:    addChangeListener,
83231         removeChangeListener: removeChangeListener,
83232
83233         getGroup:             getGroup,
83234         addGroup:             addGroup,
83235         updateGroup:          updateGroup,
83236         removeGroup:          removeGroup,
83237         getGroups:            getGroups
83238     };
83239
83240     addressBook.__defineGetter__("id", function () {
83241         return id;
83242     });
83243
83244     addressBook.__defineGetter__("name", function () {
83245         return name;
83246     });
83247
83248     addressBook.__defineGetter__("readOnly", function () {
83249         return readOnly;
83250     });
83251
83252     return addressBook;
83253 };
83254
83255 AddressBookData = function (contacts, groups) {
83256     var addressBookData;
83257
83258     // private
83259     function loadContacts() {
83260         for (var i in contacts) {
83261             addressBookData.contacts[i] = new ContactPrivate(contacts[i], false);
83262         }
83263     }
83264
83265     function loadGroups() {
83266         addressBookData.groups = groups;
83267     }
83268
83269     // public
83270     function load() {
83271         loadContacts();
83272         loadGroups();
83273     }
83274
83275     addressBookData = {
83276         contacts:  {},
83277         groups:    [],
83278         listeners: {},
83279         nListener: 0,
83280         load:      load
83281     };
83282
83283     return addressBookData;
83284 };
83285
83286 AddressBookStorage = function (id, name, readOnly, contacts, groups) {
83287     this.id       = id;
83288     this.name     = name;
83289     this.readOnly = readOnly;
83290     this.contacts = contacts;
83291     this.groups   = groups;
83292 };
83293
83294 ContactData = function () {
83295     this.listeners = {};
83296     this.nListener = 0;
83297 };
83298
83299 ContactPublic = function (prop) {
83300     var _self;
83301
83302     _self = new Contact(prop, _security);
83303
83304     _self.__defineGetter__("id", function () {
83305         return prop.id;
83306     });
83307     _self.__defineGetter__("personId", function () {
83308         return prop.personId;
83309     });
83310     _self.__defineGetter__("addressBookId", function () {
83311         return prop.addressBookId;
83312     });
83313     _self.__defineGetter__("lastUpdated", function () {
83314         return prop.lastUpdated;
83315     });
83316     _self.__defineGetter__("isFavorite", function () {
83317         return prop.isFavorite;
83318     });
83319     if (_self.name !== null) {
83320         _self.name.__defineGetter__("displayName", function () {
83321             return prop.name.displayName;
83322         });
83323     }
83324
83325     return _self;
83326 };
83327
83328 ContactPrivate = function (prop, newID) {
83329     var _self;
83330
83331     _self = utils.copy(new Contact(prop, _security));
83332
83333     if (newID) {
83334         _self.id = Math.uuid(null, 16);
83335         _self.lastUpdated = new Date();
83336
83337         if (_self.name !== null) {
83338             _self.name.__defineGetter__("displayName", function () {
83339                 var displayName = "";
83340
83341                 if ((_self.name.firstName !== null) &&
83342                     (_self.name.lastName !== null)) {
83343                     displayName = [_self.name.firstName, _self.name.middleName,
83344                             _self.name.lastName];
83345                     displayName = displayName.join(" ").replace(/ +/g, " ").trim();
83346                 } else if (_self.name.nicknames.length !== 0) {
83347                     _self.name.nicknames.some(function (nickname) {
83348                         displayName = nickname;
83349                         return displayName;
83350                     });
83351                 }
83352
83353                 return displayName;
83354             });
83355         }
83356     } else {
83357         _self.id            = prop.id;
83358         _self.personId      = prop.personId;
83359         _self.addressBookId = prop.addressBookId;
83360         _self.lastUpdated   = new Date(prop.lastUpdated);
83361     }
83362
83363     return _self;
83364 };
83365
83366 ContactGroup = function (groupInitDict) {
83367     var id, addressBookId, readOnly;
83368
83369     this.__defineGetter__("id", function () {
83370         return id;
83371     });
83372
83373     this.__defineGetter__("addressBookId", function () {
83374         return addressBookId;
83375     });
83376
83377     this.__defineGetter__("readOnly", function () {
83378         return readOnly;
83379     });
83380
83381     id               = groupInitDict.id || null;
83382     addressBookId    = groupInitDict.addressBookId || null;
83383     readOnly         = groupInitDict.readOnly || false;
83384
83385     this.name        = groupInitDict.name || "";
83386     this.ringtoneURI = groupInitDict.ringtoneURI || null;
83387     this.photoURI    = groupInitDict.photoURI || null;
83388 };
83389
83390 Person = function (personInitDict) {
83391     var id;
83392
83393     function hasContactMethod(method) {
83394         var idab, idc, contact, count = 0;
83395
83396         for (idab in _data.contacts) {
83397             for (idc in _data.contacts[idab]) {
83398                 contact = _data.contacts[idab][idc];
83399                 if (contact.personId === id) {
83400                     count += contact[method].length;
83401                 }
83402             }
83403         }
83404
83405         return (count !== 0);
83406     }
83407
83408     this.__defineGetter__("id", function () {
83409         return id;
83410     });
83411
83412     this.__defineGetter__("displayName", function () {
83413         var idab, contact, displayName = "";
83414
83415         for (idab in _data.contacts) {
83416             contact = _data.contacts[idab][this.displayContactId];
83417             if (contact !== undefined) {
83418                 if (contact.name && contact.name.displayName) {
83419                     displayName = contact.name.displayName;
83420                 }
83421                 break;
83422             }
83423         }
83424
83425         return displayName;
83426     });
83427
83428     this.__defineGetter__("contactCount", function () {
83429         var idab, idc, contactCount = 0;
83430
83431         for (idab in _data.contacts) {
83432             for (idc in _data.contacts[idab]) {
83433                 if (_data.contacts[idab][idc].personId === id) {
83434                     ++contactCount;
83435                 }
83436             }
83437         }
83438
83439         return contactCount;
83440     });
83441
83442     this.__defineGetter__("hasPhoneNumber", function () {
83443         return hasContactMethod("phoneNumbers");
83444     });
83445
83446     this.__defineGetter__("hasEmail", function () {
83447         return hasContactMethod("emails");
83448     });
83449
83450     id                    = personInitDict.id || Math.uuid(null, 16);
83451
83452     this.isFavorite       = personInitDict.isFavorite || false;
83453     this.photoURI         = personInitDict.photoURI || null;
83454     this.ringtoneURI      = personInitDict.ringtoneURI || null;
83455     this.displayContactId = personInitDict.displayContactId;
83456
83457     this.link = function (personId) {
83458         if (!_security.link) {
83459             throw new WebAPIException(errorcode.SECURITY_ERR);
83460         }
83461
83462         t.Person("link", arguments);
83463
83464         if (_data.persons[personId] === undefined) {
83465             throw new WebAPIException(errorcode.NOT_FOUND_ERR);
83466         }
83467
83468         _replacePerson(personId, id);
83469         _save();
83470     };
83471
83472     this.unlink = function (contactId) {
83473         var idab, contact, separated, i, dbAddressBook;
83474
83475         if (!_security.unlink) {
83476             throw new WebAPIException(errorcode.SECURITY_ERR);
83477         }
83478
83479         t.Person("unlink", arguments);
83480
83481         for (idab in _data.contacts) {
83482             if (_data.contacts[idab][contactId] !== undefined) {
83483                 contact = _data.contacts[idab][contactId];
83484                 break;
83485             }
83486         }
83487
83488         if (contact === undefined) {
83489             throw new WebAPIException(errorcode.NOT_FOUND_ERR);
83490         }
83491         if (contact.personId !== id) {
83492             throw new WebAPIException(errorcode.UNKNOWN_ERR);
83493         }
83494
83495         separated = new PersonBuilder(contact);
83496         _data.persons[separated.id] = separated;
83497         contact.personId = separated.id;
83498
83499         _data.dbStorage.persons[separated.id] = _serialize(separated);
83500         for (i in _data.dbStorage.addressBooks) {
83501             dbAddressBook = _data.dbStorage.addressBooks[i];
83502             if (dbAddressBook.id === idab) {
83503                 dbAddressBook.contacts[contact.id].personId = separated.id;
83504                 break;
83505             }
83506         }
83507         _save();
83508
83509         return separated;
83510     };
83511 };
83512
83513 PersonBuilder = function (contact) {
83514     var person, personInitDict = {};
83515
83516     personInitDict.displayContactId = contact.id;
83517     person = new Person(personInitDict);
83518
83519     return person;
83520 };
83521
83522 module.exports = _self;
83523
83524 });
83525 define('ripple/platform/tizen/2.0/content', function (require, exports, module) {
83526 /*
83527  *  Copyright 2012 Intel Corporation
83528  *
83529  * Licensed under the Apache License, Version 2.0 (the "License");
83530  * you may not use this file except in compliance with the License.
83531  * You may obtain a copy of the License at
83532  *
83533  * http://www.apache.org/licenses/LICENSE-2.0
83534  *
83535  * Unless required by applicable law or agreed to in writing, software
83536  * distributed under the License is distributed on an "AS IS" BASIS,
83537  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
83538  * See the License for the specific language governing permissions and
83539  * limitations under the License.
83540  */
83541
83542 var db = require('ripple/db'),
83543     utils = require('ripple/utils'),
83544     dbfs = require('ripple/platform/tizen/2.0/dbfs'),
83545     t = require('ripple/platform/tizen/2.0/typecast'),
83546     tizen1_utils = require('ripple/platform/tizen/2.0/tizen1_utils'),
83547     errorcode = require('ripple/platform/tizen/2.0/errorcode'),
83548     WebAPIError = require('ripple/platform/tizen/2.0/WebAPIError'),
83549     WebAPIException = require('ripple/platform/tizen/2.0/WebAPIException'),
83550     ContentDirectory,
83551     Content,
83552     VideoContent,
83553     AudioContent,
83554     ImageContent,
83555     ContentFactory,
83556     _data = {
83557         DB_CONTENT_KEY: "tizen1-db-content",
83558         directories:    [],
83559         contents:       [],
83560         listener:       null,
83561         dbStorage:      {}
83562     },
83563     _security = {
83564         "http://tizen.org/privilege/content.read": ["find",
83565             "setChangeListener", "unsetChangeListener"],
83566         "http://tizen.org/privilege/content.write": ["update", "updateBatch",
83567             "scanFile"]
83568     },
83569     _self;
83570
83571 function _get() {
83572     _data.dbStorage = db.retrieveObject(_data.DB_CONTENT_KEY) || require('ripple/platform/tizen/2.0/dbinit').Content;
83573 }
83574
83575 function _save() {
83576     db.saveObject(_data.DB_CONTENT_KEY, _data.dbStorage);
83577 }
83578
83579 function _initialize() {
83580     _get();
83581
83582     if (!_data.dbStorage)
83583         return;
83584
83585     utils.forEach(_data.dbStorage.directories, function (directory) {
83586         _data.directories.push(new ContentDirectory(directory, true));
83587     });
83588     utils.forEach(_data.dbStorage.contents, function (content) {
83589         _data.contents.push(new ContentFactory(content, true));
83590     });
83591
83592     _data.dbStorage.directories = _data.directories;
83593     _data.dbStorage.contents    = _data.contents;
83594
83595     _save();
83596 }
83597
83598 _self = function () {
83599     var content;
83600
83601     // private
83602     function updateContents(contents, successCallback, errorCallback) {
83603         var i, j, isFound = false, matched = [];
83604
83605         if (tizen1_utils.isValidArray(contents)) {
83606             for (i in contents) {
83607                 for (j in _data.contents) {
83608                     if (contents[i].id === _data.contents[j].id) {
83609                         matched.push(j);
83610                         break;
83611                     }
83612                 }
83613             }
83614
83615             if (matched.length === contents.length) {
83616                 for (i in matched) {
83617                     _data.contents[matched[i]] = new ContentFactory(contents[i]);
83618                 }
83619                 isFound = true;
83620             }
83621         } else {
83622             for (i in _data.contents) {
83623                 if (_data.contents[i].id === contents.id) {
83624                     _data.contents[i] = new ContentFactory(contents);
83625                     matched.push(i);
83626                     isFound = true;
83627                     break;
83628                 }
83629             }
83630         }
83631
83632         if (isFound) {
83633             _save();
83634
83635             if (successCallback) {
83636                 successCallback();
83637             }
83638             if (_data.listener !== null) {
83639                 utils.forEach(matched, function (i) {
83640                     _data.listener.oncontentupdated(new ContentFactory(_data.contents[i]));
83641                 });
83642             }
83643         } else if (errorCallback) {
83644             errorCallback(new WebAPIError(errorcode.UNKNOWN_ERR));
83645         }
83646     }
83647
83648     function getType(file) {
83649         var extName, type;
83650
83651         extName = file.substr(file.lastIndexOf(".") + 1).toLowerCase();
83652
83653         switch (extName) {
83654         case "bmp":
83655         case "gif":
83656         case "jpeg":
83657         case "jpg":
83658         case "png":
83659             type = "IMAGE";
83660             break;
83661
83662         case "avi":
83663         case "mpeg":
83664         case "mpg":
83665         case "wmv":
83666         case "mp4":
83667             type = "VIDEO";
83668             break;
83669
83670         case "wav":
83671         case "mp3":
83672             type = "AUDIO";
83673             break;
83674
83675         default:
83676             type = "OTHER";
83677             break;
83678         }
83679
83680         return type;
83681     }
83682
83683     function getMimeType(file) {
83684         var mimeTypeTab = {
83685             IMAGE: "image/x-msimage",
83686             VIDEO: "video/x-msvideo",
83687             AUDIO: "audio/x-msaudio",
83688             OTHER: "other/unknown"
83689         };
83690
83691         return mimeTypeTab[getType(file)];
83692     }
83693
83694     function getTitle(file) {
83695         var title;
83696
83697         title = file.substr(0, file.lastIndexOf("."));
83698         title = title.charAt(0).toUpperCase() + title.substr(1).toLowerCase();
83699
83700         return title;
83701     }
83702
83703     function extractProperties(entry) {
83704         var contentInitDict = {};
83705
83706         contentInitDict.editableAttributes = ["name", "title", "description", "rating"];
83707         contentInitDict.name               = entry.name;
83708         contentInitDict.type               = getType(entry.name);
83709         contentInitDict.mimeType           = getMimeType(entry.name);
83710         contentInitDict.title              = getTitle(entry.name);
83711         contentInitDict.contentURI         = entry.fullPath;
83712         contentInitDict.thumbnailURIs      = [entry.fullPath];
83713         contentInitDict.releaseDate        = entry.lastModifiedDate;
83714         contentInitDict.modifiedDate       = entry.lastModifiedDate;
83715         contentInitDict.size               = 1048576;
83716
83717         return contentInitDict;
83718     }
83719
83720     // public
83721     function update(content) {
83722         if (!_security.update) {
83723             throw new WebAPIException(errorcode.SECURITY_ERR);
83724         }
83725
83726         t.ContentManager("update", arguments);
83727
83728         updateContents(content);
83729     }
83730
83731     function updateBatch(contents, successCallback, errorCallback) {
83732         if (!_security.updateBatch) {
83733             throw new WebAPIException(errorcode.SECURITY_ERR);
83734         }
83735
83736         t.ContentManager("updateBatch", arguments);
83737
83738         window.setTimeout(function () {
83739             updateContents(contents, successCallback, errorCallback);
83740         }, 1);
83741     }
83742
83743     function getDirectories(successCallback, errorCallback) {
83744         var result = [];
83745
83746         t.ContentManager("getDirectories", arguments);
83747
83748         if (_data.directories.length === 0) {
83749             if (errorCallback) {
83750                 setTimeout(function () {
83751                     errorCallback(new WebAPIError(errorcode.UNKNOWN_ERR));
83752                 }, 1);
83753             }
83754             return;
83755         }
83756
83757         utils.forEach(_data.directories, function (directory) {
83758             result.push(new ContentDirectory(directory));
83759         });
83760
83761         setTimeout(function () {
83762             successCallback(result);
83763         }, 1);
83764     }
83765
83766     function find(successCallback, errorCallback, directoryId, filter, sortMode, count, offset) {
83767         var src = [], result = [], i, directoryURI, parentURI, contents;
83768
83769         if (!_security.find) {
83770             throw new WebAPIException(errorcode.SECURITY_ERR);
83771         }
83772
83773         t.ContentManager("find", arguments);
83774
83775         if (!directoryId) {
83776             src = _data.contents;
83777         } else {
83778             if (_data.directories.length === 0) {
83779                 if (errorCallback) {
83780                     setTimeout(function () {
83781                         errorCallback(new WebAPIError(errorcode.UNKNOWN_ERR));
83782                     }, 1);
83783                 }
83784                 return;
83785             }
83786
83787             for (i in _data.directories) {
83788                 if (_data.directories[i].id === directoryId) {
83789                     directoryURI = _data.directories[i].directoryURI;
83790                     break;
83791                 }
83792             }
83793
83794             if (!directoryURI) {
83795                 if (errorCallback) {
83796                     setTimeout(function () {
83797                         errorCallback(new WebAPIError(errorcode.UNKNOWN_ERR));
83798                     }, 1);
83799                 }
83800                 return;
83801             }
83802
83803             for (i in _data.contents) {
83804                 parentURI = _data.contents[i].contentURI;
83805                 parentURI = parentURI.slice(0, parentURI.lastIndexOf('/') + 1);
83806                 if (parentURI === directoryURI) {
83807                     src.push(_data.contents[i]);
83808                 }
83809             }
83810         }
83811
83812         if (src.length === 0) {
83813             if (errorCallback) {
83814                 setTimeout(function () {
83815                     errorCallback(new WebAPIError(errorcode.UNKNOWN_ERR));
83816                 }, 1);
83817             }
83818             return;
83819         }
83820
83821         contents = tizen1_utils.query(src, filter, sortMode, count, offset);
83822
83823         utils.forEach(contents, function (content) {
83824             result.push(new ContentFactory(content));
83825         });
83826
83827         successCallback(result);
83828     }
83829
83830     function scanFile(contentURI, successCallback, errorCallback) {
83831         var i, index, isFound = false;
83832
83833         function onStatSuccess(entry) {
83834             var contentInitDict, content, directoryURI;
83835
83836             if (isFound) {
83837                 content = new ContentFactory(_data.contents[index], true);
83838             } else {
83839                 contentInitDict = extractProperties(entry);
83840                 content = new ContentFactory(contentInitDict, true);
83841                 _data.contents.push(content);
83842             }
83843             _save();
83844
83845             if (successCallback) {
83846                 directoryURI = contentURI.slice(0,
83847                     contentURI.lastIndexOf('/') + 1);
83848
83849                 successCallback(directoryURI);
83850             }
83851             if (_data.listener !== null) {
83852                 if (isFound) {
83853                     _data.listener.oncontentupdated(new ContentFactory(content));
83854                 } else {
83855                     _data.listener.oncontentadded(new ContentFactory(content));
83856                 }
83857             }
83858         }
83859
83860         function onStatError() {
83861             var directoryURI;
83862
83863             if (isFound) {
83864                 _data.contents.splice(index, 1);
83865                 _save();
83866
83867                 if (successCallback) {
83868                     directoryURI = contentURI.slice(0,
83869                         contentURI.lastIndexOf('/') + 1);
83870
83871                     successCallback(directoryURI);
83872                 }
83873                 if (_data.listener !== null) {
83874                     _data.listener.oncontentremoved(_data.contents[index].id);
83875                 }
83876             } else if (errorCallback) {
83877                 window.setTimeout(function () {
83878                     errorCallback(new WebAPIError(errorcode.UNKNOWN_ERR));
83879                 }, 1);
83880             }
83881         }
83882
83883         if (!_security.scanFile) {
83884             throw new WebAPIException(errorcode.SECURITY_ERR);
83885         }
83886
83887         t.ContentManager("scanFile", arguments);
83888
83889         for (i in _data.contents) {
83890             if (_data.contents[i].contentURI === contentURI) {
83891                 isFound = true;
83892                 index = i;
83893                 break;
83894             }
83895         }
83896
83897         dbfs.stat(contentURI, onStatSuccess, onStatError);
83898     }
83899
83900     function setChangeListener(changeCallback) {
83901         if (!_security.setChangeListener) {
83902             throw new WebAPIException(errorcode.SECURITY_ERR);
83903         }
83904
83905         t.ContentManager("setChangeListener", arguments);
83906
83907         _data.listener = changeCallback;
83908     }
83909
83910     function unsetChangeListener() {
83911         if (!_security.unsetChangeListener) {
83912             throw new WebAPIException(errorcode.SECURITY_ERR);
83913         }
83914
83915         _data.listener = null;
83916     }
83917
83918     function handleSubFeatures(subFeatures) {
83919         var i, subFeature;
83920
83921         for (subFeature in subFeatures) {
83922             for (i in _security[subFeature]) {
83923                 _security[_security[subFeature][i]] = true;
83924             }
83925         }
83926     }
83927
83928     content = {
83929         update:              update,
83930         updateBatch:         updateBatch,
83931         getDirectories:      getDirectories,
83932         find:                find,
83933         scanFile:            scanFile,
83934         setChangeListener:   setChangeListener,
83935         unsetChangeListener: unsetChangeListener,
83936         handleSubFeatures:   handleSubFeatures
83937     };
83938
83939     return content;
83940 };
83941
83942 ContentDirectory = function (contentDirectoryInitDict, isInternal) {
83943     var id, directoryURI, title, storageType, modifiedDate;
83944
83945     id           = contentDirectoryInitDict.id || null;
83946     directoryURI = contentDirectoryInitDict.directoryURI || null;
83947     title        = contentDirectoryInitDict.title || "";
83948     storageType  = contentDirectoryInitDict.storageType || "INTERNAL";
83949     modifiedDate = new Date(contentDirectoryInitDict.modifiedDate);
83950
83951     if (!isInternal) {
83952         this.__defineGetter__("id", function () {
83953             return id;
83954         });
83955
83956         this.__defineGetter__("directoryURI", function () {
83957             return directoryURI;
83958         });
83959
83960         this.__defineGetter__("title", function () {
83961             return title;
83962         });
83963
83964         this.__defineGetter__("storageType", function () {
83965             return storageType;
83966         });
83967
83968         this.__defineGetter__("modifiedDate", function () {
83969             return modifiedDate;
83970         });
83971     } else {
83972         this.id           = id;
83973         this.directoryURI = directoryURI;
83974         this.title        = title;
83975         this.storageType  = storageType;
83976         this.modifiedDate = modifiedDate;
83977     }
83978 };
83979
83980 Content = function (contentInitDict, isInternal) {
83981     var editableAttributes, id, type, mimeType, title, contentURI,
83982         thumbnailURIs, releaseDate, modifiedDate, size;
83983
83984     editableAttributes = contentInitDict.editableAttributes || [];
83985     id                 = contentInitDict.id || Math.uuid(null, 16);
83986     type               = contentInitDict.type || "IMAGE";
83987     mimeType           = contentInitDict.mimeType || "";
83988     title              = contentInitDict.title || "";
83989     contentURI         = contentInitDict.contentURI || "";
83990     thumbnailURIs      = contentInitDict.thumbnailURIs || null;
83991     releaseDate        = new Date(contentInitDict.releaseDate);
83992     modifiedDate       = new Date(contentInitDict.modifiedDate);
83993     size               = contentInitDict.size || null;
83994     this.name          = contentInitDict.name || "";
83995     this.description   = contentInitDict.description || "";
83996     this.rating        = contentInitDict.rating || 0;
83997
83998     if (!isInternal) {
83999         this.__defineGetter__("editableAttributes", function () {
84000             return editableAttributes;
84001         });
84002
84003         this.__defineGetter__("id", function () {
84004             return id;
84005         });
84006
84007         this.__defineGetter__("type", function () {
84008             return type;
84009         });
84010
84011         this.__defineGetter__("mimeType", function () {
84012             return mimeType;
84013         });
84014
84015         this.__defineGetter__("title", function () {
84016             return title;
84017         });
84018
84019         this.__defineGetter__("contentURI", function () {
84020             return contentURI;
84021         });
84022
84023         this.__defineGetter__("thumbnailURIs", function () {
84024             return thumbnailURIs;
84025         });
84026
84027         this.__defineGetter__("releaseDate", function () {
84028             return releaseDate;
84029         });
84030
84031         this.__defineGetter__("modifiedDate", function () {
84032             return modifiedDate;
84033         });
84034
84035         this.__defineGetter__("size", function () {
84036             return size;
84037         });
84038     } else {
84039         this.editableAttributes = editableAttributes;
84040         this.id                 = id;
84041         this.type               = type;
84042         this.mimeType           = mimeType;
84043         this.title              = title;
84044         this.contentURI         = contentURI;
84045         this.thumbnailURIs      = thumbnailURIs;
84046         this.releaseDate        = releaseDate;
84047         this.modifiedDate       = modifiedDate;
84048         this.size               = size;
84049     }
84050 };
84051
84052 VideoContent = function (vidioContentInitDict, isInternal) {
84053     var _self, album, artists, duration, width, height;
84054
84055     _self = new Content(vidioContentInitDict, isInternal);
84056
84057     album             = vidioContentInitDict.album || null;
84058     artists           = vidioContentInitDict.artists || null;
84059     duration          = vidioContentInitDict.duration || 0;
84060     width             = vidioContentInitDict.width || 0;
84061     height            = vidioContentInitDict.height || 0;
84062     _self.geolocation = vidioContentInitDict.geolocation || null;
84063
84064     if (!isInternal) {
84065         _self.__defineGetter__("album", function () {
84066             return album;
84067         });
84068
84069         _self.__defineGetter__("artists", function () {
84070             return artists;
84071         });
84072
84073         _self.__defineGetter__("duration", function () {
84074             return duration;
84075         });
84076
84077         _self.__defineGetter__("width", function () {
84078             return width;
84079         });
84080
84081         _self.__defineGetter__("height", function () {
84082             return height;
84083         });
84084     } else {
84085         _self.album    = album;
84086         _self.artists  = artists;
84087         _self.duration = duration;
84088         _self.width    = width;
84089         _self.height   = height;
84090     }
84091
84092     return _self;
84093 };
84094
84095 AudioContent = function (audioContentInitDict, isInternal) {
84096     var _self, album, genres, artists, composers, lyrics, copyright, bitrate,
84097         trackNumber, duration;
84098
84099     _self = new Content(audioContentInitDict, isInternal);
84100
84101     album       = audioContentInitDict.album || null;
84102     genres      = audioContentInitDict.genres || null;
84103     artists     = audioContentInitDict.artists || null;
84104     composers   = audioContentInitDict.composers || null;
84105     lyrics      = audioContentInitDict.lyrics || null;
84106     copyright   = audioContentInitDict.copyright || null;
84107     bitrate     = audioContentInitDict.bitrate || 0;
84108     trackNumber = audioContentInitDict.trackNumber || 0;
84109     duration    = audioContentInitDict.duration || 0;
84110
84111     if (!isInternal) {
84112         _self.__defineGetter__("album", function () {
84113             return album;
84114         });
84115
84116         _self.__defineGetter__("genres", function () {
84117             return genres;
84118         });
84119
84120         _self.__defineGetter__("artists", function () {
84121             return artists;
84122         });
84123
84124         _self.__defineGetter__("composers", function () {
84125             return composers;
84126         });
84127
84128         _self.__defineGetter__("lyrics", function () {
84129             return lyrics;
84130         });
84131
84132         _self.__defineGetter__("copyright", function () {
84133             return copyright;
84134         });
84135
84136         _self.__defineGetter__("bitrate", function () {
84137             return bitrate;
84138         });
84139
84140         _self.__defineGetter__("trackNumber", function () {
84141             return trackNumber;
84142         });
84143
84144         _self.__defineGetter__("duration", function () {
84145             return duration;
84146         });
84147     } else {
84148         _self.album       = album;
84149         _self.genres      = genres;
84150         _self.artists     = artists;
84151         _self.composers   = composers;
84152         _self.lyrics      = lyrics;
84153         _self.copyright   = copyright;
84154         _self.bitrate     = bitrate;
84155         _self.trackNumber = trackNumber;
84156         _self.duration    = duration;
84157     }
84158
84159     return _self;
84160 };
84161
84162 ImageContent = function (imageContentInitDict, isInternal) {
84163     var _self, width, height;
84164
84165     _self = new Content(imageContentInitDict, isInternal);
84166
84167     width             = imageContentInitDict.width || 0;
84168     height            = imageContentInitDict.height || 0;
84169     _self.geolocation = imageContentInitDict.geolocation || null;
84170     _self.orientation = imageContentInitDict.orientation || null;
84171
84172     if (!isInternal) {
84173         _self.__defineGetter__("width", function () {
84174             return width;
84175         });
84176
84177         _self.__defineGetter__("height", function () {
84178             return height;
84179         });
84180     } else {
84181         _self.width  = width;
84182         _self.height = height;
84183     }
84184
84185     return _self;
84186 };
84187
84188 ContentFactory = function (contentInitDict, isInternal) {
84189     var _self;
84190
84191     switch (contentInitDict.type) {
84192     case "IMAGE":
84193         _self = new ImageContent(contentInitDict, isInternal);
84194         break;
84195
84196     case "VIDEO":
84197         _self = new VideoContent(contentInitDict, isInternal);
84198         break;
84199
84200     case "AUDIO":
84201         _self = new AudioContent(contentInitDict, isInternal);
84202         break;
84203
84204     default:
84205         _self = new Content(contentInitDict, isInternal);
84206         break;
84207     }
84208
84209     return _self;
84210 };
84211
84212 _initialize();
84213
84214 module.exports = _self;
84215
84216 });
84217 define('ripple/platform/tizen/2.0/datacontrol', function (require, exports, module) {
84218 /*
84219  *  Copyright 2013 Intel Corporation
84220  *
84221  * Licensed under the Apache License, Version 2.0 (the "License");
84222  * you may not use this file except in compliance with the License.
84223  * You may obtain a copy of the License at
84224  *
84225  * http://www.apache.org/licenses/LICENSE-2.0
84226  *
84227  * Unless required by applicable law or agreed to in writing, software
84228  * distributed under the License is distributed on an "AS IS" BASIS,
84229  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
84230  * See the License for the specific language governing permissions and
84231  * limitations under the License.
84232  */
84233
84234 var db = require('ripple/db'),
84235     utils = require('ripple/utils'),
84236     t = require('ripple/platform/tizen/2.0/typecast'),
84237     errorcode = require('ripple/platform/tizen/2.0/errorcode'),
84238     WebAPIError = require('ripple/platform/tizen/2.0/WebAPIError'),
84239     WebAPIException = require('ripple/platform/tizen/2.0/WebAPIException'),
84240     DataControlConsumerFactory,
84241     DataControlConsumerObject,
84242     SQLDataControlConsumer,
84243     MappedDataControlConsumer,
84244     SQLData,
84245     MappedData,
84246     _data = {
84247         DB_DATACONTROL_KEY: "tizen1-db-datacontrol",
84248         IDS_PROVIDER:       ["http://tizen.org/datacontrol/provider/DictionaryDataControlProvider"],
84249         IDS_DATA:           ["Dictionary"],
84250         PERSIST_DELAY:      1000,
84251         SQL:                null,
84252         MAP:                null,
84253         dbStorage:          null
84254     },
84255     _security = {
84256         "http://tizen.org/privilege/datacontrol.consumer":
84257             ["getDataControlConsumer", "insert", "update", "remove", "select",
84258             "addValue", "removeValue", "getValue", "updateValue"]
84259     },
84260     _self;
84261
84262 function _get() {
84263     _data.dbStorage = db.retrieveObject(_data.DB_DATACONTROL_KEY) || {};
84264 }
84265
84266 function _save() {
84267     db.saveObject(_data.DB_DATACONTROL_KEY, _data.dbStorage);
84268 }
84269
84270 function _load(type) {
84271     if (!_data.dbStorage[type])
84272         return;
84273
84274     _data[type] = {};
84275
84276     utils.forEach(_data.dbStorage[type], function (provider, id) {
84277         var dataId;
84278
84279         _data[type][id] = {};
84280
84281         for (dataId in provider) {
84282             _data[type][id][dataId] = new DataControlConsumerFactory(type,
84283                     id, dataId, provider[dataId]);
84284         }
84285     });
84286 }
84287
84288 function _initialize() {
84289     _get();
84290
84291     _load("SQL");
84292     _load("MAP");
84293 }
84294
84295 _self = function () {
84296     var datacontrol;
84297
84298     // private
84299     function initConsumer(type) {
84300         var providers;
84301
84302         _data.dbStorage[type] = {};
84303         providers = _data.dbStorage[type];
84304
84305         _data.IDS_PROVIDER.forEach(function (id) {
84306             providers[id] = {};
84307
84308             _data.IDS_DATA.forEach(function (dataId) {
84309                 providers[id][dataId] = {};
84310             });
84311         });
84312
84313         _load(type);
84314     }
84315
84316     // public
84317     function getDataControlConsumer(providerId, dataId, type) {
84318         if (!_security.getDataControlConsumer) {
84319             throw new WebAPIException(errorcode.SECURITY_ERR);
84320         }
84321
84322         t.DataControlManager("getDataControlConsumer", arguments);
84323
84324         if (_data[type] === null) {
84325             initConsumer(type);
84326         }
84327         if (!_data[type][providerId] || !_data[type][providerId][dataId]) {
84328             throw new WebAPIException(errorcode.NOT_FOUND_ERR);
84329         }
84330
84331         return _data[type][providerId][dataId];
84332     }
84333
84334     function handleSubFeatures(subFeatures) {
84335         var i, subFeature;
84336
84337         for (subFeature in subFeatures) {
84338             for (i in _security[subFeature]) {
84339                 _security[_security[subFeature][i]] = true;
84340             }
84341         }
84342     }
84343
84344     datacontrol = {
84345         getDataControlConsumer: getDataControlConsumer,
84346         handleSubFeatures:      handleSubFeatures
84347     };
84348
84349     return datacontrol;
84350 };
84351
84352 DataControlConsumerObject = function (type, providerId, dataId) {
84353     this.__defineGetter__("type", function () {
84354         return type;
84355     });
84356
84357     this.__defineGetter__("providerId", function () {
84358         return providerId;
84359     });
84360
84361     this.__defineGetter__("dataId", function () {
84362         return dataId;
84363     });
84364 };
84365
84366 SQLDataControlConsumer = function (providerId, dataId, dc) {
84367     var self, privateData = new SQLData(dc);
84368
84369     // public
84370     function insert(reqId, insertionData, successCallback, errorCallback) {
84371         if (!_security.insert) {
84372             throw new WebAPIException(errorcode.SECURITY_ERR);
84373         }
84374
84375         t.SQLDataControlConsumer("insert", arguments);
84376
84377         privateData.insert(insertionData, function (rowId) {
84378             if (successCallback) {
84379                 successCallback(reqId, rowId);
84380             }
84381         }, function (error) {
84382             if (errorCallback) {
84383                 errorCallback(reqId, error);
84384             }
84385         });
84386     }
84387
84388     function update(reqId, updateData, where, successCallback, errorCallback) {
84389         if (!_security.update) {
84390             throw new WebAPIException(errorcode.SECURITY_ERR);
84391         }
84392
84393         t.SQLDataControlConsumer("update", arguments);
84394
84395         privateData.update(updateData, where, function () {
84396             if (successCallback) {
84397                 successCallback(reqId);
84398             }
84399         }, function (error) {
84400             if (errorCallback) {
84401                 errorCallback(reqId, error);
84402             }
84403         });
84404     }
84405
84406     function remove(reqId, where, successCallback, errorCallback) {
84407         if (!_security.remove) {
84408             throw new WebAPIException(errorcode.SECURITY_ERR);
84409         }
84410
84411         t.SQLDataControlConsumer("remove", arguments);
84412
84413         privateData.remove(where, function () {
84414             if (successCallback) {
84415                 successCallback(reqId);
84416             }
84417         }, function (error) {
84418             if (errorCallback) {
84419                 errorCallback(reqId, error);
84420             }
84421         });
84422     }
84423
84424     function select(reqId, columns, where, successCallback, errorCallback, page,
84425             maxNumberPerPage) {
84426         if (!_security.select) {
84427             throw new WebAPIException(errorcode.SECURITY_ERR);
84428         }
84429
84430         t.SQLDataControlConsumer("select", arguments);
84431
84432         privateData.select(columns, where, function (rows) {
84433             successCallback(rows, reqId);
84434         }, function (error) {
84435             if (errorCallback) {
84436                 errorCallback(reqId, error);
84437             }
84438         }, page, maxNumberPerPage);
84439     }
84440
84441     self = new DataControlConsumerObject("SQL", providerId, dataId);
84442
84443     self.insert = insert;
84444     self.update = update;
84445     self.remove = remove;
84446     self.select = select;
84447
84448     return self;
84449 };
84450
84451 MappedDataControlConsumer = function (providerId, dataId, dc) {
84452     var self, privateData = new MappedData(dc);
84453
84454     function addValue(reqId, key, value, successCallback, errorCallback) {
84455         if (!_security.addValue) {
84456             throw new WebAPIException(errorcode.SECURITY_ERR);
84457         }
84458
84459         t.MappedDataControlConsumer("addValue", arguments);
84460
84461         window.setTimeout(function () {
84462             if (privateData.insert(key, value)) {
84463                 if (successCallback) {
84464                     successCallback(reqId);
84465                 }
84466             } else if (errorCallback) {
84467                 errorCallback(reqId, new WebAPIError(errorcode.UNKNOWN_ERR));
84468             }
84469         }, 1);
84470     }
84471
84472     function removeValue(reqId, key, value, successCallback, errorCallback) {
84473         if (!_security.removeValue) {
84474             throw new WebAPIException(errorcode.SECURITY_ERR);
84475         }
84476
84477         t.MappedDataControlConsumer("removeValue", arguments);
84478
84479         window.setTimeout(function () {
84480             if (privateData.remove(key, value)) {
84481                 successCallback(reqId);
84482             } else if (errorCallback) {
84483                 errorCallback(reqId, new WebAPIError(errorcode.NOT_FOUND_ERR));
84484             }
84485         }, 1);
84486     }
84487
84488     function getValue(reqId, key, successCallback, errorCallback) {
84489         if (!_security.getValue) {
84490             throw new WebAPIException(errorcode.SECURITY_ERR);
84491         }
84492
84493         t.MappedDataControlConsumer("getValue", arguments);
84494
84495         window.setTimeout(function () {
84496             var values;
84497
84498             values = privateData.search(key);
84499
84500             if (values !== null) {
84501                 successCallback(values, reqId);
84502             } else if (errorCallback) {
84503                 errorCallback(reqId, new WebAPIError(errorcode.NOT_FOUND_ERR));
84504             }
84505         }, 1);
84506     }
84507
84508     function updateValue(reqId, key, oldValue, newValue, successCallback,
84509             errorCallback) {
84510         if (!_security.updateValue) {
84511             throw new WebAPIException(errorcode.SECURITY_ERR);
84512         }
84513
84514         t.MappedDataControlConsumer("updateValue", arguments);
84515
84516         window.setTimeout(function () {
84517             if (privateData.update(key, oldValue, newValue)) {
84518                 successCallback(reqId);
84519             } else if (errorCallback) {
84520                 errorCallback(reqId, new WebAPIError(errorcode.NOT_FOUND_ERR));
84521             }
84522         }, 1);
84523     }
84524
84525     self = new DataControlConsumerObject("MAP", providerId, dataId);
84526
84527     self.addValue    = addValue;
84528     self.removeValue = removeValue;
84529     self.getValue    = getValue;
84530     self.updateValue = updateValue;
84531
84532     return self;
84533 };
84534
84535 DataControlConsumerFactory = function (type, providerId, dataId, dc) {
84536     var self;
84537
84538     switch (type) {
84539     case "SQL":
84540         self = new SQLDataControlConsumer(providerId, dataId, dc);
84541         break;
84542
84543     case "MAP":
84544         self = new MappedDataControlConsumer(providerId, dataId, dc);
84545         break;
84546     }
84547
84548     return self;
84549 };
84550
84551 SQLData = function (dc) {
84552     var self, data, columnNames, SQLErr2WebAPIErr;
84553
84554     // private
84555     function getDBTableName() {
84556         return "DC_" + Math.uuid(8, 16);
84557     }
84558
84559     function getColumnNames(tx, results) {
84560         columnNames = results.rows.item(0).sql
84561                 .replace(/^[^\(]+\(([^\)]+)\)/g, "$1")
84562                 .replace(/(^|(,) )([^ ,]+)([^,]*|$)/g, "$2$3")
84563                 .split(",");
84564     }
84565
84566     function queryColumns(columns) {
84567         return columns.join("=?,") + "=?";
84568     }
84569
84570     function queryValues(n) {
84571         return (new Array(n)).join("?,") + "?";
84572     }
84573
84574     function shedQuotes(values) {
84575         return values.every(function (value, i, arr) {
84576             arr[i] = value.replace(/^('|")(.*)\1$/g, "$2");
84577
84578             return (arr[i] !== value);
84579         });
84580     }
84581
84582     function isNull(p) {
84583         return ((p === undefined) || (p === null));
84584     }
84585
84586     function initialize() {
84587         SQLErr2WebAPIErr = [
84588             0,      // 0: UNKNOWN_ERR         0: UNKNOWN_ERR
84589             100,    // 1: DATABASE_ERR      100: IO_ERR
84590             100,    // 2: VERSION_ERR       100: IO_ERR
84591             100,    // 3: TOO_LARGE_ERR     100: IO_ERR
84592             22,     // 4: QUOTA_ERR          22: QUOTA_EXCEEDED_ERR
84593             12,     // 5: SYNTAX_ERR         12: SYNTAX_ERR
84594             100,    // 6: CONSTRAINT_ERR    100: IO_ERR
84595             23      // 7: TIMEOUT_ERR        23: TIMEOUT_ERR
84596         ];
84597
84598         if (!("table" in dc)) {
84599             dc.table = getDBTableName();
84600             columnNames = ["id"];
84601             _save();
84602         }
84603
84604         data = openDatabase('tinyHippos', '1.0', 'tiny Hippos persistence',
84605                 2 * 1024 * 1024);
84606
84607         data.transaction(function (tx) {
84608             tx.executeSql('CREATE TABLE IF NOT EXISTS ' + dc.table +
84609                     ' (id unique)');
84610             tx.executeSql('SELECT sql FROM sqlite_master WHERE type="table" AND name=?',
84611                     [dc.table], getColumnNames);
84612         });
84613     }
84614
84615     // public
84616     function insert(rowData, onSuccess, onError) {
84617         if (rowData.columns.length > rowData.values.length) {
84618             throw new WebAPIException(errorcode.INVALID_VALUES_ERR);
84619         }
84620         if (!shedQuotes(rowData.values)) {
84621             throw new WebAPIException(errorcode.INVALID_VALUES_ERR);
84622         }
84623
84624         data.transaction(function (tx) {
84625             rowData.columns.forEach(function (column) {
84626                 if (columnNames.indexOf(column) !== -1)
84627                     return;
84628
84629                 tx.executeSql('ALTER TABLE ' + dc.table + ' ADD ' + column +
84630                         ' TEXT', [], function () {
84631                             columnNames.push(column);
84632                         }, function (tx, error) {
84633                             onError(new WebAPIError(
84634                                     SQLErr2WebAPIErr[error.code],
84635                                     error.message));
84636                         });
84637             });
84638
84639             tx.executeSql('INSERT INTO ' + dc.table + ' (' +
84640                     rowData.columns.join() + ') VALUES (' +
84641                     queryValues(rowData.values.length) + ')', rowData.values,
84642                     function (tx, results) {
84643                         onSuccess(results.insertId);
84644                     }, function (tx, error) {
84645                         onError(new WebAPIError(SQLErr2WebAPIErr[error.code],
84646                                 error.message));
84647                     });
84648         });
84649     }
84650
84651     function update(rowData, where, onSuccess, onError) {
84652         if (rowData.columns.length > rowData.values.length) {
84653             throw new WebAPIException(errorcode.INVALID_VALUES_ERR);
84654         }
84655         if (!shedQuotes(rowData.values)) {
84656             throw new WebAPIException(errorcode.INVALID_VALUES_ERR);
84657         }
84658
84659         data.transaction(function (tx) {
84660             tx.executeSql('UPDATE ' + dc.table + ' SET ' +
84661                     queryColumns(rowData.columns) + ' WHERE ' + where,
84662                     rowData.values, onSuccess, function (tx, error) {
84663                         onError(new WebAPIError(SQLErr2WebAPIErr[error.code],
84664                                 error.message));
84665                     });
84666         });
84667     }
84668
84669     function remove(where, onSuccess, onError) {
84670         data.transaction(function (tx) {
84671             tx.executeSql('DELETE FROM ' + dc.table + ' WHERE ' + where, [],
84672                     onSuccess, function (tx, error) {
84673                         onError(new WebAPIError(SQLErr2WebAPIErr[error.code],
84674                                 error.message));
84675                     });
84676         });
84677     }
84678
84679     function select(columns, where, onSuccess, onError, page, maxNumberPerPage) {
84680         if (isNull(page)) {
84681             page = 1;
84682         } else {
84683             if (page <= 0) {
84684                 throw new WebAPIException(errorcode.INVALID_VALUES_ERR);
84685             }
84686             page = parseInt(page, 10);
84687         }
84688
84689         if (isNull(maxNumberPerPage)) {
84690             if (page > 1) {
84691                 throw new WebAPIException(errorcode.INVALID_VALUES_ERR);
84692             }
84693         } else {
84694             if (maxNumberPerPage <= 0) {
84695                 throw new WebAPIException(errorcode.INVALID_VALUES_ERR);
84696             }
84697             maxNumberPerPage = parseInt(maxNumberPerPage, 10);
84698         }
84699
84700         data.transaction(function (tx) {
84701             tx.executeSql('SELECT ' + columns.join() + ' FROM ' + dc.table +
84702                     ' WHERE ' + where, [], function (tx, results) {
84703                         var rows = [], rowStart, rowData, r, c;
84704
84705                         rowStart = maxNumberPerPage ?
84706                             (page - 1) * maxNumberPerPage : 0;
84707
84708                         for (r = rowStart; r < results.rows.length; ++r) {
84709                             rowData = {
84710                                 columns: columns,
84711                                 values: []
84712                             };
84713                             for (c in columns) {
84714                                 rowData.values.push(results.rows
84715                                     .item(r)[columns[c]]);
84716                             }
84717                             rows.push(rowData);
84718
84719                             if (maxNumberPerPage && (--maxNumberPerPage === 0))
84720                                 break;
84721                         }
84722
84723                         onSuccess(rows);
84724                     }, function (tx, error) {
84725                         onError(new WebAPIError(SQLErr2WebAPIErr[error.code],
84726                                 error.message));
84727                     });
84728         });
84729     }
84730
84731     initialize();
84732
84733     self = {
84734         insert: insert,
84735         update: update,
84736         remove: remove,
84737         select: select
84738     };
84739
84740     return self;
84741 };
84742
84743 MappedData = function (dc) {
84744     var self, data = {}, ioStamp = 0;
84745
84746     // private
84747     function addNode(tree, arr, i) {
84748         var key, value;
84749
84750         if (typeof arr[i] === "string") {
84751             key = arr[i];
84752             value = 1;
84753         } else {
84754             key = arr[i][0];
84755             value = arr[i][1];
84756         }
84757         tree.insert(key, value);
84758     }
84759
84760     function bisearch(tree, arr, queue) {
84761         var start, end, mid;
84762
84763         if (queue.length === 0)
84764             return;
84765
84766         start = queue.shift();
84767         end = queue.shift();
84768
84769         if (start > end)
84770             return;
84771
84772         mid = start + parseInt((end - start) / 2, 10);
84773         addNode(tree, arr, mid);
84774         queue.push(start, mid - 1);
84775         queue.push(mid + 1, end);
84776     }
84777
84778     function build(arr) {
84779         var tree, mid, lTree = [], rTree = [];
84780
84781         tree = redblack.tree();
84782         mid = parseInt(arr.length / 2, 10);
84783         addNode(tree, arr, mid);
84784
84785         lTree.push(0, mid - 1);
84786         rTree.push(mid + 1, arr.length - 1);
84787
84788         while ((lTree.length > 0) || (rTree.length > 0)) {
84789             bisearch(tree, arr, lTree);
84790             bisearch(tree, arr, rTree);
84791         }
84792
84793         return tree;
84794     }
84795
84796     function initialize() {
84797         for (var key in dc) {
84798             data[key] = build(dc[key]);
84799         }
84800     }
84801
84802     function traverse(tree, key) {
84803         dc[key] = [];
84804         tree.forEach(function (count, value) {
84805             dc[key].push((count === 1) ? value : [value, count]);
84806         });
84807     }
84808
84809     function persist() {
84810         if (ioStamp !== 0) {
84811             window.clearTimeout(ioStamp);
84812         }
84813         ioStamp = window.setTimeout(function () {
84814             var key;
84815
84816             for (key in data) {
84817                 traverse(data[key], key);
84818             }
84819
84820             _save();
84821
84822             ioStamp = 0;
84823         }, _data.PERSIST_DELAY);
84824     }
84825
84826     // public
84827     function insert(key, value) {
84828         var tree, count;
84829
84830         if (!(key in data)) {
84831             data[key] = redblack.tree();
84832         }
84833
84834         tree = data[key];
84835
84836         if (!tree)
84837             return false;
84838
84839         count = tree.get(value);
84840         tree.insert(value, count ? (count + 1) : 1);
84841         persist();
84842
84843         return true;
84844     }
84845
84846     function remove(key, value) {
84847         var tree, count;
84848
84849         if (!(key in data))
84850             return false;
84851
84852         tree = data[key];
84853         count = tree.get(value);
84854         if (count === null)
84855             return false;
84856
84857         tree.delete(value);
84858
84859         if (tree.root === null) {
84860             delete data[key];
84861             if (key in dc) {
84862                 delete dc[key];
84863             }
84864         }
84865
84866         persist();
84867
84868         return true;
84869     }
84870
84871     function search(key) {
84872         var values = [], tree;
84873
84874         if (!(key in data))
84875             return null;
84876
84877         tree = data[key];
84878         tree.forEach(function (count, value) {
84879             while (count--) {
84880                 values.push(value);
84881             }
84882         });
84883
84884         return values;
84885     }
84886
84887     function update(key, oldValue, newValue) {
84888         var tree, count;
84889
84890         if (!(key in data))
84891             return false;
84892
84893         tree = data[key];
84894         count = tree.get(oldValue);
84895         if (count === null)
84896             return false;
84897
84898         tree.delete(oldValue);
84899         tree.insert(newValue, count);
84900         persist();
84901
84902         return true;
84903     }
84904
84905     initialize();
84906
84907     self = {
84908         insert: insert,
84909         remove: remove,
84910         search: search,
84911         update: update
84912     };
84913
84914     return self;
84915 };
84916
84917 _initialize();
84918
84919 module.exports = _self;
84920
84921 });
84922 define('ripple/platform/tizen/2.0/datasync', function (require, exports, module) {
84923 /*
84924  *  Copyright 2013 Intel Corporation
84925  *
84926  * Licensed under the Apache License, Version 2.0 (the "License");
84927  * you may not use this file except in compliance with the License.
84928  * You may obtain a copy of the License at
84929  *
84930  * http://www.apache.org/licenses/LICENSE-2.0
84931  *
84932  * Unless required by applicable law or agreed to in writing, software
84933  * distributed under the License is distributed on an "AS IS" BASIS,
84934  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
84935  * See the License for the specific language governing permissions and
84936  * limitations under the License.
84937  */
84938
84939 var db = require('ripple/db'),
84940     utils = require('ripple/utils'),
84941     ET = require('ripple/platform/tizen/2.0/syncml-js-lib/elementtree'),
84942     t = require('ripple/platform/tizen/2.0/typecast'),
84943     errorcode = require('ripple/platform/tizen/2.0/errorcode'),
84944     WebAPIError = require('ripple/platform/tizen/2.0/WebAPIError'),
84945     WebAPIException = require('ripple/platform/tizen/2.0/WebAPIException'),
84946     SyncInfoMod = require('ripple/platform/tizen/2.0/SyncInfo'),
84947     SyncServiceInfoMod = require('ripple/platform/tizen/2.0/SyncServiceInfo'),
84948     SyncProfileInfoMod = require('ripple/platform/tizen/2.0/SyncProfileInfo'),
84949     SyncStatistics = require('ripple/platform/tizen/2.0/SyncStatistics'),
84950     _data = {
84951         DB_DATASYNC_ITEMS: "tizen1-db-datasync-items",
84952         DB_DATASYNC_COUNTER: "tizen1-db-datasync-counter",
84953         MAX_PROFILE_NUMBER: 5,
84954         profile_num: 0,
84955         profiles: {},
84956         sync_accounts: {},
84957         service_accounts: {},
84958         item_counter: 1000,
84959         type_table: {
84960             "TWO_WAY": 1,
84961             "SLOW": 2,
84962             "ONE_WAY_FROM_CLIENT": 3,
84963             "REFRESH_FROM_CLIENT": 4,
84964             "ONE_WAY_FROM_SERVER": 5,
84965             "REFRESH_FROM_SERVER": 6
84966         },
84967         mode_table: {
84968             "TWO_WAY": 200,
84969             "SLOW": 201,
84970             "ONE_WAY_FROM_CLIENT": 202,
84971             "REFRESH_FROM_CLIENT": 203,
84972             "ONE_WAY_FROM_SERVER": 204,
84973             "REFRESH_FROM_SERVER": 205
84974         },
84975         items: {}
84976     },
84977     _security = {
84978         "http://tizen.org/privilege/datasync":
84979             ["add", "update", "remove", "getMaxProfilesNum", "getProfilesNum",
84980             "get", "getAll", "startSync", "stopSync", "getLastSyncStatistics"]
84981     },
84982     _self,
84983     syncml = {
84984         adapter: require('ripple/platform/tizen/2.0/syncml-js-lib/adapter'),
84985         agent: require('ripple/platform/tizen/2.0/syncml-js-lib/agent'),
84986         base64: require('ripple/platform/tizen/2.0/syncml-js-lib/base64'),
84987         codec:  require('ripple/platform/tizen/2.0/syncml-js-lib/codec'),
84988         common: require('ripple/platform/tizen/2.0/syncml-js-lib/common'),
84989         constant: require('ripple/platform/tizen/2.0/syncml-js-lib/constant'),
84990         context: require('ripple/platform/tizen/2.0/syncml-js-lib/context'),
84991         ctype: require('ripple/platform/tizen/2.0/syncml-js-lib/ctype'),
84992         devinfo: require('ripple/platform/tizen/2.0/syncml-js-lib/devinfo'),
84993         item: require('ripple/platform/tizen/2.0/syncml-js-lib/item'),
84994         localadapter: require('ripple/platform/tizen/2.0/syncml-js-lib/localadapter'),
84995         matcher: require('ripple/platform/tizen/2.0/syncml-js-lib/matcher'),
84996         protocol: require('ripple/platform/tizen/2.0/syncml-js-lib/protocol'),
84997         remoteadapter: require('ripple/platform/tizen/2.0/syncml-js-lib/remoteadapter'),
84998         router: require('ripple/platform/tizen/2.0/syncml-js-lib/router'),
84999         state: require('ripple/platform/tizen/2.0/syncml-js-lib/state'),
85000         storage: require('ripple/platform/tizen/2.0/syncml-js-lib/storage'),
85001         store: require('ripple/platform/tizen/2.0/syncml-js-lib/store'),
85002         synchronizer: require('ripple/platform/tizen/2.0/syncml-js-lib/synchronizer'),
85003         useragent: require('ripple/platform/tizen/2.0/syncml-js-lib/useragent')
85004     },
85005     TizenAgent;
85006
85007 function _get() {
85008     _data.item_counter = db.retrieveObject(_data.DB_DATASYNC_COUNTER) || 1000;
85009     _data.items = db.retrieveObject(_data.DB_DATASYNC_ITEMS) || {};
85010 }
85011
85012 function _save() {
85013     db.saveObject(_data.DB_DATASYNC_COUNTER, _data.item_counter);
85014     db.saveObject(_data.DB_DATASYNC_ITEMS, _data.items);
85015 }
85016
85017 TizenAgent = syncml.agent.Agent.extend({
85018     constructor: function() {
85019     },
85020     getContentTypes: function() {
85021         return [
85022             new syncml.ctype.ContentTypeInfo('text/x-vcard', '2.1',{preferred: true})
85023         ];
85024     },
85025     dumpsItem: function(item, contentType, version, cb) {
85026         var cdata = new ET.CdataElement(item.item);
85027         cb(null, cdata);
85028     },
85029     loadsItem: function(data, contentType, version, cb) {
85030         return cb(null, {item: data._node.textContent});
85031     },
85032     getAllItems: function(cb) {
85033         var items = [];
85034         utils.forEach(_data.items, function(contact) {
85035             items.push(contact);
85036         });
85037         return cb(null, items);
85038     },
85039     addItem: function(item, cb) {
85040         _data.item_counter++;
85041         item.id = _data.item_counter.toString();
85042         _data.items[item.id] = item;
85043         _save();
85044         return cb(null, item);
85045     },
85046     getItem: function(itemID, cb) {
85047         return cb(null, _data.items[itemID]);
85048     },
85049     replaceItem: function(item, reportChanges, cb) {
85050         _data.items[item.id] = item;
85051         _save();
85052         return cb(null, null);
85053     },
85054     deleteItem: function(itemID, cb) {
85055         delete _data.items[itemID];
85056         _save();
85057         return cb(null);
85058     }
85059 });
85060 function _initialize() {
85061     _data.agent = new TizenAgent();
85062     _get();
85063 }
85064
85065 _self = function () {
85066     var datasync;
85067
85068     // private
85069     function checkProfile(profile) {
85070         var sync_account;
85071
85072         if (!profile || Object.prototype.toString.call(profile) !== "[object Object]") {
85073             throw new WebAPIException(errorcode.TYPE_MISMATCH_ERR);
85074         }
85075
85076
85077         t.SyncProfileInfo(profile);
85078
85079         if (profile.serviceInfo &&
85080             Object.prototype.toString.call(profile.serviceInfo) !== "[object Array]") {
85081             throw new WebAPIException(errorcode.TYPE_MISMATCH_ERR);
85082         }
85083
85084         // check "type" if mode is "MANUAL"
85085         // check "interval" if mode is "PERIODIC"
85086         switch (profile.syncInfo.mode) {
85087         case "MANUAL":
85088             // (syncInfo.type) null is acceptable due to spec
85089             // Spec: 
85090             //    ...the sync type 'SHOULD' be specified. The default value is TWO_WAY
85091             if (profile.syncInfo.type) {
85092                 profile.syncInfo.type = t.SyncType(profile.syncInfo.type);
85093             }
85094             break;
85095         case "PERIODIC":
85096             // (syncInfo.interval) null is acceptable
85097             // Spec:
85098             //   .. The sync interval 'SHOULD' be provided. 
85099             //   Question: Spec don't tell the default value when interval is null
85100             if (profile.syncInfo.interval) {
85101                 profile.syncInfo.interval = t.SyncInterval(profile.syncInfo.interval);
85102             }
85103             break;
85104         }
85105         // check unreadable parameter: syncInfo (id/password)
85106         if (typeof profile.syncInfo.__syncInfoID__ !== "number") {
85107             throw new WebAPIError(errorcode.TYPE_MISMATCH_ERR);
85108         }
85109         sync_account = db.retrieveObject("save-syncinfo")[profile.syncInfo.__syncInfoID__];
85110         sync_account.id = t.DOMString(sync_account.id);
85111         sync_account.password = t.DOMString(sync_account.password);
85112     }
85113
85114     function createInternalProfile(profile) {
85115         var _profile, sync_account, service_accounts;
85116
85117         sync_account = db.retrieveObject("save-syncinfo")[profile.syncInfo.__syncInfoID__];
85118
85119         _profile = {
85120             profileName: profile.profileName,
85121             syncInfo: {
85122                 url:        profile.syncInfo.url,
85123                 id:         sync_account.id,
85124                 password:   sync_account.password,
85125                 mode:       profile.syncInfo.mode
85126             },
85127             serviceInfo: []
85128         };
85129
85130         switch (_profile.syncInfo.mode) {
85131         case "MANUAL":
85132             _profile.syncInfo.type = profile.syncInfo.type || "TWO_WAY";
85133             break;
85134         case "PERIODIC":
85135             //TODO: set 1_HOUR as default value
85136             _profile.interval = profile.syncInfo.interval || "1_HOUR";
85137             _profile.syncInfo.type = "TWO_WAY";
85138             break;
85139         case "PUSH":
85140             _profile.syncInfo.type = "TWO_WAY";
85141             break;
85142         }
85143
85144         if (profile.serviceInfo) {
85145             service_accounts = db.retrieveObject("save-syncserviceinfo");
85146             utils.forEach(profile.serviceInfo, function (service) {
85147                 _profile.serviceInfo.push({
85148                     enable:             service.enable,
85149                     serviceType:        service.serviceType,
85150                     serverDatabaseUri:  service.serverDatabaseUri,
85151                     id:                 service_accounts[service.__syncServiceInfoID__].id,
85152                     password:           service_accounts[service.__syncServiceInfoID__].password
85153                 });
85154             });
85155         }
85156
85157         return _profile;
85158     }
85159
85160     function createExternalProfile(profileId) {
85161         var profile, i, _syncinfo, _serviceinfo, p;
85162
85163         p = _data.profiles[profileId];
85164
85165         switch (p.syncInfo.mode) {
85166         case "MANUAL":
85167             _syncinfo = new SyncInfoMod(p.syncInfo.url, p.syncInfo.id, p.syncInfo.password, "MANUAL", p.syncInfo.type);
85168             _syncinfo.interval = null;
85169             break;
85170         case "PERIODIC":
85171             _syncinfo = new SyncInfoMod(p.syncInfo.url, p.syncInfo.id, p.syncInfo.password, "PERIODIC", p.syncInfo.interval);
85172             break;
85173         case "PUSH":
85174             _syncinfo = new SyncInfoMod(p.syncInfo.url, p.syncInfo.id, p.syncInfo.password, "PUSH");
85175             break;
85176         }
85177
85178         if (p.serviceInfo) {
85179             _serviceinfo = [];
85180             for (i in p.serviceInfo) {
85181                 var info;
85182                 info = new SyncServiceInfoMod(p.serviceInfo[i].enable,
85183                         p.serviceInfo[i].serviceType, p.serviceInfo[i].serverDatabaseUri,
85184                         p.serviceInfo[i].id, p.serviceInfo[i].password);
85185                 _serviceinfo.push(info);
85186             }
85187         }
85188
85189         profile = new SyncProfileInfoMod(p.profileName, _syncinfo, _serviceinfo);
85190         Object.defineProperty(profile, "profileId", {value: p.profileId, writable: false});
85191
85192         return profile;
85193     }
85194
85195     // public
85196     function add(profile) {
85197         var _profile;
85198
85199         if (!_security.add) {
85200             throw new WebAPIException(errorcode.SECURITY_ERR);
85201         }
85202
85203         checkProfile(profile);
85204         _profile = createInternalProfile(profile);
85205
85206         if (_data.profile_num > _data.MAX_PROFILE_NUMBER) {
85207             throw new WebAPIException(errorcode.QUOTA_EXCEEDED_ERR);
85208         }
85209
85210         _profile.profileId = Math.uuid(null, 16);
85211         _data.profiles[_profile.profileId] = _profile;
85212         _data.profile_num++;
85213
85214         Object.defineProperty(profile, "profileId", {value: _profile.profileId, writable: false});
85215     }
85216
85217     function update(profile) {
85218         var _profile;
85219         if (!_security.update) {
85220             throw new WebAPIException(errorcode.SECURITY_ERR);
85221         }
85222
85223         checkProfile(profile);
85224         _profile = createInternalProfile(profile);
85225
85226         if (!profile.profileId || !_data.profiles[profile.profileId]) {
85227             throw new WebAPIException(errorcode.NOT_FOUND_ERR);
85228         }
85229
85230         _profile.profileId = profile.profileId;
85231         _data.profiles[_profile.profileId] = _profile;
85232     }
85233
85234     function remove(profileId) {
85235         if (!_security.remove) {
85236             throw new WebAPIException(errorcode.SECURITY_ERR);
85237         }
85238
85239         profileId = t.DOMString(profileId);
85240
85241         if (!_data.profiles[profileId]) {
85242             throw new WebAPIException(errorcode.NOT_FOUND_ERR);
85243         }
85244
85245         delete _data.profiles[profileId];
85246         _data.profile_num--;
85247     }
85248
85249     function getMaxProfilesNum() {
85250         if (!_security.getMaxProfilesNum) {
85251             throw new WebAPIException(errorcode.SECURITY_ERR);
85252         }
85253
85254         return _data.MAX_PROFILE_NUMBER;
85255     }
85256
85257     function getProfilesNum() {
85258         if (!_security.getProfilesNum) {
85259             throw new WebAPIException(errorcode.SECURITY_ERR);
85260         }
85261
85262         return _data.profile_num;
85263     }
85264
85265     function get(profileId) {
85266         var profile;
85267         if (!_security.get) {
85268             throw new WebAPIException(errorcode.SECURITY_ERR);
85269         }
85270
85271         profileId = t.DOMString(profileId);
85272
85273         if (!_data.profiles[profileId]) {
85274             throw new WebAPIException(errorcode.NOT_FOUND_ERR);
85275         }
85276
85277         profile = createExternalProfile(profileId);
85278
85279         return profile;
85280     }
85281
85282     function getAll() {
85283         var profiles = [], i;
85284         if (!_security.getAll) {
85285             throw new WebAPIException(errorcode.SECURITY_ERR);
85286         }
85287
85288         for (i in _data.profiles) {
85289             profiles.push(createExternalProfile(_data.profiles[i].profileId));
85290         }
85291
85292         return profiles;
85293     }
85294
85295     function startSync(profileId, progressCallback) {
85296         var _profile, _stores, _routes, sync_peer;
85297         if (!_security.startSync) {
85298             throw new WebAPIException(errorcode.SECURITY_ERR);
85299         }
85300
85301         profileId = t.DOMString(profileId);
85302         if (arguments.length >= 2) {
85303             if (Object.prototype.toString.call(progressCallback) !== "[object Object]" ||
85304                 (progressCallback.hasOwnProperty("onprogress") &&
85305                  typeof progressCallback.onprogress !== "function") ||
85306                 (progressCallback.hasOwnProperty("oncompleted") &&
85307                  typeof progressCallback.oncompleted !== "function") ||
85308                 (progressCallback.hasOwnProperty("onstopped") &&
85309                  typeof progressCallback.onstopped !== "function") ||
85310                 (progressCallback.hasOwnProperty("onfailed") &&
85311                  typeof progressCallback.onfailed !== "function") ||
85312                 (!progressCallback.hasOwnProperty("onprogress") &&
85313                  !progressCallback.hasOwnProperty("oncompleted") &&
85314                  !progressCallback.hasOwnProperty("onstopped") &&
85315                  !progressCallback.hasOwnProperty("onfailed"))
85316                 ) {
85317                 throw new WebAPIException(errorcode.TYPE_MISMATCH_ERR);
85318             }
85319         }
85320
85321         if (!_data.profiles[profileId]) {
85322             throw new WebAPIException(errorcode.NOT_FOUND_ERR);
85323         }
85324         _data.profiles[profileId].stop_flag = false;
85325
85326         sync_peer = function(adapter, store, peer, type) {
85327             adapter.sync(peer, type, function(err, stats) {
85328                 var p, name, hereTotal, peerTotal;
85329                 p = _data.profiles[profileId];
85330                 if (p.stop_flag === true) {
85331                     p.syncStatistics =[{
85332                         syncStatus: "STOP",
85333                         serviceType:            p.serviceInfo[0].serviceType,
85334                         lastSyncTime:           new Date(),
85335                         serverToClientTotal:    0,
85336                         serverToClientAdded:    0,
85337                         serverToClientUpdated:  0,
85338                         serverToClientRemoved:  0,
85339                         clientToServerTotal:    0,
85340                         clientToServerAdded:    0,
85341                         clientToServerUpdated:  0,
85342                         clientToServerRemoved:  0
85343                     }];
85344                     p.stop_flag = false;
85345                     return;
85346                 }
85347                 if (err) {
85348                     if (progressCallback) {
85349                         if (progressCallback.onfailed) {
85350                             progressCallback.onfailed(profileId, new WebAPIError(errorcode.UNKNOWN_ERR));
85351                         }
85352                     }
85353                     p.syncStatistics =[{
85354                         syncStatus: "FAIL",
85355                         serviceType:            p.serviceInfo[0].serviceType,
85356                         lastSyncTime:           new Date(),
85357                         serverToClientTotal:    0,
85358                         serverToClientAdded:    0,
85359                         serverToClientUpdated:  0,
85360                         serverToClientRemoved:  0,
85361                         clientToServerTotal:    0,
85362                         clientToServerAdded:    0,
85363                         clientToServerUpdated:  0,
85364                         clientToServerRemoved:  0
85365                     }];
85366                     p.stop_flag = false;
85367                     return;
85368                 }
85369                 name = p.profileName + "-" + p.serviceInfo[0].serviceType;
85370                 hereTotal = stats[name].hereAdd + stats[name].hereDel + stats[name].hereMod;
85371                 peerTotal = stats[name].peerAdd + stats[name].peerDel + stats[name].peerMod;
85372                 p.syncStatistics =[{
85373                     syncStatus: "SUCCESS",
85374                     serviceType:            p.serviceInfo[0].serviceType,
85375                     lastSyncTime:           new Date(),
85376                     serverToClientTotal:    hereTotal,
85377                     serverToClientAdded:    stats[name].hereAdd,
85378                     serverToClientUpdated:  stats[name].hereMod,
85379                     serverToClientRemoved:  stats[name].hereDel,
85380                     clientToServerTotal:    peerTotal,
85381                     clientToServerAdded:    stats[name].peerAdd,
85382                     clientToServerUpdated:  stats[name].peerMod,
85383                     clientToServerRemoved:  stats[name].peerDel
85384                 }];
85385                 p.stop_flag = false;
85386
85387                 if (progressCallback) {
85388                     if (progressCallback.oncompleted) {
85389                         progressCallback.oncompleted(profileId);
85390                     }
85391                 }
85392             });
85393         };
85394         _profile = _data.profiles[profileId];
85395         _profile.context = new syncml.context.Context({prefix: "tizen-"});
85396         _stores = [];
85397         _routes = [];
85398         utils.forEach(_profile.serviceInfo, function(service) {
85399             var name = _profile.profileName + "-" + service.serviceType;
85400             _stores.push({
85401                 uri:            name,
85402                 displayName:    name,
85403                 maxGuidSize:    64,
85404                 maxObjSize:     4000000,
85405                 agent:          _data.agent
85406             });
85407             _routes.push([name, service.serverDatabaseUri]);
85408         });
85409         _profile.context.getEasyClientAdapter({
85410             displayName: "Tizen syncML adapter",
85411             devInfo: {
85412                 devID: "tizen-syncml-03",
85413                 devType: syncml.constant.DEVTYPE_WORKSTATION,
85414                 manufacturerName: "Tizen",
85415                 modelName: "tizen.syncml.client",
85416                 hierarchicalSync: false
85417             },
85418             stores: _stores,
85419             peer: {
85420                 url:        _profile.syncInfo.url,
85421                 username:   _profile.syncInfo.id,
85422                 password:   _profile.syncInfo.password
85423             },
85424             routes: _routes
85425         }, function(err, adapter, stores, peer) {
85426             if (err) {
85427                 console.log("[datasync.syncml] getEasyClientAdapter fail:", err);
85428                 return;
85429             }
85430             utils.forEach(stores, function(store) {
85431                 var args = {
85432                     data:       _data.mode_table[_profile.syncInfo.type],
85433                     source:     store.uri,
85434                     target:     _profile.serviceInfo[0].serverDatabaseUri,
85435                     nextAnchor: syncml.common.ts()
85436                 };
85437                 if (args.data === _data.mode_table["SLOW"]) {
85438                     args.lastAnchor = null;
85439                 } else if (peer.getStore(args.target)) {
85440                     args.lastAnchor = peer.getStore(args.target)._getBinding().localAnchor;
85441                 }
85442
85443                 db.saveObject("syncml-alert-args", args);
85444                 db.saveObject("syncml-first-flag", false);
85445                 sync_peer(adapter, store, peer, _data.type_table[_profile.syncInfo.type]);
85446             });
85447         });
85448
85449     }
85450
85451     function stopSync(profileId) {
85452         if (!_security.stopSync) {
85453             throw new WebAPIException(errorcode.SECURITY_ERR);
85454         }
85455
85456         profileId = t.DOMString(profileId);
85457
85458         if (!_data.profiles[profileId]) {
85459             throw new WebAPIException(errorcode.NOT_FOUND_ERR);
85460         }
85461
85462         _data.profiles[profileId].stop_flag = true;
85463     }
85464
85465     function getLastSyncStatistics(profileId) {
85466         var s, statistics = [], i;
85467         if (!_security.getLastSyncStatistics) {
85468             throw new WebAPIException(errorcode.SECURITY_ERR);
85469         }
85470
85471         profileId = t.DOMString(profileId);
85472
85473         if (!_data.profiles[profileId]) {
85474             throw new WebAPIException(errorcode.NOT_FOUND_ERR);
85475         }
85476
85477         s = _data.profiles[profileId].syncStatistics;
85478
85479         for (i in s) {
85480             statistics.push(
85481                 new SyncStatistics(s[i].syncStatus, s[i].serviceType, s[i].lastSyncTime,
85482                     s[i].serverToClientTotal, s[i].serverToClientAdded,
85483                     s[i].serverToClientUpdated, s[i].serverToClientRemoved,
85484                     s[i].clientToServerTotal, s[i].clientToServerAdded,
85485                     s[i].clientToServerUpdated, s[i].clientToServerRemoved)
85486             );
85487         }
85488
85489         return statistics;
85490     }
85491
85492     function handleSubFeatures(subFeatures) {
85493         var i, subFeature;
85494
85495         for (subFeature in subFeatures) {
85496             for (i in _security[subFeature]) {
85497                 _security[_security[subFeature][i]] = true;
85498             }
85499         }
85500     }
85501
85502     datasync = {
85503         add:                    add,
85504         update:                 update,
85505         remove:                 remove,
85506         getMaxProfilesNum:      getMaxProfilesNum,
85507         getProfilesNum:         getProfilesNum,
85508         get:                    get,
85509         getAll:                 getAll,
85510         startSync:              startSync,
85511         stopSync:               stopSync,
85512         getLastSyncStatistics:  getLastSyncStatistics,
85513         handleSubFeatures:      handleSubFeatures
85514     };
85515
85516     return datasync;
85517 };
85518
85519 _initialize();
85520
85521 module.exports = _self;
85522
85523 });
85524 define('ripple/platform/tizen/2.0/dbfs', function (require, exports, module) {
85525 /*
85526  *  Copyright 2011 Research In Motion Limited.
85527  *  Copyright 2012 Intel Corporation.
85528  *
85529  * Licensed under the Apache License, Version 2.0 (the "License");
85530  * you may not use this file except in compliance with the License.
85531  * You may obtain a copy of the License at
85532  *
85533  * http://www.apache.org/licenses/LICENSE-2.0
85534  *
85535  * Unless required by applicable law or agreed to in writing, software
85536  * distributed under the License is distributed on an "AS IS" BASIS,
85537  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
85538  * See the License for the specific language governing permissions and
85539  * limitations under the License.
85540  */
85541
85542 var db = require('ripple/db'),
85543     utils = require('ripple/utils'),
85544     _console = require('ripple/console'),
85545     _cache = {},
85546     _self;
85547
85548 function _get(path) {
85549     return path.replace(/^\//, '').split("/").reduce(function (obj, token) {
85550         return token === "" ? obj : ((obj && obj.children) ? obj.children[token] || null : null);
85551     }, _cache);
85552 }
85553
85554 function _getInfo(path) {
85555     var parent = ("/" + path.replace(/^\//, '').replace(/\/$/, '')).split("/"),
85556         name = parent.splice(parent.length - 1, 1).join("");
85557
85558     return {
85559         name: name,
85560         parent: parent.join("/") || "/"
85561     };
85562 }
85563
85564 function _set(path, obj) {
85565     var parent = _cache,
85566         tokens = path.replace(/^\//, '').split("/"),
85567         child = tokens.splice(tokens.length - 1, 1).join("");
85568
85569     tokens.forEach(function (token) {
85570         parent = parent.children[token];
85571     });
85572
85573     parent.children = parent.children || {};
85574     parent.children[child] = obj;
85575 }
85576
85577 function _delete(path) {
85578     var parent = _cache,
85579         tokens = path.replace(/^\//, '').split("/"),
85580         child = tokens.splice(tokens.length - 1, 1).join("");
85581
85582     tokens.forEach(function (token) {
85583         parent = parent.children[token];
85584     });
85585
85586     delete parent.children[child];
85587 }
85588
85589 function _save() {
85590     db.saveObject("tizen1-db-filesystem", _cache);
85591 }
85592
85593 function _walk(path, parent) {
85594     _self.ls(path, function (entries) {
85595         parent.children = parent.children || {};
85596
85597         entries.forEach(function (entry) {
85598             parent.children[entry.name] = entry;
85599
85600             if (entry.isDirectory) {
85601                 _walk(entry.fullPath, entry);
85602             } else {
85603                 /* after getting Date out of DB, Date will become
85604                    a string, so need to recast it back to Date */
85605                 if (entry.lastModifiedDate !== null && entry.lastModifiedDate !== undefined)
85606                     entry.lastModifiedDate = new Date(entry.lastModifiedDate);
85607                 if (entry.createdDate !== null && entry.createdDate !== undefined)
85608                     entry.createdDate = new Date(entry.createdDate);
85609
85610                 _self.read(entry.fullPath, function (data) {
85611                     parent.children[entry.name].data = data;
85612                 }, function (e) {
85613                     _console.error(e);
85614                 });
85615             }
85616         });
85617     }, function (e) {
85618         _console.error(e);
85619     });
85620 }
85621
85622 function _createPath(path) {
85623     var parts = path.replace(/^\//, '').split("/"),
85624         workflow = jWorkflow.order();
85625
85626     parts.forEach(function (part, index) {
85627         var dir = "/" + utils.copy(parts).splice(0, index + 1).join("/");
85628
85629         workflow.andThen(function (prev, baton) {
85630             baton.take();
85631             _self.mkdir(dir, baton.pass, baton.pass);
85632         });
85633     });
85634
85635     workflow.start();
85636 }
85637
85638 _self = {
85639     // The order is consistent with _virtualRoots in filesystem.js
85640     roots: ["/opt/documents", "/opt/images", "/opt/music", "/opt/videos", "/opt/downloads", "/home/user/appdata/simulatedapp/wgt-package", "/home/user/appdata/simulatedapp/wgt-private", "/home/user/appdata/simulatedapp/wgt-private-tmp", "/SDCard", "/opt/attachments"],
85641     initialize: function () {
85642         // TODO: Initialize at bootstrap and emulatorBridge.link
85643         _cache = db.retrieveObject("tizen1-db-filesystem") || {};
85644         // create real root paths if empty
85645         _self.roots.every(function (root) {
85646             _createPath(root);
85647             return true;
85648         });
85649         // build the file system cache so that we could access information synchronously
85650         _walk("/", _cache);
85651     },
85652     ls: function (path, success, error) {
85653         try {
85654             var dir = _get(path),
85655                 items = [];
85656
85657             if (dir) {
85658                 utils.forEach(dir.children, function (item) {
85659                     items.push(item);
85660                 });
85661             }
85662             else {
85663                 items = {};
85664             }
85665
85666             success(items);
85667         }
85668         catch (e) {
85669             e.code = 1;
85670             error(e);
85671         }
85672     },
85673     rm: function (path, success, error, options) {
85674         _delete(path);
85675         _save();
85676         success();
85677     },
85678     rmdir: function (path, success, error, options) {
85679         _delete(path);
85680         _save();
85681         success();
85682     },
85683     mkdir: function (path, success, error) {
85684         var entry = _get(path),
85685             info = _getInfo(path);
85686
85687         if (!entry) {
85688             _set(path, {
85689                 lastModifiedDate: new Date(),
85690                 createdDate: new Date(),
85691                 name: info.name,
85692                 isDirectory: true,
85693                 fullPath: path
85694             });
85695             entry = _get(path);
85696             _save();
85697         }
85698
85699         if (entry) {
85700             success(entry);
85701         }
85702         else {
85703             error({code: 1});
85704         }
85705     },
85706     mv: function (from, to, success, error) {
85707         try {
85708             var fromEntry = _get(from),
85709                 toInfo = _getInfo(to);
85710
85711             fromEntry.fullPath = to;
85712             fromEntry.name = toInfo.name;
85713
85714             _set(to, fromEntry);
85715             _delete(from);
85716             _save();
85717             success();
85718         }
85719         catch (e) {
85720             e.code = 1;
85721             error(e);
85722         }
85723     },
85724     touch: function (path, success, error) {
85725         var entry = _get(path),
85726             info  = _getInfo(path);
85727
85728         if (!entry) {
85729             _set(path, {
85730                 lastModifiedDate: new Date(),
85731                 createdDate: new Date(),
85732                 name: info.name,
85733                 isDirectory: false,
85734                 fullPath: path,
85735                 data: ""
85736             });
85737             entry = _get(path);
85738         }
85739         _save();
85740         success(entry);
85741     },
85742     cp: function (from, to, success, error) {
85743         try {
85744             var fromEntry = _get(from),
85745                 copied = utils.copy(fromEntry);
85746
85747             copied.name  = _getInfo(to).name;
85748             copied.fullPath = to;
85749             _set(to, copied);
85750             _save();
85751             success();
85752         }
85753         catch (e) {
85754             e.code = 1;
85755             error(e);
85756         }
85757     },
85758     stat: function (path, success, error) {
85759         var entry = _get(path);
85760
85761         if (entry) {
85762             success(entry);
85763         } else {
85764             error({code: 1});
85765         }
85766     },
85767     write: function (path, contents, success, error, options) {
85768         var entry = _get(path);
85769
85770         if (entry) {
85771             entry.lastModifiedDate = new Date();
85772             entry.data = contents;
85773             _save();
85774             success();
85775         } else {
85776             error({code: 1});
85777         }
85778
85779     },
85780     read: function (path, success, error) {
85781         var entry = _get(path);
85782
85783         if (entry) {
85784             success(utils.copy(entry.data));
85785         }
85786         else {
85787             error({code: 1});
85788         }
85789     }
85790 };
85791
85792 module.exports = _self;
85793
85794 });
85795 define('ripple/platform/tizen/2.0/dbinit', function (require, exports, module) {
85796 /*
85797  *  Copyright 2013 Intel Corporation.
85798  *
85799  * Licensed under the Apache License, Version 2.0 (the "License");
85800  * you may not use this file except in compliance with the License.
85801  * You may obtain a copy of the License at
85802  *
85803  * http://www.apache.org/licenses/LICENSE-2.0
85804  *
85805  * Unless required by applicable law or agreed to in writing, software
85806  * distributed under the License is distributed on an "AS IS" BASIS,
85807  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
85808  * See the License for the specific language governing permissions and
85809  * limitations under the License.
85810  */
85811
85812 var utils = require('ripple/utils'),
85813     dbfs = require('ripple/platform/tizen/2.0/dbfs'),
85814     exception = require('ripple/exception'),
85815     filesystem = require('ripple/platform/tizen/2.0/filesystem'),
85816     DBBuilder,
85817     Content,
85818     FileSystem,
85819     _data = {
85820         dbBuilder: null
85821     },
85822     _self = {};
85823
85824 function _initialize() {
85825     _data.dbBuilder = new DBBuilder();
85826
85827     _data.dbBuilder.register("FileSystem", FileSystem);
85828     _data.dbBuilder.register("Content", Content, "dbcontent.xml");
85829 }
85830
85831 DBBuilder = function () {
85832     var self;
85833
85834     // private
85835     function formatString(str) {
85836         return str.replace(/^\s+|[\t\n\r\v]+|\s+$/g, '').replace(/\s+/g, ' ');
85837     }
85838
85839     function getAttributeValue(attr, type) {
85840         var i, value;
85841
85842         if (("childNodes" in attr) && (typeof type !== 'object')) {
85843             value = [];
85844
85845             for (i in attr.childNodes) {
85846                 value.push(getAttributeValue(attr.childNodes[i], type));
85847             }
85848
85849             return value;
85850         }
85851
85852         switch (type) {
85853         case "Date":
85854             value = new Date(formatString(attr.textContent));
85855             break;
85856
85857         case "DOMString":
85858             value = formatString(attr.textContent);
85859             break;
85860
85861         case "Number":
85862             value = Number(formatString(attr.textContent));
85863             break;
85864
85865         default:
85866             if (("childNodes" in attr) && (typeof type === 'object')) {
85867                 value = {};
85868
85869                 for (i in attr.childNodes) {
85870                     value[attr.childNodes[i].nodeName] = getAttributeValue(
85871                         attr.childNodes[i], type[attr.childNodes[i].nodeName]);
85872                 }
85873             }
85874             break;
85875         }
85876
85877         return value;
85878     }
85879
85880     // public
85881     function register(type, Module, xmlFile) {
85882         _data[type] = new Module();
85883         _self[type] = _data[type].initdb(xmlFile);
85884     }
85885
85886     function build(obj, pattern) {
85887         var i, type, self = {};
85888
85889         for (i in obj.childNodes) {
85890             type = pattern[obj.childNodes[i].nodeName];
85891
85892             if (type && obj.childNodes[i]) {
85893                 self[obj.childNodes[i].nodeName] = getAttributeValue(
85894                     obj.childNodes[i], type);
85895             }
85896         }
85897
85898         return self;
85899     }
85900
85901     function parseXml(obj) {
85902         var i, res = {};
85903
85904         res.nodeName = obj.nodeName;
85905
85906         if (obj.childElementCount === 0) {
85907             res.textContent = obj.textContent;
85908         } else {
85909             res.childNodes = [];
85910
85911             for (i in obj.childNodes) {
85912                 if (obj.childNodes[i].attributes) {
85913                     res.childNodes.push(parseXml(obj.childNodes[i]));
85914                 }
85915             }
85916         }
85917
85918         return res;
85919     }
85920
85921     self = {
85922         register: register,
85923         build:    build,
85924         parseXml: parseXml
85925     };
85926
85927     return self;
85928 };
85929
85930 /*
85931  * FileSystem
85932  */
85933
85934 FileSystem = function () {
85935     var self;
85936
85937     // private
85938     function createPath(path) {
85939         var parts = path.replace(/^\//, '').split("/"),
85940             workflow = jWorkflow.order();
85941
85942         parts.forEach(function (part, index) {
85943             var dir = "/" + utils.copy(parts).splice(0, index + 1).join("/");
85944
85945             workflow.andThen(function (prev, baton) {
85946                 baton.take();
85947                 dbfs.mkdir(dir, baton.pass, baton.pass);
85948             });
85949         });
85950
85951         workflow.start();
85952     }
85953
85954     // public
85955     function initdb() {
85956         filesystem.resolve("images", function () {});
85957         filesystem.resolve("videos", function () {});
85958         filesystem.resolve("music", function () {});
85959
85960         return null;
85961     }
85962
85963     function createFile(uri) {
85964         var directoryURI;
85965
85966         directoryURI = uri.slice(0, uri.lastIndexOf('/') + 1);
85967         dbfs.stat(directoryURI, function () {}, function () {
85968             createPath(directoryURI);
85969         });
85970
85971         dbfs.touch(uri, function () {});
85972     }
85973
85974     self = {
85975         initdb: initdb,
85976         createFile: createFile
85977     };
85978
85979     return self;
85980 };
85981
85982 /*
85983  * Content
85984  */
85985
85986 Content = function () {
85987     var self, ImageContent, VideoContent, AudioContent,
85988         DirectoryContent, ContentFactory;
85989
85990     VideoContent = {
85991         editableAttributes: "DOMString",
85992         id:                 "DOMString",
85993         name:               "DOMString",
85994         type:               "DOMString",
85995         mimeType:           "DOMString",
85996         title:              "DOMString",
85997         contentURI:         "DOMString",
85998         thumbnailURIs:      "DOMString",
85999         releaseDate:        "Date",
86000         modifiedDate:       "Date",
86001         size:               "Number",
86002         description:        "DOMString",
86003         rating:             "Number",
86004
86005         geolocation:        {latitude: "Number", longtitude: "Number"},
86006         album:              "DOMString",
86007         artists:            "DOMString",
86008         duration:           "Number",
86009         width:              "Number",
86010         height:             "Number"
86011     };
86012
86013     AudioContent = {
86014         editableAttributes: "DOMString",
86015         id:                 "DOMString",
86016         name:               "DOMString",
86017         type:               "DOMString",
86018         mimeType:           "DOMString",
86019         title:              "DOMString",
86020         contentURI:         "DOMString",
86021         thumbnailURIs:      "DOMString",
86022         releaseDate:        "Date",
86023         modifiedDate:       "Date",
86024         size:               "Number",
86025         description:        "DOMString",
86026         rating:             "Number",
86027
86028         album:              "DOMString",
86029         genres:             "DOMString",
86030         artists:            "DOMString",
86031         composers:          "DOMString",
86032         lyrics:             {
86033             type:           "DOMString",
86034             timestamps:     "DOMString",
86035             texts:          "DOMString"
86036         },
86037         copyright:          "DOMString",
86038         bitrate:            "Number",
86039         trackNumber:        "Number",
86040         duration:           "Number"
86041     };
86042
86043     ImageContent = {
86044         editableAttributes: "DOMString",
86045         id:                 "DOMString",
86046         name:               "DOMString",
86047         type:               "DOMString",
86048         mimeType:           "DOMString",
86049         title:              "DOMString",
86050         contentURI:         "DOMString",
86051         thumbnailURIs:      "DOMString",
86052         releaseDate:        "Date",
86053         modifiedDate:       "Date",
86054         size:               "Number",
86055         description:        "DOMString",
86056         rating:             "Number",
86057
86058         geolocation:        {latitude: "Number", longtitude: "Number"},
86059         width:              "Number",
86060         height:             "Number",
86061         orientation:        "DOMString"
86062     };
86063
86064     DirectoryContent = {
86065         id:                 "DOMString",
86066         directoryURI:       "DOMString",
86067         title:              "DOMString",
86068         storageType:        "DOMString",
86069         modifiedDate:       "Date"
86070     };
86071
86072     ContentFactory = function (type) {
86073         var pattern;
86074
86075         switch (type) {
86076         case "video":
86077             pattern = VideoContent;
86078             break;
86079
86080         case "audio":
86081             pattern = AudioContent;
86082             break;
86083
86084         case "image":
86085             pattern = ImageContent;
86086             break;
86087
86088         case "directory":
86089             pattern = DirectoryContent;
86090             break;
86091         }
86092
86093         return pattern;
86094     };
86095
86096     // public
86097     function initdb(dbFileName) {
86098         var i, db, results, xmlHttp;
86099
86100         db = {
86101             contents:    [],
86102             directories: []
86103         };
86104
86105         try {
86106             if (!utils.appLocation())
86107                 return null;
86108
86109             xmlHttp = new XMLHttpRequest();
86110             xmlHttp.open("GET", utils.appLocation() + dbFileName, false);
86111             xmlHttp.send();
86112
86113             if (!xmlHttp.responseXML) {
86114                 xmlHttp.open("GET", "dbsamples/" + dbFileName, false);
86115                 xmlHttp.send();
86116             }
86117         } catch (e) {
86118             exception.handle(e);
86119         }
86120
86121         if (!xmlHttp.responseXML) {
86122             return db;
86123         }
86124
86125         results = _data.dbBuilder.parseXml(xmlHttp.responseXML.documentElement);
86126         results.childNodes[0].childNodes.forEach(function (node) {
86127             db.contents.push(_data.dbBuilder.build(node,
86128                 new ContentFactory(node.nodeName)));
86129         });
86130         results.childNodes[1].childNodes.forEach(function (node) {
86131             db.directories.push(_data.dbBuilder.build(node,
86132                 new ContentFactory(node.nodeName)));
86133         });
86134
86135         for (i in db.contents) {
86136             _data.FileSystem.createFile(db.contents[i].contentURI);
86137         }
86138
86139         return db;
86140     }
86141
86142     self = {
86143         initdb: initdb
86144     };
86145
86146     return self;
86147 };
86148
86149 _initialize();
86150
86151 module.exports = _self;
86152
86153 });
86154 define('ripple/platform/tizen/2.0/download', function (require, exports, module) {
86155 /*
86156  *  Copyright 2012 Intel Corporation.
86157  *
86158  * Licensed under the Apache License, Version 2.0 (the "License");
86159  * you may not use this file except in compliance with the License.
86160  * You may obtain a copy of the License at
86161  *
86162  * http://www.apache.org/licenses/LICENSE-2.0
86163  *
86164  * Unless required by applicable law or agreed to in writing, software
86165  * distributed under the License is distributed on an "AS IS" BASIS,
86166  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
86167  * See the License for the specific language governing permissions and
86168  * limitations under the License.
86169  */
86170 var db = require('ripple/db'),
86171     event = require('ripple/event'),
86172     errorcode = require('ripple/platform/tizen/2.0/errorcode'),
86173     filesystem = require('ripple/platform/tizen/2.0/filesystem'),
86174     WebAPIError = require('ripple/platform/tizen/2.0/WebAPIError'),
86175     WebAPIException = require('ripple/platform/tizen/2.0/WebAPIException'),
86176     DownloadRequest = require('ripple/platform/tizen/2.0/DownloadRequest'),
86177     DownloadState = {
86178         QUEUED: "QUEUED",
86179         DOWNLOADING: "DOWNLOADING",
86180         PAUSED: "PAUSED",
86181         CANCELED: "CANCELED",
86182         COMPLETED: "COMPLETED",
86183         FAILED: "FAILED"
86184     },
86185     _security = {
86186         "http://tizen.org/privilege/download": ["start"]
86187     },
86188     DB_DOWNLOAD_KEY = "tizen1-db-download",
86189     DownloadItem, _isInitialized = false, INTERVAL = 1000,
86190     _downloads = [], _resources = [], _self;
86191
86192 function _checkDownloadParamters(download, callback) {
86193     if (!download || !download.url) {
86194         throw new WebAPIException(errorcode.TYPE_MISMATCH_ERR);
86195     }
86196     _checkDownloadCallback (callback);
86197 }
86198
86199 function _checkDownloadCallback (callback) {
86200     var func = ['onprogress', 'onpaused', 'oncanceled',
86201                 'oncompleted', 'onfailed'];
86202
86203     if (callback) {
86204         func.forEach(function (name) {
86205             if (callback.hasOwnProperty(name) &&
86206                 typeof callback[name] !== 'function') {
86207                 throw new WebAPIException(errorcode.TYPE_MISMATCH_ERR);
86208             }
86209         });
86210     }
86211 }
86212
86213 function _initDownloadItem(download) {
86214     var url, index, isExist = false;
86215     url = download.url;
86216     if (download.destination === null) {
86217         download.destination = "downloads";
86218     }
86219     if (download.fileName === null) {
86220         index = url.lastIndexOf('\/') + 1;
86221         download.fileName = url.substring(index);
86222     }
86223     if (!_isInitialized) {
86224         initializeResource();
86225     }
86226     _resources.some(function (value) {
86227         if (value.url === url) {
86228             download.size           = Number(value.size);
86229             download.speed          = Number(value.speed);
86230             download.estimatedTime = Math.round(value.estimatedTime * 100) / 100;
86231             download.MIMEType       = value.MIMEType;
86232             isExist =  true;
86233             return;
86234         }
86235     });
86236     if (!isExist) {
86237         download.state = DownloadState.FAILED;
86238         _exec(download.callback, 'onfailed', download.id, new WebAPIError(errorcode.NOT_FOUND_ERR));
86239         return;
86240     }
86241     return download;
86242 }
86243
86244 function _exec(callback, name, downloadId, arg1, arg2) {
86245     if (callback === null) {
86246         return;
86247     }
86248     switch (name) {
86249     case "onprogress" :
86250         callback[name](downloadId, arg1, arg2);
86251         break;
86252     case "onpaused" :
86253         callback[name](downloadId);
86254         break;
86255     case "oncanceled" :
86256         callback[name](downloadId);
86257         break;
86258     case "oncompleted" :
86259         callback[name](downloadId, arg1);
86260         break;
86261     case "onfailed" :
86262         callback[name](downloadId, arg1);
86263         break;
86264     default:
86265         break;
86266     }
86267 }
86268
86269 function _getDownloadObjById(id) {
86270     var isFound = false, backObj;
86271     if (typeof id !== "number") {
86272         throw new WebAPIError(errorcode.TYPE_MISMATCH_ERR);
86273     }
86274     id = Number(id);
86275     _downloads.some(function (obj) {
86276         if (obj.id === id) {
86277             backObj = obj;
86278             isFound = true;
86279             return;
86280         }
86281     });
86282     if (!isFound) {
86283         throw new WebAPIError(errorcode.NOT_FOUND_ERR);
86284     }
86285     return backObj;
86286 }
86287
86288 function initializeResource() {
86289     _resources = db.retrieveObject(DB_DOWNLOAD_KEY);
86290     _isInitialized = true;
86291 }
86292
86293 function _saveFile(downloadObj, callback) {
86294     var name, path, content;
86295
86296     name = downloadObj.fileName;
86297     path = downloadObj.destination;
86298     content = 'size|' + downloadObj.size + ',speed|' + downloadObj.speed + ',url|' + downloadObj.url + ',estimatedTime|' + downloadObj.estimatedTime;
86299     function onsuccess(fs) {
86300         fs.write(content);
86301         fs.close();
86302     }
86303     function onerror(e) {
86304         _exec(downloadObj.callback, 'onfailed', downloadObj.id, e);
86305     }
86306     function rename(name) { //index.html==>index_1.html
86307         var index, c;
86308         index = name.lastIndexOf('.');
86309         if (index < 0) {
86310             index = name.length;
86311         }
86312         c = name.substr(index - 2, 1);
86313         if (c === '_') {
86314             name = name.substr(0, index - 1) + (Number(name.substr(index - 1, 1)) + 1) + name.substring(index);
86315         } else {
86316             name = name.substr(0, index) + "_1" + name.substring(index);
86317         }
86318         return name;
86319     }
86320
86321     filesystem.resolve(path, function (dir) {
86322         var file, isExist = true;
86323         while (isExist) {
86324             try {
86325                 file = dir.resolve(name);
86326                 name = rename(name);
86327             } catch (e) {
86328                 isExist = false;
86329             }
86330         }
86331         file = dir.createFile(name);
86332         file.openStream('w', onsuccess, onerror, 'UTF-8');
86333         callback(name);
86334     }, onerror, "rw");
86335 }
86336
86337 DownloadItem = function (download, callback) {
86338     var _self;
86339     _self = {
86340         id           : Number(Math.uuid(8, 10)),
86341         url          : download.url,
86342         state        : DownloadState.QUEUED,
86343         fileName     : download.fileName || null,
86344         destination  : download.destination || null,
86345         callback     : callback || null
86346     };
86347     return _self;
86348 };
86349
86350 _self = function () {
86351     function start(downloadRequest, downloadCallback) {
86352         if (!_security.all && !_security.start) {
86353             throw new WebAPIError(errorcode.SECURITY_ERR);
86354         }
86355         var downloadObj, fileSize, increment, receivedSize = 0, intervalId;
86356
86357         _checkDownloadParamters(downloadRequest, downloadCallback);
86358         downloadObj = new DownloadItem(downloadRequest, downloadCallback);
86359         _downloads.push(downloadObj);
86360         downloadObj = _initDownloadItem(downloadObj);
86361         if (downloadObj === null || downloadObj === undefined) {
86362             return;
86363         }
86364         downloadObj.state = DownloadState.DOWNLOADING;
86365
86366         fileSize = downloadObj.size;
86367         increment = downloadObj.speed;
86368         intervalId = setInterval(function () {
86369             if (receivedSize >= fileSize) {//Finish downloading
86370                 receivedSize = fileSize;
86371                 downloadObj.state = DownloadState.COMPLETED;
86372                 _saveFile(downloadObj, function (fileName) {
86373                     _exec(downloadObj.callback, 'oncompleted', downloadObj.id, fileName);
86374                 });
86375                 clearInterval(intervalId);
86376             } else { // Continue downloading
86377                 receivedSize += increment;
86378                 downloadObj.receivedSize = receivedSize;
86379                 _exec(downloadObj.callback, 'onprogress', downloadObj.id, receivedSize, fileSize);
86380             }
86381         }, INTERVAL);
86382         downloadObj.intervalId = intervalId;
86383         return downloadObj.id;
86384     }
86385
86386     function cancel(downloadId) {
86387         var downloadObj = _getDownloadObjById(downloadId);
86388         clearInterval(downloadObj.intervalId);
86389         if (downloadObj.state !== DownloadState.DOWNLOADING &&
86390             downloadObj.state !== DownloadState.PAUSED) {
86391             _exec(downloadObj.callback, 'onfailed', downloadObj.id, new WebAPIError(errorcode.INVALID_VALUES_ERR));
86392             return;
86393         }
86394         downloadObj.state = DownloadState.CANCELED;
86395         _exec(downloadObj.callback, 'oncanceled', downloadObj.id);
86396     }
86397
86398     function pause(downloadId) {
86399         var downloadObj = _getDownloadObjById(downloadId);
86400         clearInterval(downloadObj.intervalId);
86401         if (downloadObj.state !== DownloadState.DOWNLOADING) {
86402             _exec(downloadObj.callback, 'onfailed', downloadObj.id, new WebAPIError(errorcode.INVALID_VALUES_ERR));
86403             return;
86404         }
86405         downloadObj.state = DownloadState.PAUSED;
86406         _exec(downloadObj.callback, 'onpaused', downloadObj.id);
86407     }
86408
86409     function resume(downloadId) {
86410         var downloadObj, fileSize, receivedSize, increment, intervalId;
86411
86412         downloadObj  = _getDownloadObjById(downloadId);
86413         fileSize     = downloadObj.size;
86414         receivedSize = downloadObj.receivedSize;
86415         increment    = downloadObj.speed;
86416
86417         if (downloadObj.state !== DownloadState.PAUSED) {
86418             _exec(downloadObj.callback, 'onfailed', downloadObj.id, new WebAPIError(errorcode.INVALID_VALUES_ERR));
86419             return;
86420         }
86421         downloadObj.state = DownloadState.DOWNLOADING;
86422         intervalId = setInterval(function () {
86423             if (receivedSize >= fileSize) {//Finish downloading
86424                 receivedSize = fileSize;
86425                 downloadObj.state = DownloadState.COMPLETED;
86426                 _saveFile(downloadObj, function (fileName) {
86427                     _exec(downloadObj.callback, 'oncompleted', downloadObj.id, fileName);
86428                 });
86429                 clearInterval(intervalId);
86430             } else {// Continue downloading
86431                 receivedSize += increment;
86432                 downloadObj.receivedSize = receivedSize;
86433                 _exec(downloadObj.callback, 'onprogress', downloadObj.id, receivedSize, fileSize);
86434             }
86435         }, INTERVAL);
86436         downloadObj.intervalId = intervalId;
86437     }
86438
86439     function getState(downloadId) {
86440         var downloadObj = _getDownloadObjById(downloadId);
86441         return downloadObj.state;
86442     }
86443
86444     function getDownloadRequest(downloadId) {
86445         var req, downloadObj;
86446         downloadObj = _getDownloadObjById(downloadId);
86447         req = new DownloadRequest(downloadObj.url, downloadObj.destination, downloadObj.fileName);
86448         return req;
86449     }
86450
86451     function getMIMEType(downloadId) {
86452         var downloadObj = _getDownloadObjById(downloadId);
86453         return downloadObj.MIMEType;
86454     }
86455
86456     function setListener(downloadId, callback) {
86457         var downloadObj = _getDownloadObjById(downloadId);
86458         if (downloadObj) {
86459             _checkDownloadCallback (callback);
86460             downloadObj.callback = callback;
86461         }
86462     }
86463
86464     function handleSubFeatures(subFeatures) {
86465         var i, subFeature;
86466
86467         for (subFeature in subFeatures) {
86468             for (i in _security[subFeature]) {
86469                 _security[_security[subFeature][i]] = true;
86470             }
86471         }
86472     }
86473
86474     var download = {
86475         start: start,
86476         cancel: cancel,
86477         pause: pause,
86478         resume: resume,
86479         getState: getState,
86480         getDownloadRequest: getDownloadRequest,
86481         getMIMEType: getMIMEType,
86482         setListener: setListener,
86483         handleSubFeatures : handleSubFeatures
86484     };
86485
86486     return download;
86487 };
86488
86489 event.on('downloadResourceChanged', function () {
86490     _isInitialized = false;
86491 });
86492 module.exports = _self;
86493
86494
86495 });
86496 define('ripple/platform/tizen/2.0/errorcode', function (require, exports, module) {
86497 /*
86498  *  Copyright 2011 Intel Corporation.
86499  *
86500  * Licensed under the Apache License, Version 2.0 (the "License"),
86501  * you may not use this file except in compliance with the License.
86502  * You may obtain a copy of the License at
86503  *
86504  * http://www.apache.org/licenses/LICENSE-2.0
86505  *
86506  * Unless required by applicable law or agreed to in writing, software
86507  * distributed under the License is distributed on an "AS IS" BASIS,
86508  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
86509  * See the License for the specific language governing permissions and
86510  * limitations under the License.
86511  */
86512
86513 var _self = {};
86514
86515 _self.__defineGetter__("UNKNOWN_ERR", function () {
86516     return 0;
86517 });
86518
86519 _self.__defineGetter__("INDEX_SIZE_ERR", function () {
86520     return 1;
86521 });
86522
86523 _self.__defineGetter__("DOMSTRING_SIZE_ERR", function () {
86524     return 2;
86525 });
86526
86527 _self.__defineGetter__("HIERARCHY_REQUEST_ERR", function () {
86528     return 3;
86529 });
86530
86531 _self.__defineGetter__("WRONG_DOCUMENT_ERR", function () {
86532     return 4;
86533 });
86534
86535 _self.__defineGetter__("INVALID_CHARACTER_ERR", function () {
86536     return 5;
86537 });
86538
86539 _self.__defineGetter__("NO_DATA_ALLOWED_ERR", function () {
86540     return 6;
86541 });
86542
86543 _self.__defineGetter__("NO_MODIFICATION_ALLOWED_ERR", function () {
86544     return 7;
86545 });
86546
86547 _self.__defineGetter__("NOT_FOUND_ERR", function () {
86548     return 8;
86549 });
86550
86551 _self.__defineGetter__("NOT_SUPPORTED_ERR", function () {
86552     return 9;
86553 });
86554
86555 _self.__defineGetter__("INUSE_ATTRIBUTE_ERR", function () {
86556     return 10;
86557 });
86558
86559 _self.__defineGetter__("INVALID_STATE_ERR", function () {
86560     return 11;
86561 });
86562
86563 _self.__defineGetter__("SYNTAX_ERR", function () {
86564     return 12;
86565 });
86566
86567 _self.__defineGetter__("INVALID_MODIFICATION_ERR", function () {
86568     return 13;
86569 });
86570
86571 _self.__defineGetter__("NAMESPACE_ERR", function () {
86572     return 14;
86573 });
86574
86575 _self.__defineGetter__("INVALID_ACCESS_ERR", function () {
86576     return 15;
86577 });
86578
86579 _self.__defineGetter__("VALIDATION_ERR", function () {
86580     return 16;
86581 });
86582
86583 _self.__defineGetter__("TYPE_MISMATCH_ERR", function () {
86584     return 17;
86585 });
86586
86587 _self.__defineGetter__("SECURITY_ERR", function () {
86588     return 18;
86589 });
86590
86591 _self.__defineGetter__("NETWORK_ERR", function () {
86592     return 19;
86593 });
86594
86595 _self.__defineGetter__("ABORT_ERR", function () {
86596     return 20;
86597 });
86598
86599 _self.__defineGetter__("URL_MISMATCH_ERR", function () {
86600     return 21;
86601 });
86602
86603 _self.__defineGetter__("QUOTA_EXCEEDED_ERR", function () {
86604     return 22;
86605 });
86606
86607 _self.__defineGetter__("TIMEOUT_ERR", function () {
86608     return 23;
86609 });
86610
86611 _self.__defineGetter__("INVALID_NODE_TYPE_ERR", function () {
86612     return 24;
86613 });
86614
86615 _self.__defineGetter__("DATA_CLONE_ERR", function () {
86616     return 25;
86617 });
86618
86619 _self.__defineGetter__("INVALID_VALUES_ERR", function () {
86620     return 99;
86621 });
86622
86623 _self.__defineGetter__("IO_ERR", function () {
86624     return 100;
86625 });
86626
86627 _self.__defineGetter__("SERVICE_NOT_AVAILABLE_ERR", function () {
86628     return 111;
86629 });
86630
86631 module.exports = _self;
86632
86633
86634 });
86635 define('ripple/platform/tizen/2.0/filesystem', function (require, exports, module) {
86636 /*
86637  *  Copyright 2012 Intel Corporation.
86638  *
86639  * Licensed under the Apache License, Version 2.0 (the "License");
86640  * you may not use this file except in compliance with the License.
86641  * You may obtain a copy of the License at
86642  *
86643  * http://www.apache.org/licenses/LICENSE-2.0
86644  *
86645  * Unless required by applicable law or agreed to in writing, software
86646  * distributed under the License is distributed on an "AS IS" BASIS,
86647  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
86648  * See the License for the specific language governing permissions and
86649  * limitations under the License.
86650  */
86651
86652 var event = require('ripple/event'),
86653     errorcode = require('ripple/platform/tizen/2.0/errorcode'),
86654     WebAPIError = require('ripple/platform/tizen/2.0/WebAPIError'),
86655     WebAPIException = require('ripple/platform/tizen/2.0/WebAPIException'),
86656     utils = require('ripple/utils'),
86657     dbfs  = require('ripple/platform/tizen/2.0/dbfs'),
86658     tizen1_utils = require('ripple/platform/tizen/2.0/tizen1_utils'),
86659     _maxPathLength = 256,
86660     _virtualRoots = ["documents", "images", "music", "videos", "downloads", "wgt-package", "wgt-private", "wgt-private-tmp", "removable", "attachments"],
86661     _security = {
86662         "http://tizen.org/privilege/filesystem": [],
86663         "http://tizen.org/privilege/filesystem.read": ["copyTo", "moveTo", "createDirectory", "createFile", "deleteDirectory", "deleteFile", "openStreamR"],
86664         "http://tizen.org/privilege/filesystem.write": ["readAsText", "openStreamW"],
86665         all: true
86666     },
86667     _realRoots = dbfs.roots,
86668     _r2vmap = {},
86669     _v2rmap = {},
86670     _initialized = false,
86671     _readOnly  = false,
86672     _writeOnly = false,
86673     _defaultMode = "rw",
86674     _storages = [], // filesystem storages
86675     _observers = [],
86676     File,
86677     FileStream,
86678     FileFilter,
86679     FileSystemStorage;
86680
86681 function _isValidChar(c) {
86682     return  (c >= '0' && c <= '9') ||
86683         (c >= 'a' && c <= 'z') ||
86684         (c >= 'A' && c <= 'Z') ||
86685         (c === ' ') ||
86686         (c === '_') ||
86687         (c === '-') ||
86688         (c === '.');
86689 }
86690
86691 function _isValidFileName(name) {
86692     var _valid = true,
86693         _c;
86694
86695     if (name === '' || name === '.' || name === '..' || (name.length > _maxPathLength)) {
86696         _valid = false;
86697     } else {
86698         for (_c = 0; _c < name.length; _c++) {
86699             if (!_isValidChar(name[_c])) {
86700                 _valid = false;
86701                 break;
86702             }
86703         }
86704     }
86705
86706     return _valid;
86707 }
86708
86709 function _initialize() {
86710     var _i;
86711
86712     _storages.push(FileSystemStorage("InternalFlash", "INTERNAL", "MOUNTED" ));
86713     _storages.push(FileSystemStorage("MMC", "EXTERNAL", "REMOVED"));
86714     dbfs.initialize();
86715
86716     // set up the map between real path and virtual path
86717     for (_i = 0; _i < _virtualRoots.length; _i++) {
86718         _r2vmap[_realRoots[_i]] = _virtualRoots[_i];
86719     }
86720
86721     utils.forEach(_r2vmap, function (value, key) {
86722         _v2rmap[value] = key;
86723     });
86724 }
86725
86726 function _resolveSync(srcLocation, onSuccess, onError, accessMode) {
86727     var _parts = srcLocation.replace(/\/$/, '').split("/"),
86728         _header, _fullPath,
86729         _i;
86730
86731     // TODO: Initialize at bootstrap and emulatorBridge.link
86732     if (!_initialized) {
86733         _initialize();
86734         _initialized = true;
86735     }
86736
86737     for (_i = 0; _i < _parts.length; _i++) {
86738         if (!_isValidFileName(_parts[_i])) {
86739             if (onError) {
86740                 onError(new WebAPIError(errorcode.INVALID_VALUES_ERR));
86741             }
86742             return;
86743         }
86744     }
86745
86746     _header = _v2rmap[_parts[0]];
86747     if (_header === undefined) {
86748         if (onError) {
86749             onError(new WebAPIError(errorcode.NOT_FOUND_ERR));
86750         }
86751         return;
86752     }
86753
86754     if (_parts.length === 1) {
86755         _fullPath = _header;
86756     } else {
86757         _fullPath = _header + "/" + _parts.splice(1, _parts.length - 1).join("/");
86758     }
86759
86760     dbfs.stat(_fullPath,
86761             function (entry) {
86762                 onSuccess(new File(entry, accessMode));
86763             },
86764             function () {
86765                 if (onError) {
86766                     onError(new WebAPIError(errorcode.NOT_FOUND_ERR));
86767                 }
86768             });
86769 }
86770
86771 function _resolveAsync(onSuccess, onError, srcLocation, accessMode) {
86772     _resolveSync(srcLocation,
86773                 function (file) {
86774                     setTimeout(function () {
86775                         onSuccess(file);
86776                     }, 1);
86777                 },
86778                 function (e) {
86779                     setTimeout(function () {
86780                         onError(e);
86781                     }, 1);
86782                 },
86783                 accessMode);
86784 }
86785
86786 File = function (entry, mode) {
86787     var _entry = entry,
86788         _mode = mode,
86789         _parent,
86790         _self;
86791
86792     function _r2v(rpath) {
86793         var i, v, r, regExp;
86794
86795         for (i = 0; i < _virtualRoots.length; i++) {
86796             v = _virtualRoots[i];
86797             r = _v2rmap[v];
86798             if (rpath.match("^" + r)) {
86799                 regExp = new RegExp("^" + r);
86800                 return rpath.replace(regExp, v);
86801             }
86802         }
86803
86804         return "";
86805     }
86806
86807     function _v2r(vpath) {
86808         var i, v, r, regExp;
86809
86810         for (i = 0; i < _virtualRoots.length; i++) {
86811             v = _virtualRoots[i];
86812             r = _v2rmap[v];
86813             if (vpath.match("^" + v)) {
86814                 regExp = new RegExp("^" + v);
86815                 return vpath.replace(regExp, r);
86816             }
86817         }
86818
86819         return "";
86820     }
86821
86822     function _copyMoveInternal(onSuccess, onError, src, dst, overwrite, func) {
86823         var _srcName = String(src),
86824             _dstName = String(dst),
86825             _src = null,
86826             _dst = null,
86827             _error = false,
86828             _dstParent = null,
86829             _dstParts  = _dstName.split("/"),
86830             _dstParentName = _dstParts.splice(0, _dstParts.length - 1).join("/");
86831
86832         if (!_entry.isDirectory) {
86833             if (onError) {
86834                 setTimeout(function () {
86835                     onError(new WebAPIError(errorcode.IO_ERR));
86836                 }, 1);
86837             }
86838             return undefined;
86839         }
86840
86841         _resolveSync(_srcName,
86842                 function (file) {
86843                     _src = file;
86844                 },
86845                 function (e) {
86846                     setTimeout(function () {
86847                         onError(e);
86848                     }, 1);
86849                 },
86850                 _mode);
86851
86852         if (_src) {
86853             if (_src.parent.fullPath === _self.fullPath) {
86854                 if (!_readOnly && _mode !== "r") {
86855                     _resolveSync(_dstParentName,
86856                             function (file) {
86857                                 _dstParent = file;
86858                             },
86859                             function (e) {
86860                                 setTimeout(function () {
86861                                     onError(e);
86862                                 }, 1);
86863                             },
86864                             _mode);
86865
86866                     if (_dstParent === null) {
86867                         return undefined;
86868                     }
86869
86870                     _resolveSync(_dstName,
86871                             function (file) {
86872                                 _dst = file;
86873                             },
86874                             function (e) {
86875                                 if (e.code !== errorcode.NOT_FOUND_ERR) {
86876                                     setTimeout(function () {
86877                                         onError(e);
86878                                     }, 1);
86879                                     _error = true;
86880                                 }
86881                             },
86882                             _mode);
86883
86884                     if (_error) {
86885                         return undefined;
86886                     }
86887
86888                     if (_src.isFile) {
86889                         if (_dst === null) {
86890                             func(_v2r(_srcName), _v2r(_dstName),
86891                                     function () {
86892                                         setTimeout(function () {
86893                                             onSuccess();
86894                                         }, 1);
86895                                     },
86896                                     function () {});
86897                             return null;
86898                         } else {
86899                             if (_dst.isFile && Boolean(overwrite) && (_srcName !== _dstName)) {
86900                                 func(_v2r(_srcName), _v2r(_dstName),
86901                                         function () {
86902                                             setTimeout(function () {
86903                                                 onSuccess();
86904                                             }, 1);
86905                                         },
86906                                         function () {});
86907                                 return null;
86908                             } else {
86909                                 setTimeout(function () {
86910                                     onError(new WebAPIError(errorcode.IO_ERR));
86911                                 }, 1);
86912                             }
86913                         }
86914                     } else {
86915                         if (_dst === null) {
86916                             func(_v2r(_srcName), _v2r(_dstName),
86917                                 function () {
86918                                     setTimeout(function () {
86919                                         onSuccess();
86920                                     }, 1);
86921                                 },
86922                                 function () {});
86923                             return null;
86924                         } else {
86925                             setTimeout(function () {
86926                                 onError(new WebAPIError(errorcode.IO_ERR));
86927                             }, 1);
86928                         }
86929                     }
86930                 } else {
86931                     if (onError) {
86932                         setTimeout(function () {
86933                             onError(new WebAPIError(errorcode.SECURITY_ERR));
86934                         }, 1);
86935                     }
86936                 }
86937             } else {
86938                 if (onError) {
86939                     setTimeout(function () {
86940                         onError(new WebAPIError(errorcode.IO_ERR));
86941                     }, 1);
86942                 }
86943             }
86944         }
86945
86946         return undefined;
86947     }
86948
86949     _self = {
86950         toURI: function () {
86951             return "file://" + _entry.fullPath;
86952         },
86953         listFiles: function (onSuccess, onError, filter) {
86954             var _filter, _filterName, _startCreated, _endCreated, _startModified, _endModified;
86955
86956             if (filter !== null && filter !== undefined) {
86957
86958                 if (typeof filter === 'number' || typeof filter === 'string') {
86959                     throw new WebAPIException(errorcode.TYPE_MISMATCH_ERR);
86960                 }
86961                 _filter = filter;
86962                 _filterName = _filter.name;
86963                 _startModified = _filter.startModified;
86964                 _endModified   = _filter.endModified;
86965                 _startCreated = _filter.startCreated;
86966                 _endCreated   = _filter.endCreated;
86967
86968             }
86969             if ((_filterName !== undefined && typeof _filterName !== 'string') ||
86970                 (_startModified !== undefined && !tizen1_utils.isValidDate(_startModified)) ||
86971                 (_endModified !== undefined && !tizen1_utils.isValidDate(_endModified)) ||
86972                 (_endCreated !== undefined && !tizen1_utils.isValidDate(_endCreated)) ||
86973                 (_startCreated !== undefined && !tizen1_utils.isValidDate(_startCreated))) {
86974                 throw new WebAPIException(errorcode.TYPE_MISMATCH_ERR);
86975             }
86976
86977             function _matchName(fileName) {
86978                 var _matched = true,
86979                     _name1 = String(_filterName).toLowerCase(),
86980                     _name2 = fileName.toLowerCase(),
86981                     _pattern;
86982
86983                 if (_filterName !== undefined && _filterName !== null) {
86984                     if (!_name1.match("\\\\%")) {
86985                         if (_name1.match("%")) {
86986                             _pattern = new RegExp("^" + _name1.replace(/%/g, ".*") + "$");
86987                             _matched = _name2.match(_pattern) ? true : false;
86988                         } else {
86989                             _matched = (_name1 === _name2);
86990                         }
86991                     } else {
86992                         // % is not allowed as a part of file name
86993                         _matched = false;
86994                     }
86995                 }
86996
86997                 return _matched;
86998             }
86999
87000             function _matchDate(date) {
87001                 var _matched = true;
87002
87003                 if (date === undefined) return true;
87004
87005                 if (_startModified !== undefined && _startModified !== null) {
87006                     _matched = (date.getTime() >= _startModified.getTime());
87007                 }
87008
87009                 if (_matched && (_endModified !== undefined && _endModified !== null)) {
87010                     _matched = (date.getTime() <= _endModified.getTime());
87011                 }
87012
87013                 return _matched;
87014             }
87015
87016             function _matchFilter(entry) {
87017                 return _matchName(entry.name) && _matchDate(entry.lastModifiedDate) && _matchDate(entry.createdDate);
87018             }
87019
87020             function _listFiles() {
87021                 var _files = [];
87022
87023                 if (!_entry.isDirectory) {
87024                     if (onError) {
87025                         setTimeout(function () {
87026                             onError(new WebAPIError(errorcode.IO_ERR));
87027                         }, 1);
87028                     }
87029                     return undefined;
87030                 }
87031
87032                 utils.forEach(_entry.children, function (child) {
87033                     if (_matchFilter(child)) {
87034                         _files.push(new File(child, _mode));
87035                     }
87036                 });
87037
87038                 setTimeout(function () {
87039                     onSuccess(_files);
87040                 }, 1);
87041
87042                 return null;
87043             }
87044
87045             return tizen1_utils.validateTypeMismatch(onSuccess, onError, "listFiles", _listFiles);
87046         },
87047         openStream: function (mode, onSuccess, onError, encoding) {
87048             function _openStream() {
87049                 var  _openMode = String(mode),
87050                     _encoding = encoding ? String(encoding) : "UTF-8";
87051
87052                 if (_openMode !== "r" && _openMode !== "w" && _openMode !== "a") {
87053                     if (onError) {
87054                         setTimeout(function () {
87055                             onError(new WebAPIError(errorcode.INVALID_VALUES_ERR));
87056                         }, 1);
87057                     }
87058                     return undefined;
87059                 }
87060
87061                 if (!_security.all && ((!_security.openStreamR && _openMode === "r") || (!_security.openStreamW && _openMode === "w"))) {
87062                     throw new WebAPIException(errorcode.SECURITY_ERR);
87063                 }
87064
87065                 if (_encoding !== "UTF-8" && _encoding !== "ISO-8859-1") {
87066                     if (onError) {
87067                         setTimeout(function () {
87068                             onError(new WebAPIError(errorcode.INVALID_VALUES_ERR));
87069                         }, 1);
87070                     }
87071                     return undefined;
87072                 }
87073
87074                 if (((_readOnly || _mode === "r") && (_openMode === "w" || _openMode === "a")) ||
87075                     (_writeOnly && _openMode === "r")) {
87076                     if (onError) {
87077                         setTimeout(function () {
87078                             onError(new WebAPIError(errorcode.SECURITY_ERR));
87079                         }, 1);
87080                     }
87081                     return undefined;
87082                 }
87083
87084                 setTimeout(function () {
87085                     onSuccess(new FileStream(_entry, _openMode, _encoding));
87086                 }, 1);
87087
87088                 return null;
87089             }
87090
87091             return tizen1_utils.validateTypeMismatch(onSuccess, onError, "openStream", _openStream);
87092         },
87093         readAsText: function (onSuccess, onError, encoding) {
87094             if (!_security.all && !_security.readAsText) {
87095                 throw new WebAPIException(errorcode.SECURITY_ERR);
87096             }
87097
87098             function _readAsText() {
87099                 var _encoding = encoding ? String(encoding) : "UTF-8";
87100                 if (_encoding !== "UTF-8" && _encoding !== "ISO-8859-1") {
87101                     if (onError) {
87102                         setTimeout(function () {
87103                             onError(new WebAPIError(errorcode.INVALID_VALUES_ERR));
87104                         }, 1);
87105                     }
87106                     return undefined;
87107                 }
87108
87109                 if (_writeOnly) {
87110                     if (onError) {
87111                         setTimeout(function () {
87112                             onError(new WebAPIError(errorcode.SECURITY_ERR));
87113                         }, 1);
87114                     }
87115                     return undefined;
87116                 }
87117
87118                 if (_self.isFile) {
87119                     dbfs.read(_entry.fullPath,
87120                             function (data) {
87121                                 setTimeout(function () {
87122                                     onSuccess(data);
87123                                 }, 1);
87124                             },
87125                             function () {});
87126                     return null;
87127                 } else {
87128                     if (onError) {
87129                         setTimeout(function () {
87130                             onError(new WebAPIError(errorcode.IO_ERR));
87131                         }, 1);
87132                     }
87133                 }
87134
87135                 return undefined;
87136             }
87137
87138             return tizen1_utils.validateTypeMismatch(onSuccess, onError, "readAsText", _readAsText);
87139         },
87140         copyTo: function (src, dst, overwrite, onSuccess, onError) {
87141             if (!_security.all && !_security.copyTo) {
87142                 throw new WebAPIException(errorcode.SECURITY_ERR);
87143             }
87144
87145             function _copyTo() {
87146                 return _copyMoveInternal(onSuccess, onError, src, dst, overwrite, dbfs.cp);
87147             }
87148
87149             return tizen1_utils.validateTypeMismatch(onSuccess, onError, "copyTo", _copyTo);
87150         },
87151         moveTo: function (src, dst, overwrite, onSuccess, onError) {
87152             if (!_security.all && !_security.moveTo) {
87153                 throw new WebAPIException(errorcode.SECURITY_ERR);
87154             }
87155
87156             function _moveTo() {
87157                 return _copyMoveInternal(onSuccess, onError, src, dst, overwrite, dbfs.mv);
87158             }
87159
87160             return tizen1_utils.validateTypeMismatch(onSuccess, onError, "moveTo", _moveTo);
87161         },
87162         createDirectory: function (dirPath) {
87163             var _path  = String(dirPath),
87164                 _parts = _path.replace(/\/$/, "").split("/"),
87165                 _dir   = null,
87166                 _exist = null,
87167                 _current = _entry.fullPath,
87168                 _i;
87169
87170             if (!_security.all && !_security.createDirectory) {
87171                 throw new WebAPIException(errorcode.SECURITY_ERR);
87172             }
87173
87174             function onSuccess(entry) {
87175                 _dir = entry;
87176             }
87177
87178             for (_i = 0; _i < _parts.length; _i++) {
87179                 if (!_isValidFileName(_parts[_i])) {
87180                     throw new WebAPIException(errorcode.INVALID_VALUES_ERR);
87181                 }
87182             }
87183
87184             if (!entry.isDirectory) {
87185                 throw new WebAPIException(errorcode.IO_ERR);
87186             }
87187
87188             _exist = _parts.reduce(function (obj, token) {
87189                 return token === "" ? obj : (obj.children ? obj.children[token] || null : null);
87190             }, _entry);
87191
87192             if (_exist) {
87193                 throw new WebAPIException(errorcode.IO_ERR);
87194             }
87195
87196             if (_readOnly || _mode === "r") {
87197                 throw new WebAPIException(errorcode.SECURITY_ERR);
87198             }
87199
87200             for (_i = 0; _i < _parts.length; _i++) {
87201                 _current = _current + "/" + _parts[_i];
87202                 dbfs.mkdir(_current, onSuccess);
87203             }
87204
87205             return new File(_dir, _mode);
87206         },
87207         createFile: function (filePath) {
87208             var _name = String(filePath),
87209                 _file = null;
87210
87211             if (!_security.all && !_security.createFile) {
87212                 throw new WebAPIException(errorcode.SECURITY_ERR);
87213             }
87214
87215             if (!_isValidFileName(_name)) {
87216                 throw new WebAPIException(errorcode.INVALID_VALUES_ERR);
87217             }
87218
87219             if (!entry.isDirectory || (_entry.children && _entry.children[_name])) {
87220                 throw new WebAPIException(errorcode.IO_ERR);
87221             }
87222
87223             if (_readOnly || _mode === "r") {
87224                 throw new WebAPIException(errorcode.SECURITY_ERR);
87225             }
87226
87227             dbfs.touch(_entry.fullPath + "/" + _name,
87228                         function (entry) {
87229                             _file = new File(entry, _mode);
87230                         },
87231                         function () {});
87232
87233             return _file;
87234         },
87235         resolve: function (filePath) {
87236             var _fullPath = _self.fullPath + "/" + String(filePath),
87237                 _file = null;
87238
87239             if (!_entry.isDirectory) {
87240                 throw new WebAPIException(errorcode.IO_ERR);
87241             }
87242
87243             _resolveSync(_fullPath,
87244                     function (file) {
87245                         _file = file;
87246                     },
87247                     function (e) {
87248                         throw (e);
87249                     },
87250                     _mode);
87251
87252             return _file;
87253         },
87254         deleteDirectory: function (directory, recursive, onSuccess, onError) {
87255             if (!_security.all && !_security.deleteDirectory) {
87256                 throw new WebAPIException(errorcode.SECURITY_ERR);
87257             }
87258
87259             function _deleteDirectory() {
87260                 var _dir = null,
87261                     _dirName = String(directory);
87262                 _resolveSync(_dirName,
87263                         function (file) {
87264                             _dir = file;
87265                         },
87266                         function (e) {
87267                             setTimeout(function () {
87268                                 onError(e);
87269                             }, 1);
87270                         },
87271                         _mode);
87272
87273                 if (_dir) {
87274                     if (_dir.isDirectory &&
87275                         _dir.parent.fullPath === _self.fullPath &&
87276                         (!recursive && _dir.length === 0)) {
87277                         if (!_readOnly && _mode !== "r") {
87278                             dbfs.rmdir(_v2r(_dirName),
87279                                     function () {
87280                                         setTimeout(function () {
87281                                             onSuccess();
87282                                         }, 1);
87283                                     },
87284                                     function () {});
87285                             return null;
87286                         } else {
87287                             if (onError) {
87288                                 setTimeout(function () {
87289                                     onError(new WebAPIError(errorcode.SECURITY_ERR));
87290                                 }, 1);
87291                             }
87292                         }
87293                     } else {
87294                         if (onError) {
87295                             setTimeout(function () {
87296                                 onError(new WebAPIError(errorcode.IO_ERR));
87297                             }, 1);
87298                         }
87299                     }
87300                 }
87301
87302                 return undefined;
87303             }
87304
87305             return tizen1_utils.validateTypeMismatch(onSuccess, onError, "deleteDirectory", _deleteDirectory);
87306         },
87307         deleteFile: function (fileName, onSuccess, onError) {
87308             if (!_security.all && !_security.deleteFile) {
87309                 throw new WebAPIException(errorcode.SECURITY_ERR);
87310             }
87311
87312             function _deleteFile() {
87313                 var _file = null;
87314                 _resolveSync(String(fileName),
87315                         function (file) {
87316                             _file = file;
87317                         },
87318                         function (e) {
87319                             if (onError) {
87320                                 setTimeout(function () {
87321                                     onError(e);
87322                                 }, 1);
87323                             }
87324                         },
87325                         _mode);
87326
87327                 if (_file) {
87328                     if (_file.isFile && _file.parent.fullPath === _self.fullPath) {
87329                         if (!_readOnly && _mode !== "r") {
87330                             dbfs.rm(_v2r(fileName),
87331                                     function () {
87332                                         setTimeout(function () {
87333                                             onSuccess();
87334                                         }, 1);
87335                                     },
87336                                     function () {});
87337                             return null;
87338                         } else {
87339                             if (onError) {
87340                                 setTimeout(function () {
87341                                     onError(new WebAPIError(errorcode.SECURITY_ERR));
87342                                 }, 1);
87343                             }
87344                         }
87345                     } else {
87346                         if (onError) {
87347                             setTimeout(function () {
87348                                 onError(new WebAPIError(errorcode.IO_ERR));
87349                             }, 1);
87350                         }
87351                     }
87352                 }
87353
87354                 return undefined;
87355             }
87356
87357             return tizen1_utils.validateTypeMismatch(onSuccess, onError, "deleteFile", _deleteFile);
87358         }
87359     };
87360
87361     _self.__defineGetter__("parent", function () {
87362         var _parts = _self.fullPath.split("/");
87363
87364         if (_parent === undefined) {
87365             if (_parts.length === 1) {
87366                 // virtual root's parent is null
87367                 _parent = null;
87368             } else {
87369                 _resolveSync(_parts.splice(0, _parts.length - 1).join("/"),
87370                         function (file) {
87371                             _parent = file;
87372                         },
87373                         function () {},
87374                         _mode);
87375             }
87376             return _parent;
87377         } else {
87378             return _parent;
87379         }
87380     });
87381
87382     _self.__defineGetter__("readOnly", function () {
87383         return false;
87384     });
87385
87386     _self.__defineGetter__("isFile", function () {
87387         return !_entry.isDirectory;
87388     });
87389
87390     _self.__defineGetter__("isDirectory", function () {
87391         return _entry.isDirectory;
87392     });
87393
87394     _self.__defineGetter__("created", function () {
87395         return _entry.createdDate;
87396     });
87397
87398     _self.__defineGetter__("modified", function () {
87399         return _entry.lastModifiedDate;
87400     });
87401
87402     _self.__defineGetter__("path", function () {
87403         var _parts = _self.fullPath.split("/");
87404
87405         if (_parts.length === 1) {
87406             // virtual root
87407             return _parts.join("");
87408         } else {
87409             return _parts.splice(0, _parts.length - 1).join("/") + "/";
87410         }
87411     });
87412
87413     _self.__defineGetter__("name", function () {
87414         return _entry.name;
87415     });
87416
87417     _self.__defineGetter__("fullPath", function () {
87418         return _r2v(_entry.fullPath);
87419     });
87420
87421     _self.__defineGetter__("fileSize", function () {
87422         if (_entry.isDirectory) {
87423             return undefined;
87424         } else {
87425             return _entry.data.length;
87426         }
87427     });
87428
87429     _self.__defineGetter__("length", function () {
87430         var _l = 0;
87431         if (_entry.isDirectory) {
87432             utils.forEach(_entry.children, function () {
87433                 _l++;
87434             });
87435             return _l;
87436         } else {
87437             return undefined;
87438         }
87439     });
87440
87441     return _self;
87442 };
87443
87444 FileStream = function (entry, mode, encoding) {
87445     var _entry = entry,
87446         _data = entry.data,
87447         _mode = mode,
87448         _position = (_mode === "a" ? _data.length : 0),
87449         _self;
87450
87451     _self = {
87452         close: function () {
87453             var _element;
87454             if (mode === "a" || mode === "w") {
87455                 dbfs.write(_entry.fullPath, _data, function () {}, function () {});
87456             }
87457             for (_element in _self) {
87458                 delete _self[_element];
87459             }
87460         },
87461         read: function (charCount) {
87462             var _count  = charCount | 0,
87463                 _substr = _data.substring(_position, _position + _count);
87464
87465             if (_position + _count > _data.length) {
87466                 _position = _data.length;
87467             } else {
87468                 _position += _count;
87469             }
87470
87471             return _substr;
87472         },
87473         readBytes: function (byteCount) {
87474             var _substr = _self.read(byteCount),
87475                 _bytes = [],
87476                 _i;
87477
87478             for (_i = 0; _i < _substr.length; _i++) {
87479                 _bytes.push(_substr.charCodeAt(_i));
87480             }
87481
87482             return _bytes;
87483         },
87484         readBase64: function (byteCount) {
87485             var _substr = _self.read(byteCount);
87486
87487             return window.atob(_substr);
87488         },
87489         write: function (stringData) {
87490             var _stringData = String(stringData),
87491                 _substr = _data.substring(0, _position);
87492
87493             _data = _substr.concat(_stringData);
87494             _position = _data.length;
87495         },
87496         writeBytes: function (byteData) {
87497             _self.write(String.fromCharCode.apply(String, byteData));
87498         },
87499         writeBase64: function (base64Data) {
87500             _self.write(window.btoa(String(base64Data)));
87501         }
87502     };
87503
87504     _self.__defineGetter__("eof", function () {
87505         return _position === _data.length;
87506     });
87507
87508     _self.__defineGetter__("position", function () {
87509         return _position;
87510     });
87511
87512     _self.__defineSetter__("position", function (value) {
87513         var _value = value | 0;
87514
87515         if (_value >= 0 && _value <= _data.length) {
87516             _position = _value;
87517         } else {
87518             throw new WebAPIException(errorcode.INVALID_VALUES_ERR);
87519         }
87520     });
87521
87522     _self.__defineGetter__("bytesAvailable", function () {
87523         return (_data.length - _position) || -1;
87524     });
87525
87526     return _self;
87527 };
87528
87529 FileFilter = function (name, startModified, endModified, startCreated, endCreated) {
87530     var _self = {
87531         name: name,
87532         startModified: utils.copy(startModified),
87533         endModified: utils.copy(endModified),
87534         endCreated: utils.copy(endCreated)
87535     };
87536
87537     return _self;
87538 };
87539
87540 FileSystemStorage = function (label, type, state) {
87541     var _self = {
87542         label: label,
87543         type: type,
87544         state: state
87545     };
87546
87547     return _self;
87548 };
87549
87550 module.exports = {
87551     maxPathLength: _maxPathLength,
87552     resolve: function (srcLocation, onSuccess, onError, accessMode) {
87553         function _resolve() {
87554             var _mode = accessMode ? String(accessMode) : _defaultMode;
87555
87556             if (_mode === "r" || _mode === "rw") {
87557                 _resolveAsync(onSuccess, onError, String(srcLocation), _mode);
87558                 return null;
87559             } else {
87560                 if (onError) {
87561                     setTimeout(function () {
87562                         onError(new WebAPIError(errorcode.INVALID_VALUES_ERR));
87563                     }, 1);
87564                 }
87565             }
87566             return undefined;
87567         }
87568
87569         return tizen1_utils.validateTypeMismatch(onSuccess, onError, "resolve", _resolve);
87570     },
87571
87572     getStorage: function (label, onSuccess, onError) {
87573         var storage = null, _label = String(label);
87574
87575         _storages.some(function (value) {
87576             if (value.label === _label) {
87577                 storage = utils.copy(value);
87578                 setTimeout(function () {
87579                     onSuccess(storage);
87580                 }, 1);
87581                 return true;
87582             }
87583         });
87584
87585         if (!storage) {
87586             if(onError) {
87587                 setTimeout(function () {
87588                     onError(new WebAPIError(errorcode.NOT_FOUND_ERR));
87589                 }, 1);
87590
87591             } else {
87592                 throw new WebAPIException(errorcode.NOT_FOUND_ERR);
87593             }
87594         }
87595     },
87596
87597     listStorages: function (onSuccess, onError) {
87598         function _listStorages() {
87599             setTimeout(function () {
87600                 onSuccess(utils.copy(_storages));
87601             }, 1);
87602         }
87603
87604         return tizen1_utils.validateTypeMismatch(onSuccess, onError, "listStorages", _listStorages);
87605     },
87606
87607     addStorageStateChangeListener: function(onSuccess, onError) {
87608         function _addStorageStateChangeListener() {
87609             var watchId = (new Date()).getTime() || 0;
87610                 _observers[watchId] = function(storage) {//storage is which state is changed
87611                 onSuccess(storage);
87612             };
87613
87614             // This event should be triggered from outside
87615             event.on("StateChange", _observers[watchId]);
87616             return Number(watchId);
87617         }
87618
87619         return tizen1_utils.validateTypeMismatch(onSuccess, onError, "addStorageStateChangeListener", _addStorageStateChangeListener);
87620     },
87621
87622     removeStorageStateChangeListener: function (watchId) {
87623         if (!watchId || typeof watchId !== "number") {
87624             throw new WebAPIException(errorcode.TYPE_MISMATCH_ERR);
87625         }
87626         watchId = String(watchId);
87627
87628         if (_observers[watchId]) {
87629             event.deleteEventHandler("StateChange", _observers[watchId]);
87630             delete _observers[watchId];
87631         } else {
87632             throw new WebAPIException(errorcode.INVALID_VALUES_ERR);
87633         }
87634     },
87635
87636     handleSubFeatures: function (subFeatures) {
87637         function setSecurity(_security) {
87638             return function (method) {
87639                 _security[method] = true;
87640             };
87641         }
87642
87643         for (var subFeature in subFeatures) {
87644             if (_security[subFeature].length === 0) {
87645                 _security.all = true;
87646                 return;
87647             }
87648             _security.all = false;
87649             utils.forEach(_security[subFeature], setSecurity);
87650         }
87651     }
87652 };
87653
87654
87655 });
87656 define('ripple/platform/tizen/2.0/geoBackend_local', function (require, exports, module) {
87657 /*
87658  *  Copyright 2012 Intel Corporation.
87659  *
87660  * Licensed under the Apache License, Version 2.0 (the "License");
87661  * you may not use this file except in compliance with the License.
87662  * You may obtain a copy of the License at
87663  *
87664  * http://www.apache.org/licenses/LICENSE-2.0
87665  *
87666  * Unless required by applicable law or agreed to in writing, software
87667  * distributed under the License is distributed on an "AS IS" BASIS,
87668  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
87669  * See the License for the specific language governing permissions and
87670  * limitations under the License.
87671  */
87672
87673 var db = require('ripple/db'),
87674     utils = require('ripple/utils'),
87675     lbs = require('ripple/platform/tizen/2.0/lbs_utils'),
87676     errorcode = require('ripple/platform/tizen/2.0/errorcode'),
87677     WebAPIError = require('ripple/platform/tizen/2.0/WebAPIError'),
87678     tizen1_utils = require('ripple/platform/tizen/2.0/tizen1_utils'),
87679     PendingObject = require('ripple/platform/tizen/2.0/pendingObject'),
87680     PendingOperation = require('ripple/platform/tizen/2.0/pendingoperation'),
87681     GeocodeResult = require('ripple/platform/tizen/2.0/GeocodeResult'),
87682     _GEO_OBJECTS = "tizen1.0-geocode-objects",
87683     _get, _save, _geoList_init, GeoEntry,
87684     _checkAddressType, _transAddressStr,
87685     _geocodeByString, _findCoordsByString, _geocodeByAddress,
87686     _reverseGeocodeBySimple, _reverseGeocodeByGeo, _checkCoordsType,
87687     _geoList = [],
87688     _PENDING_TIME = 10;
87689
87690 function _get() {
87691     var geoList = [],
87692         data = db.retrieveObject(_GEO_OBJECTS);
87693
87694     utils.forEach(data, function (geo) {
87695         geoList.push(geo);
87696     });
87697     return geoList;
87698 }
87699
87700 function _save() {
87701     db.saveObject(_GEO_OBJECTS, _geoList);
87702 }
87703
87704 function _geoList_init() {
87705     var entry;
87706     _geoList = _get();
87707
87708     /* Put some default data if database is empty */
87709     if (_geoList.length === 0) {
87710         entry = new GeoEntry(new lbs.StructuredAddress({
87711             country : "UK",
87712             region : "London",
87713             county : "Lambeth",
87714             city : "London",
87715             street : "Westminster Bridge Road",
87716             streetNumber : "1",
87717             premises : "Riverside Building",
87718             additionalInformation : "London Eye",
87719             postalCode : "SE1 7PB"
87720         }),
87721             new lbs.GeoCoordinates({
87722             latitude : 51.510452,
87723             longitude : -0.119820,
87724             altitude : 0,
87725             accuracy : 0,
87726             altitudeAccuracy : 0,
87727             heading : 0,
87728             speed : 0
87729         }));
87730         _geoList.push(entry);
87731         entry = new GeoEntry(new lbs.StructuredAddress({
87732             country : "UK",
87733             city : "London",
87734             street : "Baker Street",
87735             streetNumber : "221B",
87736             postalCode : "NW1 6XE"
87737         }),
87738             new lbs.GeoCoordinates({
87739             latitude : 51.524552,
87740             longitude : -0.158615,
87741             altitude : 0,
87742             accuracy : 0,
87743             altitudeAccuracy : 0,
87744             heading : 0,
87745             speed : 0
87746         }));
87747         _geoList.push(entry);
87748         entry = new GeoEntry(new lbs.StructuredAddress({
87749             country : "US",
87750             region : "OR",
87751             city : "Portland",
87752             street : "SE Water Ave",
87753             streetNumber : "1945",
87754             additionalInformation : "OMSI",
87755         }),
87756             new lbs.GeoCoordinates({
87757             latitude : 45.508490,
87758             longitude : -122.665953,
87759             altitude : 0,
87760             accuracy : 0,
87761             altitudeAccuracy : 0,
87762             heading : 0,
87763             speed : 0
87764         }));
87765         _geoList.push(entry);
87766         entry = new GeoEntry(new lbs.StructuredAddress({
87767             country : "US",
87768             region : "OR",
87769             city : "Portland",
87770             street : "NW Pittock Drive",
87771             streetNumber : "3229",
87772             additionalInformation : "Pittock Mansion",
87773         }),
87774             new lbs.GeoCoordinates({
87775             latitude : 45.531365,
87776             longitude : -122.716255,
87777             altitude : 0,
87778             accuracy : 0,
87779             altitudeAccuracy : 0,
87780             heading : 0,
87781             speed : 0
87782         }));
87783         _geoList.push(entry);
87784         entry = new GeoEntry(new lbs.StructuredAddress({
87785             region : "OR",
87786             city : "Hillsboro",
87787             street : "NE 25th St",
87788             streetNumber : "2111",
87789             postalCode : "97124"
87790         }),
87791             new lbs.GeoCoordinates({
87792             latitude : 45.543479,
87793             longitude : -122.9621601,
87794             altitude : 0,
87795             accuracy : 0,
87796             altitudeAccuracy : 0,
87797             heading : 0,
87798             speed : 0
87799         }));
87800         _geoList.push(entry);
87801         _save();
87802     }
87803 }
87804
87805 function _pendingOperate(operate) {
87806     var pendingObj, pendingOperation, i, argumentVector = [];
87807
87808     for (i = 0; i < arguments.length - 1; i++)
87809         argumentVector[i] = arguments[i + 1];
87810
87811     pendingObj = new PendingObject();
87812
87813     pendingObj.pendingID = window.setTimeout(function () {
87814         pendingObj.setCancelFlag(false);
87815         operate.apply(this, argumentVector);
87816     }, _PENDING_TIME);
87817
87818     pendingOperation = new PendingOperation(pendingObj);
87819
87820     return pendingOperation;
87821 }
87822
87823 function GeoEntry(addr, coord) {
87824     var _self;
87825     _self = {
87826         address : addr || null,
87827         coordinate : coord || null
87828     };
87829     return _self;
87830 }
87831
87832 function SortMode() {
87833     var _self;
87834     _self = {
87835         attributeName : "",
87836         order : "ASC"
87837     };
87838     return _self;
87839 }
87840
87841 function _transAddressStr(addr) {
87842     var str = "";
87843     if (addr.additionalInformation !== null && addr.additionalInformation !== undefined)
87844         str = str + addr.additionalInformation + ", ";
87845     if (addr.premises !== null && addr.premises !== undefined)
87846         str = str + addr.premises + ", ";
87847     if (addr.streetNumber !== null && addr.streetNumber !== undefined)
87848         str = str + addr.streetNumber + " ";
87849     if (addr.street !== null && addr.street !== undefined)
87850         str = str + addr.street + ", ";
87851     if (addr.city !== null && addr.city !== undefined)
87852         str = str + addr.city + ", ";
87853     if (addr.county !== null && addr.county !== undefined)
87854         str = str + addr.county + ", ";
87855     if (addr.region !== null && addr.region !== undefined)
87856         str = str + addr.region + ", ";
87857     if (addr.country !== null && addr.country !== undefined)
87858         str = str + addr.country + ", ";
87859     if (addr.postalCode !== null && addr.postalCode !== undefined)
87860         str = str + addr.postalCode;
87861
87862     if (str.lastIndexOf(", ") === str.length - 2)
87863         str = str.slice(0, -2);
87864     return str;
87865 }
87866
87867 function _concatAddress(addr) {
87868     var str = "";
87869     if (addr.additionalInformation !== null && addr.additionalInformation !== undefined)
87870         str = str + addr.additionalInformation + " ";
87871     if (addr.premises !== null && addr.premises !== undefined)
87872         str = str + addr.premises + " ";
87873     if (addr.streetNumber !== null && addr.streetNumber !== undefined)
87874         str = str + addr.streetNumber + " ";
87875     if (addr.street !== null && addr.street !== undefined)
87876         str = str + addr.street + " ";
87877     if (addr.city !== null && addr.city !== undefined)
87878         str = str + addr.city + " ";
87879     if (addr.county !== null && addr.county !== undefined)
87880         str = str + addr.county + " ";
87881     if (addr.region !== null && addr.region !== undefined)
87882         str = str + addr.region + " ";
87883     if (addr.country !== null && addr.country !== undefined)
87884         str = str + addr.country + " ";
87885     if (addr.postalCode !== null && addr.postalCode !== undefined)
87886         str = str + addr.postalCode;
87887
87888     return str;
87889 }
87890
87891 function _findCoordsByString(address) {
87892     var array = [], reg, str, searchAddr, pieces, i;
87893     if (address.length === 0)
87894         return array;
87895
87896     pieces = address.split(",");
87897     searchAddr = "";
87898     for (i = 0; i < pieces.length; i++) {
87899         searchAddr = searchAddr + pieces[i];
87900     }
87901     reg = new RegExp(searchAddr, "i");
87902
87903     utils.forEach(_geoList, function (item) {
87904         str = _concatAddress(item.address);
87905         if (str.search(reg) !== -1)
87906             array.push(new GeocodeResult(item.coordinate.latitude, item.coordinate.longitude));
87907     });
87908
87909     return array;
87910 }
87911
87912 function _geocodeByString(address, successCB, errorCB, options) {
87913     var array;
87914     array = _findCoordsByString(address);
87915     successCB(array);
87916 }
87917
87918 function _findCoordsByAddress(addr) {
87919     var array = [], select = false, i;
87920     for (i = 0; i < _geoList.length; i++) {
87921         select = false;
87922         if (addr.country !== null && addr.country !== undefined) {
87923             if (addr.country === _geoList[i].address.country)
87924                 select = true;
87925             else
87926                 continue;
87927         }
87928
87929         if (addr.region !== null && addr.region !== undefined) {
87930             if (addr.region === _geoList[i].address.region)
87931                 select = true;
87932             else
87933                 continue;
87934         }
87935
87936         if (addr.county !== null && addr.county !== undefined) {
87937             if (addr.county === _geoList[i].address.county)
87938                 select = true;
87939             else
87940                 continue;
87941         }
87942
87943         if (addr.city !== null && addr.city !== undefined) {
87944             if (addr.city === _geoList[i].address.city)
87945                 select = true;
87946             else
87947                 continue;
87948         }
87949
87950         if (addr.street !== null && addr.street !== undefined) {
87951             if (addr.street === _geoList[i].address.street)
87952                 select = true;
87953             else
87954                 continue;
87955         }
87956
87957         if (addr.streetNumber !== null && addr.streetNumber !== undefined) {
87958             if (addr.streetNumber === _geoList[i].address.streetNumber)
87959                 select = true;
87960             else
87961                 continue;
87962         }
87963
87964         if (addr.premises !== null && addr.premises !== undefined) {
87965             if (addr.premises === _geoList[i].address.premises)
87966                 select = true;
87967             else
87968                 continue;
87969         }
87970
87971         if (addr.additionalInformation !== null &&
87972             addr.additionalInformation !== undefined) {
87973             if (addr.additionalInformation === _geoList[i].address.additionalInformation)
87974                 select = true;
87975             else
87976                 continue;
87977         }
87978
87979         if (addr.postalCode !== null && addr.postalCode !== undefined) {
87980             if (addr.postalCode === _geoList[i].address.postalCode)
87981                 select = true;
87982             else
87983                 continue;
87984         }
87985
87986         if (select === true) {
87987             array.push(new GeocodeResult(_geoList[i].coordinate.latitude, _geoList[i].coordinate.longitude));
87988         }
87989     }
87990
87991     return array;
87992 }
87993
87994 function _geocodeByAddress(address, successCB, errorCB, options) {
87995     var array;
87996     array = _findCoordsByAddress(address);
87997     successCB(array);
87998 }
87999
88000 function _checkAddressType(address) {
88001     var str;
88002     if (typeof address === "string") {
88003         str = "string";
88004     } else if (typeof address === "object") {
88005         str = "StructuredAddress";
88006     } else {
88007         str = "typeMismatch";
88008     }
88009     return str;
88010 }
88011
88012 function _checkCoordsType(coord) {
88013     var str;
88014     /* SimpleCoordinates is a subset of GeoCoordinates.
88015        SimpleCoordinates includes latitude, longitude as mandatory fields only.
88016        GeoCoordinates not only includes latitude, longitude as mandatory fields
88017        but also at least includes one more other optional fields */
88018     if (typeof coord !== "object") {
88019         str = "typeMismatch";
88020     } else if (typeof coord.latitude === "number" &&
88021                 typeof coord.longitude === "number") {
88022         str = "simpleCoordinates";
88023         if (typeof coord.altitude === "number" ||
88024             typeof coord.accuracy === "number" ||
88025             typeof coord.altitudeAccuracy === "number" ||
88026             typeof coord.heading === "number" ||
88027             typeof coord.speed === "number") {
88028             str = "geoCoordinates";
88029         }
88030     } else {
88031         str = "typeMismatch";
88032     }
88033
88034     return str;
88035 }
88036
88037 function _findReverseGeocode(coords, options) {
88038     var array = [], _isStructured = false, i;
88039     if (options !== null && options !== undefined) {
88040         if (options.resultType === "STRUCTURED") {
88041             _isStructured = true;
88042         }
88043     }
88044     for (i = 0; i < _geoList.length; i++) {
88045         if (_geoList[i].coordinate.latitude === coords.latitude &&
88046             _geoList[i].coordinate.longitude === coords.longitude) {
88047             if (coords.altitude) {
88048                 if (_geoList[i].coordinate.altitude !== coords.altitude)
88049                     continue;
88050             }
88051             if (coords.accuracy) {
88052                 if (_geoList[i].coordinate.accuracy !== coords.accuracy)
88053                     continue;
88054             }
88055             if (coords.altitudeAccuracy) {
88056                 if (_geoList[i].coordinate.altitudeAccuracy !== coords.altitudeAccuracy)
88057                     continue;
88058             }
88059             if (coords.heading) {
88060                 if (_geoList[i].coordinate.heading !== coords.heading)
88061                     continue;
88062             }
88063             if (coords.speed) {
88064                 if (_geoList[i].coordinate.speed !== coords.speed)
88065                     continue;
88066             }
88067
88068             if (_isStructured === true) {
88069                 array.push(new lbs.StructuredAddress(_geoList[i].address));
88070             } else {
88071                 array.push(_transAddressStr(_geoList[i].address));
88072             }
88073         }
88074     }
88075     return array;
88076 }
88077
88078 function _reverseGeocodeByGeo(coordinates, successCB, errorCB, options) {
88079     var array, coord;
88080     coord = new lbs.GeoCoordinates(coordinates);
88081     array = _findReverseGeocode(coord, options);
88082     return successCB(array);
88083 }
88084
88085 function _reverseGeocodeBySimple(coordinates, successCB, errorCB, options) {
88086     var array, coord;
88087     coord = new lbs.GeoCoordinates({
88088             latitude : coordinates.latitude,
88089             longitude : coordinates.longitude
88090         });
88091     array = _findReverseGeocode(coord, options);
88092     return successCB(array);
88093 }
88094
88095 module.exports = function (prop) {
88096     var _self = new lbs.LocationServiceProvider(prop);
88097     _geoList_init();
88098
88099     _self.geocode = function (address, successCB, errorCB, options) {
88100         function _geocode() {
88101             var ret;
88102
88103             ret = _pendingOperate(function () {
88104                 /* address: its type is AbstractAddress.
88105                    It could be StructuredAddress or String */
88106                 if (_checkAddressType(address) === "string") {
88107                     _geocodeByString(address, successCB, errorCB, options);
88108                 } else if (_checkAddressType(address) === "StructuredAddress") {
88109                     _geocodeByAddress(address, successCB, errorCB, options);
88110                 } else {
88111                     throw (new WebAPIError(errorcode.TYPE_MISMATCH_ERR));
88112                 }
88113             });
88114         }
88115
88116         tizen1_utils.validateTypeMismatch(successCB, errorCB, "geocode", _geocode);
88117     };
88118
88119     _self.reverseGeocode = function (coordinates, successCB, errorCB, options) {
88120         function _reverseGeocode() {
88121             var ret;
88122
88123             ret = _pendingOperate(function () {
88124                 /* coordinates: Its type is AbstractCoordinates.
88125                    It could be SimpleCoordinates or GeoCoordinates */
88126                 if (_checkCoordsType(coordinates) === "simpleCoordinates") {
88127                     _reverseGeocodeBySimple(coordinates, successCB, errorCB, options);
88128                 } else if (_checkCoordsType(coordinates) === "geoCoordinates") {
88129                     _reverseGeocodeByGeo(coordinates, successCB, errorCB, options);
88130                 } else {
88131                     throw (new WebAPIError(errorcode.TYPE_MISMATCH_ERR));
88132                 }
88133             });
88134         }
88135
88136         tizen1_utils.validateTypeMismatch(successCB, errorCB, "reverseGeocode", _reverseGeocode);
88137     };
88138
88139     return _self;
88140 };
88141
88142
88143 });
88144 define('ripple/platform/tizen/2.0/geoBackend_nominatim', function (require, exports, module) {
88145 /*
88146  *  Copyright 2012 Intel Corporation.
88147  *
88148  * Licensed under the Apache License, Version 2.0 (the "License");
88149  * you may not use this file except in compliance with the License.
88150  * You may obtain a copy of the License at
88151  *
88152  * http://www.apache.org/licenses/LICENSE-2.0
88153  *
88154  * Unless required by applicable law or agreed to in writing, software
88155  * distributed under the License is distributed on an "AS IS" BASIS,
88156  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
88157  * See the License for the specific language governing permissions and
88158  * limitations under the License.
88159  */
88160
88161 var lbs = require('ripple/platform/tizen/2.0/lbs_utils'),
88162     errorcode = require('ripple/platform/tizen/2.0/errorcode'),
88163     WebAPIError = require('ripple/platform/tizen/2.0/WebAPIError'),
88164     tizen1_utils = require('ripple/platform/tizen/2.0/tizen1_utils'),
88165     GeocodeResult = require('ripple/platform/tizen/2.0/GeocodeResult');
88166
88167 function _concatAddrString(addr) {
88168     var ret = "", i, pieces;
88169     if (typeof addr === "string") {
88170         pieces = addr.split(" ");
88171         for (i = 0; i < pieces.length; i++) {
88172             ret = ret + pieces[i] + "+";
88173         }
88174     } else if (typeof addr === "object") {
88175         if (addr.premises !== null && addr.premises !== undefined) {
88176             ret = ret + addr.premises + "+";
88177         }
88178         if (addr.streetNumber !== null && addr.streetNumber !== undefined) {
88179             ret = ret + addr.streetNumber + "+";
88180         }
88181         if (addr.street !== null && addr.street !== undefined) {
88182             ret = ret + addr.street + "+";
88183         }
88184         if (addr.city !== null && addr.city !== undefined) {
88185             ret = ret + addr.city + "+";
88186         }
88187         if (addr.county !== null && addr.county !== undefined) {
88188             ret = ret + addr.county + "+";
88189         }
88190         if (addr.region !== null && addr.region !== undefined) {
88191             ret = ret + addr.region + "+";
88192         }
88193         if (addr.postalCode !== null && addr.postalCode !== undefined) {
88194             ret = ret + addr.postalCode + "+";
88195         }
88196         if (addr.country !== null && addr.country !== undefined) {
88197             ret = ret + addr.country + "+";
88198         }
88199     } else {
88200         return undefined;
88201     }
88202     ret = ret.slice(0, -1);
88203     return ret;
88204 }
88205
88206 module.exports = function (prop) {
88207     var _self = new lbs.LocationServiceProvider(prop);
88208
88209     _self.geocode = function (address, successCB, errorCB, options) {
88210         function _geocode() {
88211             var i, searchStr, coordinates = [], result;
88212
88213             searchStr = _concatAddrString(address);
88214             if (searchStr === undefined) {
88215                 throw (new WebAPIError(errorcode.TYPE_MISMATCH_ERR));
88216             }
88217             searchStr = "http://nominatim.openstreetmap.org/search?q=" + searchStr + "&format=json&polygon=1&addressdetails=1";
88218
88219             /* use nominatim online geo service. (http://nominatim.openstreetmap.org) */
88220             $.getJSON(searchStr, function (data) {
88221                 for (i = 0; i < data.length; i++) {
88222                     result = new GeocodeResult(parseFloat(data[i].lat), parseFloat(data[i].lon));
88223                     coordinates.push(result);
88224                 }
88225                 successCB(coordinates);
88226             }).error(function () {
88227                 if (errorCB) {
88228                     setTimeout(function () {
88229                         errorCB(new WebAPIError(errorcode.NETWORK_ERR));
88230                     }, 1);
88231                 }
88232             });
88233         }
88234
88235         tizen1_utils.validateTypeMismatch(successCB, errorCB, "geocode", _geocode);
88236     };
88237
88238     _self.reverseGeocode = function (coordinates, successCB, errorCB, options) {
88239         function _reverseGeocode() {
88240             var searchStr = "";
88241             if (typeof coordinates !== "object" ||
88242                 typeof coordinates.latitude !== "number" ||
88243                 typeof coordinates.longitude !== "number") {
88244                 throw (new WebAPIError(errorcode.TYPE_MISMATCH_ERR));
88245             }
88246             searchStr = "http://nominatim.openstreetmap.org/reverse?format=json&lat=" +
88247                         coordinates.latitude + "&lon=" + coordinates.longitude + "&zoom=18&addressdetails=1";
88248
88249             /* use nominatim online geo service. (http://nominatim.openstreetmap.org) */
88250             $.getJSON(searchStr, function (data) {
88251                 var addr;
88252
88253                 if (options && options.resultType === "STRUCTURED") {
88254                     addr = new lbs.StructuredAddress({
88255                         country : data.address.country,
88256                         region : data.address.state,
88257                         county : data.address.county,
88258                         city : data.address.city,
88259                         street : data.address.road,
88260                         streetNumber : data.address.streetNumber,
88261                         postalCode : data.address.postcode
88262                     });
88263                 } else {
88264                     addr = data.display_name;
88265                 }
88266                 successCB([addr]);
88267             }).error(function () {
88268                 if (errorCB) {
88269                     setTimeout(function () {
88270                         errorCB(new WebAPIError(errorcode.NETWORK_ERR));
88271                     }, 1);
88272                 }
88273             });
88274         }
88275
88276         tizen1_utils.validateTypeMismatch(successCB, errorCB, "reverseGeocode", _reverseGeocode);
88277     };
88278
88279     return _self;
88280 };
88281
88282
88283 });
88284 define('ripple/platform/tizen/2.0/geocoder', function (require, exports, module) {
88285 /*
88286  *  Copyright 2012 Intel Corporation.
88287  *
88288  * Licensed under the Apache License, Version 2.0 (the "License");
88289  * you may not use this file except in compliance with the License.
88290  * You may obtain a copy of the License at
88291  *
88292  * http://www.apache.org/licenses/LICENSE-2.0
88293  *
88294  * Unless required by applicable law or agreed to in writing, software
88295  * distributed under the License is distributed on an "AS IS" BASIS,
88296  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
88297  * See the License for the specific language governing permissions and
88298  * limitations under the License.
88299  */
88300
88301 var SimpleCoordinates = require('ripple/platform/tizen/2.0/SimpleCoordinates'),
88302     ProviderLocal = require('ripple/platform/tizen/2.0/geoBackend_local'),
88303     ProviderNominatim = require('ripple/platform/tizen/2.0/geoBackend_nominatim'), // Nominatim geocode service
88304     _getProviders,
88305     _providers,
88306     _self;
88307
88308 function _initialize() {
88309     _providers = [new ProviderNominatim({name : "Nominatim", connectivity : "ONLINE"})
88310                   /* ,new ProviderLocal({name : "Tizen Database", connectivity : "OFFLINE"}) */];
88311 }
88312
88313 _initialize();
88314
88315 _self = {
88316     getDefaultProvider : function () {
88317         return _providers[0];
88318     },
88319     getProviders : function () {
88320         return _providers;
88321     }
88322 };
88323
88324 module.exports = _self;
88325
88326 });
88327 define('ripple/platform/tizen/2.0/lbs_utils', function (require, exports, module) {
88328 /*
88329  *  Copyright 2012 Intel Corporation.
88330  *
88331  * Licensed under the Apache License, Version 2.0 (the "License");
88332  * you may not use this file except in compliance with the License.
88333  * You may obtain a copy of the License at
88334  *
88335  * http://www.apache.org/licenses/LICENSE-2.0
88336  *
88337  * Unless required by applicable law or agreed to in writing, software
88338  * distributed under the License is distributed on an "AS IS" BASIS,
88339  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
88340  * See the License for the specific language governing permissions and
88341  * limitations under the License.
88342  */
88343
88344 var tizen1_utils = require('ripple/platform/tizen/2.0/tizen1_utils'),
88345     _self;
88346
88347 function CoordinateProperties(prop) {
88348     var _self;
88349     _self = {
88350         latitude : prop.latitude || 0,
88351         longitude : prop.longitude || 0,
88352         altitude : prop.altitude || 0,
88353         accuracy : prop.accuracy || 0,
88354         altitudeAccuracy : prop.altitudeAccuracy || 0,
88355         heading : prop.heading || 0,
88356         speed : prop.speed || 0
88357     };
88358     return _self;
88359 }
88360
88361 function _checkAddressProperties(p, dst) {
88362     if (p.country !== null && p.country !== undefined)
88363         dst.country = String(p.country);
88364     if (p.region !== null && p.region !== undefined)
88365         dst.region = String(p.region);
88366     if (p.county !== null && p.county !== undefined)
88367         dst.county = String(p.county);
88368     if (p.city !== null && p.city !== undefined)
88369         dst.city = String(p.city);
88370     if (p.street !== null && p.street !== undefined)
88371         dst.street = String(p.street);
88372     if (p.streetNumber !== null && p.streetNumber !== undefined)
88373         dst.streetNumber = String(p.streetNumber);
88374     if (p.premises !== null && p.premises !== undefined)
88375         dst.premises = String(p.premises);
88376     if (p.additionalInformation !== null &&
88377         p.additionalInformation !== undefined)
88378         dst.additionalInformation = String(p.additionalInformation);
88379     if (p.postalCode !== null && p.postalCode !== undefined)
88380         dst.postalCode = String(p.postalCode);
88381 }
88382
88383 function AddressProperties(prop) {
88384     var _self;
88385     _self = {
88386         country : null,
88387         region : null,
88388         county : null,
88389         city : null,
88390         street : null,
88391         streetNumber : null,
88392         premises : null,
88393         additionalInformation : null,
88394         postalCode : null
88395     };
88396     if (prop) {
88397         if (_checkAddressProperties(prop, _self) === false)
88398             return undefined;
88399     }
88400     return _self;
88401 }
88402
88403 _self = {
88404     LocationServiceProvider : function (prop) {
88405         var _self;
88406         _self = {
88407             name : "",
88408             metaData : Object,
88409             attribution : "",
88410             supportedOptions : [],
88411             setOptions : function (options, successCB, errorCB) {},
88412             connectivity : "" // "ONLINE" "OFFLINE" "HYBRID"
88413         };
88414
88415         if (prop.name !== null && prop.name !== undefined)
88416             _self.name = String(prop.name);
88417         if (prop.metaData !== null && prop.metaData !== undefined)
88418             _self.metaData = prop.metaData;
88419
88420         if (prop.attribution !== null && prop.attribution !== undefined)
88421             _self.attribution = String(prop.attribution);
88422
88423         if (prop.supportedOptions !== null && prop.supportedOptions !== undefined)
88424             _self.supportedOptions = [prop.supportedOptions];
88425
88426         if (prop.setOptions !== null && prop.setOptions !== undefined)
88427             _self.setOptions = prop.setOptions;
88428
88429         if (prop.connectivity !== null && prop.connectivity !== undefined)
88430             _self.connectivity = String(prop.connectivity);
88431
88432         return _self;
88433     },
88434
88435     GeoCoordinates : function (prop) {
88436         var _self = new CoordinateProperties(prop);
88437         if (tizen1_utils.isEmptyObject(_self)) {
88438             return undefined;
88439         }
88440
88441         return _self;
88442     },
88443
88444     StructuredAddress : function (prop) {
88445         var _self;
88446         _self = new AddressProperties(prop);
88447         if (tizen1_utils.isEmptyObject(_self)) {
88448             return undefined;
88449         }
88450
88451         return _self;
88452     }
88453 };
88454
88455 module.exports = _self;
88456
88457 });
88458 define('ripple/platform/tizen/2.0/map', function (require, exports, module) {
88459 /*
88460  *  Copyright 2012 Intel Corporation
88461  *
88462  * Licensed under the Apache License, Version 2.0 (the "License");
88463  * you may not use this file except in compliance with the License.
88464  * You may obtain a copy of the License at
88465  *
88466  * http://www.apache.org/licenses/LICENSE-2.0
88467  *
88468  * Unless required by applicable law or agreed to in writing, software
88469  * distributed under the License is distributed on an "AS IS" BASIS,
88470  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
88471  * See the License for the specific language governing permissions and
88472  * limitations under the License.
88473  */
88474
88475 var lbs = require('ripple/platform/tizen/2.0/lbs_utils'),
88476     mapProviders = [],
88477     MapStyle,
88478     MapProvider,
88479     _self;
88480
88481 function _initialize() {
88482     // EPSG:3857 is a Spherical Mercator projection coordinate system popularized by web services such as Google and later OpenStreetMap
88483     // mapStyles are from http://wiki.openstreetmap.org/wiki/Slippy_map_tilenames
88484     var projection = "EPSG:3857",
88485         mapStyle1 = new MapStyle("Mapnik", "http://b.tile.openstreetmap.org/${z}/${x}/${y}.png"),
88486         mapStyle2 = new MapStyle("Cycle", "http://b.tile.opencyclemap.org/cycle/${z}/${x}/${y}.png");
88487
88488     mapProviders = [new MapProvider({name: "OpenStreetMap", connectivity: "ONLINE"}, projection, [mapStyle1, mapStyle2])];
88489 }
88490
88491 _self = {
88492     getDefaultProvider: function () {
88493         return mapProviders[0];
88494     },
88495     getProviders: function () {
88496         return mapProviders;
88497     }
88498 };
88499
88500 MapStyle = function (name, url) {
88501     return {
88502         name: name,
88503         url: url
88504     };
88505 };
88506
88507 MapProvider = function (prop, projection, mapStyles) {
88508     var mapProvider = new lbs.LocationServiceProvider(prop);
88509
88510     mapProvider.__defineGetter__("projection", function () {
88511         return projection;
88512     });
88513
88514     mapProvider.__defineGetter__("mapStyles", function () {
88515         return mapStyles;
88516     });
88517
88518     return mapProvider;
88519 };
88520
88521 _initialize();
88522
88523 module.exports = _self;
88524
88525 });
88526 define('ripple/platform/tizen/2.0/messaging', function (require, exports, module) {
88527 /*
88528  *  Copyright 2012 Intel Corporation.
88529  *
88530  * Licensed under the Apache License, Version 2.0 (the "License");
88531  * you may not use this file except in compliance with the License.
88532  * You may obtain a copy of the License at
88533  *
88534  * http://www.apache.org/licenses/LICENSE-2.0
88535  *
88536  * Unless required by applicable law or agreed to in writing, software
88537  * distributed under the License is distributed on an "AS IS" BASIS,
88538  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
88539  * See the License for the specific language governing permissions and
88540  * limitations under the License.
88541  */
88542
88543 var _self,
88544     errorcode = require('ripple/platform/tizen/2.0/errorcode'),
88545     WebAPIException = require('ripple/platform/tizen/2.0/WebAPIException'),
88546     MessagingService = require('ripple/platform/tizen/2.0/MessagingService'),
88547     t = require('ripple/platform/tizen/2.0/typedef'),
88548     TypeCoerce = require('ripple/platform/tizen/2.0/typecoerce'),
88549     TIZEN_MESSAGING_SMS = "messaging.sms",
88550     TIZEN_MESSAGING_MMS = "messaging.mms",
88551     TIZEN_MESSAGING_EMAIL = "messaging.email",
88552     _security_check = {read: false, write: false},
88553     _sms_service = null,
88554     _mms_service = null,
88555     _email_service = null;
88556
88557 _self = function () {
88558     this.getMessageServices = function (messageServiceType, onSuccess, onError) {
88559         var service;
88560
88561         if (!(new TypeCoerce(t.MessageServiceTag)).match(messageServiceType)) {
88562             throw new WebAPIException(errorcode.TYPE_MISMATCH_ERR);
88563         }
88564         if (!(new TypeCoerce(t.MessageServiceArraySuccessCallback)).match(onSuccess)) {
88565             throw new WebAPIException(errorcode.TYPE_MISMATCH_ERR);
88566         }
88567         if (onError && !(new TypeCoerce(t.ErrorCallback)).match(onError)) {
88568             throw new WebAPIException(errorcode.TYPE_MISMATCH_ERR);
88569         }
88570
88571         switch (messageServiceType) {
88572         case "messaging.sms":
88573             if (_sms_service === null) {
88574                 _sms_service = [new MessagingService("Tizen SMS Service 1", TIZEN_MESSAGING_SMS, _security_check), new MessagingService("Tizen SMS Service 2", TIZEN_MESSAGING_SMS, _security_check)];
88575             }
88576             service = _sms_service;
88577             break;
88578         case "messaging.mms":
88579             if (_mms_service === null) {
88580                 _mms_service = [new MessagingService("Tizen MMS Service", TIZEN_MESSAGING_MMS, _security_check)];
88581             }
88582             service = _mms_service;
88583             break;
88584         case "messaging.email":
88585             if (_email_service === null) {
88586                 _email_service = [new MessagingService("Tizen Email Service", TIZEN_MESSAGING_EMAIL, _security_check)];
88587             }
88588             service = _email_service;
88589             break;
88590         default:
88591             throw (new WebAPIException(errorcode.INVALID_VALUES_ERR));
88592         }
88593         setTimeout(function () {
88594             onSuccess(service);
88595         }, 1);
88596     };
88597     this.handleSubFeatures = function (subFeatures) {
88598         if (subFeatures.hasOwnProperty('http://tizen.org/privilege/messaging.read')) {
88599             _security_check.read = true;
88600         }
88601         if (subFeatures.hasOwnProperty('http://tizen.org/privilege/messaging.write')) {
88602             _security_check.write = true;
88603         }
88604     };
88605 };
88606
88607 module.exports = _self;
88608
88609 });
88610 define('ripple/platform/tizen/2.0/msg_utils', function (require, exports, module) {
88611 /*
88612  *  Copyright 2012 Intel Corporation.
88613  *
88614  * Licensed under the Apache License, Version 2.0 (the "License");
88615  * you may not use this file except in compliance with the License.
88616  * You may obtain a copy of the License at
88617  *
88618  * http://www.apache.org/licenses/LICENSE-2.0
88619  *
88620  * Unless required by applicable law or agreed to in writing, software
88621  * distributed under the License is distributed on an "AS IS" BASIS,
88622  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
88623  * See the License for the specific language governing permissions and
88624  * limitations under the License.
88625  */
88626
88627
88628 var db = require('ripple/db'),
88629     utils = require('ripple/utils'),
88630     tizen1_utils = require('ripple/platform/tizen/2.0/tizen1_utils'),
88631     MessageBody = require('ripple/platform/tizen/2.0/MessageBody'),
88632     _TIZEN_MESSAGE_DB_KEY = "tizen_db_messages",
88633     MessageElement = function (_type, _id) {
88634         return {
88635             type: _type,
88636             id: _id,
88637             msg: {},
88638             conv: {}
88639         };
88640     },
88641
88642     _conversationCount = function (msg, cid, rst) {
88643         var old_time = new Date(0), t;
88644
88645         utils.forEach(msg.msg, function (o) {
88646             if (o.priv.conversationId === cid &&
88647                 o.priv.messageStatus !== "DRAFT") {
88648                 rst.cnt += 1;
88649                 t = new Date(o.priv.timestamp);
88650                 if (t > old_time) {
88651                     rst.lastid = o.priv.id;
88652                     old_time = t;
88653                 }
88654                 if (o.isRead === false) {
88655                     rst.unread++;
88656                 }
88657             }
88658         });
88659     },
88660
88661     _updateConversation = function (msg, cid) {
88662         var privConv = {}, lastm, rst = {};
88663
88664         rst.cnt = 0;
88665         rst.unread = 0;
88666         rst.lastid = "";
88667         _conversationCount(msg, cid, rst);
88668         if (rst.cnt === 0) {
88669             if (msg.conv[cid] !== undefined) {
88670                 delete msg.conv[cid];
88671             }
88672             return;
88673         }
88674         lastm = msg.msg[rst.lastid];
88675
88676         privConv.id = cid;
88677         privConv.type = msg.type;
88678         privConv.timestamp = new Date(lastm.priv.timestamp);
88679         privConv.messageCount = rst.cnt;
88680         privConv.unreadMessages = rst.unread;
88681         privConv.preview = lastm.body.plainBody;
88682         privConv.subject = lastm.subject;
88683         privConv.isRead = lastm.isRead;
88684         privConv.from = lastm.priv.from;
88685         privConv.to = lastm.to.slice(0);
88686         privConv.cc = lastm.cc.slice(0);
88687         privConv.bcc = lastm.bcc.slice(0);
88688         privConv.lastMessageId = rst.lastid;
88689         msg.conv[cid] = privConv;
88690     };
88691
88692 module.exports = {
88693     conversationCount: _conversationCount,
88694     setMsg: function (m, newm) {
88695         if ((m.to === null) || (m.to === undefined)) {
88696             newm.to = [];
88697         } else {
88698             if (tizen1_utils.isValidArray(m.to)) {
88699                 newm.to = m.to.slice(0);
88700             } else {
88701                 return false;
88702             }
88703         }
88704
88705         if ((m.cc === null) || (m.cc === undefined)) {
88706             newm.cc = [];
88707         } else {
88708             if (tizen1_utils.isValidArray(m.cc)) {
88709                 newm.cc = m.cc.slice(0);
88710             } else {
88711                 return false;
88712             }
88713         }
88714
88715         if ((m.bcc === null) || (m.bcc === undefined)) {
88716             newm.bcc = [];
88717         } else {
88718             if (tizen1_utils.isValidArray(m.bcc)) {
88719                 newm.bcc = m.bcc.slice(0);
88720             } else {
88721                 return false;
88722             }
88723         }
88724
88725         if ((m.body === null) || (m.body === undefined)) {
88726             if (m.htmlBody === null || m.htmlBody === undefined) {
88727                 m.htmlBody = "";
88728             }
88729             if (m.plainBody === null || m.plainBody === undefined) {
88730                 m.plainBody = "";
88731             }
88732             if (typeof m.plainBody !== 'string' || typeof m.htmlBody !== 'string') {
88733                 return false;
88734             }
88735             m.body = new MessageBody(null, true, m.plainBody, m.htmlBody, []);
88736         } else {
88737             if (typeof m.body.plainBody !== 'string' || typeof m.body.htmlBody !== 'string') {
88738                 return false;
88739             }
88740             m.body = new MessageBody(null, true, m.body.plainBody, m.body.htmlBody, []);
88741         }
88742         newm.body = utils.copy(m.body);
88743
88744         if (typeof m.isRead === 'boolean') {
88745             newm.isRead = m.isRead;
88746         } else {
88747             newm.isRead = false;
88748         }
88749
88750         if (typeof m.isHighPriority === 'boolean') {
88751             newm.isHighPriority = m.isHighPriority;
88752         } else {
88753             newm.isHighPriority = false;
88754         }
88755
88756         if ((m.subject === null) || (m.subject === undefined)) {
88757             newm.subject = "";
88758         } else {
88759             newm.subject = String(m.subject);
88760         }
88761
88762         if ((m.inResponseTo === null) || (m.inResponseTo === undefined)) {
88763             newm.inResponseTo = null;
88764         } else {
88765             newm.inResponseTo = String(m.inResponseTo);
88766         }
88767
88768         if ((m.attachments === null) || (m.attachments === undefined)) {
88769             newm.attachments = [];
88770         } else {
88771             newm.attachments = utils.copy(m.attachments);
88772         }
88773         return true;
88774     },
88775
88776     loadMsg: function (type, id) {
88777         var i, ret, msg = db.retrieveObject(_TIZEN_MESSAGE_DB_KEY) || null;
88778         if (msg === null) {
88779             ret = new MessageElement(type, id);
88780         } else {
88781             for (i = 0; i < msg.length; i++) {
88782                 if (msg[i].type === type && msg[i].id === id) {
88783                     ret = msg[i];
88784                     break;
88785                 }
88786             }
88787             if (ret === undefined) {
88788                 ret = new MessageElement(type, id);
88789             } else {
88790                 /* after getting Date out of DB, Date will become
88791                    a string, so need to recast it back to Date */
88792                 for (i in ret.msg) {
88793                     ret.msg[i].priv.timestamp = new Date(ret.msg[i].priv.timestamp);
88794                 }
88795             }
88796         }
88797         return ret;
88798     },
88799
88800     delMsg: function (m) { // m is a PrivMessage
88801         var i, _msg = db.retrieveObject(_TIZEN_MESSAGE_DB_KEY) || [];
88802         if (_msg.length === 0) {
88803             return;
88804         } else {
88805             for (i = 0; i < _msg.length; i++) {
88806                 if (_msg[i].type === m.priv.type && _msg[i].id === m.priv.serviceId) {
88807                     delete _msg[i].msg[m.priv.id];
88808                     if (m.priv.messageStatus !== "DRAFT") {
88809                         _updateConversation(_msg[i], m.priv.conversationId);
88810                     }
88811                     db.saveObject(_TIZEN_MESSAGE_DB_KEY, _msg);
88812                     return;
88813                 }
88814             }
88815         }
88816     },
88817
88818     saveMsg: function (m) { // m is a PrivMessage
88819         var i, new_msg, _msg = db.retrieveObject(_TIZEN_MESSAGE_DB_KEY) || [];
88820         if (_msg.length === 0) {
88821             _msg = new MessageElement(m.priv.type, m.priv.serviceId);
88822             _msg.msg[m.priv.id] = m;
88823             if (m.priv.messageStatus !== "DRAFT") {
88824                 _updateConversation(_msg, m.priv.conversationId);
88825             }
88826             db.saveObject(_TIZEN_MESSAGE_DB_KEY, [_msg]);
88827         } else {
88828             for (i = 0; i < _msg.length; i++) {
88829                 if (_msg[i].type === m.priv.type && _msg[i].id === m.priv.serviceId) {
88830                     _msg[i].msg[m.priv.id] = m;
88831                     if (m.priv.messageStatus !== "DRAFT") {
88832                         _updateConversation(_msg[i], m.priv.conversationId);
88833                     }
88834                     db.saveObject(_TIZEN_MESSAGE_DB_KEY, _msg);
88835                     break;
88836                 }
88837             }
88838             if (i === _msg.length) {
88839                 new_msg = new MessageElement(m.priv.type, m.priv.serviceId);
88840                 new_msg.msg[m.priv.id] = m;
88841                 if (m.priv.messageStatus !== "DRAFT") {
88842                     _updateConversation(new_msg, m.priv.conversationId);
88843                 }
88844                 _msg.push(new_msg);
88845                 db.saveObject(_TIZEN_MESSAGE_DB_KEY, _msg);
88846             }
88847         }
88848     },
88849
88850     loadConv: function (type, id) {
88851         var i, ret;
88852         ret = this.loadMsg(type, id).conv;
88853         for (i in ret) {
88854             ret[i].timestamp = new Date(ret[i].timestamp);
88855         }
88856         return ret;
88857     }
88858 };
88859
88860 });
88861 define('ripple/platform/tizen/2.0/navigator', function (require, exports, module) {
88862 /*
88863  *  Copyright 2011 Research In Motion Limited.
88864  *  Copyright 2012 Intel Corporation.
88865  *
88866  * Licensed under the Apache License, Version 2.0 (the "License");
88867  * you may not use this file except in compliance with the License.
88868  * You may obtain a copy of the License at
88869  *
88870  * http://www.apache.org/licenses/LICENSE-2.0
88871  *
88872  * Unless required by applicable law or agreed to in writing, software
88873  * distributed under the License is distributed on an "AS IS" BASIS,
88874  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
88875  * See the License for the specific language governing permissions and
88876  * limitations under the License.
88877  */
88878 var _original = window.navigator,
88879     utils = require('ripple/utils'),
88880     devices = require('ripple/devices'),
88881     constants = require('ripple/constants'),
88882     vibration = require('ripple/platform/tizen/2.0/vibration'),
88883     _self = {};
88884
88885 (function () {
88886     var key,
88887         nav = window.navigator;
88888
88889     function _handle(obj, key) {
88890         return typeof obj[key] !== "function" ? obj[key] : function () {
88891             return obj[key].apply(obj, Array.prototype.slice.call(arguments));
88892         };
88893     }
88894
88895     for (key in nav) {
88896         _self[key] = _handle(nav, key);
88897     }
88898 }());
88899
88900 _self.__defineGetter__('userAgent', function () {
88901     var currentUserAgent = devices.getCurrentDevice().userAgent;
88902
88903     return currentUserAgent === constants.COMMON.USER_AGENT_DEFAULT ?
88904         _original.userAgent : currentUserAgent;
88905 });
88906
88907 _self.__defineGetter__('vibrate', function () {
88908     return vibration.vibrate;
88909 });
88910
88911 module.exports = _self;
88912
88913 });
88914 define('ripple/platform/tizen/2.0/networkbearerselection', function (require, exports, module) {
88915 /*
88916  *  Copyright 2013 Intel Corporation.
88917  *
88918  * Licensed under the Apache License, Version 2.0 (the "License");
88919  * you may not use this file except in compliance with the License.
88920  * You may obtain a copy of the License at
88921  *
88922  * http://www.apache.org/licenses/LICENSE-2.0
88923  *
88924  * Unless required by applicable law or agreed to in writing, software
88925  * distributed under the License is distributed on an "AS IS" BASIS,
88926  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
88927  * See the License for the specific language governing permissions and
88928  * limitations under the License.
88929  */
88930
88931 var event = require('ripple/event'),
88932     t = require('ripple/platform/tizen/2.0/typecast'),
88933     errorcode = require('ripple/platform/tizen/2.0/errorcode'),
88934     WebAPIError = require('ripple/platform/tizen/2.0/WebAPIError'),
88935     WebAPIException = require('ripple/platform/tizen/2.0/WebAPIException'),
88936     TypeCoerce = require('ripple/platform/tizen/2.0/typecoerce'),
88937     _security = {
88938         "http://tizen.org/privilege/networkbearerselection":
88939             ["requestRouteToHost", "releaseRouteToHost"]
88940     },
88941     _self;
88942
88943 _self = function () {
88944     var networkBearerSelection;
88945
88946     function requestRouteToHost(networkType, domainName, successCallback, errorCallback) {
88947         var evNetworkOpened       = "NO_" + networkType + "_" + domainName,
88948             evNetworkDisconnected = "ND_" + networkType + "_" + domainName;
88949
88950         if (!_security.requestRouteToHost) {
88951             throw new WebAPIException(errorcode.SECURITY_ERR);
88952         }
88953
88954         networkType     = t.NetworkType(networkType);
88955         domainName      = t.DOMString(domainName);
88956         successCallback = t.NetworkSuccessCallback(successCallback);
88957         errorCallback   = t.ErrorCallback(errorCallback, "?");
88958
88959         if (!domainName) {
88960             if (errorCallback) {
88961                 errorCallback(new WebAPIError(errorcode.INVALID_VALUES_ERR));
88962             }
88963             return;
88964         }
88965
88966         event.once(evNetworkOpened, function (isOpened) {
88967             if (!isOpened)
88968                 return;
88969
88970             successCallback.onsuccess();
88971         });
88972         event.once(evNetworkDisconnected, successCallback.ondisconnected);
88973         event.trigger("NetworkRequest", [networkType, domainName]);
88974     }
88975
88976     function releaseRouteToHost(networkType, domainName, successCallback, errorCallback) {
88977         var evNetworkDisconnected = "ND_" + networkType + "_" + domainName;
88978
88979         if (!_security.releaseRouteToHost) {
88980             throw new WebAPIException(errorcode.SECURITY_ERR);
88981         }
88982
88983         networkType     = t.NetworkType(networkType);
88984         domainName      = t.DOMString(domainName);
88985         successCallback = t.SuccessCallback(successCallback);
88986         errorCallback   = t.ErrorCallback(errorCallback, "?");
88987
88988         if (!domainName) {
88989             if (errorCallback) {
88990                 errorCallback(new WebAPIError(errorcode.INVALID_VALUES_ERR));
88991             }
88992             return;
88993         }
88994
88995         event.once(evNetworkDisconnected, successCallback);
88996         event.trigger("NetworkRelease", [networkType, domainName]);
88997     }
88998
88999     function handleSubFeatures(subFeatures) {
89000         var i, subFeature;
89001
89002         for (subFeature in subFeatures) {
89003             for (i in _security[subFeature]) {
89004                 _security[_security[subFeature][i]] = true;
89005             }
89006         }
89007     }
89008
89009     networkBearerSelection = {
89010         requestRouteToHost: requestRouteToHost,
89011         releaseRouteToHost: releaseRouteToHost,
89012         handleSubFeatures:  handleSubFeatures
89013     };
89014
89015     return networkBearerSelection;
89016 };
89017
89018 module.exports = _self;
89019
89020 });
89021 define('ripple/platform/tizen/2.0/nfc', function (require, exports, module) {
89022 /*
89023  *  Copyright 2012 Intel Corporation
89024  *
89025  * Licensed under the Apache License, Version 2.0 (the "License");
89026  * you may not use this file except in compliance with the License.
89027  * You may obtain a copy of the License at
89028  *
89029  * http://www.apache.org/licenses/LICENSE-2.0
89030  *
89031  * Unless required by applicable law or agreed to in writing, software
89032  * distributed under the License is distributed on an "AS IS" BASIS,
89033  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
89034  * See the License for the specific language governing permissions and
89035  * limitations under the License.
89036  */
89037
89038 var db = require('ripple/db'),
89039     event = require('ripple/event'),
89040     errorcode = require('ripple/platform/tizen/2.0/errorcode'),
89041     WebAPIError = require('ripple/platform/tizen/2.0/WebAPIError'),
89042     tizen1_utils = require('ripple/platform/tizen/2.0/tizen1_utils'),
89043     NDEFRecord = require('ripple/platform/tizen/2.0/NDEFRecord'),
89044     NDEFMessage = require('ripple/platform/tizen/2.0/NDEFMessage'),
89045     _NFC_TAG = "tizen1.0-nfc-tag",
89046     _NFC_PEER = "tizen1.0-nfc-peer",
89047     _NFC_OUTPUT_MESSAGE = "tizen1.0-nfc-output-message",
89048     NFCAdapter, NFCTag, NFCPeer,
89049     tag,
89050     peer,
89051     isPeerConnected = false,
89052     _data = {
89053         INTERVAL : 1000,
89054         listener : {
89055             onCardEmulationChanged : null,
89056             onTagDetected : null,
89057             onPeerDetected : null,
89058             onNDEFReceived : null
89059         },
89060         pairedNFC : null,
89061         nfcAdapter : {},
89062         nfcCardEmulation : {},
89063         nfcTags : [],
89064         nfcTag: {},
89065         nfcPeer : {},
89066         isNear : false,     // Identify the device is whether near
89067         isDetectTag : false, // Identify NFC tag is detected
89068         connectedState : false
89069     },
89070     _security = {
89071         "http://tizen.org/privilege/nfc.admin": ["setPowered"],
89072         "http://tizen.org/privilege/nfc.common": ["getDefaultAdapter", "setExclusiveMode", "getCachedMessage"],
89073         "http://tizen.org/privilege/nfc.p2p": ["setPeerListener", "unsetPeerListener", "setReceiveNDEFListener", "unsetReceiveNDEFListener", "sendNDEF"],
89074         "http://tizen.org/privilege/nfc.tag": ["setTagListener", "unsetTagListener", "readNDEF", "writeNDEF", "transceive"]
89075     },
89076     _self;
89077
89078 //validate the type match
89079 function _validateCallbackType(onSuccess) {
89080     if (onSuccess &&
89081         typeof onSuccess !== "function" &&
89082         typeof onSuccess !== "object") {
89083         throw new WebAPIError(errorcode.TYPE_MISMATCH_ERR);
89084     }
89085     tizen1_utils.validateArgumentType(onSuccess.onattach, "function",
89086         new WebAPIError(errorcode.TYPE_MISMATCH_ERR));
89087     tizen1_utils.validateArgumentType(onSuccess.ondetach, "function",
89088         new WebAPIError(errorcode.TYPE_MISMATCH_ERR));
89089 }
89090
89091 _self = function () {
89092     var nfc, _exclusiveMode = false;
89093     function getDefaultAdapter() {
89094         if (!_security.getDefaultAdapter) {
89095             throw new WebAPIError(errorcode.SECURITY_ERR);
89096         }
89097         if (arguments.length > 0) {
89098             throw new WebAPIError(errorcode.TYPE_MISMATCH_ERR);
89099         }
89100
89101         if (!_data.nfcAdapter) {
89102             throw new WebAPIError(errorcode.UNKNOWN_ERR);
89103         }
89104
89105         return _data.nfcAdapter;
89106     }
89107
89108     /* API Description:
89109      *   If it gets priority and it is in foreground, system doesn't
89110      *   send app controls that are usually sent when detecting NFC Tag
89111      *   or receiving NDEF Message from the connected NFC peer-to-peer target
89112      *
89113      * Implementation detail:
89114      *   due to simulator only support single running instance and doesn't have
89115      *   other app controls which be called by design. we just put some system
89116      *   exclusive mode info on the 'System Summary' panel
89117      */
89118     function setExclusiveMode(mode) {
89119         if (!_security.setExclusiveMode) {
89120             throw new WebAPIError(errorcode.SECURITY_ERR);
89121         }
89122
89123         if (typeof mode !== "boolean") {
89124             throw new WebAPIError(errorcode.TYPE_MISMATCH_ERR);
89125         }
89126         _exclusiveMode = mode;
89127         jQuery("#NFCExclusiveModeValue").text(_exclusiveMode);
89128     }
89129
89130     function handleSubFeatures(subFeatures) {
89131         var i, subFeature;
89132
89133         for (subFeature in subFeatures) {
89134             for (i in _security[subFeature]) {
89135                 _security[_security[subFeature][i]] = true;
89136             }
89137         }
89138     }
89139
89140     nfc = {
89141         getDefaultAdapter: getDefaultAdapter,
89142         setExclusiveMode: setExclusiveMode,
89143         handleSubFeatures: handleSubFeatures
89144     };
89145
89146     nfc.__defineGetter__("NFC_RECORD_TNF_EMPTY", function () {
89147         return 0;
89148     });
89149
89150     nfc.__defineGetter__("NFC_RECORD_TNF_WELL_KNOWN", function () {
89151         return 1;
89152     });
89153
89154     nfc.__defineGetter__("NFC_RECORD_TNF_MIME_MEDIA", function () {
89155         return 2;
89156     });
89157
89158     nfc.__defineGetter__("NFC_RECORD_TNF_URI", function () {
89159         return 3;
89160     });
89161
89162     nfc.__defineGetter__("NFC_RECORD_TNF_EXTERNAL_RTD", function () {
89163         return 4;
89164     });
89165
89166     nfc.__defineGetter__("NFC_RECORD_TNF_UNKNOWN", function () {
89167         return 5;
89168     });
89169
89170     nfc.__defineGetter__("NFC_RECORD_TNF_UNCHANGED", function () {
89171         return 6;
89172     });
89173
89174     return nfc;
89175 };
89176
89177
89178 NFCAdapter = function () {
89179     var nfcAdapter,
89180         interval,
89181         powered = false, // Identify the device on or off
89182         polling = false, // Identify the device is polled
89183         seType = "NONE"; // Identify card emulation type
89184         
89185     event.trigger("nfc-power-changed", [powered]);
89186     event.on("nfc-power-setting", function (status) {
89187         _updatePowerStatus(status);
89188     });
89189     event.on("nfc-attach-setting", function (type, isAttached) {
89190         var isDetectTag;
89191         isDetectTag = type === "Tag" ? true : false;
89192         _updateIsNear(isDetectTag, isAttached);
89193     });
89194     event.on("nfc-tag-send", function (status) {
89195         if (status) {
89196             tag = db.retrieveObject(_NFC_TAG);
89197             if (tag.isSupportedNDEF) {
89198                 _data.nfcTag = new NFCTag(tag.type, tag.isSupportedNDEF, tag.ndefSize, null, true, tag.ndefs);
89199             } else {
89200                 _data.nfcTag = new NFCTag(tag.type, tag.isSupportedNDEF, tag.ndefSize, null, true, tag.rawData);
89201             }
89202             if (_data.listener.onTagDetected) {
89203                 _data.listener.onTagDetected.onattach(_data.nfcTag);
89204             }
89205         } else {
89206             tag = {};
89207             if (_data.listener.onTagDetected) {
89208                 _data.listener.onTagDetected.ondetach();
89209             }
89210         }
89211     });
89212     event.on("nfc-peer-send", function (status) {
89213         if (status) {
89214             _data.nfcPeer = new NFCPeer(true);
89215             if (_data.listener.onPeerDetected) {
89216                 _data.listener.onPeerDetected.onattach(_data.nfcPeer);
89217             }
89218             isPeerConnected = true;
89219         } else {
89220             if (_data.listener.onPeerDetected) {
89221                 _data.listener.onPeerDetected.ondetach();
89222             }
89223             isPeerConnected = false;
89224         }
89225     });
89226     event.on("nfc-peer-sending-ndef", function () {
89227         var _records = [], rec, _ndef, i;
89228         if (isPeerConnected) {
89229             peer = db.retrieveObject(_NFC_PEER);
89230             for (i in peer.ndef.records) {
89231                 rec = peer.ndef.records[i];
89232                 _records.push(new NDEFRecord(rec.tnf, rec.type, rec.payload, rec.id));
89233             }
89234             _ndef = new NDEFMessage(_records);
89235             if (_data.listener.onNDEFReceived) {
89236                 _data.listener.onNDEFReceived(_ndef);
89237             }
89238         }
89239     });
89240
89241     // private
89242     function _updatePowerStatus(status) {
89243         if (powered === status) {
89244             return;
89245         }
89246         if (!status) {
89247             _updateIsNear(_data.isDetectTag, false);
89248             _data.listener.onTagDetected = null;
89249             _data.listener.onPeerDetected = null;
89250             _data.listener.onNDEFReceived = null;
89251             _data.listener.onCardEmulationChanged = null;
89252         }
89253         powered = status;
89254         _updatePollingStatus(status);
89255
89256         event.trigger("nfc-power-changed", [powered]);
89257     }
89258     function _updatePollingStatus(status) {
89259         if (!powered)
89260             return;
89261         if (polling === status) {
89262             return;
89263         }
89264         polling = status;
89265         event.trigger("nfc-polling-changed", [polling]);
89266         if (polling) {
89267             interval = setInterval(poll, _data.INTERVAL);
89268         } else {
89269             clearInterval(interval);
89270         }
89271     }
89272     function _updateIsNear(isDetectTag, isAttached) {
89273         _data.isDetectTag = isDetectTag;
89274         _data.isNear = isAttached;
89275         if (!_data.isNear) {
89276             _data.connectedState = false;
89277             event.trigger("nfc-connectedState-changed", [false]);
89278         }
89279     }
89280     function poll() {
89281         if (!_data.isNear) {
89282             return;
89283         }
89284         if (!_data.connectedState) {
89285             _data.connectedState = true;
89286             event.trigger("nfc-connectedState-changed", [true]);
89287
89288         }
89289     }
89290
89291     // public
89292     // Turns NFC adapter on or off.
89293     function setPowered(state, successCallback, errorCallback) {
89294         if (!_security.setPowered) {
89295             throw new WebAPIError(errorcode.SECURITY_ERR);
89296         }
89297
89298         tizen1_utils.validateArgumentType(state, "boolean",
89299             new WebAPIError(errorcode.TYPE_MISMATCH_ERR));
89300
89301         tizen1_utils.validateCallbackType(successCallback, errorCallback);
89302
89303         _updatePowerStatus(state);
89304         if (successCallback) {
89305             successCallback();
89306         }
89307     }
89308 /*
89309     function setCardEmulation(_seType, successCallback, errorCallback) {
89310         var originalType;
89311         if (!_security.all && !_security.setCardEmulation) {
89312             throw new WebAPIError(errorcode.SECURITY_ERR);
89313         }
89314         tizen1_utils.validateCallbackType(successCallback, errorCallback);
89315
89316         switch (_seType) {
89317         case "NONE":
89318         case "UICC":
89319             break;
89320         default:
89321             throw new WebAPIError(errorcode.TYPE_MISMATCH_ERR);
89322         }
89323
89324         if (!powered) {
89325             return;
89326         }
89327
89328         originalType = seType;
89329         seType = _seType;
89330
89331         if (_data.listener.onCardEmulationChanged && originalType !== seType) {
89332             _data.listener.onCardEmulationChanged(seType);
89333         }
89334         if (successCallback) {
89335             successCallback();
89336         }
89337     }
89338     function setCardEmulationChangeListener(changeCallback) {
89339         if (!_security.all && !_security.setCardEmulationChangeListener) {
89340             throw new WebAPIError(errorcode.SECURITY_ERR);
89341         }
89342         tizen1_utils.validateArgumentType(changeCallback, "function",
89343                 new WebAPIError(errorcode.TYPE_MISMATCH_ERR));
89344         if (!powered) {
89345             return;
89346         }
89347         _data.listener.onCardEmulationChanged = changeCallback;
89348     }
89349
89350     function unsetCardEmulationChangeListener() {
89351         if (!_security.all && !_security.unsetCardEmulationChangeListener) {
89352             throw new WebAPIError(errorcode.SECURITY_ERR);
89353         }
89354         if (!powered || !_data.listener.onCardEmulationChanged) {
89355             return;
89356         }
89357
89358         _data.listener.onCardEmulationChanged = null;
89359     }
89360 */
89361
89362     // Registers a callback function to invoke when NFC tag is detected.
89363     function setTagListener(detectCallback, tagFilter) {
89364         if (!_security.setTagListener) {
89365             throw new WebAPIError(errorcode.SECURITY_ERR);
89366         }
89367
89368         _validateCallbackType(detectCallback);
89369
89370         if (tagFilter) {
89371             tizen1_utils.validateArgumentType(tagFilter, "array",
89372                 new WebAPIError(errorcode.TYPE_MISMATCH_ERR));
89373         }
89374         //TODO: tagFilter support
89375         if (!powered) {
89376             return;
89377         }
89378         _data.listener.onTagDetected = detectCallback;
89379     }
89380
89381     // Registers a callback function to be invoked when NFC peer-to-peer target is detected.
89382     function setPeerListener(detectCallback) {
89383         if (!_security.setPeerListener) {
89384             throw new WebAPIError(errorcode.SECURITY_ERR);
89385         }
89386
89387         _validateCallbackType(detectCallback);
89388
89389         if (!powered) {
89390             return;
89391         }
89392         _data.listener.onPeerDetected = detectCallback;
89393     }
89394
89395     // Unregisters the listener for detecting an NFC tag.
89396     function unsetTagListener() {
89397         if (!_security.unsetTagListener) {
89398             throw new WebAPIError(errorcode.SECURITY_ERR);
89399         }
89400
89401         if (!powered || !_data.listener.onTagDetected) {
89402             return;
89403         }
89404
89405         _data.listener.onTagDetected = null;
89406     }
89407
89408     // Unregisters the listener for detecting an NFC peer-to-peer target.
89409     function unsetPeerListener() {
89410         if (!_security.unsetPeerListener) {
89411             throw new WebAPIError(errorcode.SECURITY_ERR);
89412         }
89413
89414         if (!powered || !_data.listener.onPeerDetected) {
89415             return;
89416         }
89417
89418         _data.listener.onPeerDetected = null;
89419     }
89420
89421     // Gets NDEF message cached when the tag is detected.
89422     function getCachedMessage() {
89423         if (!_security.getCachedMessage) {
89424             throw new WebAPIError(errorcode.SECURITY_ERR);
89425         }
89426
89427         return _data.pairedNFC || new NDEFMessage([]);
89428     }
89429
89430     nfcAdapter = {
89431         setPowered : setPowered,
89432         //setCardEmulation: setCardEmulation,
89433         //setCardEmulationChangeListener: setCardEmulationChangeListener,
89434         //unsetCardEmulationChangeListener: unsetCardEmulationChangeListener,
89435         setTagListener : setTagListener,
89436         setPeerListener : setPeerListener,
89437         unsetTagListener : unsetTagListener,
89438         unsetPeerListener : unsetPeerListener,
89439         getCachedMessage : getCachedMessage
89440     };
89441
89442     nfcAdapter.__defineGetter__("powered", function () {
89443         return powered;
89444     });
89445
89446     nfcAdapter.__defineGetter__("seType", function () {
89447         return seType;
89448     });
89449
89450     return nfcAdapter;
89451 };
89452
89453 NFCTag = function (type, isSupportedNDEF, ndefSize, properties, isConnected, ndefs) {
89454     var nfcTag, i, j,
89455         _ndefs,
89456         rec,
89457         _records,
89458         _ndefs_index = 0;
89459         
89460     type = type || null;
89461     isSupportedNDEF = isSupportedNDEF || false;
89462     ndefSize = ndefSize || 1;
89463     properties = null;
89464     isConnected = isConnected || false;
89465
89466     _ndefs = [];
89467     for (i in ndefs) {
89468         _records = [];
89469         for (j in ndefs[i].records) {
89470             rec = ndefs[i].records[j];
89471             _records.push(new NDEFRecord(rec.tnf, rec.type, rec.payload, rec.id));
89472         }
89473         _ndefs.push(new NDEFMessage(_records));
89474     }
89475
89476     // Reads NDEF data.
89477     function readNDEF(readCallback, errorCallback) {
89478         if (!_security.readNDEF) {
89479             throw new WebAPIError(errorcode.SECURITY_ERR);
89480         }
89481         function _readNDEF() {
89482             if (!isConnected || !isSupportedNDEF) {
89483                 if (errorCallback) {
89484                     errorCallback(new WebAPIError(errorcode.UNKNOWN_ERR));
89485                 }
89486                 return;
89487             }
89488             if (_ndefs_index >= ndefSize) {
89489                 errorCallback(new WebAPIError(errorcode.UNKNOWN_ERR));
89490             } else {
89491                 _data.pairedNFC = _ndefs[_ndefs_index];
89492                 readCallback(_ndefs[_ndefs_index]);
89493                 _ndefs_index++;
89494             }
89495         }
89496
89497         tizen1_utils.validateTypeMismatch(readCallback, errorCallback, "nfc:readNDEF", _readNDEF);
89498     }
89499
89500     // Writes NDEF data.
89501     function writeNDEF(ndefMessage, successCallback, errorCallback) {
89502         if (!_security.writeNDEF) {
89503             throw new WebAPIError(errorcode.SECURITY_ERR);
89504         }
89505
89506         tizen1_utils.validateCallbackType(successCallback, errorCallback);
89507
89508         tizen1_utils.validateArgumentType(ndefMessage, "object",
89509             new WebAPIError(errorcode.TYPE_MISMATCH_ERR));
89510
89511         if (!isConnected || !isSupportedNDEF) {
89512             if (errorCallback) {
89513                 errorCallback(new WebAPIError(errorcode.UNKNOWN_ERR));
89514             }
89515             return;
89516         }
89517         db.saveObject(_NFC_OUTPUT_MESSAGE, ndefMessage);
89518         event.trigger("nfc-output-msg", []);
89519         if (successCallback) {
89520             successCallback();
89521         }
89522     }
89523
89524     // Access the raw format card.
89525     function transceive(data, dataCallback, errorCallback) {
89526         if (!_security.transceive) {
89527             throw new WebAPIError(errorcode.SECURITY_ERR);
89528         }
89529         function _transceive() {
89530             if (!tizen1_utils.isValidArray(data))
89531                 throw new WebAPIError(errorcode.TYPE_MISMATCH_ERR);
89532
89533             if (!isConnected || isSupportedNDEF) {
89534                 if (errorCallback) {
89535                     errorCallback(new WebAPIError(errorcode.UNKNOWN_ERR));
89536                 }
89537                 return;
89538             }
89539             db.saveObject(_NFC_OUTPUT_MESSAGE, data);
89540             event.trigger("nfc-output-msg", []);
89541             dataCallback(ndefs);
89542         }
89543
89544         tizen1_utils.validateTypeMismatch(dataCallback, errorCallback, "nfc:transceive", _transceive);
89545     }
89546
89547     // Formats the detected tag that can store NDEF messages.
89548     /*
89549     function formatNDEF(successCallback, errorCallback, key) {
89550
89551         tizen1_utils.validateCallbackType(successCallback, errorCallback);
89552
89553         if (key) {
89554             tizen1_utils.validateArgumentType(key, "array",
89555                 new WebAPIError(errorcode.TYPE_MISMATCH_ERR));
89556         }
89557
89558         if (!isConnected || !isSupportedNDEF) {
89559             if (errorCallback) {
89560                 errorCallback(new WebAPIError(errorcode.UNKNOWN_ERR));
89561             }
89562             return;
89563         }
89564
89565         successCallback();
89566     }
89567     */
89568
89569     nfcTag = {
89570         readNDEF : readNDEF,
89571         writeNDEF : writeNDEF,
89572         transceive : transceive,
89573         //formatNDEF : formatNDEF
89574     };
89575
89576     nfcTag.__defineGetter__("type", function () {
89577         return type;
89578     });
89579
89580     nfcTag.__defineGetter__("isSupportedNDEF", function () {
89581         return isSupportedNDEF;
89582     });
89583
89584     nfcTag.__defineGetter__("ndefSize", function () {
89585         return ndefSize;
89586     });
89587
89588     nfcTag.__defineGetter__("properties", function () {
89589         return properties;
89590     });
89591
89592     nfcTag.__defineGetter__("isConnected", function () {
89593         return isConnected;
89594     });
89595
89596     return nfcTag;
89597 };
89598
89599 NFCPeer = function (isConnected) {
89600     var nfcPeer;
89601
89602     isConnected = isConnected || false;
89603
89604     // Registers a callback function to be invoked when NDEF message is received from NFC peer-to-peer target connected.
89605     function setReceiveNDEFListener(successCallback, errorCallback) {
89606         if (!_security.setReceiveNDEFListener) {
89607             throw new WebAPIError(errorcode.SECURITY_ERR);
89608         }
89609         function _setReceiveNDEFListener() {
89610             if (!isConnected) {
89611                 if (errorCallback) {
89612                     errorCallback(new WebAPIError(errorcode.UNKNOWN_ERR));
89613                 }
89614                 return;
89615             }
89616             _data.listener.onNDEFReceived = successCallback;
89617         }
89618
89619         tizen1_utils.validateTypeMismatch(successCallback, errorCallback, "nfc:setReceiveNDEFListener", _setReceiveNDEFListener);
89620     }
89621
89622     // Unregisters the listener for receiving NDEFMessage from NFC peer-to-peer target connected.
89623     function unsetReceiveNDEFListener() {
89624         if (!_security.unsetReceiveNDEFListener) {
89625             throw new WebAPIError(errorcode.SECURITY_ERR);
89626         }
89627
89628         _data.listener.onNDEFReceived = null;
89629     }
89630
89631     // Sends data to NFC peer-to-peer target.
89632     function sendNDEF(ndefMessage, successCallback, errorCallback) {
89633         if (!_security.sendNDEF) {
89634             throw new WebAPIError(errorcode.SECURITY_ERR);
89635         }
89636
89637         tizen1_utils.validateCallbackType(successCallback, errorCallback);
89638
89639         tizen1_utils.validateArgumentType(ndefMessage, "object",
89640             new WebAPIError(errorcode.TYPE_MISMATCH_ERR));
89641
89642         if (!isConnected) {
89643             if (errorCallback) {
89644                 errorCallback(new WebAPIError(errorcode.UNKNOWN_ERR));
89645             }
89646             return;
89647         }
89648
89649         db.saveObject(_NFC_OUTPUT_MESSAGE, ndefMessage);
89650         event.trigger("nfc-output-msg", []);
89651         if (successCallback) {
89652             successCallback();
89653         }
89654     }
89655
89656     nfcPeer = {
89657         setReceiveNDEFListener : setReceiveNDEFListener,
89658         unsetReceiveNDEFListener : unsetReceiveNDEFListener,
89659         sendNDEF : sendNDEF
89660     };
89661
89662     nfcPeer.__defineGetter__("isConnected", function () {
89663         return isConnected;
89664     });
89665
89666     return nfcPeer;
89667 };
89668
89669 function _initialize() {
89670     _data.nfcAdapter = new NFCAdapter();
89671 }
89672 _initialize();
89673
89674 module.exports = _self;
89675
89676
89677 });
89678 define('ripple/platform/tizen/2.0/notification', function (require, exports, module) {
89679 /*
89680  *  Copyright 2012 Intel Corporation.
89681  *
89682  * Licensed under the Apache License, Version 2.0 (the "License");
89683  * you may not use this file except in compliance with the License.
89684  * You may obtain a copy of the License at
89685  *
89686  * http://www.apache.org/licenses/LICENSE-2.0
89687  *
89688  * Unless required by applicable law or agreed to in writing, software
89689  * distributed under the License is distributed on an "AS IS" BASIS,
89690  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
89691  * See the License for the specific language governing permissions and
89692  * limitations under the License.
89693  */
89694
89695 var db = require('ripple/db'),
89696     utils = require('ripple/utils'),
89697     event = require('ripple/event'),
89698     errorcode = require('ripple/platform/tizen/2.0/errorcode'),
89699     WebAPIError = require('ripple/platform/tizen/2.0/WebAPIError'),
89700     _notificationStack,
89701     _security = {
89702         "http://tizen.org/privilege/notification": ["post", "update", "remove", "removeAll"]
89703     },
89704     _self;
89705
89706 function _validateNotification(notification) {
89707     if (typeof notification !== "object") {
89708         return false;
89709     }
89710
89711     if (typeof notification.id !== "string") {
89712         return false;
89713     }
89714
89715     if (typeof notification.type !== "string" || notification.type !== "STATUS") {
89716         return false;
89717     }
89718
89719     if (typeof notification.title !== "string") {
89720         return false;
89721     }
89722
89723     if (notification.content && typeof notification.content !== "string") {
89724         return false;
89725     }
89726
89727     return true;
89728 }
89729
89730 _self = function () {
89731     function post(notification) {
89732         if (!_security.post) {
89733             throw new WebAPIError(errorcode.SECURITY_ERR);
89734         }
89735         if (!_validateNotification(notification)) {
89736             throw (new WebAPIError(errorcode.TYPE_MISMATCH_ERR));
89737         }
89738
89739         if (notification.statusType === "PROGRESS" && notification.progressValue &&
89740             (notification.progressValue < 1 || notification.progressValue > 100)) {
89741             throw new WebAPIError(errorcode.INVALID_VALUES_ERR);
89742         }
89743
89744         if (!_notificationStack[notification.id]) {
89745             Object.defineProperty(notification, "postedTime", {value: new Date().toString(), writable: false});
89746             _notificationStack[notification.id] = utils.copy(notification);
89747             db.saveObject("posted-notifications", _notificationStack);
89748             event.trigger("refreshNotificationUI", [], true);
89749         }
89750     }
89751
89752     function update(notification) {
89753         if (!_security.update) {
89754             throw new WebAPIError(errorcode.SECURITY_ERR);
89755         }
89756         if (!_validateNotification(notification)) {
89757             throw (new WebAPIError(errorcode.TYPE_MISMATCH_ERR));
89758         }
89759
89760         if (notification.statusType === "PROGRESS" && notification.progressValue &&
89761             (notification.progressValue < 1 || notification.progressValue > 100)) {
89762             throw new WebAPIError(errorcode.INVALID_VALUES_ERR);
89763         }
89764
89765         if (_notificationStack[notification.id]) {
89766             _notificationStack[notification.id] = utils.copy(notification);
89767             db.saveObject("posted-notifications", _notificationStack);
89768             event.trigger("refreshNotificationUI", [], true);
89769         }
89770
89771     }
89772
89773     function remove(id) {
89774         if (!_security.remove) {
89775             throw new WebAPIError(errorcode.SECURITY_ERR);
89776         }
89777         if (typeof id !== "string") {
89778             throw (new WebAPIError(errorcode.TYPE_MISMATCH_ERR));
89779         }
89780
89781         if (!_notificationStack[id]) {
89782             throw (new WebAPIError(errorcode.NOT_FOUND_ERR));
89783         }
89784
89785         delete _notificationStack[id];
89786         db.saveObject("posted-notifications", _notificationStack);
89787         event.trigger('refreshNotificationUI', [], true);
89788     }
89789
89790     function removeAll() {
89791         if (!_security.removeAll) {
89792             throw new WebAPIError(errorcode.SECURITY_ERR);
89793         }
89794         _notificationStack = {};
89795         db.saveObject("posted-notifications", _notificationStack);
89796         event.trigger('refreshNotificationUI', [], true);
89797     }
89798
89799     function get(id) {
89800         if (typeof id !== "string") {
89801             throw (new WebAPIError(errorcode.TYPE_MISMATCH_ERR));
89802         }
89803
89804         if (!_notificationStack[id]) {
89805             throw (new WebAPIError(errorcode.NOT_FOUND_ERR));
89806         }
89807
89808         return utils.copy(_notificationStack[id]);
89809     }
89810
89811     function getAll() {
89812         var notifications = [];
89813         utils.forEach(_notificationStack, function (item) {
89814             notifications.push(utils.copy(item));
89815         });
89816         return notifications;
89817     }
89818
89819     function handleSubFeatures(subFeatures) {
89820         var i, subFeature;
89821
89822         for (subFeature in subFeatures) {
89823             for (i in _security[subFeature]) {
89824                 _security[_security[subFeature][i]] = true;
89825             }
89826         }
89827     }
89828
89829     var notification = {
89830         post: post,
89831         update: update,
89832         remove: remove,
89833         removeAll: removeAll,
89834         get: get,
89835         getAll: getAll,
89836         handleSubFeatures: handleSubFeatures
89837     };
89838
89839     return notification;
89840 };
89841
89842 function _initilize() {
89843     _notificationStack = db.retrieveObject("posted-notifications") || {};
89844     event.on("refreshNotificationStack", function () {
89845         _notificationStack = db.retrieveObject("posted-notifications");
89846     });
89847 }
89848
89849 _initilize();
89850
89851 module.exports = _self;
89852
89853 });
89854 define('ripple/platform/tizen/2.0/package', function (require, exports, module) {
89855 /*
89856  *  Copyright 2013 Intel Corporation.
89857  *
89858  * Licensed under the Apache License, Version 2.0 (the "License");
89859  * you may not use this file except in compliance with the License.
89860  * You may obtain a copy of the License at
89861  *
89862  * http://www.apache.org/licenses/LICENSE-2.0
89863  *
89864  * Unless required by applicable law or agreed to in writing, software
89865  * distributed under the License is distributed on an "AS IS" BASIS,
89866  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
89867  * See the License for the specific language governing permissions and
89868  * limitations under the License.
89869  */
89870 var db = require('ripple/db'),
89871     event = require('ripple/event'),
89872     utils = require('ripple/utils'),
89873     errorcode = require('ripple/platform/tizen/2.0/errorcode'),
89874     WebAPIError = require('ripple/platform/tizen/2.0/WebAPIError'),
89875     WebAPIException = require('ripple/platform/tizen/2.0/WebAPIException'),
89876     TypeCoerce = require('ripple/platform/tizen/2.0/typecoerce'),
89877     PackageInformation = require('ripple/platform/tizen/2.0/PackageInformation'),
89878     t = require('ripple/platform/tizen/2.0/typedef'),
89879     _security = {
89880         "http://tizen.org/privilege/packagemanager.install": ["install", "uninstall"],
89881         "http://tizen.org/privilege/package.info": ["getPackagesInfo", "getPackageInfo",
89882                     "setPackageInfoEventListener", "unsetPackageInfoEventListener"]
89883     },
89884     DB_PACKAGE_KEY = "tizen-db-package",
89885     _listeners = [],
89886     _data = {
89887         packageList: {},
89888         installedList: {}
89889     },
89890     INTERVAL = 1000, // INTERVAL = 1sec
89891     INSTALL_AMOUNT = 3072, // installation speed amount = 3072 (KB/sec)
89892     _self;
89893
89894 function _get() {
89895     _data = db.retrieveObject(DB_PACKAGE_KEY);
89896     utils.forEach(_data.installedList, function (item) {
89897         item.lastModified = new Date(item.lastModified);
89898     });
89899 }
89900
89901 function _save() {
89902     db.saveObject(DB_PACKAGE_KEY, _data);
89903 }
89904
89905 function _exec(callback, name, id, arg1) {
89906     switch (name) {
89907     case "onprogress":
89908         callback[name](id, arg1);
89909         break;
89910     case "oncomplete":
89911         callback[name](id);
89912         break;
89913     default:
89914         break;
89915     }
89916 }
89917
89918 _self = function () {
89919     var _package;
89920     //public
89921     function install(path, progressCallback, errorCallback) {
89922         var intervalId, installedSize = 0, packageSize, updateFlag = false, item, info, progress;
89923         if (!_security.install) {
89924             throw new WebAPIException(errorcode.SECURITY_ERR);
89925         }
89926         if (!(new TypeCoerce(t.DOMString)).match(path) ||
89927             !(new TypeCoerce(t.PackageProgressCallback)).match(progressCallback) ||
89928             (errorCallback && !(new TypeCoerce(t.ErrorCallback)).match(errorCallback))) {
89929             throw new WebAPIException(errorcode.TYPE_MISMATCH_ERR);
89930         }
89931         if (!_data.packageList[path]) {
89932             if (errorCallback) {
89933                 errorCallback(new WebAPIError(errorcode.NOT_FOUND_ERR));
89934             }
89935             return;
89936         }
89937         item = _data.packageList[path];
89938         //check package has been installed or not
89939         if (_data.installedList[item.id]) {
89940             updateFlag = true;
89941         }
89942         packageSize = item.totalSize;
89943         intervalId = setInterval(function () {
89944             if (installedSize >= packageSize) {
89945                 //install complete
89946                 _data.installedList[item.id] = new PackageInformation(
89947                     item.id, item.name, item.iconPath, item.version,
89948                     item.totalSize, item.dataSize, new Date(),
89949                     item.author, item.description, item.appIds
89950                 );
89951                 event.trigger("install-apps", [item.appIds]);
89952                 _save();
89953                 _exec(progressCallback, "oncomplete", item.id);
89954                 clearInterval(intervalId);
89955                 item = _data.installedList[item.id];
89956                 utils.forEach(_listeners, function (listener) {
89957                     info = new PackageInformation(
89958                         item.id, item.name, item.iconPath, item.version,
89959                         item.totalSize, item.dataSize, item.lastModified,
89960                         item.author, item.description, item.appIds);
89961                     if (!updateFlag) {
89962                         listener.oninstalled(info);
89963                     } else {
89964                         listener.onupdated(info);
89965                     }
89966                 });
89967                 event.trigger("installedList-updated");
89968             } else {
89969                 installedSize += INSTALL_AMOUNT;
89970                 if (installedSize > packageSize) {
89971                     progress = 100;
89972                 } else {
89973                     progress = Math.floor(installedSize * 100 / packageSize);
89974                 }
89975                 _exec(progressCallback, "onprogress", item.id, progress);
89976             }
89977
89978         }, INTERVAL);
89979     }
89980
89981     function uninstall(id, progressCallback, errorCallback) {
89982         var intervalId, removedSize = 0, packageSize, item, progress;
89983         if (!_security.uninstall) {
89984             throw new WebAPIException(errorcode.SECURITY_ERR);
89985         }
89986         if (!(new TypeCoerce(t.PackageId)).match(id) ||
89987             !(new TypeCoerce(t.PackageProgressCallback)).match(progressCallback) ||
89988             (errorCallback && !(new TypeCoerce(t.ErrorCallback)).match(errorCallback))) {
89989             throw new WebAPIException(errorcode.TYPE_MISMATCH_ERR);
89990         }
89991         if (!_data.installedList[id]) {
89992             if (errorCallback) {
89993                 errorCallback(new WebAPIError(errorcode.NOT_FOUND_ERR));
89994             }
89995             return;
89996         }
89997         item = _data.installedList[id];
89998         packageSize = item.totalSize;
89999         intervalId = setInterval(function () {
90000             if (removedSize >= packageSize) {
90001                 //remove complete
90002                 utils.forEach(_data.packageList, function (_package) {
90003                     if (_package.id === id) {
90004                         event.trigger("remove-apps", [_package.appIds]);
90005                     }
90006                 });
90007                 delete _data.installedList[item.id];
90008                 _save();
90009                 _exec(progressCallback, "oncomplete", item.id);
90010                 clearInterval(intervalId);
90011                 item = _data.installedList[item.id];
90012                 utils.forEach(_listeners, function (listener) {
90013                     listener.onuninstalled(id);
90014                 });
90015                 event.trigger("installedList-updated");
90016             } else {
90017                 removedSize += INSTALL_AMOUNT * 10;
90018                 if (removedSize > packageSize) {
90019                     progress = 100;
90020                 } else {
90021                     progress = Math.floor(removedSize * 100 / packageSize);
90022                 }
90023                 _exec(progressCallback, "onprogress", item.id, progress);
90024             }
90025         }, INTERVAL);
90026     }
90027
90028     function getPackagesInfo(successCallback, errorCallback) {
90029         var packageArray = [];
90030         if (!_security.getPackagesInfo) {
90031             throw new WebAPIException(errorcode.SECURITY_ERR);
90032         }
90033         if (!(new TypeCoerce(t.PackageInformationArraySuccessCallback)).match(successCallback) ||
90034             (errorCallback && !(new TypeCoerce(t.ErrorCallback)).match(errorCallback))) {
90035             throw new WebAPIException(errorcode.TYPE_MISMATCH_ERR);
90036         }
90037         utils.forEach(_data.installedList, function (item) {
90038             var i;
90039             i = new PackageInformation(
90040                     item.id, item.name, item.iconPath, item.version,
90041                     item.totalSize, item.dataSize, item.lastModified,
90042                     item.author, item.description, item.appIds
90043                 );
90044             packageArray.push(i);
90045         });
90046         successCallback(packageArray);
90047     }
90048
90049     function getPackageInfo(id) {
90050         var p, item;
90051         if (!_security.getPackageInfo) {
90052             throw new WebAPIException(errorcode.SECURITY_ERR);
90053         }
90054
90055         //assgin the defaul package ID
90056         if (arguments.length === 0) {
90057             id = "api1pack00";
90058         }
90059
90060         if (!(new TypeCoerce(t.PackageId)).match(id)) {
90061             throw new WebAPIException(errorcode.TYPE_MISMATCH_ERR);
90062         }
90063         if (!_data.installedList[id]) {
90064             throw new WebAPIException(errorcode.NOT_FOUND_ERR);
90065         }
90066         item = _data.installedList[id];
90067         p = new PackageInformation(
90068                     item.id, item.name, item.iconPath, item.version,
90069                     item.totalSize, item.dataSize, item.lastModified,
90070                     item.author, item.description, item.appIds
90071                 );
90072         return p;
90073     }
90074
90075     function setPackageInfoEventListener(eventCallback) {
90076         if (!_security.setPackageInfoEventListener) {
90077             throw new WebAPIException(errorcode.SECURITY_ERR);
90078         }
90079         if (!(new TypeCoerce(t.PackageInfomationEventCallback)).match(eventCallback)) {
90080             throw new WebAPIException(errorcode.TYPE_MISMATCH_ERR);
90081         }
90082         _listeners.push(eventCallback);
90083     }
90084
90085     function unsetPackageInfoEventListener() {
90086         if (!_security.unsetPackageInfoEventListener) {
90087             throw new WebAPIException(errorcode.SECURITY_ERR);
90088         }
90089         _listeners = [];
90090     }
90091
90092     function handleSubFeatures(subFeatures) {
90093         var i, subFeature;
90094         for (subFeature in subFeatures) {
90095             for (i in _security[subFeature]) {
90096                 _security[_security[subFeature][i]] = true;
90097             }
90098         }
90099     }
90100
90101     function updatePackage(path, updateFlag) {
90102         var item, p, info;
90103         if (!_data.packageList[path]) {
90104             return;
90105         }
90106         _get();
90107         p = _data.packageList[path];
90108         item = _data.installedList[p.id];
90109         utils.forEach(_listeners, function (listener) {
90110             info = new PackageInformation(
90111                 item.id, item.name, item.iconPath, item.version,
90112                 item.totalSize, item.dataSize, item.lastModified,
90113                 item.author, item.description, item.appIds);
90114             if (!updateFlag) {
90115                 listener.oninstalled(info);
90116             } else {
90117                 listener.onupdated(info);
90118             }
90119         });
90120     }
90121
90122     event.on("install-packge", function (path) {
90123         updatePackage(path, false);
90124     });
90125     event.on("update-package", function (path) {
90126         updatePackage(path, true);
90127     });
90128
90129     event.on("uninstall-package", function (id) {
90130         _get();
90131         utils.forEach(_listeners, function (listener) {
90132             listener.onuninstalled(id);
90133         });
90134     });
90135
90136     _package = {
90137         install: install,
90138         uninstall: uninstall,
90139         getPackagesInfo: getPackagesInfo,
90140         getPackageInfo: getPackageInfo,
90141         setPackageInfoEventListener: setPackageInfoEventListener,
90142         unsetPackageInfoEventListener: unsetPackageInfoEventListener,
90143         handleSubFeatures: handleSubFeatures
90144     };
90145
90146     return _package;
90147 };
90148
90149 function _initialize() {
90150     _get();
90151 }
90152
90153 _initialize();
90154
90155 module.exports = _self;
90156
90157
90158 });
90159 define('ripple/platform/tizen/2.0/pendingObject', function (require, exports, module) {
90160 /*
90161  *  Copyright 2011 Intel Corporation.
90162  *
90163  * Licensed under the Apache License, Version 2.0 (the "License");
90164  * you may not use this file except in compliance with the License.
90165  * You may obtain a copy of the License at
90166  *
90167  * http://www.apache.org/licenses/LICENSE-2.0
90168  *
90169  * Unless required by applicable law or agreed to in writing, software
90170  * distributed under the License is distributed on an "AS IS" BASIS,
90171  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
90172  * See the License for the specific language governing permissions and
90173  * limitations under the License.
90174  */
90175
90176 module.exports = function (pendingObj) {
90177     var cancelFlag = true;
90178     this.setCancelFlag = function (flag) {
90179         cancelFlag = flag;
90180     };
90181     this.getCancelFlag = function () {
90182         return cancelFlag;
90183     };
90184     this.userCancel = null;
90185     this.pendingID = null;
90186 };
90187
90188 });
90189 define('ripple/platform/tizen/2.0/pendingoperation', function (require, exports, module) {
90190 /*
90191  *  Copyright 2011 Intel Corporation.
90192  *
90193  * Licensed under the Apache License, Version 2.0 (the "License");
90194  * you may not use this file except in compliance with the License.
90195  * You may obtain a copy of the License at
90196  *
90197  * http://www.apache.org/licenses/LICENSE-2.0
90198  *
90199  * Unless required by applicable law or agreed to in writing, software
90200  * distributed under the License is distributed on an "AS IS" BASIS,
90201  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
90202  * See the License for the specific language governing permissions and
90203  * limitations under the License.
90204  */
90205
90206 module.exports = function (pendingObj) {
90207     var pending = true;
90208     this.cancel = function () {
90209         if (pending === true) {
90210             if (typeof (pendingObj.getCancelFlag) === "function" && pendingObj.getCancelFlag() === false) {
90211                 pending = false;
90212                 // this clearTimeout is for the case when a 3rd party is invoked to do the task, and it's finished sooner than the intended timeout. therefore, the 3rd party set CancelFlag false, and this cancel is called before timeout
90213                 clearTimeout(pendingObj.pendingID);
90214                 return false;
90215             }
90216             if (typeof (pendingObj.userCancel) === "function") {
90217                 pendingObj.userCancel();
90218             }
90219             clearTimeout(pendingObj.pendingID);
90220             pending = false;
90221             return true;
90222         } else {
90223             return false;
90224         }
90225     };
90226 };
90227
90228
90229 });
90230 define('ripple/platform/tizen/2.0/poi', function (require, exports, module) {
90231 /*
90232  *  Copyright 2012 Intel Corporation.
90233  *
90234  * Licensed under the Apache License, Version 2.0 (the "License");
90235  * you may not use this file except in compliance with the License.
90236  * You may obtain a copy of the License at
90237  *
90238  * http://www.apache.org/licenses/LICENSE-2.0
90239  *
90240  * Unless required by applicable law or agreed to in writing, software
90241  * distributed under the License is distributed on an "AS IS" BASIS,
90242  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
90243  * See the License for the specific language governing permissions and
90244  * limitations under the License.
90245  */
90246
90247 var OpenMapQuestProvider = require('ripple/platform/tizen/2.0/poiBackend_openmapquest'), // opne.MapQuest.xapi service
90248     _providers,
90249     _security = {
90250         "http://tizen.org/api/poi": [],
90251         "http://tizen.org/api/poi.read": ["find"],
90252         "http://tizen.org/api/poi.write": ["add", "remove", "update"],
90253         all: true
90254     },
90255     _self;
90256
90257 function _initialize() {
90258     _providers = [new OpenMapQuestProvider({name : "MapQuest", connectivity : "ONLINE", metaData : _security})];
90259 }
90260
90261 _self = function () {
90262     var poi;
90263
90264     poi = {
90265         getDefaultProvider : function () {
90266             return _providers[0];
90267         },
90268         getProviders : function () {
90269             return _providers;
90270         },
90271         handleSubFeatures: function (subFeatures) {
90272             var i, subFeature;
90273             for (subFeature in subFeatures) {
90274                 if (_security[subFeature].length === 0) {
90275                     _security.all = true;
90276                     break;
90277                 }
90278                 _security.all = false;
90279                 for (i = 0; i < _security[subFeature].length; i++) {
90280                     _security[_security[subFeature][i]] = true;
90281                 }
90282             }
90283             _initialize();
90284         }
90285     };
90286
90287     return poi;
90288 };
90289
90290 module.exports = _self;
90291
90292 });
90293 define('ripple/platform/tizen/2.0/poiBackend_openmapquest', function (require, exports, module) {
90294 /*
90295  *  Copyright 2012 Intel Corporation.
90296  *
90297  * Licensed under the Apache License, Version 2.0 (the "License");
90298  * you may not use this file except in compliance with the License.
90299  * You may obtain a copy of the License at
90300  *
90301  * http://www.apache.org/licenses/LICENSE-2.0
90302  *
90303  * Unless required by applicable law or agreed to in writing, software
90304  * distributed under the License is distributed on an "AS IS" BASIS,
90305  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
90306  * See the License for the specific language governing permissions and
90307  * limitations under the License.
90308  */
90309
90310 var lbs = require('ripple/platform/tizen/2.0/lbs_utils'),
90311     errorcode = require('ripple/platform/tizen/2.0/errorcode'),
90312     WebAPIError = require('ripple/platform/tizen/2.0/WebAPIError'),
90313     tizen1_utils = require('ripple/platform/tizen/2.0/tizen1_utils'),
90314     POIGeometry = require('ripple/platform/tizen/2.0/POIGeometry'),
90315     SimpleCoordinates = require('ripple/platform/tizen/2.0/SimpleCoordinates'),
90316     _security;
90317
90318 function POIPublic(prop) {
90319     /* This is created for public use */
90320     var _self, i, copy, attr,  _id = null, _providerName = null;
90321     if (prop.id) {
90322         _id = prop.id;
90323     }
90324     if (prop.providerName) {
90325         _providerName = prop.providerName;
90326     }
90327     _self = {
90328         name : null,
90329         categories : [],
90330         address : null,
90331         phoneNumbers : [],
90332         geometry : null,
90333         urls : [],
90334         rating : null,
90335         tags : null,
90336         toGeoJSON : function () {
90337             throw new WebAPIError(errorcode.NOT_SUPPORTED_ERR);
90338         }
90339     };
90340
90341     _self.__defineGetter__("id", function () {
90342         return _id;
90343     });
90344
90345     _self.__defineGetter__("providerName", function () {
90346         return _providerName;
90347     });
90348
90349     if (prop) {
90350         if (prop.name) {
90351             _self.name = String(prop.name);
90352         }
90353         if (tizen1_utils.isValidArray(prop.categories)) {
90354             _self.categories = [];
90355             for (i in prop.categories) {
90356                 _self.categories.push(String(prop.categories[i]));
90357             }
90358         }
90359         if (prop.address) {
90360             if (typeof prop.address === "string") {
90361                 _self.address = String(prop.address);
90362             } else if (Object.prototype.toString.call(prop.address) === "[object Object]") {
90363                 copy = prop.address.constructor();
90364                 for (attr in prop.address) {
90365                     if (prop.address.hasOwnProperty(attr)) {
90366                         copy[attr] = prop.address[attr];
90367                     }
90368                 }
90369                 _self.address = copy;
90370             }
90371         }
90372         if (tizen1_utils.isValidArray(prop.phoneNumbers)) {
90373             _self.phoneNumbers = [];
90374             for (i in prop.phoneNumbers) {
90375                 _self.phoneNumbers.push(String(prop.phoneNumbers[i]));
90376             }
90377         }
90378         if (prop.geometry) {
90379             _self.geometry = new POIGeometry(prop.geometry.position, prop.geometry.viewport, prop.geometry.wkt);
90380         }
90381         if (tizen1_utils.isValidArray(prop.urls)) {
90382             _self.urls = [];
90383             for (i in prop.urls) {
90384                 _self.urls.push(String(prop.urls[i]));
90385             }
90386         }
90387         if (typeof prop.rating === "number") {
90388             _self.rating = prop.rating;
90389         }
90390         if (Object.prototype.toString.call(prop.tags) === "[object Object]") {
90391             copy = prop.tags.constructor();
90392             for (attr in prop.tags) {
90393                 if (prop.tags.hasOwnProperty(attr)) {
90394                     copy[attr] = prop.tags[attr];
90395                 }
90396             }
90397             _self.tags = copy;
90398         }
90399     }
90400
90401     return _self;
90402 }
90403
90404 module.exports = function (prop) {
90405
90406     var _self = new lbs.LocationServiceProvider(prop);
90407
90408     if (prop.metaData) {
90409         _security = prop.metaData;
90410     }
90411
90412     _self.__defineGetter__("supportedFilterTypes", function () {
90413         return [];
90414     });
90415
90416     _self.__defineGetter__("supportedPOIFilterAttributes", function () {
90417         return [];
90418     });
90419
90420     _self.__defineGetter__("supportedCategories", function () {
90421         /* reference: http://wiki.openstreetmap.org/wiki/Map_Features#Amenity */
90422         return ["bar", "bbq", "biergarten", "cafe", "drinking_water", "fast_food", "food_court", "ice_cream",
90423                 "pub", "restaurant", "college", "kindergarten", "library", "school", "university",
90424                 "bicycle_parking", "bicycle_rental", "bus_station", "car_rental", "car_sharing", "car_wash",
90425                 "ev_charging", "ferry_terminal", "fuel", "grit_bin", "parking", "parking_entrance",
90426                 "parking_space", "taxi", "atm", "bank", "bureau_de_change", "baby_hatch", "clinic",
90427                 "dentist", "doctors", "hospital", "nursing_home", "pharmacy", "social_facility", "veterinary",
90428                 "arts_centre", "cinema", "community_centre", "fountain", "nightclub", "social_centre",
90429                 "stripclub", "studio", "swingerclub", "theatre", "bench", "brothel", "clock", "courthouse",
90430                 "crematorium", "embassy", "fire_station", "grave_yard", "hunting_stand", "marketplace",
90431                 "place_of_worship", "police", "post_box", "post_office", "prison", "public_building",
90432                 "recycling", "sauna", "shelter", "shower", "telephone", "toilets", "townhall", "vending_machine",
90433                 "waste_basket", "waste_disposal", "watering_place"];
90434     });
90435
90436     _self.__defineGetter__("capabilities", function () {
90437         /* The set is empty, indicating that this provider supports only 'find' operations */
90438         return [];
90439     });
90440
90441     _self.find = function (point, successCallback, errorCallback, options) {
90442         /* This provider only supports searching by "GeoRectBounds" due to MapQuest XAPI limitation */
90443
90444         function _find() {
90445             var searchStr, pois = [], isTypeOK = false,
90446                 id, providerName, name, categories = [], geometry;
90447
90448             if (Object.prototype.toString.call(point) === "[object Object]") {
90449                 if (point.southWest && point.northEast) {
90450                     if (typeof point.southWest.latitude === "number" &&
90451                         typeof point.southWest.longitude === "number" &&
90452                         typeof point.northEast.latitude === "number" &&
90453                         typeof point.northEast.longitude === "number") {
90454                         isTypeOK = true;
90455                     }
90456                 }
90457             }
90458
90459             if (!isTypeOK) {
90460                 throw (new WebAPIError(errorcode.TYPE_MISMATCH_ERR));
90461             }
90462
90463             searchStr = "http://open.mapquestapi.com/xapi/api/0.6/node";
90464             if (options && tizen1_utils.isValidArray(options.categories) &&
90465                 options.categories.length > 0 && typeof options.categories[0] === "string") {
90466                 /* xapi support single amenity only */
90467                 searchStr += "[amenity=" + options.categories[0] + "]";
90468             }
90469             searchStr += "[bbox=" + point.southWest.longitude + "," + point.southWest.latitude + "," +
90470                 point.northEast.longitude + "," + point.northEast.latitude + "]";
90471
90472             /* use Open MapQuest online xapi service. (http://open.mapquestapi.com/xapi/) */
90473             $.ajax({
90474                 type: "GET",
90475                 url: searchStr,
90476                 dataType: "xml",
90477                 timeout: 15000, /* 15 secs timeout */
90478                 success: function (xml) {
90479                     providerName = $(xml).find("osm").attr("generator");
90480                     $(xml).find("node").each(function () {
90481                         var $item = $(this);
90482                         categories = [];
90483                         id = $item.attr("id");
90484                         geometry = new POIGeometry(new SimpleCoordinates($item.attr("lat"), $item.attr("lon")));
90485                         $item.find("tag").each(function () {
90486                             if ($(this).attr("k") === "name") {
90487                                 name = $(this).attr("v");
90488                             } else if ($(this).attr("k") === "amenity") {
90489                                 categories.push($(this).attr("v"));
90490                             }
90491                         });
90492                         pois.push(new POIPublic({id: id, providerName: providerName, name: name,
90493                                                 categories: categories, geometry: geometry}));
90494                     });
90495                     successCallback(pois);
90496                 },
90497                 error: function (obj, msg) {
90498                     if (errorCallback) {
90499                         if (msg === "timeout") {
90500                             setTimeout(function () {
90501                                 errorCallback(new WebAPIError(errorcode.TIMEOUT_ERR));
90502                             }, 1);
90503                         } else {
90504                             setTimeout(function () {
90505                                 errorCallback(new WebAPIError(errorcode.NETWORK_ERR));
90506                             }, 1);
90507                         }
90508                     }
90509                 }
90510             });
90511         }
90512
90513         if (!_security.all && !_security.find) {
90514             throw new WebAPIError(errorcode.SECURITY_ERR);
90515         }
90516
90517         tizen1_utils.validateTypeMismatch(successCallback, errorCallback, "find", _find);
90518     };
90519
90520     _self.update = function (poi, successCallback, errorCallback) {
90521         if (!_security.all && !_security.update) {
90522             throw new WebAPIError(errorcode.SECURITY_ERR);
90523         }
90524
90525         throw new WebAPIError(errorcode.NOT_SUPPORTED_ERR);
90526     };
90527
90528     _self.add = function (poi, successCallback, errorCallback) {
90529         if (!_security.all && !_security.add) {
90530             throw new WebAPIError(errorcode.SECURITY_ERR);
90531         }
90532
90533         throw new WebAPIError(errorcode.NOT_SUPPORTED_ERR);
90534     };
90535
90536     _self.remove = function (poi, successCallback, errorCallback) {
90537         if (!_security.all && !_security.remove) {
90538             throw new WebAPIError(errorcode.SECURITY_ERR);
90539         }
90540
90541         throw new WebAPIError(errorcode.NOT_SUPPORTED_ERR);
90542     };
90543
90544     return _self;
90545 };
90546
90547 });
90548 define('ripple/platform/tizen/2.0/power', function (require, exports, module) {
90549 /*
90550  *  Copyright 2012 Intel Corporation.
90551  *
90552  * Licensed under the Apache License, Version 2.0 (the "License");
90553  * you may not use this file except in compliance with the License.
90554  * You may obtain a copy of the License at
90555  *
90556  * http://www.apache.org/licenses/LICENSE-2.0
90557  *
90558  * Unless required by applicable law or agreed to in writing, software
90559  * distributed under the License is distributed on an "AS IS" BASIS,
90560  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
90561  * See the License for the specific language governing permissions and
90562  * limitations under the License.
90563  */
90564 var event = require('ripple/event'),
90565     constants = require('ripple/constants'),
90566     deviceSettings = require('ripple/deviceSettings'),
90567     errorcode = require('ripple/platform/tizen/2.0/errorcode'),
90568     WebAPIError = require('ripple/platform/tizen/2.0/WebAPIError'),
90569     tizen1_utils = require('ripple/platform/tizen/2.0/tizen1_utils'),
90570     _POWER_RESOURCE = constants.POWER_RESOURCE,
90571     _SCREEN_STATE = constants.POWER_RESOURCE.SCREEN.STATE,
90572     ScreenState = {"previous" : null, "current" : null},
90573     _listeners = [],
90574     _isScreenResourceOccupied = false,
90575     _originalBrightness,
90576     _isCPUAwake = false,
90577     _isScreenOn = true,
90578     _normalBrightness,
90579     _minimal_screen_state = null,
90580     _security = {
90581         "http://tizen.org/privilege/power": ["request", "setScreenBrightness", "turnScreenOn", "turnScreenOff"]
90582     },
90583     _self;
90584
90585 /**initialize**/
90586 function initState() {
90587     _normalBrightness = deviceSettings.retrieve("DISPLAY.brightness");
90588     updateResourceState();
90589 }
90590
90591 function getResourceState(value) {
90592     var state;
90593     value = Number(value);
90594     if (value <=  _SCREEN_STATE.SCREEN_OFF.MAX) {
90595         state = _SCREEN_STATE.SCREEN_OFF.NAME;
90596     } else if (value < _SCREEN_STATE.SCREEN_DIM.MAX) {
90597         state = _SCREEN_STATE.SCREEN_DIM.NAME;
90598     } else if (value < _SCREEN_STATE.SCREEN_NORMAL.MAX) {
90599         state = _SCREEN_STATE.SCREEN_NORMAL.NAME;
90600     } else {
90601         state = _SCREEN_STATE.SCREEN_BRIGHT.NAME;
90602     }
90603     return state;
90604 }
90605
90606 function updateResourceState() {
90607     var brightness, actualState;
90608     brightness = deviceSettings.retrieve("DISPLAY.brightness");
90609     actualState = getResourceState(brightness);
90610     ScreenState.previous = ScreenState.current;
90611     ScreenState.current = actualState;
90612 }
90613
90614 function callListeners(listeners, previousState, changedState) {
90615     listeners.forEach(function (listener) {
90616         setTimeout(function () {
90617             listener(previousState, changedState);
90618         }, 1);
90619     });
90620 }
90621
90622 function triggerListenerCB(stateObj) {
90623     if (stateObj.previous !== stateObj.current) {
90624         callListeners(_listeners, stateObj.previous, stateObj.current);
90625     }
90626 }
90627
90628 _self = function () {
90629     function request(resource, state) {
90630         if (!_security.request) {
90631             throw new WebAPIError(errorcode.SECURITY_ERR);
90632         }
90633         if (typeof resource !== 'string' || typeof state !== 'string') {
90634             throw new WebAPIError(errorcode.TYPE_MISMATCH_ERR);
90635         }
90636         //Check resource
90637         if (!_POWER_RESOURCE.hasOwnProperty(resource)) {
90638             throw new WebAPIError(errorcode.INVALID_VALUES_ERR);
90639         }
90640         //Check state
90641         if (!_POWER_RESOURCE[resource].STATE.hasOwnProperty(state)) {
90642             throw new WebAPIError(errorcode.INVALID_VALUES_ERR);
90643         }
90644         // Exception check: SCREEN_OFF is a state cannot be requested
90645         if (resource === "SCREEN" && state === "SCREEN_OFF") {
90646             throw new WebAPIError(errorcode.INVALID_VALUES_ERR);
90647         }
90648         switch (resource) {
90649         case "SCREEN" :
90650             if ((_minimal_screen_state === null) ||
90651                (_minimal_screen_state === "SCREEN_DIM" && (state === "SCREEN_NORMAL" || state === "SCREEN_BRIGHT")) ||
90652                (_minimal_screen_state === "SCREEN_NORMAL" && state === "SCREEN_BRIGHT")) {
90653                 _minimal_screen_state = state;
90654             }
90655             break;
90656         case "CPU" :
90657             _isCPUAwake = true;
90658             break;
90659         default:
90660             break;
90661         }
90662     }
90663
90664     function release(resource) {
90665         switch (resource) {
90666         case "SCREEN" :
90667             if (_isScreenResourceOccupied) {
90668                 _isScreenResourceOccupied = false;
90669                 deviceSettings.persist("DISPLAY.brightness", _originalBrightness);
90670                 event.trigger("DisplayBrightnessChangedByPower", [_originalBrightness]);
90671                 updateResourceState();
90672                 triggerListenerCB(ScreenState);
90673             }
90674             _minimal_screen_state = null;
90675             break;
90676         case "CPU" :
90677             _isCPUAwake = false;
90678             break;
90679         default:
90680             if (typeof resource === "string") {
90681                 throw (new WebAPIError(errorcode.INVALID_VALUES_ERR));
90682             } else  {
90683                 throw (new WebAPIError(errorcode.TYPE_MISMATCH_ERR));
90684             }
90685         }
90686     }
90687
90688     function setScreenStateChangeListener(listener) {
90689         tizen1_utils.validateArgumentType(listener, "function",
90690                 new WebAPIError(errorcode.TYPE_MISMATCH_ERR));
90691         _listeners.push(listener);
90692     }
90693
90694     function unsetScreenStateChangeListener() {
90695         _listeners = [];
90696     }
90697
90698     function getScreenBrightness() {
90699         var brightness = deviceSettings.retrieve("DISPLAY.brightness");
90700         return brightness;
90701     }
90702
90703     function setScreenBrightness(brightness) {
90704         if (!_security.setScreenBrightness) {
90705             throw new WebAPIError(errorcode.SECURITY_ERR);
90706         }
90707         if (typeof brightness !== 'number') {
90708             throw new WebAPIError(errorcode.TYPE_MISMATCH_ERR);
90709         }
90710         if (brightness < 0 || brightness > 1) {
90711             throw new WebAPIError(errorcode.INVALID_VALUES_ERR);
90712         }
90713         if (!_isScreenResourceOccupied) {
90714             _originalBrightness = deviceSettings.retrieve("DISPLAY.brightness");
90715             _isScreenResourceOccupied = true;
90716         }
90717         deviceSettings.persist("DISPLAY.brightness", brightness);
90718         event.trigger("DisplayBrightnessChangedByPower", [brightness]);
90719         updateResourceState();
90720         triggerListenerCB(ScreenState);
90721     }
90722
90723     function isScreenOn() {
90724         return _isScreenOn;
90725     }
90726
90727     function restoreScreenBrightness() {
90728         if (_isScreenResourceOccupied) {
90729             _isScreenResourceOccupied = false;
90730             deviceSettings.persist("DISPLAY.brightness", _originalBrightness);
90731             event.trigger("DisplayBrightnessChangedByPower", [_originalBrightness]);
90732             updateResourceState();
90733             triggerListenerCB(ScreenState);
90734         }
90735     }
90736
90737     function turnScreenOn() {
90738         var brightness, value, flag = false;
90739         if (!_security.turnScreenOn) {
90740             throw new WebAPIError(errorcode.SECURITY_ERR);
90741         }
90742         brightness = deviceSettings.retrieve("DISPLAY.brightness");
90743         switch (_minimal_screen_state) {
90744         case "SCREEN_DIM":
90745             if (brightness <= _SCREEN_STATE.SCREEN_OFF.VALUE) {
90746                 if (!_isScreenResourceOccupied) {
90747                     _originalBrightness = brightness;
90748                     _isScreenResourceOccupied = true;
90749                 }
90750                 value = _SCREEN_STATE.SCREEN_DIM.VALUE;
90751                 flag = true;
90752             }
90753             break;
90754         case "SCREEN_NORMAL":
90755             if (brightness < _SCREEN_STATE.SCREEN_NORMAL.MIN) {
90756                 if (!_isScreenResourceOccupied) {
90757                     _originalBrightness = brightness;
90758                     _isScreenResourceOccupied = true;
90759                 }
90760                 value = _normalBrightness;
90761                 flag = true;
90762             }
90763             break;
90764         case "SCREEN_BRIGHT":
90765             if (brightness < _SCREEN_STATE.SCREEN_BRIGHT.MIN) {
90766                 if (!_isScreenResourceOccupied) {
90767                     _originalBrightness = brightness;
90768                     _isScreenResourceOccupied = true;
90769                 }
90770                 value = _SCREEN_STATE.SCREEN_BRIGHT.VALUE;
90771                 flag = true;
90772             }
90773             break;
90774         }
90775         if (flag) {
90776             deviceSettings.persist("DISPLAY.brightness", value);
90777             event.trigger("DisplayBrightnessChangedByPower", [value]);
90778             updateResourceState();
90779             triggerListenerCB(ScreenState);
90780         }
90781         _isScreenOn = true;
90782     }
90783
90784     function turnScreenOff() {
90785         if (!_security.turnScreenOff) {
90786             throw new WebAPIError(errorcode.SECURITY_ERR);
90787         }
90788         _isScreenOn = false;
90789     }
90790
90791     function handleSubFeatures(subFeatures) {
90792         var i, subFeature;
90793
90794         for (subFeature in subFeatures) {
90795             for (i in _security[subFeature]) {
90796                 _security[_security[subFeature][i]] = true;
90797             }
90798         }
90799     }
90800
90801     var power = {
90802         request: request,
90803         release: release,
90804         setScreenStateChangeListener: setScreenStateChangeListener,
90805         unsetScreenStateChangeListener: unsetScreenStateChangeListener,
90806         getScreenBrightness: getScreenBrightness,
90807         setScreenBrightness: setScreenBrightness,
90808         isScreenOn: isScreenOn,
90809         restoreScreenBrightness: restoreScreenBrightness,
90810         turnScreenOn: turnScreenOn,
90811         turnScreenOff: turnScreenOff,
90812         handleSubFeatures : handleSubFeatures
90813     };
90814
90815     return power;
90816 };
90817
90818 initState();
90819 event.on("CpuLoadChanged", function (value) {
90820     var load;
90821     if (_isCPUAwake && Number(value) === 0) {
90822         load = _POWER_RESOURCE.CPU.STATE.CPU_AWAKE.DEFAULT_VALUE;
90823         deviceSettings.persist("CPU.load", load);
90824         event.trigger("CpuLoadChangedByPower", [load]);
90825     }
90826 });
90827 event.on("DisplayBrightnessChanged", function () {
90828     _normalBrightness = deviceSettings.retrieve("DISPLAY.brightness");
90829     updateResourceState();
90830     triggerListenerCB(ScreenState);
90831 });
90832
90833 module.exports = _self;
90834
90835 });
90836 define('ripple/platform/tizen/2.0/push', function (require, exports, module) {
90837 /*
90838  *  Copyright 2013 Intel Corporation.
90839  *
90840  * Licensed under the Apache License, Version 2.0 (the "License");
90841  * you may not use this file except in compliance with the License.
90842  * You may obtain a copy of the License at
90843  *
90844  * http://www.apache.org/licenses/LICENSE-2.0
90845  *
90846  * Unless required by applicable law or agreed to in writing, software
90847  * distributed under the License is distributed on an "AS IS" BASIS,
90848  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
90849  * See the License for the specific language governing permissions and
90850  * limitations under the License.
90851  */
90852
90853 var event = require('ripple/event'),
90854     errorcode = require('ripple/platform/tizen/2.0/errorcode'),
90855     t = require('ripple/platform/tizen/2.0/typedef'),
90856     Notification = require('ripple/platform/tizen/2.0/notification'),
90857     StatusNotification = require('ripple/platform/tizen/2.0/StatusNotification'),
90858     WebAPIError = require('ripple/platform/tizen/2.0/WebAPIError'),
90859     WebAPIException = require('ripple/platform/tizen/2.0/WebAPIException'),
90860     TypeCoerce = require('ripple/platform/tizen/2.0/typecoerce'),
90861     PushMessage,
90862     _data = {
90863         service: {
90864 /*          "ID_APPLICATION_0": {
90865  *              appId:          null,
90866  *              registrationId: null,
90867  *              appControl:     null,
90868  *              isRegistered:   false,
90869  *              isConnected:    false,
90870  *              onpushed:       null
90871  *          }
90872  */
90873         }
90874     },
90875     _security = {
90876         "http://tizen.org/privilege/push": ["registerService",
90877             "unregisterService", "connectService", "disconnectService",
90878             "getRegistrationId"]
90879     },
90880     _self;
90881
90882 function _initialize() {
90883     event.on("PushNotified", function (appId, pushMessage) {
90884         var appService, notificationDict, statusNotification, notification;
90885
90886         appService = _data.service[appId];
90887
90888         if (!appService)
90889             return;
90890
90891         if (appService.isConnected) {
90892             appService.onpushed(new PushMessage(pushMessage));
90893         } else {
90894             notificationDict = {
90895                 content: pushMessage.appData,
90896                 appControl: appService.appControl,
90897                 appId: appId
90898             };
90899             statusNotification = new StatusNotification("SIMPLE",
90900                 pushMessage.alertMessage, notificationDict);
90901             notification = new Notification();
90902
90903             notification.post(statusNotification);
90904         }
90905     });
90906 }
90907
90908 function _getCurrentApplicationId() {
90909     return "ID_APPLICATION_0";
90910 }
90911
90912 _self = function () {
90913     var push;
90914
90915     function registerService(appControl, successCallback, errorCallback) {
90916         var appId, appService;
90917
90918         if (!_security.registerService) {
90919             throw new WebAPIException(errorcode.SECURITY_ERR);
90920         }
90921         if (!(new TypeCoerce(t.ApplicationControl)).match(appControl) ||
90922             !(new TypeCoerce(t.PushRegisterSuccessCallback)).match(successCallback) ||
90923             (errorCallback && !(new TypeCoerce(t.ErrorCallback)).match(errorCallback))) {
90924             throw new WebAPIException(errorcode.TYPE_MISMATCH_ERR);
90925         }
90926
90927         appId = _getCurrentApplicationId();
90928         appService = {
90929             appId:          appId,
90930             registrationId: null,
90931             appControl:     appControl,
90932             isRegistered:   false
90933         };
90934         _data.service[appId] = appService;
90935
90936         event.trigger("PushRequest", ["REGISTER", appService], true);
90937
90938         if (appService.registrationId !== null) {
90939             appService.isRegistered = true;
90940             successCallback(appService.registrationId);
90941         } else if (errorCallback) {
90942             window.setTimeout(function () {
90943                 errorCallback(new WebAPIError(errorcode.UNKNOWN_ERR));
90944             }, 1);
90945         }
90946     }
90947
90948     function unregisterService(successCallback, errorCallback) {
90949         var appId, appService;
90950
90951         if (!_security.unregisterService) {
90952             throw new WebAPIException(errorcode.SECURITY_ERR);
90953         }
90954         if ((successCallback && !(new TypeCoerce(t.SuccessCallback)).match(successCallback)) ||
90955             (errorCallback && !(new TypeCoerce(t.ErrorCallback)).match(errorCallback))) {
90956             throw new WebAPIException(errorcode.TYPE_MISMATCH_ERR);
90957         }
90958
90959         appId = _getCurrentApplicationId();
90960         delete _data.service[appId];
90961         event.trigger("PushRequest", ["UNREGISTER", appId]);
90962         if (successCallback) {
90963             window.setTimeout(function () {
90964                 successCallback();
90965             }, 1);
90966         }
90967     }
90968
90969     function connectService(notificationCallback) {
90970         var appId, appService;
90971
90972         if (!_security.connectService) {
90973             throw new WebAPIException(errorcode.SECURITY_ERR);
90974         }
90975         if (!(new TypeCoerce(t.PushNotificationCallback)).match(notificationCallback)) {
90976             throw new WebAPIException(errorcode.TYPE_MISMATCH_ERR);
90977         }
90978
90979         appId = _getCurrentApplicationId();
90980         appService = _data.service[appId];
90981         if (!appService || !appService.isRegistered) {
90982             throw new WebAPIException(errorcode.UNKNOWN_ERR);
90983         }
90984
90985         appService.isConnected = true;
90986         appService.onpushed    = notificationCallback;
90987         event.trigger("PushRequest", ["CONNECT", appId]);
90988     }
90989
90990     function disconnectService() {
90991         var appId, appService;
90992
90993         if (!_security.disconnectService) {
90994             throw new WebAPIException(errorcode.SECURITY_ERR);
90995         }
90996
90997         appId = _getCurrentApplicationId();
90998         appService = _data.service[appId];
90999         if (!appService || !appService.isRegistered) {
91000             throw new WebAPIException(errorcode.UNKNOWN_ERR);
91001         }
91002         if (!appService.isConnected) {
91003             return;
91004         }
91005
91006         appService.onpushed    = null;
91007         appService.isConnected = false;
91008         event.trigger("PushRequest", ["DISCONNECT", appId]);
91009     }
91010
91011     function getRegistrationId() {
91012         var appService;
91013
91014         if (!_security.getRegistrationId) {
91015             throw new WebAPIException(errorcode.SECURITY_ERR);
91016         }
91017
91018         appService = _data.service[_getCurrentApplicationId()];
91019         if (!appService || !appService.isRegistered) {
91020             return null;
91021         }
91022
91023         return appService.registrationId;
91024     }
91025
91026     function handleSubFeatures(subFeatures) {
91027         var i, subFeature;
91028
91029         for (subFeature in subFeatures) {
91030             for (i in _security[subFeature]) {
91031                 _security[_security[subFeature][i]] = true;
91032             }
91033         }
91034     }
91035
91036     push = {
91037         registerService:   registerService,
91038         unregisterService: unregisterService,
91039         connectService:    connectService,
91040         disconnectService: disconnectService,
91041         getRegistrationId: getRegistrationId,
91042         handleSubFeatures: handleSubFeatures
91043     };
91044
91045     return push;
91046 };
91047
91048 _initialize();
91049
91050 PushMessage = function (pushMessageInitDict) {
91051     var appData, alertMessage, date;
91052
91053     this.__defineGetter__("appData", function () {
91054         return appData;
91055     });
91056
91057     this.__defineGetter__("alertMessage", function () {
91058         return alertMessage;
91059     });
91060
91061     this.__defineGetter__("date", function () {
91062         return date;
91063     });
91064
91065     appData      = pushMessageInitDict.appData || "";
91066     alertMessage = pushMessageInitDict.alertMessage || "";
91067     date         = pushMessageInitDict.date || new Date();
91068 };
91069
91070 module.exports = _self;
91071
91072 });
91073 define('ripple/platform/tizen/2.0/route', function (require, exports, module) {
91074 /*
91075  *  Copyright 2012 Intel Corporation.
91076  *
91077  * Licensed under the Apache License, Version 2.0 (the "License");
91078  * you may not use this file except in compliance with the License.
91079  * You may obtain a copy of the License at
91080  *
91081  * http://www.apache.org/licenses/LICENSE-2.0
91082  *
91083  * Unless required by applicable law or agreed to in writing, software
91084  * distributed under the License is distributed on an "AS IS" BASIS,
91085  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
91086  * See the License for the specific language governing permissions and
91087  * limitations under the License.
91088  */
91089
91090 var errorcode = require('ripple/platform/tizen/2.0/errorcode'),
91091     WebAPIError = require('ripple/platform/tizen/2.0/WebAPIError'),
91092     SimpleCoordinates = require('ripple/platform/tizen/2.0/SimpleCoordinates'),
91093     ProviderNominatim = require('ripple/platform/tizen/2.0/routeBackend_navigation'), // navigation route service
91094     _getProviders,
91095     _providers,
91096     _self;
91097
91098 function _initialize() {
91099     _providers = [new ProviderNominatim({name : "Nominatim", connectivity : "ONLINE"})];
91100 }
91101
91102 _initialize();
91103
91104 _self = {
91105     getDefaultProvider : function () {
91106         if (arguments.length !== 0) {
91107             throw (new WebAPIError(errorcode.INVALID_VALUES_ERR));
91108         }
91109         return _providers[0];
91110     },
91111     getProviders : function () {
91112         if (arguments.length !== 0) {
91113             throw (new WebAPIError(errorcode.INVALID_VALUES_ERR));
91114         }
91115         return _providers;
91116     }
91117 };
91118
91119 module.exports = _self;
91120
91121 });
91122 define('ripple/platform/tizen/2.0/routeBackend_local', function (require, exports, module) {
91123 /*
91124  *  Copyright 2012 Intel Corporation.
91125  *
91126  * Licensed under the Apache License, Version 2.0 (the "License");
91127  * you may not use this file except in compliance with the License.
91128  * You may obtain a copy of the License at
91129  *
91130  * http://www.apache.org/licenses/LICENSE-2.0
91131  *
91132  * Unless required by applicable law or agreed to in writing, software
91133  * distributed under the License is distributed on an "AS IS" BASIS,
91134  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
91135  * See the License for the specific language governing permissions and
91136  * limitations under the License.
91137  */
91138
91139 var db = require('ripple/db'),
91140     utils = require('ripple/utils'),
91141     errorcode = require('ripple/platform/tizen/2.0/errorcode'),
91142     WebAPIError = require('ripple/platform/tizen/2.0/WebAPIError'),
91143     SimpleCoordinates = require('ripple/platform/tizen/2.0/SimpleCoordinates'),
91144     tizen1_utils = require('ripple/platform/tizen/2.0/tizen1_utils'),
91145     lbs = require('ripple/platform/tizen/2.0/lbs'),
91146     LocationServiceProvider = {},
91147     RouteWaypoint,
91148     RouteDistance,
91149     RouteDuration,
91150     RouteStep,
91151     RouteSegment,
91152     RouteRequestOptions,
91153     RouteResultSummary,
91154     RouteResult,
91155     _data = {
91156         DB_ROUTE_LOCATION_KEY: "tizen1-db-route",
91157         DB_ROUTE_COLLEAGE_KEY: "tizen2-db-route",
91158         routeProvider: {},
91159         routes: [],
91160         RouteDistanceUnit: ["M", "KM", "MI", "FT"],
91161         providers: [],
91162         path: []
91163     },
91164     _self;
91165
91166 // The RouteWaypoint object
91167 RouteWaypoint = function () {
91168     return {
91169         position: {
91170             latitude: 0,
91171             longitude: 0
91172         },
91173         isStopover: true
91174     };
91175 };
91176
91177 // The RouteDistance object
91178 RouteDistance = function () {
91179     return {
91180         text: "",
91181         value: 0,
91182         unit: "KM"
91183     };
91184 };
91185
91186 // The RouteDuration object
91187 RouteDuration = function () {
91188     return {
91189         text: "",
91190         value: 0 // The duration in a seconds
91191     };
91192 };
91193
91194 // The RouteStep object
91195 RouteStep = function () {
91196     var _self = {
91197         mode: "",        // The way of the travel, for example: car, bike, foot
91198         instruction: "", // The instruction of this step
91199         points: []       // The points of this step
91200     };
91201
91202     _self.origin      = new SimpleCoordinates(0, 0);
91203     _self.destination = new SimpleCoordinates(0, 0);
91204     _self.distance    = new RouteDistance();
91205     _self.duration    = new RouteDuration();
91206
91207     return _self;
91208 };
91209
91210 // The RouteSegment object
91211 RouteSegment = function () {
91212     var _self = {
91213         steps: []
91214     };
91215
91216     _self.origin      = new SimpleCoordinates(0, 0);
91217     _self.destination = new SimpleCoordinates(0, 0);
91218     _self.distance    = new RouteDistance();
91219     _self.duration    = new RouteDuration();
91220
91221     return _self;
91222 };
91223
91224 // The RouteRequestOptions object
91225 RouteRequestOptions = function () {
91226     return {
91227         mode: "", // CAR, BIKE
91228         unit: "KM",
91229         routeGoal: "SHORTEST",
91230         constraints: ["HIGHWAY", "TOLL", "UNPAVED"],
91231         wayPoints: [],
91232         maxResults: 1
91233     };
91234 };
91235
91236 // The RouteResultSummary object
91237 RouteResultSummary = function () {
91238     var _self = {};
91239
91240     _self.origin        = new SimpleCoordinates(0, 0);
91241     _self.destination   = new SimpleCoordinates(0, 0);
91242     _self.totalDistance = new RouteDistance();
91243     _self.totalDuration = new RouteDuration();
91244
91245     return _self;
91246 };
91247
91248 // The RouteResult object
91249 RouteResult = function () {
91250     var _self = {
91251         segments: []
91252     };
91253
91254     _self.summary = new RouteResultSummary();
91255
91256     return _self;
91257 };
91258
91259 // Floyd arithmetic in Mathematics, solving the optimal way
91260 function floyd(e, n, startIndex, endIndex) {
91261     var MAX = Infinity,
91262         a = new Array(n), i, j, k, p = new Array(n),
91263         paths, pathWay = [];
91264
91265     for (i = 1; i < n + 1; i++) {
91266         a[i] = new Array(n);
91267     }
91268     for (i = 1; i < n + 1; i++) {
91269         p[i] = new Array(n);
91270     }
91271     for (i = 1; i < n + 1; i++) {
91272         for (j = 1; j < n + 1; j++) {
91273             if (i === j || e[i][j] === "MIN") {
91274                 a[i][j] = 0;
91275             } else if (e[i][j] !== 0 && e[i][j] !== "MIN") {
91276                 a[i][j] = e[i][j];
91277             } else {
91278                 a[i][j] = MAX;
91279             }
91280             p[i][j] = 0;
91281         }
91282     }
91283     for (i = 1; i < n + 1; i++) {
91284         a[i][i] = 0;
91285     }
91286     for (k = 1; k < n + 1; k++) {
91287         for (i = 1; i < n + 1; i++) {
91288             for (j = 1; j < n + 1; j++) {
91289                 if (parseInt(a[i][k], 10) + parseInt(a[k][j], 10) < a[i][j]) {
91290                     a[i][j] = parseInt(a[i][k], 10) + parseInt(a[k][j], 10);
91291                     p[i][j] = k;
91292                 }
91293             }
91294         }
91295     }
91296     _data.path = [];
91297     paths = findPath(startIndex, endIndex, p);
91298     pathWay = [];
91299     pathWay.push(startIndex);
91300     for (i = 0; i < paths.length; i++) {
91301         pathWay.push(paths[i]);
91302     }
91303     pathWay.push(endIndex);
91304
91305     return pathWay;
91306 }
91307
91308 // Find the best way in the locations
91309 function findPath(i, j, p) {
91310     var k = p[i][j];
91311
91312     if (k === 0 || i === j) {
91313         return _data.path;
91314     }
91315     findPath(i, k, p);
91316     _data.path.push(k);
91317
91318     return findPath(k, j, p);
91319 }
91320
91321 // Find the index in the locations by string
91322 function findIndexByStr(str, locations) {
91323     for (var i in locations) {
91324         if (locations[i].name === str) {
91325             return parseInt(i, 10) + 1;
91326         }
91327     }
91328     return -1;
91329 }
91330
91331 // Find the index in the colleages by name1 and name2
91332 function findValueByStr(start, end, locations, colleages) {
91333     for (var i in colleages) {
91334         if (colleages[i].name1 === locations[start - 1].name && colleages[i].name2 === locations[end - 1].name) {
91335             return parseInt(i, 10);
91336         } else if (colleages[i].name2 === locations[start - 1].name && colleages[i].name1 === locations[end - 1].name) {
91337             return parseInt(i, 10);
91338         }
91339     }
91340     return -1;
91341 }
91342
91343 // Find the index in the locations by latitude and longitude
91344 function searchIndexBycoodinates(latitude, longitude, locations) {
91345     if (latitude !== null && longitude !== null) {
91346         for (var i in locations) {
91347             if (locations[i].latitude === latitude && locations[i].longitude === longitude) {
91348                 return parseInt(i, 10) + 1;
91349             }
91350         }
91351     }
91352     return -1;
91353 }
91354
91355 // Get the relation among the locations
91356 function getRelation(n, colleages, locations, goal) {
91357     var i, j, start, end, relation = new Array(n + 1);
91358     for (i = 1; i < n + 2; i++) {
91359         relation[i] = new Array(n + 1);
91360     }
91361     for (i = 1; i < n + 1; i++) {
91362         for (j = 1; j < n + 1; j++) {
91363             relation[i][j] = 0;
91364         }
91365     }
91366     for (i in colleages) {
91367         start = findIndexByStr(colleages[i].name1, locations);
91368         end = findIndexByStr(colleages[i].name2, locations);
91369         if (start !== -1 && end !== -1 && start !== end) {
91370             switch (goal) {
91371             case "distance":
91372                 relation[start][end] = colleages[i].distance;
91373                 relation[end][start] = colleages[i].distance;
91374                 break;
91375
91376             case "duration":
91377                 relation[start][end] = colleages[i].duration;
91378                 relation[end][start] = colleages[i].duration;
91379                 break;
91380
91381             case "simple":
91382                 relation[start][end] = 1;
91383                 relation[end][start] = 1;
91384                 break;
91385
91386             case "scenic":
91387                 if (colleages[i].addition.scenic === "SCENIC") {
91388                     relation[start][end] = 1;
91389                     relation[start][end] = 1;
91390                 } else if (colleages[i].addition.scenic === "") {
91391                     relation[start][end] = "MIN";
91392                     relation[start][end] = "MIN";
91393                 }
91394                 break;
91395
91396             case "cheap":
91397                 if (colleages[i].addition.toll === "TOLL") {
91398                     relation[start][end] = 1;
91399                     relation[end][start] = 1;
91400                 } else if (colleages[i].addition.toll === "") {
91401                     relation[start][end] = "MIN";
91402                     relation[start][end] = "MIN";
91403                 }
91404                 break;
91405
91406             case "safe":
91407                 if (colleages[i].addition.hazardous === "HAZARDOUS") {
91408                     relation[start][end] = 1;
91409                     relation[end][start] = 1;
91410                 } else if (colleages[i].addition.hazardous === "") {
91411                     relation[start][end] = "MIN";
91412                     relation[end][start] = "MIN";
91413                 }
91414                 break;
91415
91416             default:
91417                 return null;
91418             }
91419         }
91420     }
91421
91422     return relation;
91423 }
91424
91425 // Get the distance relationship among the locations
91426 function distanceRelation(n, colleages, locations) {
91427     return getRelation(n, colleages, locations, "distance");
91428 }
91429
91430 // Get the duration relationship among the locations
91431 function durationRelation(n, colleages, locations) {
91432     return getRelation(n, colleages, locations, "duration");
91433 }
91434
91435 // Get the simple relationship among the locations
91436 function simpleRelation(n, colleages, locations) {
91437     return getRelation(n, colleages, locations, "simple");
91438 }
91439
91440 // Get the cheap relationship among the locations
91441 function cheapRelation(n, colleages, locations) {
91442     return getRelation(n, colleages, locations, "cheap");
91443 }
91444
91445 // Get the safe relationship among the locations
91446 function safeRelation(n, colleages, locations) {
91447     return getRelation(n, colleages, locations, "safe");
91448 }
91449
91450 // Get the scenic relationship among the locations
91451 function scenicRelation(n, colleages, locations) {
91452     return getRelation(n, colleages, locations, "scenic");
91453 }
91454
91455 // Get the shortest way by origin, destination, locations and colleages
91456 function optimalWay(origin, destination, locations, colleages, relation) {
91457     var n = locations.length, i, steps = [], step, relations, routeLocations,
91458         originIndex, destinationIndex, startIndex, endIndex, colleageIndex,
91459         originLatitude, originLongitude, destinationLatitude, destinationLongitude,
91460         startLatitude, startLongitude, endLatitude, endLongitude,
91461         originLocation, destinationLocation, segment, result;
91462
91463     originLatitude = origin.latitude;
91464     originLongitude = origin.longitude;
91465     originIndex = searchIndexBycoodinates(originLatitude, originLongitude, locations);
91466
91467     destinationLatitude = destination.latitude;
91468     destinationLongitude = destination.longitude;
91469     destinationIndex = searchIndexBycoodinates(destinationLatitude, destinationLongitude, locations);
91470
91471     relations = relation(n, colleages, locations);
91472
91473     if (originIndex !== -1 && destinationIndex !== -1) {
91474         routeLocations = floyd(relations, n, parseInt(originIndex, 10), parseInt(destinationIndex, 10));
91475
91476         for (i = 0; i < routeLocations.length - 1; i++) {
91477             colleageIndex = findValueByStr(routeLocations[i], routeLocations[i + 1], locations, colleages);
91478
91479             if (colleageIndex !== -1) {
91480                 step = new RouteStep();
91481                 startIndex = parseInt(routeLocations[i], 10) - 1;
91482                 endIndex = parseInt(routeLocations[i + 1], 10) - 1;
91483
91484                 startLatitude = locations[startIndex].latitude;
91485                 startLongitude = locations[startIndex].longitude;
91486                 originLocation = new SimpleCoordinates(startLatitude, startLongitude);
91487
91488                 endLatitude = locations[endIndex].latitude;
91489                 endLongitude = locations[endIndex].longitude;
91490                 destinationLocation = new SimpleCoordinates(endLatitude, endLongitude);
91491
91492                 step.origin = originLocation;
91493                 step.destination = destinationLocation;
91494                 step.distance = colleages[colleageIndex].distance;
91495                 step.duration = colleages[colleageIndex].duration;
91496                 step.mode = colleages[colleageIndex].mode;
91497                 step.addition = colleages[colleageIndex].addition;
91498
91499                 steps.push(step);
91500             } else if (colleageIndex === -1) {
91501                 return null;
91502             }
91503         }
91504
91505         segment = new RouteSegment();
91506         segment.steps = steps;
91507         result = new RouteResult();
91508         result.segments[0] = segment;
91509
91510         return result;
91511     }
91512     return null;
91513 }
91514
91515 // Get the shortest way by origin, destination, locations and colleages
91516 function shortestWay(origin, destination, locations, colleages) {
91517     return optimalWay(origin, destination, locations, colleages, distanceRelation);
91518 }
91519
91520 // Get the fastest way by origin, destination, locations and colleages
91521 function fastestWay(origin, destination, locations, colleages) {
91522     return optimalWay(origin, destination, locations, colleages, durationRelation);
91523 }
91524
91525 // Get the simplest way by origin, destination, locations and colleages
91526 function simplestWay(origin, destination, locations, colleages) {
91527     return optimalWay(origin, destination, locations, colleages, simpleRelation);
91528 }
91529
91530 // Get the most scenic way by origin, destination, locations and colleages
91531 function mostScenicWay(origin, destination, locations, colleages) {
91532     return optimalWay(origin, destination, locations, colleages, scenicRelation);
91533 }
91534
91535 // Get the cheapest way by origin, destination, locations and colleages
91536 function cheapestWay(origin, destination, locations, colleages) {
91537     return optimalWay(origin, destination, locations, colleages, cheapRelation);
91538 }
91539
91540 // Get the safest way by origin, destination, locations and colleages
91541 function safestWay(origin, destination, locations, colleages) {
91542     return optimalWay(origin, destination, locations, colleages, safeRelation);
91543 }
91544
91545 // Uniquelize the array
91546 function uniquelize(array) {
91547     var temp = {}, result = [], i;
91548     for (i = array.length; i--;) {
91549         temp[array[i]] = array[i];
91550     }
91551     for (i in temp) {
91552         result.push(temp[i]);
91553     }
91554     return result;
91555 }
91556
91557 // Is it intersect between the Array a and b
91558 function intersect(a, b) {
91559     var i, j;
91560
91561     a = uniquelize(a);
91562     if (a.length === 0 && b.length === 0) {
91563         return true;
91564     }
91565     for (i in a) {
91566         for (j in b) {
91567             if (a[i] === b[j])
91568                 return true;
91569         }
91570     }
91571     return false;
91572 }
91573
91574 function getConstrains(result) {
91575     var steps = result.segments[0].steps, constrains = [];
91576
91577     utils.forEach(steps, function (item, index) {
91578         if (item.addition.highway === "HIGHWAY") {
91579             constrains.push("HIGHWAY");
91580         }
91581         if (item.addition.toll === "TOLL") {
91582             constrains.push("TOLL");
91583         }
91584         if (item.addition.bridge === "BRIDGE") {
91585             constrains.push("BRIDGE");
91586         }
91587         if (item.addition.hazardous === "HAZARDOUS") {
91588             constrains.push("HAZARDOUS");
91589         }
91590         if (item.addition.scenic === "SCENIC") {
91591             constrains.push("SCENIC");
91592         }
91593     });
91594     if (constrains.length > 0) {
91595         return uniquelize(constrains);
91596     }
91597     return constrains;
91598 }
91599
91600 module.exports = function (prop) {
91601     var _self = new lbs.LocationServiceProvider(prop);
91602     _self.find = function (origin, destination, successCallback, errorCallback, options) {
91603         function _find() {
91604             var locations, colleages, i, result = {}, emptyResult = [], modes = [], resultModes = [], constrains = [], resultconstrains = [];
91605
91606             locations = db.retrieveObject(_data.DB_ROUTE_LOCATION_KEY);
91607             colleages = db.retrieveObject(_data.DB_ROUTE_COLLEAGE_KEY);
91608
91609             modes = options.modes;
91610             constrains = options.constrains;
91611             if (locations.length > 0 && colleages.length > 0) {
91612                 switch (options.routeGoal) {
91613                 case "SHORTEST":
91614                     result = shortestWay(origin, destination, locations, colleages);
91615                     break;
91616
91617                 case "FASTEST":
91618                     result = fastestWay(origin, destination, locations, colleages);
91619                     break;
91620
91621                 case "SIMPLEST":
91622                     result = simplestWay(origin, destination, locations, colleages);
91623                     break;
91624
91625                 case "MOST_SCENIC":
91626                     result = mostScenicWay(origin, destination, locations, colleages);
91627                     break;
91628
91629                 case "CHEAPEST":
91630                     result = cheapestWay(origin, destination, locations, colleages);
91631                     break;
91632
91633                 case "SAFEST":
91634                     result = safestWay(origin, destination, locations, colleages);
91635                     break;
91636
91637                 default:
91638                     result = shortestWay(origin, destination, locations, colleages);
91639                     break;
91640                 }
91641                 if (result !== null) {
91642                     for (i in result.segments[0].steps) {
91643                         resultModes.push(result.segments[0].steps[i].mode);
91644                     }
91645                     resultconstrains = getConstrains(result);
91646                     if (intersect(resultModes, modes) && intersect(resultconstrains, constrains)) {
91647                         successCallback(result);
91648                     } else {
91649                         successCallback(null);
91650                     }
91651                 }
91652             } else {
91653                 successCallback(emptyResult);
91654             }
91655         }
91656         tizen1_utils.validateTypeMismatch(successCallback, errorCallback, "find", _find);
91657     };
91658     return _self;
91659 };
91660
91661 });
91662 define('ripple/platform/tizen/2.0/routeBackend_navigation', function (require, exports, module) {
91663 /*
91664  *  Copyright 2012 Intel Corporation.
91665  *
91666  * Licensed under the Apache License, Version 2.0 (the "License");
91667  * you may not use this file except in compliance with the License.
91668  * You may obtain a copy of the License at
91669  *
91670  * http://www.apache.org/licenses/LICENSE-2.0
91671  *
91672  * Unless required by applicable law or agreed to in writing, software
91673  * distributed under the License is distributed on an "AS IS" BASIS,
91674  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
91675  * See the License for the specific language governing permissions and
91676  * limitations under the License.
91677  */
91678
91679 var tizen1_utils = require('ripple/platform/tizen/2.0/tizen1_utils'),
91680     lbs_utils = require('ripple/platform/tizen/2.0/lbs_utils'),
91681     errorcode = require('ripple/platform/tizen/2.0/errorcode'),
91682     WebAPIError = require('ripple/platform/tizen/2.0/WebAPIError'),
91683     SimpleCoordinates = require('ripple/platform/tizen/2.0/SimpleCoordinates'),
91684     RouteWaypoint,
91685     RouteDistance,
91686     RouteDuration,
91687     RouteStep,
91688     RouteSegment,
91689     RouteRequestOptions,
91690     RouteResultSummary,
91691     RouteResult,
91692     _data = {
91693         positionDistance: {},
91694         positionDuration: {},
91695         routeProvider: {},
91696         routes: [],
91697         RouteDistanceUnit: ["M", "KM", "MI", "FT"],
91698         providers: [],
91699         path: []
91700     },
91701     _self;
91702
91703 // The RouteWaypoint object
91704 RouteWaypoint = function () {
91705     return {
91706         position: {
91707             latitude: 0,
91708             longitude: 0
91709         },
91710         isStopover: true
91711     };
91712 };
91713
91714 // The RouteDistance object
91715 RouteDistance = function () {
91716     return {
91717         text : "Distance",
91718         value : "0",
91719         unit : "KM "
91720     };
91721 };
91722
91723 // The RouteDuration object
91724 RouteDuration = function () {
91725     return {
91726         text : "Duration",
91727         value : "0" // The duration in a seconds
91728     };
91729 };
91730
91731 // The RouteStep object
91732 RouteStep = function () {
91733     var _self = {
91734         mode: "",        // The way of the travel, for example: car, bike, foot
91735         instruction: "", // The instruction of this step
91736         points: []       // The points of this step
91737     };
91738
91739     _self.origin      = new SimpleCoordinates(0, 0);
91740     _self.destination = new SimpleCoordinates(0, 0);
91741     _self.distance    = new RouteDistance();
91742     _self.duration    = new RouteDuration();
91743
91744     return _self;
91745 };
91746 // The RouteSegment object
91747 RouteSegment = function () {
91748     var _self = {
91749         steps: []
91750     };
91751
91752     _self.origin      = new SimpleCoordinates(0, 0);
91753     _self.destination = new SimpleCoordinates(0, 0);
91754     _self.distance    = new RouteDistance();
91755     _self.duration    = new RouteDuration();
91756
91757     return _self;
91758 };
91759
91760 // The RouteRequestOptions object
91761 RouteRequestOptions = function () {
91762     return {
91763         mode: "", // CAR, BIKE
91764         unit: "KM",
91765         routeGoal: "SHORTEST",
91766         constraints: ["HIGHWAY", "TOLL", "UNPAVED"],
91767         wayPoints: [],
91768         maxResults: 1
91769     };
91770 };
91771
91772 // The RouteResultSummary object
91773 RouteResultSummary = function () {
91774     var _self = {};
91775
91776     _self.origin        = new SimpleCoordinates(0, 0);
91777     _self.destination   = new SimpleCoordinates(0, 0);
91778     _self.totalDistance = new RouteDistance();
91779     _self.totalDuration = new RouteDuration();
91780
91781     return _self;
91782 };
91783
91784 // The RouteResult object
91785 RouteResult = function () {
91786     var _self, jsonStr, jsonObj;
91787     jsonObj = {
91788             "type" : "Point",
91789             "coordinates" : []
91790         };
91791     jsonStr = JSON.stringify(jsonObj);
91792     _self = {
91793         segments : [],
91794         toGeoJSON : function () {
91795                 return jsonStr;
91796             }
91797     };
91798     _self.summary = new RouteResultSummary();
91799     return _self;
91800 };
91801
91802 function calcDegree(distance) {
91803     return distance * Math.PI / 180.0;
91804 }
91805
91806 //calcute the distance
91807 function  calculateDistance(lat1, lat2, lon1, lon2) {
91808     var R = 6371, dLat, dLon, a, c, distance; // km
91809     dLat = calcDegree(parseFloat(lat2) - parseFloat(lat1));
91810     dLon = calcDegree(parseFloat(lon2) - parseFloat(lon1));
91811
91812     lat1 = calcDegree(lat1);
91813     lat2 = calcDegree(lat2);
91814
91815     a = Math.sin(dLat / 2) * Math.sin(dLat / 2) +
91816              Math.sin(dLon / 2) * Math.sin(dLon / 2) * Math.cos(lat1) * Math.cos(lat2);
91817     c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
91818     distance = R * c;
91819     return distance;
91820 }
91821
91822 function calculateDuration(mode, distance) {
91823     var duration, v;
91824     switch (mode) {
91825     case "motorcar" :
91826         v = 50;
91827         duration = distance / v;
91828         break;
91829     case "bicycle" :
91830         v = 20;
91831         duration = distance / v;
91832         break;
91833     case "foot" :
91834         v = 5;
91835         duration = distance / v;
91836         break;
91837     default:
91838         duration = 0;
91839     }
91840     return duration;
91841 }
91842
91843 function optimalWay(points, mode) {
91844     var steps = [], startLatitude, startLongitude, originLocation, endLatitude, endLongitude,
91845     destinationLocation, step, distance, i, routeDistance, routeDuration;
91846     for (i = 0;i < points.length - 1;i++) {
91847         startLatitude       = points[i].lat;
91848         startLongitude      = points[i].lon;
91849         originLocation      = new SimpleCoordinates(startLatitude, startLongitude);
91850         endLatitude         = points[i + 1].lat;
91851         endLongitude        = points[i + 1].lon;
91852         destinationLocation = new SimpleCoordinates(endLatitude, endLongitude);
91853         step                = new RouteStep();
91854         step.origin         = originLocation;
91855         step.destination    = destinationLocation;
91856         distance            = calculateDistance(startLatitude, endLatitude, startLongitude, endLongitude);
91857         routeDistance       = new RouteDistance();
91858         routeDistance.value = distance;
91859         routeDistance.unit  = "km";
91860         step.distance       = routeDistance;
91861         routeDuration       = new RouteDuration();
91862         routeDuration.value = calculateDuration(mode, distance);
91863         step.duration       = routeDuration;
91864         steps.push(step);
91865     }
91866     return steps;
91867 }
91868
91869 function existInSupports(str, array) {
91870     for (var i in array) {
91871         if (str === array[i]) {
91872             return true;
91873         }
91874     }
91875     return false;
91876 }
91877
91878 function navigation(searchStr, flat, flon, tlat, tlon, v, fast) {
91879     var positions = [];
91880
91881     _data.positionDistance = {};
91882     _data.positionDuration = {};
91883     jQuery.ajax({
91884         type : "get",
91885         async : false,
91886         url : searchStr,
91887         data : {
91888             flat : flat,
91889             flon : flon,
91890             tlat : tlat,
91891             tlon : tlon,
91892             v : v,
91893             fast : fast,
91894             layer : 'mapnik',
91895             format : "geojson"
91896         },
91897         contentType : "application/json; charset=utf-8",
91898         dataType : "json",
91899         cache : false,
91900         success : function (data) {
91901             $.each(data.coordinates, function (i, item) {
91902                 var point = {};
91903                 point.lon = item[0];
91904                 point.lat = item[1];
91905                 positions.push(point);
91906             });
91907             $.each(data.properties, function (i, item) {
91908                 if (typeof item === "number") {
91909                     _data.positionDistance = new RouteDistance();
91910                     _data.positionDistance.value = item;
91911                     _data.positionDistance.unit = "km";
91912                     _data.positionDuration = new RouteDuration();
91913                     _data.positionDuration.value = calculateDuration(v, item);
91914                 }
91915             });
91916         },
91917         error : function (errorCB) {
91918             if (errorCB) {
91919                 setTimeout(function () {
91920                     errorCB(new WebAPIError(errorcode.NETWORK_ERR));
91921                 }, 1);
91922             }
91923         }
91924     });
91925     return positions;
91926 }
91927
91928
91929 function filterWaypoints(routeWaypoints) {
91930     var mathWaypoints = [], i;
91931     for (i in routeWaypoints) {
91932         if (routeWaypoints[i].position.latitude !== "" &&
91933             routeWaypoints[i].position.latitude !== undefined &&
91934             routeWaypoints[i].position.latitude !== null &&
91935             routeWaypoints[i].position.longitude !== null &&
91936             routeWaypoints[i].position.longitude !== "" &&
91937             routeWaypoints[i].position.longitude !== undefined) {
91938             mathWaypoints.push(routeWaypoints[i]);
91939         }
91940     }
91941     return mathWaypoints;
91942 }
91943
91944 module.exports = function (prop) {
91945     var _self = new lbs_utils.LocationServiceProvider(prop);
91946
91947     _self.supportedGoals       = ["SHORTEST", "FASTEST", "MOST_SCENIC", "SIMPLEST", "CHEAPEST", "SAFEST" ];
91948     _self.supportedModes       = ["motorcar", "bicycle", "foot"];
91949     _self.supportedConstraints = ["HIGHWAY", "TOLL", "UNPAVED", "BORDER", "GRAVEL_PAVING", "TUNNEL", "BRIDGE", "LEFT_TURN", "CARPOOL", "HAZARDOUS_CARGO" ];
91950     _self.supportsWayPoints    = true;
91951     _self.find = function (origin, destination, successCallback, errorCallback, options) {
91952         function _find() {
91953             var flat, flon, tlat, tlon, v, fast, searchStr, result,
91954                 routeWaypoints = [],
91955                 segmentPositions = [],
91956                 positions = [],
91957                 segments = [],
91958                 totalDistances = 0, totalDurations = 0,
91959                 k, key, segment, startPosition, endPosition,
91960                 summary, distance, duration;
91961
91962             v = options.mode;
91963             //init
91964             if (!existInSupports(v, _self.supportedModes)) {
91965                 throw new WebAPIError(errorcode.TYPE_MISMATCH_ERR);
91966             }
91967             if (!existInSupports(options.routeGoal, _self.supportedGoals)) {
91968                 throw new WebAPIError(errorcode.TYPE_MISMATCH_ERR);
91969             }
91970             switch (options.routeGoal) {
91971             case "SHORTEST":
91972                 fast = 0;
91973                 break;
91974
91975             case "FASTEST":
91976                 fast = 1;
91977                 break;
91978
91979             case "SIMPLEST":
91980                 break;
91981
91982             case "MOST_SCENIC":
91983                 break;
91984
91985             case "CHEAPEST":
91986                 break;
91987
91988             case "SAFEST":
91989                 break;
91990
91991             default:
91992                 fast = 0;
91993             }
91994             searchStr      = "http://www.yournavigation.org/api/dev/gosmore.php";
91995             routeWaypoints = options.wayPoints;
91996             routeWaypoints = filterWaypoints(routeWaypoints);
91997             segmentPositions.push(origin);
91998
91999             if (routeWaypoints.length > 0) {
92000                 for (k in routeWaypoints) {
92001                     segmentPositions.push(routeWaypoints[k].position);
92002                 }
92003             }
92004             segmentPositions.push(destination);
92005
92006             for (key = 0; key < segmentPositions.length - 1; key++) {
92007                 segment             = new RouteSegment();
92008                 startPosition       = segmentPositions[key];
92009                 endPosition         = segmentPositions[key + 1];
92010                 segment.origin      = startPosition;
92011                 segment.destination = endPosition;
92012                 flat                = startPosition.latitude;
92013                 flon                = startPosition.longitude;
92014                 tlat                = endPosition.latitude;
92015                 tlon                = endPosition.longitude;
92016                 positions           = navigation(searchStr, flat, flon, tlat, tlon, v, fast);
92017                 segment.steps       = optimalWay(positions, v);
92018                 segment.distance    = _data.positionDistance;
92019                 totalDistances     += _data.positionDistance.value;
92020                 segment.duration    = _data.positionDuration;
92021                 totalDurations     += _data.positionDuration.value;
92022                 segments.push(segment);
92023             }
92024             result                = new RouteResult();
92025             summary               = new RouteResultSummary();
92026             summary.origin        = segmentPositions[0];
92027             summary.destination   = segmentPositions[segmentPositions.length - 1];
92028             distance              = new RouteDistance();
92029             distance.value        = totalDistances;
92030             distance.unit         = "km";
92031             summary.totalDistance = distance;
92032             duration              = new RouteDuration();
92033             duration.value        = totalDurations;
92034             summary.totalDuration = duration;
92035             result.segments       = segments;
92036             result.summary        = summary;
92037             successCallback(result);
92038         }
92039
92040         tizen1_utils.validateTypeMismatch(successCallback, errorCallback, "find", _find);
92041     };
92042
92043     return _self;
92044 };
92045
92046 });
92047 define('ripple/platform/tizen/2.0/sensors', function (require, exports, module) {
92048 /*
92049  *  Copyright 2012 Intel Corporation.
92050  *
92051  * Licensed under the Apache License, Version 2.0 (the "License");
92052  * you may not use this file except in compliance with the License.
92053  * You may obtain a copy of the License at
92054  *
92055  * http://www.apache.org/licenses/LICENSE-2.0
92056  *
92057  * Unless required by applicable law or agreed to in writing, software
92058  * distributed under the License is distributed on an "AS IS" BASIS,
92059  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
92060  * See the License for the specific language governing permissions and
92061  * limitations under the License.
92062  */
92063
92064 var utils = require('ripple/utils'),
92065     sensors = require('ripple/platform/tizen/2.0/spec/sensor'),
92066     _sensors = ["Accelerometer", "MagneticField", "Rotation", "Orientation"],
92067     _permission = true,
92068     _isWriteable = false,
92069     _self;
92070
92071 function SensorError(code, msg) {
92072     this.__defineGetter__("message", function () {
92073         return msg;
92074     });
92075     this.__defineGetter__("code", function () {
92076         return code;
92077     });
92078
92079     this.PERMISSION_DENIED = -100;
92080 }
92081
92082 function SensorRequest() {
92083     var _self = {
92084         result: [],
92085         error: null,
92086         readyState: "processing"
92087     };
92088
92089     this.__defineGetter__("result", function () {
92090         return _self.result;
92091     });
92092     this.__defineSetter__("result", function (resultData) {
92093         if (_isWriteable) {
92094             _self.result = utils.copy(resultData);
92095             _isWriteable = false;
92096             return;
92097         }
92098     });
92099
92100     this.__defineGetter__("error", function () {
92101         return _self.error;
92102     });
92103     this.__defineSetter__("error", function (errorData) {
92104         if (_isWriteable) {
92105             _self.error = utils.copy(errorData);
92106             _isWriteable = false;
92107             return;
92108         }
92109     });
92110
92111     this.__defineGetter__("readyState", function () {
92112         return _self.readyState;
92113     });
92114     this.__defineSetter__("readyState", function (readyStateData) {
92115         if (_isWriteable) {
92116             _self.readyState = readyStateData;
92117             _isWriteable = false;
92118             return;
92119         }
92120     });
92121 }
92122
92123 _self = {
92124     findSensors: function (type) {
92125         var sensorRequest = new SensorRequest(), index, sensorName = "";
92126
92127         setTimeout(function () {
92128             if (_permission) {
92129                 for (index = 0; index < _sensors.length; index++) {
92130                     sensorName = _sensors[index];
92131                     if (type === null || type === undefined || type === sensorName) {
92132                         _isWriteable = true;
92133                         sensorRequest.result.push(sensors[sensorName]);
92134                     }
92135                 }
92136
92137                 _isWriteable = true;
92138                 sensorRequest.readyState = "done";
92139
92140                 if (sensorRequest.onsuccess) {
92141                     sensorRequest.onsuccess();
92142                 }
92143             }
92144             else {
92145                 // error event on the request with error code PERMISSION_DENIED must be fired.
92146                 sensorRequest.error = new SensorError(-100, "permission denied!");
92147                 if (sensorRequest.onerror) {
92148                     sensorRequest.onerror();
92149                 }
92150             }
92151         }, 1);
92152
92153         return sensorRequest;
92154     }
92155 };
92156
92157 module.exports = _self;
92158
92159
92160 });
92161 define('ripple/platform/tizen/2.0/spec/btdevices', function (require, exports, module) {
92162 /*
92163  *  Copyright 2012 Intel Corporation.
92164  *
92165  * Licensed under the Apache License, Version 2.0 (the "License");
92166  * you may not use this file except in compliance with the License.
92167  * You may obtain a copy of the License at
92168  *
92169  * http://www.apache.org/licenses/LICENSE-2.0
92170  *
92171  * Unless required by applicable law or agreed to in writing, software
92172  * distributed under the License is distributed on an "AS IS" BASIS,
92173  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
92174  * See the License for the specific language governing permissions and
92175  * limitations under the License.
92176  */
92177
92178 module.exports = {
92179     "22:33:44:12:34:56": {
92180         "name": "Tizen Phone",
92181         "address": "22:33:44:12:34:56",
92182         "deviceClass": {
92183             "major": 0x02,
92184             "majorName": "PHONE",
92185             "minor": 0x03,
92186             "minorName": "PHONE_SMARTPHONE",
92187             "services": [0x0080],
92188             "servicesName": ["OBJECT_TRANSFER"]
92189         },
92190         "isTrusted": false,
92191         "services": {
92192             "5bce9431-6c75-32ab-afe0-2ec108a30860" : {
92193                 "name": "Data Exchange",
92194                 "uuid": "5bce9431-6c75-32ab-afe0-2ec108a30860",
92195                 "protocol": "RFCOMM"
92196             },
92197             "3537d485-0c1e-445a-a066-43fafcfb61d1" : {
92198                 "name": "Data Transfer",
92199                 "uuid": "3537d485-0c1e-445a-a066-43fafcfb61d1",
92200                 "protocol": "RFCOMM"
92201             }
92202         }
92203     },
92204     "22:33:44:12:34:88": {
92205         "name": "Keyboard",
92206         "address": "22:33:44:12:34:88",
92207         "deviceClass": {
92208             "major": 0x05,
92209             "majorName": "PERIPHERAL",
92210             "minor": 0x10,
92211             "minorName": "PERIPHERAL_KEYBOARD",
92212             "services": [0x0080],
92213             "servicesName": ["OBJECT_TRANSFER"]
92214         },
92215         "isTrusted": true,
92216         "services": {
92217             "3537d485-0c1e-445a-a066-43fafcfb61d1" : {
92218                 "name": "Data Exchange",
92219                 "uuid": "3537d485-0c1e-445a-a066-43fafcfb61d1",
92220                 "protocol": "RFCOMM"
92221             }
92222         }
92223     },
92224     "22:33:44:88:34:58": {
92225         "name": "Tizen Laptop",
92226         "address": "22:33:44:88:34:58",
92227         "deviceClass": {
92228             "major": 0x01,
92229             "majorName": "COMPUTER",
92230             "minor": 0x03,
92231             "minorName": "COMPUTER_LAPTOP",
92232             "services": [0x0080],
92233             "servicesName": ["OBJECT_TRANSFER"]
92234         },
92235         "isTrusted": true,
92236         "services": {
92237             "3537d485-0c1e-445a-a066-43fafcfb61d1" : {
92238                 "name": "Data Exchange",
92239                 "uuid": "3537d485-0c1e-445a-a066-43fafcfb61d1",
92240                 "protocol": "RFCOMM"
92241             }
92242         }
92243     }
92244 };
92245
92246 });
92247 define('ripple/platform/tizen/2.0/spec/config', function (require, exports, module) {
92248 /*
92249  *  Copyright 2011 Research In Motion Limited.
92250  *  Copyright 2011 Intel Corporation.
92251  *
92252  * Licensed under the Apache License, Version 2.0 (the "License");
92253  * you may not use this file except in compliance with the License.
92254  * You may obtain a copy of the License at
92255  *
92256  * http://www.apache.org/licenses/LICENSE-2.0
92257  *
92258  * Unless required by applicable law or agreed to in writing, software
92259  * distributed under the License is distributed on an "AS IS" BASIS,
92260  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
92261  * See the License for the specific language governing permissions and
92262  * limitations under the License.
92263  */
92264 var utils = require('ripple/utils'),
92265     db = require('ripple/db'),
92266     constants = require('ripple/constants');
92267
92268 module.exports = {
92269     fileName: "config.xml",
92270     validateVersion: function (configValidationObject) {
92271         var valid = true;
92272         // no xmlns:JIL in wac 2.0 spec
92273         valid = !!configValidationObject.widget.validationResult[0].attributes.xmlns.valid;
92274
92275         return valid;
92276     },
92277     extractInfo: function (configValidationObject) {
92278         if (!configValidationObject) {
92279             return null;
92280         }
92281
92282         var widgetInfo = {},
92283             configFeatures,
92284             configPreferences,
92285             preferenceName,
92286             platform;
92287
92288         widgetInfo.id = configValidationObject.widget.validationResult[0].attributes.id.value || "";
92289         widgetInfo.name = configValidationObject.widget.children.name.validationResult[0].value;
92290         widgetInfo.icon = configValidationObject.widget.children.icon.validationResult[0].attributes.src.value;
92291         widgetInfo.version = configValidationObject.widget.validationResult[0].attributes.version.value;
92292
92293         widgetInfo.features = {};
92294
92295         if (configValidationObject.widget.children.setting.hasOwnProperty('validationResult') === true &&
92296             configValidationObject.widget.children.setting.validationResult[0].valid === true) {
92297             db.save("layout", configValidationObject.widget.children.setting.validationResult[0].attributes["screen-orientation"].value);
92298         }
92299
92300         configFeatures = configValidationObject.widget.children.feature.validationResult;
92301         utils.forEach(configFeatures, function (f) {
92302             if (f.valid === true) {
92303                 var feature = {id: f.attributes.name.value,
92304                          required: f.attributes.required.valid};
92305                 widgetInfo.features[feature.id] = feature;
92306             }
92307         });
92308
92309         widgetInfo.preferences = {};
92310
92311         configPreferences = configValidationObject.widget.children.preference.validationResult;
92312
92313         platform = require('ripple/platform');
92314         utils.forEach(configPreferences, function (preference) {
92315             preferenceName = preference.attributes.name.value;
92316             if (preferenceName) {
92317                 widgetInfo.preferences[preferenceName] = {
92318                     "key": preferenceName,
92319                     "value": preference.attributes.value.value || "",
92320                     "readonly": preference.attributes.readonly.value === "true"
92321                 };
92322
92323                 db.save(preferenceName,
92324                         widgetInfo.preferences[preferenceName].value,
92325                         platform.getPersistencePrefix(widgetInfo.id));
92326             }
92327         });
92328
92329         return widgetInfo;
92330     },
92331     schema: {
92332         rootElement: "widget",
92333         widget: {
92334             nodeName: "widget",
92335             required: true,
92336             occurrence: 1,
92337             helpText: "\"widget\" element describes widget information in configuration documents and serves as a container for other elements. It must be used in the configuration document and may have the following child elments: name,description,icon,author,license,content,feature and preference.The \"widget\" element MAY have following attributes: id,version,height,width, defaultlocale, xml:lang and dir",
92338             attributes: {
92339                 xmlns: {
92340                     attributeName: "xmlns",
92341                     required: true,
92342                     type: "list",
92343                     listValues: ["http://www.w3.org/ns/widgets"]
92344                 },
92345                 "xmlns:tizen": {
92346                     attributeName: "xmlns:tizen",
92347                     required: false,
92348                     type: "list",
92349                     listValues: ["http://tizen.org/ns/widgets"]
92350                 },
92351                 "xml:lang": {
92352                     attributeName: "xml:lang",
92353                     required: false,
92354                     type: "iso-language"
92355                 },
92356                 dir: {
92357                     attributeName: "dir",
92358                     required: false,
92359                     type: "list",
92360                     listValues: ["ltr", "rtl", "lro", "rlo"]
92361                 },
92362                 id: {
92363                     attributeName: "id",
92364                     required: false,
92365                     type: "string"
92366                 },
92367                 version: {
92368                     attributeName: "version",
92369                     required: false,
92370                     type: "string"
92371                 },
92372                 height: {
92373                     attributeName: "height",
92374                     required: false,
92375                     type: "integer"
92376                 },
92377                 width: {
92378                     attributeName: "width",
92379                     required: false,
92380                     type: "integer"
92381                 },
92382                 viewmodes: {
92383                     attributeName: "viewmodes",
92384                     required: false,
92385                     type: "list",
92386                     listValues: ["windowed", "floating", "fullscreen", "maximized", "minimized"]
92387                 },
92388                 defaultlocale: {
92389                     attributeName: "defaultlocale",
92390                     required: false,
92391                     type: "iso-language"
92392                 },
92393             },
92394             children: {
92395                 name: {
92396                     nodeName: "name",
92397                     required: false,
92398                     occurrence: 0,
92399                     type: "string",
92400                     attributes: {
92401                         "xml:lang": {
92402                             attributeName: "xml:lang",
92403                             required: false,
92404                             type: "iso-language",
92405                             unique: true
92406                         },
92407                         dir: {
92408                             attributeName: "dir",
92409                             required: false,
92410                             type: "list",
92411                             listValues: ["ltr", "rtl", "lro", "rlo"]
92412                         },
92413                         "short": {
92414                             attributeName: "short",
92415                             required: false,
92416                             type: "string"
92417                         }
92418                     },
92419                     children: {
92420                         span: {
92421                             nodeName: "span",
92422                             required: false,
92423                             type: "string",
92424                             attributes: {
92425                                 "xml:lang": {
92426                                     attributeName: "xml:lang",
92427                                     required: false,
92428                                     type: "iso-language",
92429                                     unique: true
92430                                 },
92431                                 dir: {
92432                                     attributeName: "dir",
92433                                     required: false,
92434                                     type: "list",
92435                                     listValues: ["ltr", "rtl", "lro", "rlo"]
92436                                 }
92437                             }
92438                         }
92439                     }
92440                 },
92441                 description: {
92442                     nodeName: "description",
92443                     required: false,
92444                     occurrence: 0,
92445                     type: "string",
92446                     attributes: {
92447                         "xml:lang": {
92448                             attributeName: "xml:lang",
92449                             required: false,
92450                             type: "iso-language",
92451                             unique: true
92452                         },
92453                         dir: {
92454                             attributeName: "dir",
92455                             required: false,
92456                             type: "list",
92457                             listValues: ["ltr", "rtl", "lro", "rlo"]
92458                         }
92459                     },
92460                     children: {
92461                         span: {
92462                             nodeName: "span",
92463                             required: false,
92464                             type: "string",
92465                             attributes: {
92466                                 "xml:lang": {
92467                                     attributeName: "xml:lang",
92468                                     required: false,
92469                                     type: "iso-language",
92470                                     unique: true
92471                                 },
92472                                 dir: {
92473                                     attributeName: "dir",
92474                                     required: false,
92475                                     type: "list",
92476                                     listValues: ["ltr", "rtl", "lro", "rlo"]
92477                                 }
92478                             }
92479                         }
92480                     }
92481                 },
92482                 author: {
92483                     nodeName: "author",
92484                     required: false,
92485                     occurrence: 0,
92486                     type: "string",
92487                     attributes: {
92488                         "xml:lang": {
92489                             attributeName: "xml:lang",
92490                             required: false,
92491                             type: "iso-language",
92492                         },
92493                         dir: {
92494                             attributeName: "dir",
92495                             required: false,
92496                             type: "list",
92497                             listValues: ["ltr", "rtl", "lro", "rlo"]
92498                         },
92499                         href: {
92500                             attributeName: "href",
92501                             required: false,
92502                             type: "regex",
92503                             regex: constants.REGEX.URL
92504                         },
92505                         email: {
92506                             attributeName: "email",
92507                             required: false,
92508                             type: "regex",
92509                             regex: constants.REGEX.EMAIL
92510                         }
92511                     },
92512                     children: {
92513                         span: {
92514                             nodeName: "span",
92515                             required: false,
92516                             type: "string",
92517                             attributes: {
92518                                 "xml:lang": {
92519                                     attributeName: "xml:lang",
92520                                     required: false,
92521                                     type: "iso-language",
92522                                     unique: true
92523                                 },
92524                                 dir: {
92525                                     attributeName: "dir",
92526                                     required: false,
92527                                     type: "list",
92528                                     listValues: ["ltr", "rtl", "lro", "rlo"]
92529                                 }
92530                             }
92531                         }
92532                     }
92533                 },
92534                 license: {
92535                     nodeName: "license",
92536                     required: false,
92537                     occurrence: 0,
92538                     type: "string",
92539                     attributes: {
92540                         "xml:lang": {
92541                             attributeName: "xml:lang",
92542                             required: false,
92543                             type: "iso-language",
92544                         },
92545                         dir: {
92546                             attributeName: "dir",
92547                             required: false,
92548                             type: "list",
92549                             listValues: ["ltr", "rtl", "lro", "rlo"]
92550                         },
92551                         href: {
92552                             attributeName: "href",
92553                             type: "regex",
92554                             required: false,
92555                             regex: constants.REGEX.URL
92556                         }
92557                     },
92558                     children: {
92559                         span: {
92560                             nodeName: "span",
92561                             required: false,
92562                             type: "string",
92563                             attributes: {
92564                                 "xml:lang": {
92565                                     attributeName: "xml:lang",
92566                                     required: false,
92567                                     type: "iso-language",
92568                                     unique: true
92569                                 },
92570                                 dir: {
92571                                     attributeName: "dir",
92572                                     required: false,
92573                                     type: "list",
92574                                     listValues: ["ltr", "rtl", "lro", "rlo"]
92575                                 }
92576                             }
92577                         }
92578                     }
92579                 },
92580                 icon: {
92581                     nodeName: "icon",
92582                     required: false,
92583                     occurrence: 0,
92584                     attributes: {
92585                         "xml:lang": {
92586                             attributeName: "xml:lang",
92587                             required: false,
92588                             type: "iso-language",
92589                         },
92590                         dir: {
92591                             attributeName: "dir",
92592                             required: false,
92593                             type: "list",
92594                             listValues: ["ltr", "rtl", "lro", "rlo"]
92595                         },
92596                         src: {
92597                             attributeName: "src",
92598                             required: true,
92599                             type: "string"
92600                         },
92601                         width: {
92602                             attributeName: "width",
92603                             required: false,
92604                             type: "integer"
92605                         },
92606                         height: {
92607                             attributeName: "height",
92608                             required: false,
92609                             type: "integer"
92610                         }
92611                     }
92612                 },
92613                 content: {
92614                     nodeName: "content",
92615                     required: false,
92616                     occurrence: 1,
92617                     attributes: {
92618                         "xml:lang": {
92619                             attributeName: "xml:lang",
92620                             required: false,
92621                             type: "iso-language",
92622                             unique: true
92623                         },
92624                         dir: {
92625                             attributeName: "dir",
92626                             required: false,
92627                             type: "list",
92628                             listValues: ["ltr", "rtl", "lro", "rlo"]
92629                         },
92630                         src: {
92631                             attributeName: "src",
92632                             required: true,
92633                             type: "string"
92634                         },
92635                         encoding: {
92636                             attributeName: "encoding",
92637                             required: false,
92638                             type: "string"
92639                         },
92640                         type: {
92641                             attributeName: "type",
92642                             required: false,
92643                             type: "string"
92644                         }
92645                     }
92646                 },
92647                 setting: {
92648                     nodeName: "tizen:setting",
92649                     required: false,
92650                     occurrence: 0,
92651                     attributes: {
92652                         'screen-orientation': {
92653                             attributeName: "screen-orientation",
92654                             required: false,
92655                             type: "list",
92656                             listValues: ['portrait', 'landscape']
92657                         },
92658                         'context-menu': {
92659                             attributeName: "context-menu",
92660                             required: false,
92661                             type: "list",
92662                             listValues: ['enable', 'disable']
92663                         },
92664                         'background-support': {
92665                             attributeName: "background-support",
92666                             required: false,
92667                             type: "list",
92668                             listValues: ['enable', 'disable']
92669                         },
92670                         'encryption': {
92671                             attributeName: "encryption",
92672                             required: true,
92673                             type: "list",
92674                             listValues: ['enable', 'disable']
92675                         },
92676                         'install-location': {
92677                             attributeName: "install-location",
92678                             required: false,
92679                             type: "list",
92680                             listValues: ['auto', 'internal-only', 'perfer-external']
92681                         }
92682                     }
92683                 },
92684                 application: {
92685                     nodeName: "tizen:application",
92686                     required: true,
92687                     occurrence: 1,
92688                     attributes: {
92689                         id: {
92690                             attributeName: "id",
92691                             required: true,
92692                             type: "string"
92693                         },
92694                         required_version: {
92695                             attributeName: "required_version",
92696                             required: true,
92697                             type: "string"
92698                         },
92699                         package: {
92700                             attributeName: "package",
92701                             required: false,
92702                             type: "string"
92703                         }
92704                     }
92705                 },
92706                 "tizen:content": {
92707                     nodeName: "tizen:content",
92708                     required: true,
92709                     occurrence: 1,
92710                     attributes: {
92711                         src: {
92712                             attributeName: "src",
92713                             required: true,
92714                             type: "string"
92715                         }
92716                     }
92717                 },
92718                 control: {
92719                     nodeName: "tizen:app-control",
92720                     required: false,
92721                     occurrence: 0,
92722                     children: {
92723                         src: {
92724                             nodeName: "tizen:src",
92725                             required: true,
92726                             occurence: 0,
92727                             attributes: {
92728                                 name: {
92729                                     attributeName: "name",
92730                                     required: false,
92731                                     type: "string"
92732                                 }
92733                             }
92734                         },
92735                         operation: {
92736                             nodeName: "tizen:operation",
92737                             required: true,
92738                             occurence: 0,
92739                             attributes: {
92740                                 name: {
92741                                     attributeName: "name",
92742                                     required: false,
92743                                     type: "string"
92744                                 }
92745                             }
92746                         },
92747                         uri: {
92748                             nodeName: "tizen:uri",
92749                             required: false,
92750                             occurence: 0,
92751                             attributes: {
92752                                 name: {
92753                                     attributeName: "name",
92754                                     required: false,
92755                                     type: "string"
92756                                 }
92757                             }
92758                         },
92759                         mime: {
92760                             nodeName: "tizen:mime",
92761                             required: false,
92762                             occurence: 0,
92763                             attributes: {
92764                                 name: {
92765                                     attributeName: "name",
92766                                     required: false,
92767                                     type: "string"
92768                                 }
92769                             }
92770                         }
92771                     }
92772                 },
92773                 "app-widget": {
92774                     nodeName: "tizen:app-widget",
92775                     required: false,
92776                     occurrence: 0,
92777                     attributes: {
92778                         id: {
92779                             attributeName: "id",
92780                             required: true,
92781                             type: "string"
92782                         },
92783                         primary: {
92784                             attributeName: "primary",
92785                             required: true,
92786                             type: "list",
92787                             listValues: ['true', 'false']
92788                         },
92789                         "auto-launch": {
92790                             attributeName: "auto-launch",
92791                             required: false,
92792                             type: "list",
92793                             listValues: ['true', 'false']
92794                         },
92795                         "update-period": {
92796                             attributeName: "update-period",
92797                             required: false,
92798                             type: "integer"
92799                         }
92800                     },
92801                     children: {
92802                         "box-label": {
92803                             nodeName: "tizen:box-label",
92804                             required: true,
92805                             occurence: 1
92806                         },
92807                         "box-icon": {
92808                             nodeName: "tizen:box-icon",
92809                             required: true,
92810                             occurence: 1,
92811                             attributes: {
92812                                 src: {
92813                                     attributeName: "src",
92814                                     required: true,
92815                                     type: "string"
92816                                 }
92817                             }
92818                         },
92819                         "box-content": {
92820                             nodeName: "tizen:box-content",
92821                             required: true,
92822                             occurence: 1,
92823                             attributes: {
92824                                 src: {
92825                                     attributeName: "src",
92826                                     required: true,
92827                                     type: "string"
92828                                 },
92829                                 "mouse-event": {
92830                                     attributeName: "mouse-event",
92831                                     required: false,
92832                                     type: "string"
92833                                 },
92834                                 "touch-event": {
92835                                     attributeName: "touch-event",
92836                                     required: false,
92837                                     type: "string"
92838                                 }
92839                             },
92840                             children: {
92841                                 "box-size": {
92842                                     nodeName: "tizen:box-size",
92843                                     required: false,
92844                                     occurence: 1,
92845                                     attributes: {
92846                                         "preview": {
92847                                             attributeName: "preview",
92848                                             required: false,
92849                                             type: "string"
92850                                         }
92851                                     }
92852                                 },
92853                                 pd: {
92854                                     nodeName: "tizen:pd",
92855                                     required: false,
92856                                     occurence: 1,
92857                                     attributes: {
92858                                         "src": {
92859                                             attributeName: "src",
92860                                             required: true,
92861                                             type: "string"
92862                                         },
92863                                         "width": {
92864                                             attributeName: "width",
92865                                             required: true,
92866                                             type: "integer"
92867                                         },
92868                                         "height": {
92869                                             attributeName: "height",
92870                                             required: true,
92871                                             type: "integer"
92872                                         }
92873                                     }
92874                                 }
92875                             }
92876                         }
92877                     }
92878                 },
92879                 account: {
92880                     nodeName: "tizen:account",
92881                     required: false,
92882                     occurrence: 0,
92883                     attributes: {
92884                         "multiple-account-support": {
92885                             attributeName: "multiple-account-support",
92886                             required: true,
92887                             type: "list",
92888                             listValues: ['true', 'false']
92889                         }
92890                     },
92891                     children: {
92892                         icon: {
92893                             nodeName: "tizen:icon",
92894                             required: false,
92895                             occurence: 1,
92896                             attributes: {
92897                                 section: {
92898                                     attributeName: "section",
92899                                     required: true,
92900                                     type: "string"
92901                                 }
92902                             }
92903                         },
92904                         "display-name": {
92905                             nodeName: "tizen:display-name",
92906                             required: false,
92907                             occurence: 1,
92908                             attributes: {
92909                                 "xml:lang": {
92910                                     attributeName: "xml:lang",
92911                                     required: false,
92912                                     type: "string"
92913                                 }
92914                             }
92915                         },
92916                         capability: {
92917                             nodeName: "capability",
92918                             required: false,
92919                             occurence: 1
92920                         }
92921                     }
92922                 },
92923                 feature: {
92924                     nodeName: "tizen:privilege",
92925                     required: false,
92926                     occurrence: 0,
92927                     attributes: {
92928                         "xml:lang": {
92929                             attributeName: "xml:lang",
92930                             required: false,
92931                             type: "iso-language",
92932                         },
92933                         dir: {
92934                             attributeName: "dir",
92935                             required: false,
92936                             type: "list",
92937                             listValues: ["ltr", "rtl", "lro", "rlo"]
92938                         },
92939                         name: {
92940                             attributeName: "name",
92941                             required: true,
92942                             type: "list",
92943                             listValues: ["http://www.w3.org/TR/battery-status/",
92944                                          "http://www.w3.org/TR/geolocation-API/",
92945                                          "http://www.w3.org/TR/touch-events/",
92946                                          "http://www.w3.org/TR/vibration/",
92947                                          "http://tizen.org/privilege/tizen",
92948                                          "http://tizen.org/privilege/alarm",
92949                                          "http://tizen.org/privilege/application.launch",
92950                                          "http://tizen.org/privilege/appmanager.kill", "http://tizen.org/privilege/appmanager.certificate",
92951                                          "http://tizen.org/privilege/bluetoothmanager", "http://tizen.org/privilege/bluetooth.admin",
92952                                          "http://tizen.org/privilege/bluetooth.gap", "http://tizen.org/privilege/bluetooth.spp",
92953                                          "http://tizen.org/privilege/bookmark.read", "http://tizen.org/privilege/bookmark.write",
92954                                          "http://tizen.org/privilege/calendar.read", "http://tizen.org/privilege/calendar.write",
92955                                          "http://tizen.org/privilege/callhistory.read", "http://tizen.org/privilege/callhistory.write",
92956                                          "http://tizen.org/privilege/contact.read", "http://tizen.org/privilege/contact.write",
92957                                          "http://tizen.org/privilege/content.read", "http://tizen.org/privilege/content.write",
92958                                          "http://tizen.org/privilege/datacontrol.consumer",
92959                                          "http://tizen.org/privilege/datasync",
92960                                          "http://tizen.org/privilege/download",
92961                                          "http://tizen.org/privilege/filesystem.read", "http://tizen.org/privilege/filesystem.write",
92962                                          "http://tizen.org/privilege/messaging.read", "http://tizen.org/privilege/messaging.write",
92963                                          "http://tizen.org/privilege/networkbearerselection",
92964                                          "http://tizen.org/privilege/nfc.common", "http://tizen.org/privilege/nfc.admin",
92965                                          "http://tizen.org/privilege/nfc.tag", "http://tizen.org/privilege/nfc.p2p",
92966                                          "http://tizen.org/privilege/notification",
92967                                          "http://tizen.org/privilege/packagemanager.install", "http://tizen.org/privilege/package.info",
92968                                          "http://tizen.org/privilege/power",
92969                                          "http://tizen.org/privilege/push",
92970                                          "http://tizen.org/privilege/setting",
92971                                          "http://tizen.org/privilege/system", "http://tizen.org/privilege/systemmanager",
92972                                          "http://tizen.org/privilege/time"]
92973                         },
92974                         required: {
92975                             attributeName: "required",
92976                             type: "boolean",
92977                             required: false
92978                         }
92979                     },
92980                     children: {
92981                         param: {
92982                             nodeName: "param",
92983                             required: false,
92984                             occurrence: 0,
92985                             attributes: {
92986                                 "xml:lang": {
92987                                     attributeName: "xml:lang",
92988                                     required: false,
92989                                     type: "iso-language",
92990                                 },
92991                                 dir: {
92992                                     attributeName: "dir",
92993                                     required: false,
92994                                     type: "list",
92995                                     listValues: ["ltr", "rtl", "lro", "rlo"]
92996                                 },
92997                                 name: {
92998                                     attributeName: "name",
92999                                     required: true,
93000                                     type: "string",
93001                                 },
93002                                 value: {
93003                                     attributeName: "value",
93004                                     required: true,
93005                                     type: "string",
93006                                 }
93007                             }
93008                         }
93009                     }
93010                 },
93011                 preference: {
93012                     nodeName: "preference",
93013                     required: false,
93014                     occurrence: 0,
93015                     attributes: {
93016                         "xml:lang": {
93017                             attributeName: "xml:lang",
93018                             required: false,
93019                             type: "iso-language",
93020                         },
93021                         dir: {
93022                             attributeName: "dir",
93023                             required: false,
93024                             type: "list",
93025                             listValues: ["ltr", "rtl", "lro", "rlo"]
93026                         },
93027                         name: {
93028                             attributeName: "name",
93029                             required: true,
93030                             type: "string"
93031                         },
93032                         value: {
93033                             type: "string",
93034                             required: false,
93035                             attributeName: "value"
93036                         },
93037                         readonly: {
93038                             attributeName: "readonly",
93039                             type: "boolean",
93040                             required: false
93041                         }
93042                     }
93043                 }
93044             }
93045         }
93046     }
93047 };
93048
93049 });
93050 define('ripple/platform/tizen/2.0/spec/device', function (require, exports, module) {
93051 /*
93052  *  Copyright 2011 Intel Corporation.
93053  *
93054  * Licensed under the Apache License, Version 2.0 (the "License");
93055  * you may not use this file except in compliance with the License.
93056  * You may obtain a copy of the License at
93057  *
93058  * http://www.apache.org/licenses/LICENSE-2.0
93059  *
93060  * Unless required by applicable law or agreed to in writing, software
93061  * distributed under the License is distributed on an "AS IS" BASIS,
93062  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
93063  * See the License for the specific language governing permissions and
93064  * limitations under the License.
93065  */
93066 var event = require('ripple/event'),
93067     utils = require('ripple/utils'),
93068     StorageTypeTable = {
93069         "UNKNOWN": "UNKNOWN",
93070         "INTERNAL": "INTERNAL",
93071         "MMC": "MMC",
93072         "USB_HOST": "USB_HOST"
93073     },
93074     NetworkTypeTable = {
93075         "NONE": "NONE",
93076         "2G": "2G",
93077         "2.5G": "2.5G",
93078         "3G": "3G",
93079         "4G": "4G",
93080         "WIFI": "WIFI",
93081         "ETHERNET": "ETHERNET",
93082         "UNKNOWN": "UNKNOWN"
93083     },
93084     LocaleTable = {
93085         "eng_USA": "eng_USA",
93086         "eng_CAN": "eng_CAN",
93087         "deu_DEU": "deu_DEU",
93088         "jpn_JPN": "jpn_JPN",
93089         "zho_CHN": "zho_CHN",
93090         "UNKNOWN": "UNKNOWN"
93091     },
93092     SimStateTable = {
93093         "ABSENT": "ABSENT",
93094         "INITIALIZING": "INITIALIZING",
93095         "READY": "READY",
93096         "PIN_REQUIRED": "PIN_REQUIRED",
93097         "PUK_REQUIRED":"PUK_REQUIRED",
93098         "NETWORK_LOCKED": "NETWORK_LOCKED",
93099         "SIM_LOCKED": "SIM_LOCKED",
93100         "UNKNOWN": "UNKNOWN"
93101     };
93102
93103 function deviceStatusEventTrigger(setting) {
93104     event.trigger("DeviceStatusChanged", [setting]);
93105 }
93106
93107 module.exports = {
93108     "Config": {
93109         "vibratingMode": {
93110             "name": "Vibrator",
93111             "control": {
93112                 "type": "checkbox",
93113                 "value": true
93114             },
93115             "callback": function (setting) {
93116                 event.trigger("VibratingModeChanged", [setting]);
93117             }
93118         },
93119         "lockScreen": {
93120             "name": "Lock Screen",
93121             "control": {
93122                 "type": "checkbox",
93123                 "value": false
93124             },
93125             "callback": function (setting) {
93126                 event.trigger("LockScreenChanged", [setting]);
93127             }
93128         }
93129     },
93130     "DEVICE_ORIENTATION": {
93131         "status": {
93132             "name": "Status",
93133             "control": {
93134                 "type": "label",
93135                 "innertext": "PORTRAIT_PRIMARY",
93136                 "value": "PORTRAIT_PRIMARY"
93137             },
93138             "event": "LayoutChanged"
93139         }
93140     },
93141     "CPU": {
93142         "load": {
93143             "name": "Load",
93144             "control": {
93145                 "type": "number",
93146                 "value": 0.1
93147             },
93148             "event": "CpuLoadChanged",
93149             "callback": function (setting) {
93150                 if (setting > 1) setting = 1;
93151                 if (setting < 0) setting = 0;
93152                 event.trigger("CpuLoadChanged", [setting]);
93153             }
93154         }
93155     },
93156     "STORAGE": {
93157         "type": {
93158             "name": "Type",
93159             "control": {
93160                 "type": "select",
93161                 "value": StorageTypeTable["INTERNAL"]
93162             },
93163             "options": (function () {
93164                 var optionList = {};
93165                 utils.forEach(StorageTypeTable, function (key, value) {
93166                     optionList[key] = StorageTypeTable[value];
93167                 });
93168
93169                 return optionList;
93170             }())
93171         },
93172         "capacity": {
93173             "name": "Capacity",
93174             "control": {
93175                 "type": "label",
93176                 "value": 16000000000
93177             },
93178         },
93179         "availableCapacity": {
93180             "name": "AvailableCapacity",
93181             "control": {
93182                 "type": "number",
93183                 "value": 12000000000
93184             },
93185             "callback": function (setting) {
93186                 event.trigger("AvailCapacityChanged", [setting]);
93187             }
93188         },
93189         "isRemovable": {
93190             "name": "IsRemovable",
93191             "control": {
93192                 "type": "checkbox",
93193                 "value": true
93194             }
93195         }
93196     },
93197     "BUILD": {
93198         "model": {
93199             "name": "Model",
93200             "control": {
93201                 "type": "label",
93202                 "innertext": "tizen-2.2 build",
93203                 "value": "tizen-2.2 build"
93204             }
93205         },
93206         "manufacturer": {
93207             "name": "Manufacturer",
93208             "control": {
93209                 "type": "label",
93210                 "innertext": "Tizen",
93211                 "value": "Tizen"
93212             }
93213         }
93214     },
93215     "LOCALE": {
93216         "language": {
93217             "name": "Language",
93218             "control": {
93219                 "type": "select",
93220                 "value": LocaleTable["eng_USA"]
93221             },
93222             "options": (function () {
93223                 var optionList = {};
93224                 utils.forEach(LocaleTable, function (key, value) {
93225                     optionList[key] = LocaleTable[value];
93226                 });
93227
93228                 return optionList;
93229             }())
93230         },
93231         "country": {
93232             "name": "Country",
93233             "control": {
93234                 "type": "select",
93235                 "value": LocaleTable["eng_USA"]
93236             },
93237             "options": (function () {
93238                 var optionList = {};
93239                 utils.forEach(LocaleTable, function (key, value) {
93240                     optionList[key] = LocaleTable[value];
93241                 });
93242
93243                 return optionList;
93244             }())
93245         }
93246     },
93247     "DISPLAY": {
93248         "resolutionWidth": {
93249             "name": "Resolution Width",
93250             "control": {
93251                 "type": "label",
93252                 "value": 0
93253             }
93254         },
93255         "resolutionHeight": {
93256             "name": "Resolution Height",
93257             "control": {
93258                 "type": "label",
93259                 "value": 0
93260             }
93261         },
93262         "dotsPerInchWidth": {
93263             "name": "DPI-X",
93264             "control": {
93265                 "type": "label",
93266                 "value": 0
93267             }
93268         },
93269         "dotsPerInchHeight": {
93270             "name": "DPI-Y",
93271             "control": {
93272                 "type": "label",
93273                 "value": 0
93274             }
93275         },
93276         "physicalWidth": {
93277             "name": "Physical Width",
93278             "control": {
93279                 "type": "label",
93280                 "value": 0
93281             }
93282         },
93283         "physicalHeight": {
93284             "name": "Physical Height",
93285             "control": {
93286                 "type": "label",
93287                 "value": 0
93288             }
93289         },
93290         "brightness": {
93291             "name": "Brightness",
93292             "control": {
93293                 "type": "number",
93294                 "value": 1
93295             },
93296             "event": "DisplayBrightnessChanged",
93297             "callback": function (setting) {
93298                 if (setting > 1) setting = 1;
93299                 if (setting < 0) setting = 0;
93300                 event.trigger("DisplayBrightnessChanged", [setting]);
93301             }
93302         }
93303     },
93304     "NETWORK": {
93305         "networkType": {
93306             "name": "Network Type",
93307             "control" : {
93308                 "type": "select",
93309                 "value": NetworkTypeTable["NONE"]
93310             },
93311             "options": (function () {
93312                 var optionList = {};
93313                 utils.forEach(NetworkTypeTable, function (key, value) {
93314                     optionList[key] = NetworkTypeTable[value];
93315                 });
93316
93317                 return optionList;
93318             }())
93319         }
93320     },
93321     "WIFI_NETWORK": {
93322         "status": {
93323             "name": "Status",
93324             "control": {
93325                 "type": "checkbox",
93326                 "value": false
93327             },
93328             "event": "WiFiNetworkStatusChanged",
93329             "callback": function (setting) {
93330                 event.trigger("WiFiNetworkStatusChanged", [setting]);
93331             }
93332         },
93333         "ssid": {
93334             "name": "SSID",
93335             "control": {
93336                 "type": "text",
93337                 "value": "Tizen WiFi"
93338             }
93339         },
93340         "ipAddress": {
93341             "name": "IP Address",
93342             "control": {
93343                 "type": "text",
93344                 "value": "192.168.0.1"
93345             }
93346         },
93347         "ipv6Address": {
93348             "name": "IPv6 Address",
93349             "control": {
93350                 "type": "text",
93351                 "value": "2001:db8:85a3:0:0:0:70:7334"
93352             }
93353         },
93354         "signalStrength": {
93355             "name": "Signal Strength",
93356             "control": {
93357                 "type": "select",
93358                 "value": 0
93359             },
93360             "options": (function () {
93361                 var i,
93362                     optionList = {};
93363
93364                 for (i = 0; i <= 10; i++) {
93365                     optionList[i] = i;
93366                 }
93367
93368                 return optionList;
93369             }())
93370         }
93371     },
93372     "CELLULAR_NETWORK": {
93373         "status": {
93374             "name": "Status",
93375             "control": {
93376                 "type": "checkbox",
93377                 "value": true
93378             },
93379             "event": "CellularNetworkStatusChanged",
93380             "callback": function (setting) {
93381                 event.trigger("CellularNetworkStatusChanged", [setting]);
93382             }
93383         },
93384         "apn": {
93385             "name": "APN",
93386             "control": {
93387                 "type": "text",
93388                 "value": "Tizen"
93389             }
93390         },
93391         "ipAddress": {
93392             "name": "IP Address",
93393             "control": {
93394                 "type": "text",
93395                 "value": "10.0.2.16"
93396             }
93397         },
93398         "ipv6Address": {
93399             "name": "IPv6 Address",
93400             "control": {
93401                 "type": "text",
93402                 "value": "2001:db8:85a3:0:0:0:70:7334"
93403             }
93404         },
93405         "mcc": {
93406             "name": "MCC",
93407             "control": {
93408                 "type": "number",
93409                 "value": 460
93410             }
93411         },
93412         "mnc": {
93413             "name": "MNC",
93414             "control": {
93415                 "type": "number",
93416                 "value": 0
93417             }
93418         },
93419         "cellId": {
93420             "name": "Cell ID",
93421             "control": {
93422                 "type": "number",
93423                 "value": 0
93424             }
93425         },
93426         "lac": {
93427             "name": "LAC",
93428             "control": {
93429                 "type": "number",
93430                 "value": 0
93431             }
93432         },
93433         "isRoaming": {
93434             "name": "Roaming",
93435             "control": {
93436                 "type": "checkbox",
93437                 "value": true
93438             }
93439         },
93440         "isFlightMode": {
93441             "name": "Flight Mode",
93442             "control": {
93443                 "type": "checkbox",
93444                 "value": false
93445             },
93446             "callback": function (setting) {
93447                 event.trigger("FlightModeChanged", [setting]);
93448             }
93449         },
93450         "imei": {
93451             "name": "IMEI",
93452             "control": {
93453                 "type": "text",
93454                 "value": "012417005203000"
93455             }
93456         }
93457     },
93458     "SIM": {
93459         "state": {
93460             "name": "State",
93461             "control": {
93462                 "type": "select",
93463                 "value": SimStateTable["READY"]
93464             },
93465             "options": (function () {
93466                 var optionList = {};
93467                 utils.forEach(SimStateTable, function (key, value) {
93468                     optionList[key] = SimStateTable[value];
93469                 });
93470
93471                 return optionList;
93472             }())
93473         },
93474         "operatorName": {
93475             "name": "Operator Name",
93476             "control": {
93477                 "type": "text",
93478                 "value": "Tizen"
93479             }
93480         },
93481         "msisdn": {
93482             "name": "MSISDN",
93483             "control": {
93484                 "type": "text",
93485                 "value": "088123456789"
93486             }
93487         },
93488         "iccid": {
93489             "name": "ICCID",
93490             "control": {
93491                 "type": "text",
93492                 "value": "123000MFSSYYGXXXXXXP"
93493             }
93494         },
93495         "mcc": {
93496             "name": "MCC",
93497             "control": {
93498                 "type": "number",
93499                 "value": 460
93500             }
93501         },
93502         "mnc": {
93503             "name": "MNC",
93504             "control": {
93505                 "type": "number",
93506                 "value": 0
93507             }
93508         },
93509         "msin": {
93510             "name": "MSIN",
93511             "control": {
93512                 "type": "text",
93513                 "value": "H1 H2 H3 S 12345"
93514             }
93515         },
93516         "spn": {
93517             "name": "SPN",
93518             "control": {
93519                 "type": "text",
93520                 "value": "TizenSPN"
93521             }
93522         }
93523     },
93524     "PERIPHERAL": {
93525         "isVideoOutputOn": {
93526             "name": "Video Output",
93527             "control": {
93528                 "type": "checkbox",
93529                 "value": false
93530             }
93531         }
93532     }
93533 };
93534
93535
93536 });
93537 define('ripple/platform/tizen/2.0/spec/sensor', function (require, exports, module) {
93538 /*
93539  *  Copyright 2012 Intel Corporation.
93540  *
93541  * Licensed under the Apache License, Version 2.0 (the "License");
93542  * you may not use this file except in compliance with the License.
93543  * You may obtain a copy of the License at
93544  *
93545  * http://www.apache.org/licenses/LICENSE-2.0
93546  *
93547  * Unless required by applicable law or agreed to in writing, software
93548  * distributed under the License is distributed on an "AS IS" BASIS,
93549  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
93550  * See the License for the specific language governing permissions and
93551  * limitations under the License.
93552  */
93553 var event = require('ripple/event');
93554
93555 function sensorStatusEventTrigger(setting) {
93556     event.trigger("SensorStatusChanged", [setting]);
93557 }
93558
93559 module.exports = {
93560     "Accelerometer": {
93561         "resolution": 0.039239998906850815,
93562         "minDelay": 20,
93563         "range": 20.051639556884766,
93564         "name": "Accelerometer",
93565         "type": "Accelerometer"
93566     },
93567     "MagneticField": {
93568         "x": {
93569             "name": "X",
93570             "control": {
93571                 "type": "range",
93572                 "value": 100.0000000000000000,
93573                 "min": 0.0000000000000000,
93574                 "max": 200.0000000000000000,
93575                 "step": 0.0000000000000001
93576             },
93577             "callback": function (setting) {
93578                 event.trigger("MagneticField-xChanged", [setting]);
93579             }
93580         },
93581
93582         "y": {
93583             "name": "Y",
93584             "control": {
93585                 "type": "range",
93586                 "value": 100.0000000000000000,
93587                 "min": 0.0000000000000000,
93588                 "max": 200.0000000000000000,
93589                 "step": 0.0000000000000001
93590             },
93591             "callback": function (setting) {
93592                 event.trigger("MagneticField-yChanged", [setting]);
93593             }
93594         },
93595
93596         "z": {
93597             "name": "Z",
93598             "control": {
93599                 "type": "range",
93600                 "value": 100.0000000000000000,
93601                 "min": 0.0000000000000000,
93602                 "max": 200.0000000000000000,
93603                 "step": 0.0000000000000001
93604             },
93605             "callback": function (setting) {
93606                 event.trigger("MagneticField-zChanged", [setting]);
93607             }
93608         },
93609
93610         "resolution": 1,
93611         "minDelay": 20,
93612         "range": 359,
93613         "name": "MagneticField",
93614         "type": "MagneticField"
93615     },
93616     "Rotation": {
93617         "resolution": 1,
93618         "minDelay": 20,
93619         "range": 359,
93620         "name": "Rotation",
93621         "type": "Rotation"
93622     },
93623     "Orientation": {
93624         "resolution": 1,
93625         "minDelay": 20,
93626         "range": 359,
93627         "name": "Orientation",
93628         "type": "Orientation"
93629     }
93630 };
93631
93632 });
93633 define('ripple/platform/tizen/2.0/spec/ui', function (require, exports, module) {
93634 /*
93635  *  Copyright 2011 Intel Corporation.
93636  *
93637  * Licensed under the Apache License, Version 2.0 (the "License");
93638  * you may not use this file except in compliance with the License.
93639  * You may obtain a copy of the License at
93640  *
93641  * http://www.apache.org/licenses/LICENSE-2.0
93642  *
93643  * Unless required by applicable law or agreed to in writing, software
93644  * distributed under the License is distributed on an "AS IS" BASIS,
93645  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
93646  * See the License for the specific language governing permissions and
93647  * limitations under the License.
93648  */
93649 module.exports = {
93650     plugins: [
93651         "sensors",
93652         "communication",
93653         "geoView",
93654         "widgetConfig",
93655         "deviceSettings",
93656         "application",
93657         "network",
93658         "power",
93659         "download",
93660         "package"
93661     ]
93662 };
93663
93664 });
93665 define('ripple/platform/tizen/2.0/spec', function (require, exports, module) {
93666 /*
93667  *  Copyright 2012 Intel Corporation.
93668  *
93669  * Licensed under the Apache License, Version 2.0 (the "License");
93670  * you may not use this file except in compliance with the License.
93671  * You may obtain a copy of the License at
93672  *
93673  * http://www.apache.org/licenses/LICENSE-2.0
93674  *
93675  * Unless required by applicable law or agreed to in writing, software
93676  * distributed under the License is distributed on an "AS IS" BASIS,
93677  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
93678  * See the License for the specific language governing permissions and
93679  * limitations under the License.
93680  */
93681
93682 module.exports = {
93683
93684     id: "tizen",
93685     version: "2.2",
93686     name: "TIZEN",
93687
93688     persistencePrefix: "tizen1-",
93689
93690     config: require('ripple/platform/tizen/2.0/spec/config'),
93691     ui: require('ripple/platform/tizen/2.0/spec/ui'),
93692     device: require('ripple/platform/tizen/2.0/spec/device'),
93693     sensor: require('ripple/platform/tizen/2.0/spec/sensor'),
93694     DeviceMotionEvent: require('ripple/platform/tizen/2.0/DeviceMotionEvent'),
93695     DeviceOrientationEvent: require('ripple/platform/tizen/2.0/DeviceOrientationEvent'),
93696
93697     objects: {
93698         Coordinates: {
93699             path: "w3c/1.0/Coordinates"
93700         },
93701         Position: {
93702             path: "w3c/1.0/Position"
93703         },
93704         PositionError: {
93705             path: "w3c/1.0/PositionError"
93706         },
93707         SensorConnection: {
93708             path: "w3c/1.0/SensorConnection"
93709         },
93710         navigator: {
93711             path: "tizen/2.0/navigator",
93712             children: {
93713                 geolocation: {
93714                     path: "wac/2.0/geolocation"
93715                 },
93716                 battery: {
93717                     path: "tizen/2.0/battery"
93718                 }
93719             }
93720         },
93721         tizen: {
93722             feature: "http://tizen.org/privilege/tizen",
93723             children: {
93724                 AlarmAbsolute: {
93725                     path: "tizen/2.0/AlarmAbsolute"
93726                 },
93727                 AlarmRelative: {
93728                     path: "tizen/2.0/AlarmRelative"
93729                 },
93730                 ApplicationControl: {
93731                     path: "tizen/2.0/ApplicationControl"
93732                 },
93733                 ApplicationControlData: {
93734                     path: "tizen/2.0/ApplicationControlData"
93735                 },
93736                 AttributeFilter: {
93737                     path: "tizen/2.0/AttributeFilter"
93738                 },
93739                 AttributeRangeFilter: {
93740                     path: "tizen/2.0/AttributeRangeFilter"
93741                 },
93742                 BookmarkFolder: {
93743                     path: "tizen/2.0/BookmarkFolder"
93744                 },
93745                 BookmarkItem: {
93746                     path: "tizen/2.0/BookmarkItem"
93747                 },
93748                 CalendarAlarm: {
93749                     path: "tizen/2.0/CalendarAlarm"
93750                 },
93751                 CalendarAttendee: {
93752                     path: "tizen/2.0/CalendarAttendee"
93753                 },
93754                 CalendarEvent: {
93755                     path: "tizen/2.0/CalendarEvent"
93756                 },
93757                 CalendarEventId: {
93758                     path: "tizen/2.0/CalendarEventId"
93759                 },
93760                 CalendarRecurrenceRule: {
93761                     path: "tizen/2.0/CalendarRecurrenceRule"
93762                 },
93763                 CalendarTask: {
93764                     path: "tizen/2.0/CalendarTask"
93765                 },
93766                 CompositeFilter: {
93767                     path: "tizen/2.0/CompositeFilter"
93768                 },
93769                 Contact: {
93770                     path: "tizen/2.0/ContactBase"
93771                 },
93772                 ContactAddress: {
93773                     path: "tizen/2.0/ContactAddress"
93774                 },
93775                 ContactAnniversary: {
93776                     path: "tizen/2.0/ContactAnniversary"
93777                 },
93778                 ContactEmailAddress: {
93779                     path: "tizen/2.0/ContactEmailAddress"
93780                 },
93781                 ContactGroup: {
93782                     path: "tizen/2.0/ContactGroup"
93783                 },
93784                 ContactName: {
93785                     path: "tizen/2.0/ContactName"
93786                 },
93787                 ContactOrganization: {
93788                     path: "tizen/2.0/ContactOrganization"
93789                 },
93790                 ContactPhoneNumber: {
93791                     path: "tizen/2.0/ContactPhoneNumber"
93792                 },
93793                 ContactRef: {
93794                     path: "tizen/2.0/ContactRef"
93795                 },
93796                 ContactWebSite: {
93797                     path: "tizen/2.0/ContactWebSite"
93798                 },
93799                 DownloadRequest: {
93800                     path: "tizen/2.0/DownloadRequest"
93801                 },
93802                 Message: {
93803                     path: "tizen/2.0/Message"
93804                 },
93805                 NDEFMessage: {
93806                     path: "tizen/2.0/NDEFMessage"
93807                 },
93808                 NDEFRecord: {
93809                     path: "tizen/2.0/NDEFRecord"
93810                 },
93811                 NDEFRecordMedia: {
93812                     path: "tizen/2.0/NDEFRecordMedia"
93813                 },
93814                 NDEFRecordText: {
93815                     path: "tizen/2.0/NDEFRecordText"
93816                 },
93817                 NDEFRecordURI: {
93818                     path: "tizen/2.0/NDEFRecordURI"
93819                 },
93820                 NotificationDetailInfo: {
93821                     path: "tizen/2.0/NotificationDetailInfo"
93822                 },
93823                 SimpleCoordinates: {
93824                     path: "tizen/2.0/SimpleCoordinates"
93825                 },
93826                 SortMode: {
93827                     path: "tizen/2.0/SortMode"
93828                 },
93829                 StatusNotification: {
93830                     path: "tizen/2.0/StatusNotification"
93831                 },
93832                 SyncInfo: {
93833                     path: "tizen/2.0/SyncInfo"
93834                 },
93835                 SyncServiceInfo: {
93836                     path: "tizen/2.0/SyncServiceInfo"
93837                 },
93838                 SyncProfileInfo: {
93839                     path: "tizen/2.0/SyncProfileInfo"
93840                 },
93841                 TZDate: {
93842                     path: "tizen/2.0/TZDate"
93843                 },
93844                 TimeDuration: {
93845                     path: "tizen/2.0/TimeDuration"
93846                 },
93847                 alarm: {
93848                     path: "tizen/2.0/alarm",
93849                     feature: "http://tizen.org/privilege/alarm",
93850                     handleSubfeatures: true
93851                 },
93852                 application: {
93853                     path: "tizen/2.0/application",
93854                     feature: "http://tizen.org/privilege/application.launch|http://tizen.org/privilege/appmanager.kill|http://tizen.org/privilege/appmanager.certificate",
93855                     handleSubfeatures: true
93856                 },
93857                 bluetooth: {
93858                     path: "tizen/2.0/bluetooth",
93859                     feature: "http://tizen.org/privilege/bluetoothmanager|http://tizen.org/privilege/bluetooth.admin|http://tizen.org/privilege/bluetooth.gap|http://tizen.org/privilege/bluetooth.spp",
93860                     handleSubfeatures: true
93861                 },
93862                 bookmark: {
93863                     path: "tizen/2.0/bookmark",
93864                     feature: "http://tizen.org/privilege/bookmark.read|http://tizen.org/privilege/bookmark.write",
93865                     handleSubfeatures: true
93866                 },
93867                 callhistory: {
93868                     path: "tizen/2.0/callHistory",
93869                     feature: "http://tizen.org/privilege/callhistory|http://tizen.org/privilege/callhistory.read|http://tizen.org/privilege/callhistory.write",
93870                     handleSubfeatures: true
93871                 },
93872                 calendar: {
93873                     path: "tizen/2.0/calendar",
93874                     feature: "http://tizen.org/privilege/calendar.read|http://tizen.org/privilege/calendar.write",
93875                     handleSubfeatures: true
93876                 },
93877                 contact: {
93878                     path: "tizen/2.0/contact",
93879                     feature: "http://tizen.org/privilege/contact.read|http://tizen.org/privilege/contact.write",
93880                     handleSubfeatures: true
93881                 },
93882                 content: {
93883                     path: "tizen/2.0/content",
93884                     feature: "http://tizen.org/privilege/content.read|http://tizen.org/privilege/content.write",
93885                     handleSubfeatures: true
93886                 },
93887                 datacontrol: {
93888                     path: "tizen/2.0/datacontrol",
93889                     feature: "http://tizen.org/privilege/datacontrol.consumer",
93890                     handleSubfeatures: true
93891                 },
93892                 datasync: {
93893                     path: "tizen/2.0/datasync",
93894                     feature: "http://tizen.org/privilege/datasync",
93895                     handleSubfeatures: true
93896                 },
93897                 download: {
93898                     path: "tizen/2.0/download",
93899                     feature: "http://tizen.org/privilege/download",
93900                     handleSubfeatures: true
93901                 },
93902                 filesystem: {
93903                     path: "tizen/2.0/filesystem",
93904                     feature: "http://tizen.org/privilege/filesystem.read|http://tizen.org/privilege/filesystem.write"
93905                 },
93906                 messaging: {
93907                     path: "tizen/2.0/messaging",
93908                     feature: "http://tizen.org/privilege/messaging.send|http://tizen.org/privilege/messaging.read|http://tizen.org/privilege/messaging.write",
93909                     handleSubfeatures: true
93910                 },
93911                 networkbearerselection: {
93912                     path: "tizen/2.0/networkbearerselection",
93913                     feature: "http://tizen.org/privilege/networkbearerselection",
93914                     handleSubfeatures: true
93915                 },
93916                 nfc: {
93917                     path: "tizen/2.0/nfc",
93918                     feature: "http://tizen.org/privilege/nfc.common|http://tizen.org/privilege/nfc.admin|http://tizen.org/privilege/nfc.tag|http://tizen.org/privilege/nfc.p2p",
93919                     handleSubfeatures: true
93920                 },
93921                 notification: {
93922                     path: "tizen/2.0/notification",
93923                     feature: "http://tizen.org/privilege/notification",
93924                     handleSubfeatures: true
93925                 },
93926                 package: {
93927                     path: "tizen/2.0/package",
93928                     feature: "http://tizen.org/privilege/packagemanager.install|http://tizen.org/privilege/package.info",
93929                     handleSubfeatures: true
93930                 },
93931                 power: {
93932                     path: "tizen/2.0/power",
93933                     feature: "http://tizen.org/privilege/power",
93934                     handleSubfeatures: true
93935                 },
93936                 push: {
93937                     path: "tizen/2.0/push",
93938                     feature: "http://tizen.org/privilege/push",
93939                     handleSubfeatures: true
93940                 },
93941                 systeminfo: {
93942                     path: "tizen/2.0/systeminfo",
93943                     feature: "http://tizen.org/privilege/system|http://tizen.org/privilege/systemmanager",
93944                     handleSubfeatures: true
93945                 },
93946                 systemsetting: {
93947                     path: "tizen/2.0/systemsetting",
93948                     feature: "http://tizen.org/privilege/setting",
93949                     handleSubfeatures: true
93950                 },
93951                 time: {
93952                     path: "tizen/2.0/time",
93953                     feature: "http://tizen.org/privilege/time",
93954                     handleSubfeatures: true
93955                 }
93956             }
93957         }
93958     }
93959 };
93960
93961 });
93962 define('ripple/platform/tizen/2.0/syncml-js-lib/adapter', function (require, exports, module) {
93963 // -*- coding: utf-8 -*-
93964 //-----------------------------------------------------------------------------
93965 // file: $Id$
93966 // lib:  syncml-js.adapter
93967 // auth: griffin <griffin@uberdev.org>
93968 // date: 2012/10/22
93969 // copy: (C) CopyLoose 2012 UberDev <hardcore@uberdev.org>, No Rights Reserved.
93970 //-----------------------------------------------------------------------------
93971
93972 var common = require('ripple/platform/tizen/2.0/syncml-js-lib/common'),
93973     constant = require('ripple/platform/tizen/2.0/syncml-js-lib/constant'),
93974     storemod = require('ripple/platform/tizen/2.0/syncml-js-lib/store');
93975
93976
93977 var _self = (function () {
93978
93979     var exports = {};
93980
93981     //---------------------------------------------------------------------------
93982     exports.Adapter = common.Base.extend({
93983
93984         // //-------------------------------------------------------------------------
93985         // constructor: function(context, options, devInfo) {
93986
93987         //-------------------------------------------------------------------------
93988         normUri: function(uri) {
93989             return common.normpath(uri);
93990         },
93991
93992         //-------------------------------------------------------------------------
93993         getStores: function() {
93994             return _.values(this._stores);
93995         },
93996
93997         //-------------------------------------------------------------------------
93998         getStore: function(uri) {
93999             return this._stores[this.normUri(uri)];
94000         },
94001
94002         //-------------------------------------------------------------------------
94003         addStore: function(store, cb) {
94004             var self = this;
94005             if ( store instanceof storemod.Store )
94006             {
94007                 store.uri = self.normUri(store.uri);
94008                 store._a  = self;
94009             }
94010             else
94011                 store = new storemod.Store(this, store);
94012             store._updateModel(function(err) {
94013                 if ( err )
94014                 return cb(err);
94015             self._stores[store.uri] = store;
94016
94017             // TODO: remove this sensitivity...
94018             if ( ! self.isLocal )
94019                 return cb();
94020
94021             self._save(self._c._txn(), function(err) {
94022                 if ( err )
94023                 return cb(err);
94024             cb(null, store);
94025             });
94026             });
94027         },
94028
94029         //-------------------------------------------------------------------------
94030         removeStore: function(uri, cb) {
94031             var self = this;
94032             if ( ! self.isLocal )
94033                 // todo: implement
94034                 return cb(new common.LogicalError(
94035                             'cannot remove remote store "' + uri + '": remote peer responsibility'));
94036             if ( ! self._stores[uri] )
94037                 return cb(new common.InternalError(
94038                             'cannot remove store "' + uri + '": no such store'));
94039             delete self._stores[uri];
94040             var model = self._getModel();
94041             model.stores = _.filter(model.stores, function(store) {
94042                 return store.uri != uri;
94043             });
94044             _.each(model.peers, function(peer) {
94045                 peer.routes = _.filter(peer.routes, function(route) {
94046                     return route.localUri != uri;
94047                 });
94048                 _.each(peer.stores, function(store) {
94049                     if ( store.binding && store.binding.uri == uri )
94050                     store.binding = null;
94051                 });
94052             });
94053             return cb();
94054         },
94055
94056         //-------------------------------------------------------------------------
94057         _isMapper: function() {
94058             // indicates whether or not this adapter is capable of mapping
94059             // items. in the standard SyncML peer model, only the server
94060             // ever does mapping, but in the dream-land of syncml-js, all
94061             // peers can be mappers, or even better, implements an extension
94062             // "is-uuid/adopted" that does not require mapping. so, since
94063             // that is just a dream-land for now, this will try to identify
94064             // if this adapter represents a server...
94065             // todo: enhance syncml-js so that it is not needed!...
94066             if ( ! this.isLocal )
94067                 return this.url && this.url.length > 0;
94068             return this.devInfo && this.devInfo.devType == constant.DEVTYPE_SERVER;
94069         },
94070
94071         //-------------------------------------------------------------------------
94072         describe: function(stream, cb) {
94073             var self = this;
94074             if ( self.url )
94075                 stream.writeln('URL: ' + self.url);
94076             stream.writeln('Device ID: ' + self.devID);
94077             var s1 = stream.indented();
94078             var s2 = s1.indented();
94079
94080             var describe_stores = function(cb) {
94081                 var stores = self.getStores();
94082                 if ( stores.length <= 0 )
94083                 {
94084                     stream.writeln('Data stores: (none)');
94085                     return cb();
94086                 }
94087                 stream.writeln('Data stores:');
94088                 common.cascade(stores, function(store, cb) {
94089                     s1.writeln(( store.displayName || store.uri ) + ':');
94090                     store.describe(s2, cb);
94091                 }, cb);
94092             };
94093
94094             var describe_peers = function(cb) {
94095                 if ( ! self.getPeers )
94096                     return cb();
94097                 var peers = self.getPeers();
94098                 if ( peers.length <= 0 )
94099                 {
94100                     stream.writeln('Known peers: (none)');
94101                     return cb();
94102                 }
94103                 stream.writeln('Known peers:');
94104                 common.cascade(peers, function(peer, cb) {
94105                     s1.writeln(( peer.displayName || peer.url ) + ':');
94106                     peer.describe(s2, cb);
94107                 }, cb);
94108             }
94109
94110             describe_stores(function(err) {
94111                 if ( err )
94112                 return cb(err);
94113             describe_peers(cb);
94114             });
94115         }
94116
94117     });
94118
94119     return exports;
94120
94121     })();
94122
94123     module.exports = _self;
94124
94125 });
94126 define('ripple/platform/tizen/2.0/syncml-js-lib/agent', function (require, exports, module) {
94127 // -*- coding: utf-8 -*-
94128 //-----------------------------------------------------------------------------
94129 // file: $Id$
94130 // lib:  syncml-js.agent
94131 // auth: griffin <griffin@uberdev.org>
94132 // date: 2012/10/22
94133 // copy: (C) CopyLoose 2012 UberDev <hardcore@uberdev.org>, No Rights Reserved.
94134 //-----------------------------------------------------------------------------
94135
94136 var common = require('ripple/platform/tizen/2.0/syncml-js-lib/common');
94137
94138 var _self = (function () {
94139
94140     var exports = {};
94141
94142     //---------------------------------------------------------------------------
94143     exports.Agent = common.Base.extend({
94144
94145         //-------------------------------------------------------------------------
94146         constructor: function(options) {
94147             options = _.defaults(options, {
94148                 hierarchicalSync: false
94149             });
94150             this.hierarchicalSync = options.hierarchicalSync;
94151         },
94152
94153         //-------------------------------------------------------------------------
94154         dumpItem: function(item, stream, contentType, version, cb) {
94155             return this.dumpsItem(
94156                 item, contentType, version,
94157                 function(err, data, new_contentType, new_version) {
94158                     if ( err ) {
94159                         return cb(err);
94160                     }
94161                     stream.write(data, function(err) {
94162                         if ( err ) {
94163                             return cb(err);
94164                         }
94165                         cb(null, new_contentType, new_version);
94166                     });
94167                 });
94168         },
94169
94170         //-------------------------------------------------------------------------
94171         loadItem: function(stream, contentType, version, cb) {
94172             var self = this;
94173             stream.read(function(err, data) {
94174                 if ( err ) {
94175                     cb(err);
94176                 }
94177                 self.loadsItem(data, contentType, version, cb);
94178             });
94179         },
94180
94181         //-------------------------------------------------------------------------
94182         deleteAllItems: function(cb) {
94183             var self = this;
94184             self.getAllItems(function(err, items) {
94185                 if ( err ) {
94186                     return cb(err);
94187                 }
94188                 common.cascade(items, function(e, cb) {
94189                     self.deleteItem(e, cb);
94190                 }, cb);
94191             });
94192         },
94193
94194         // TODO: add documentation about all expected methods...
94195
94196         getAllItems: function(cb) {
94197             // cb(null, LIST)
94198             return cb(new common.NotImplementedError());
94199         },
94200
94201         dumpsItem: function(item, contentType, version, cb) {
94202             // cb(null, DATA [, NEW-CONTENTTYPE [, NEW-VERSION]])
94203             return cb(new common.NotImplementedError());
94204         },
94205
94206         loadsItem: function(data, contentType, version, cb) {
94207             // cb(null, ITEM)
94208             return cb(new common.NotImplementedError());
94209         },
94210
94211         addItem: function(item, cb) {
94212             // cb(null, ITEM)
94213             return cb(new common.NotImplementedError());
94214         },
94215
94216         getItem: function(itemID, cb) {
94217             // cb(null, ITEM)
94218             return cb(new common.NotImplementedError());
94219         },
94220
94221         replaceItem: function(item, reportChanges, cb) {
94222             // cb(null [, CSPEC])
94223             return cb(new common.NotImplementedError());
94224         },
94225
94226         deleteItem: function(itemID, cb) {
94227             // cb(null)
94228             return cb(new common.NotImplementedError());
94229         },
94230
94231         getContentTypes: function() {
94232             throw new common.NotImplementedError();
94233         },
94234
94235         matchItem: function(item, cb) {
94236             this.getAllItems(function(err, list) {
94237                 if ( err ) {
94238                     return cb(err);
94239                 }
94240                 var match = _.find(list, function(cur) {
94241                     return cur.compare && cur.compare(item) == 0;
94242                 });
94243                 return cb(null, match);
94244             });
94245         }
94246
94247     // TODO: mergeItems()
94248
94249     });
94250
94251     return exports;
94252
94253 })();
94254
94255 module.exports = _self;
94256
94257 });
94258 define('ripple/platform/tizen/2.0/syncml-js-lib/base64', function (require, exports, module) {
94259 // -*- coding: utf-8 -*-
94260 //-----------------------------------------------------------------------------
94261 // file: $Id$
94262 //-----------------------------------------------------------------------------
94263
94264 var _self = (function() {
94265
94266     // shamelessly scrubbed from:
94267     //   http://www.webtoolkit.info/javascript-base64.html
94268
94269     /**
94270      *
94271      *  Base64 encode / decode
94272      *  http://www.webtoolkit.info/
94273      *
94274      **/
94275
94276     var Base64 = {
94277
94278         // private property
94279         _keyStr : "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",
94280
94281       // public method for encoding
94282       encode : function (input) {
94283           var output = "";
94284           var chr1, chr2, chr3, enc1, enc2, enc3, enc4;
94285           var i = 0;
94286
94287           input = Base64._utf8_encode(input);
94288
94289           while (i < input.length) {
94290
94291               chr1 = input.charCodeAt(i++);
94292               chr2 = input.charCodeAt(i++);
94293               chr3 = input.charCodeAt(i++);
94294
94295               enc1 = chr1 >> 2;
94296               enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
94297               enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
94298               enc4 = chr3 & 63;
94299
94300               if (isNaN(chr2)) {
94301                   enc3 = enc4 = 64;
94302               } else if (isNaN(chr3)) {
94303                   enc4 = 64;
94304               }
94305
94306               output = output +
94307                   this._keyStr.charAt(enc1) + this._keyStr.charAt(enc2) +
94308                   this._keyStr.charAt(enc3) + this._keyStr.charAt(enc4);
94309
94310           }
94311
94312           return output;
94313       },
94314
94315       // public method for decoding
94316       decode : function (input) {
94317           var output = "";
94318           var chr1, chr2, chr3;
94319           var enc1, enc2, enc3, enc4;
94320           var i = 0;
94321
94322           input = input.replace(/[^A-Za-z0-9\+\/\=]/g, "");
94323
94324           while (i < input.length) {
94325
94326               enc1 = this._keyStr.indexOf(input.charAt(i++));
94327               enc2 = this._keyStr.indexOf(input.charAt(i++));
94328               enc3 = this._keyStr.indexOf(input.charAt(i++));
94329               enc4 = this._keyStr.indexOf(input.charAt(i++));
94330
94331               chr1 = (enc1 << 2) | (enc2 >> 4);
94332               chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);
94333               chr3 = ((enc3 & 3) << 6) | enc4;
94334
94335               output = output + String.fromCharCode(chr1);
94336
94337               if (enc3 != 64) {
94338                   output = output + String.fromCharCode(chr2);
94339               }
94340               if (enc4 != 64) {
94341                   output = output + String.fromCharCode(chr3);
94342               }
94343
94344           }
94345
94346           output = Base64._utf8_decode(output);
94347
94348           return output;
94349
94350       },
94351
94352       // private method for UTF-8 encoding
94353       _utf8_encode : function (string) {
94354           string = string.replace(/\r\n/g,"\n");
94355           var utftext = "";
94356
94357           for (var n = 0; n < string.length; n++) {
94358
94359               var c = string.charCodeAt(n);
94360
94361               if (c < 128) {
94362                   utftext += String.fromCharCode(c);
94363               }
94364               else if((c > 127) && (c < 2048)) {
94365                   utftext += String.fromCharCode((c >> 6) | 192);
94366                   utftext += String.fromCharCode((c & 63) | 128);
94367               }
94368               else {
94369                   utftext += String.fromCharCode((c >> 12) | 224);
94370                   utftext += String.fromCharCode(((c >> 6) & 63) | 128);
94371                   utftext += String.fromCharCode((c & 63) | 128);
94372               }
94373
94374           }
94375
94376           return utftext;
94377       },
94378
94379       // private method for UTF-8 decoding
94380       _utf8_decode : function (utftext) {
94381           var string = "";
94382           var i = 0;
94383           var c = c1 = c2 = 0;
94384
94385           while ( i < utftext.length ) {
94386
94387               c = utftext.charCodeAt(i);
94388
94389               if (c < 128) {
94390                   string += String.fromCharCode(c);
94391                   i++;
94392               }
94393               else if((c > 191) && (c < 224)) {
94394                   c2 = utftext.charCodeAt(i+1);
94395                   string += String.fromCharCode(((c & 31) << 6) | (c2 & 63));
94396                   i += 2;
94397               }
94398               else {
94399                   c2 = utftext.charCodeAt(i+1);
94400                   c3 = utftext.charCodeAt(i+2);
94401                   string += String.fromCharCode(((c & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63));
94402                   i += 3;
94403               }
94404
94405           }
94406
94407           return string;
94408       }
94409
94410     };
94411
94412     return Base64;
94413
94414 })();
94415
94416 module.exports = _self;
94417
94418 });
94419 define('ripple/platform/tizen/2.0/syncml-js-lib/codec', function (require, exports, module) {
94420 // -*- coding: utf-8 -*-
94421 //-----------------------------------------------------------------------------
94422 // file: $Id$
94423 // auth: metagriffin <metagriffin@uberdev.org>
94424 // date: 2012/10/13
94425 // copy: (C) CopyLoose 2012 UberDev <hardcore@uberdev.org>, No Rights Reserved.
94426 //-----------------------------------------------------------------------------
94427
94428 var common = require('ripple/platform/tizen/2.0/syncml-js-lib/common'),
94429     constant = require('ripple/platform/tizen/2.0/syncml-js-lib/constant'),
94430     _self;
94431
94432 _self = (function () {
94433
94434     var exports = {};
94435
94436     //---------------------------------------------------------------------------
94437     exports.Codec = common.Base.extend({
94438
94439         encode: function(xtree, cb) {
94440             throw new common.NotImplementedError();
94441         },
94442
94443         decode: function(contentType, data, cb) {
94444             throw new common.NotImplementedError();
94445         },
94446     }, {
94447
94448         factory: function(codec) {
94449             // todo: should this be converted to callback-based?...
94450             if ( codec == constant.CODEC_XML )
94451         return new exports.XmlCodec()
94452         // TODO
94453         // if ( codec == constant.CODEC_WBXML )
94454         //   return exports.WbxmlCodec()
94455         throw new common.UnknownCodec('unknown or unimplemented codec "' + codec + '"')
94456         },
94457
94458             autoEncode: function(xtree, codecName, cb) {
94459                 exports.Codec.factory(codecName).encode(xtree, cb);
94460             },
94461
94462             autoDecode: function(contentType, data, cb) {
94463                 if ( contentType.indexOf(constant.TYPE_SYNCML + '+') != 0 )
94464                     return cb('unknown or unimplemented content type "' + contentType + '"');
94465                 var ct = contentType.slice((constant.TYPE_SYNCML + '+').length).split(';')[0];
94466                 exports.Codec.factory(ct).decode(contentType, data, function(err, tree) {
94467                     if ( err )
94468                     return cb(err);
94469                 return cb(null, tree, ct);
94470                 });
94471             },
94472     });
94473
94474     //---------------------------------------------------------------------------
94475     exports.XmlCodec = exports.Codec.extend({
94476
94477         name: constant.CODEC_XML,
94478
94479         encode: function(xtree, cb) {
94480             // todo: really enforce this charset...
94481             var ctype = constant.TYPE_SYNCML + '+' + this.name + '; charset=UTF-8';
94482             var ret = ET.tostring(xtree);
94483             if ( ret.charAt(0) == '<' && ret.charAt(1) == '?' )
94484     {
94485         var idx = ret.indexOf('?>');
94486         if ( idx >= 0 )
94487         ret = ret.substr(0, idx + 2).replace(/'/g, '"') + ret.substr(idx + 2);
94488     }
94489     cb(null, ctype, ret);
94490         },
94491
94492         decode: function(contentType, data, cb) {
94493             var expCT = constant.TYPE_SYNCML + '+' + this.name;
94494             if ( contentType.indexOf(expCT) != 0 )
94495         cb(new common.ProtocolError(
94496                 'received unexpected content-type "' + contentType + '" (expected "'
94497                     + expCT + '")'));
94498             try
94499             {
94500                 return cb(null, ET.parse(data).getroot());
94501             }
94502             catch(e)
94503             {
94504                 return cb(new common.ProtocolError('could not parse XML: ' + e, e));
94505             }
94506         }
94507
94508     });
94509
94510     //---------------------------------------------------------------------------
94511     // TODO: implement wbxml...
94512     // exports.WbXmlCodec = exports.Codec.extend({
94513     //   encode: function(xtree, cb) {
94514     //   },
94515     //   decode: function(contentType, data, cb) {
94516     //   }
94517     // });
94518
94519     return exports;
94520
94521 })();
94522
94523 module.exports = _self;
94524
94525 });
94526 define('ripple/platform/tizen/2.0/syncml-js-lib/common', function (require, exports, module) {
94527 // -*- coding: utf-8 -*-
94528 //-----------------------------------------------------------------------------
94529 // file: $Id$
94530 // auth: metagriffin <metagriffin@uberdev.org>
94531 // date: 2012/10/13
94532 // copy: (C) CopyLoose 2012 UberDev <hardcore@uberdev.org>, No Rights Reserved.
94533 //-----------------------------------------------------------------------------
94534
94535 var constant = require('ripple/platform/tizen/2.0/syncml-js-lib/constant'),
94536     _self;
94537
94538 _self = (function () {
94539     var exports = {};
94540
94541     //---------------------------------------------------------------------------
94542     // object inheritance helper routines shamelessly scrubbed from backbone.js
94543
94544     // The self-propagating extend function that Backbone classes use.
94545     var extend = exports.extend = function (protoProps, classProps) {
94546         var child = inherits(this, protoProps, classProps);
94547         child.extend = this.extend;
94548         return child;
94549     };
94550
94551     // Shared empty constructor function to aid in prototype-chain creation.
94552     var ctor = function(){};
94553
94554     // Helper function to correctly set up the prototype chain, for subclasses.
94555     // Similar to `goog.inherits`, but uses a hash of prototype properties and
94556     // class properties to be extended.
94557     var inherits = function(parent, protoProps, staticProps) {
94558         var child;
94559
94560         // The constructor function for the new subclass is either defined by you
94561         // (the "constructor" property in your `extend` definition), or defaulted
94562         // by us to simply call the parent's constructor.
94563         if (protoProps && protoProps.hasOwnProperty('constructor')) {
94564             child = protoProps.constructor;
94565         } else {
94566             child = function(){ parent.apply(this, arguments); };
94567         }
94568
94569         // Inherit class (static) properties from parent.
94570         _.extend(child, parent);
94571
94572         // Set the prototype chain to inherit from `parent`, without calling
94573         // `parent`'s constructor function.
94574         ctor.prototype = parent.prototype;
94575         child.prototype = new ctor();
94576
94577         // Add prototype properties (instance properties) to the subclass,
94578         // if supplied.
94579         if (protoProps) _.extend(child.prototype, protoProps);
94580
94581         // Add static properties to the constructor function, if supplied.
94582         if (staticProps) _.extend(child, staticProps);
94583
94584         // Correctly set child's `prototype.constructor`.
94585         child.prototype.constructor = child;
94586
94587         // Set a convenience property in case the parent's prototype is needed later.
94588         child.__super__ = parent.prototype;
94589
94590         return child;
94591     };
94592
94593     //-----------------------------------------------------------------------------
94594     exports.Base = function() {};
94595     exports.Base.extend = extend;
94596
94597     //-----------------------------------------------------------------------------
94598     var SyncmlError = exports.Base.extend({
94599         constructor: function(msg, exception, attrs) {
94600             this.message = this.name;
94601             if ( msg != undefined )
94602         this.message += ': ' + msg;
94603     this.exception = exception;
94604     if ( attrs )
94605         _.extend(this, attrs);
94606         },
94607         toString: function() {
94608             return this.message;
94609         }
94610     });
94611
94612     //---------------------------------------------------------------------------
94613     exports.Stream = exports.Base.extend({
94614
94615         writeln: function(data) {
94616             if ( data == undefined )
94617         return;
94618     return this.write(data + '\n');
94619         },
94620
94621         indented: function(indent) {
94622             return new exports.IndentStream(this, indent || this._indent);
94623         }
94624
94625     });
94626
94627     _.extend(exports, {
94628
94629         //---------------------------------------------------------------------------
94630         // exceptions
94631         SyncmlError:           SyncmlError.extend({name: 'SyncmlError'}),
94632         TypeError:             SyncmlError.extend({name: 'TypeError'}),
94633         NotImplementedError:   SyncmlError.extend({name: 'NotImplementedError'}),
94634         ProtocolError:         SyncmlError.extend({name: 'ProtocolError'}),
94635         InternalError:         SyncmlError.extend({name: 'InternalError'}),
94636         ConflictError:         SyncmlError.extend({name: 'ConflictError'}),
94637         FeatureNotSupported:   SyncmlError.extend({name: 'FeatureNotSupported'}),
94638         LogicalError:          SyncmlError.extend({name: 'LogicalError'}),
94639         CredentialsRequired:   SyncmlError.extend({name: 'CredentialsRequired'}),
94640         InvalidCredentials:    SyncmlError.extend({name: 'InvalidCredentials'}),
94641         InvalidContext:        SyncmlError.extend({name: 'InvalidContext'}),
94642         InvalidAdapter:        SyncmlError.extend({name: 'InvalidAdapter'}),
94643         InvalidStore:          SyncmlError.extend({name: 'InvalidStore'}),
94644         InvalidContentType:    SyncmlError.extend({name: 'InvalidContentType'}),
94645         InvalidAgent:          SyncmlError.extend({name: 'InvalidAgent'}),
94646         InvalidContent:        SyncmlError.extend({name: 'InvalidContent'}),
94647         InvalidItem:           SyncmlError.extend({name: 'InvalidItem'}),
94648         UnknownCodec:          SyncmlError.extend({name: 'UnknownCodec'}),
94649         NoSuchRoute:           SyncmlError.extend({name: 'NoSuchRoute'}),
94650         UnknownAuthType:       SyncmlError.extend({name: 'UnknownAuthType'}),
94651         UnknownFormatType:     SyncmlError.extend({name: 'UnknownFormatType'}),
94652
94653         //---------------------------------------------------------------------------
94654         // UUID generation
94655         makeID: function() {
94656             // shamelessly scrubbed from:
94657             //   http://stackoverflow.com/questions/105034/how-to-create-a-guid-uuid-in-javascript/2117523#2117523
94658             // (adjusted to remove the dashes)
94659             // todo: see some of those links on how to make this more "robust"...
94660             return 'xxxxxxxxxxxx4xxxyxxxxxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
94661                 var r = Math.random()*16|0, v = c == 'x' ? r : (r&0x3|0x8);
94662                 return v.toString(16);
94663             });
94664         },
94665
94666         //-------------------------------------------------------------------------
94667         synctype2alert: function(type) {
94668             return constant.SyncTypeToAlert[type];
94669         },
94670
94671         //-------------------------------------------------------------------------
94672         alert2synctype: function(alert) {
94673             for ( var key in constant.SyncTypeToAlert )
94674             {
94675                 if ( constant.SyncTypeToAlert[key] == alert )
94676                     return exports.int(key);
94677             }
94678             return null;
94679         },
94680
94681         //-------------------------------------------------------------------------
94682         mode2string: function(code) {
94683             switch ( code )
94684             {
94685                 case constant.ALERT_TWO_WAY:                       return 'two-way';
94686                 case constant.ALERT_SLOW_SYNC:                     return 'slow-sync';
94687                 case constant.ALERT_ONE_WAY_FROM_CLIENT:           return 'one-way-from-client';
94688                 case constant.ALERT_REFRESH_FROM_CLIENT:           return 'refresh-from-client';
94689                 case constant.ALERT_ONE_WAY_FROM_SERVER:           return 'one-way-from-server';
94690                 case constant.ALERT_REFRESH_FROM_SERVER:           return 'refresh-from-server';
94691                 case constant.ALERT_TWO_WAY_BY_SERVER:             return 'two-way-by-server';
94692                 case constant.ALERT_ONE_WAY_FROM_CLIENT_BY_SERVER: return 'one-way-from-client-by-server';
94693                 case constant.ALERT_REFRESH_FROM_CLIENT_BY_SERVER: return 'refresh-from-client-by-server';
94694                 case constant.ALERT_ONE_WAY_FROM_SERVER_BY_SERVER: return 'one-way-from-server-by-server';
94695                 case constant.ALERT_REFRESH_FROM_SERVER_BY_SERVER: return 'refresh-from-server-by-server';
94696                 default: return 'UNKNOWN';
94697             }
94698         },
94699
94700         //-------------------------------------------------------------------------
94701         state2string: function(state) {
94702             switch ( state )
94703             {
94704                 case constant.ITEM_OK:           return 'ok';
94705                 case constant.ITEM_ADDED:        return 'added';
94706                 case constant.ITEM_MODIFIED:     return 'modified';
94707                 case constant.ITEM_DELETED:      return 'deleted';
94708                 case constant.ITEM_SOFTDELETED:  return 'soft-deleted';
94709                 default: return 'UNKNOWN';
94710             }
94711         },
94712
94713         //-------------------------------------------------------------------------
94714         oneWay: function(mode) {
94715             switch ( mode )
94716             {
94717                 case constant.ALERT_TWO_WAY:
94718                 case constant.ALERT_SLOW_SYNC:
94719                     return false;
94720                 case constant.ALERT_ONE_WAY_FROM_CLIENT:
94721                 case constant.ALERT_REFRESH_FROM_CLIENT:
94722                 case constant.ALERT_ONE_WAY_FROM_SERVER:
94723                 case constant.ALERT_REFRESH_FROM_SERVER:
94724                     return true;
94725                     // case constant.ALERT_TWO_WAY_BY_SERVER:
94726                     // case constant.ALERT_ONE_WAY_FROM_CLIENT_BY_SERVER:
94727                     // case constant.ALERT_REFRESH_FROM_CLIENT_BY_SERVER:
94728                     // case constant.ALERT_ONE_WAY_FROM_SERVER_BY_SERVER:
94729                     // case constant.ALERT_REFRESH_FROM_SERVER_BY_SERVER:
94730                 default:
94731                     throw new exports.InternalError('invalid mode "' + mode + '"');
94732             }
94733         },
94734
94735         //-------------------------------------------------------------------------
94736         oneWayIn: function(session, mode) {
94737             switch ( mode )
94738             {
94739                 case constant.ALERT_TWO_WAY:
94740                 case constant.ALERT_SLOW_SYNC:
94741                     return false;
94742                 case constant.ALERT_ONE_WAY_FROM_CLIENT:
94743                 case constant.ALERT_REFRESH_FROM_CLIENT:
94744                     return !! session.isServer;
94745                 case constant.ALERT_ONE_WAY_FROM_SERVER:
94746                 case constant.ALERT_REFRESH_FROM_SERVER:
94747                     return ! session.isServer;
94748                     // case constant.ALERT_TWO_WAY_BY_SERVER:
94749                     // case constant.ALERT_ONE_WAY_FROM_CLIENT_BY_SERVER:
94750                     // case constant.ALERT_REFRESH_FROM_CLIENT_BY_SERVER:
94751                     // case constant.ALERT_ONE_WAY_FROM_SERVER_BY_SERVER:
94752                     // case constant.ALERT_REFRESH_FROM_SERVER_BY_SERVER:
94753                 default:
94754                     throw new exports.InternalError('invalid mode "' + mode + '"');
94755             }
94756         },
94757
94758         //-------------------------------------------------------------------------
94759         oneWayOut: function(session, mode) {
94760             switch ( mode )
94761             {
94762                 case constant.ALERT_TWO_WAY:
94763                 case constant.ALERT_SLOW_SYNC:
94764                     return false;
94765                 case constant.ALERT_ONE_WAY_FROM_CLIENT:
94766                 case constant.ALERT_REFRESH_FROM_CLIENT:
94767                     return ! session.isServer;
94768                 case constant.ALERT_ONE_WAY_FROM_SERVER:
94769                 case constant.ALERT_REFRESH_FROM_SERVER:
94770                     return !! session.isServer;
94771                     // case constant.ALERT_TWO_WAY_BY_SERVER:
94772                     // case constant.ALERT_ONE_WAY_FROM_CLIENT_BY_SERVER:
94773                     // case constant.ALERT_REFRESH_FROM_CLIENT_BY_SERVER:
94774                     // case constant.ALERT_ONE_WAY_FROM_SERVER_BY_SERVER:
94775                     // case constant.ALERT_REFRESH_FROM_SERVER_BY_SERVER:
94776                 default:
94777                     throw new exports.InternalError('invalid mode "' + mode + '"');
94778             }
94779         },
94780
94781         //-------------------------------------------------------------------------
94782         cascade: function(list, iterator, cb) {
94783             if ( ! cb && iterator )
94784             {
94785                 cb = iterator;
94786                 iterator = null;
94787             }
94788             if ( ! list )
94789                 return cb();
94790             var cur = 0;
94791             var next = function() {
94792                 if ( cur >= list.length )
94793                     return cb();
94794                 var curcb = function(err) {
94795                     if ( err )
94796                         return cb(err);
94797                     cur += 1;
94798                     var args = [];
94799                     for ( var idx=1 ; idx<arguments.length ; idx++ )
94800                         args.push(arguments[idx]);
94801                     return next.apply(null, args);
94802                 };
94803                 var func = iterator || list[cur];
94804                 var args = [];
94805                 if ( iterator )
94806                     args.push(list[cur]);
94807                 for ( var idx=0 ; idx<arguments.length ; idx++ )
94808                     args.push(arguments[idx]);
94809                 args.push(curcb);
94810                 return func.apply(null, args);
94811             };
94812             return next();
94813         },
94814
94815         //-------------------------------------------------------------------------
94816         ts: function() {
94817             return Math.floor((new Date()).getTime() / 1000);
94818         },
94819
94820         //-------------------------------------------------------------------------
94821         j: function(obj) {
94822             return JSON.stringify(obj);
94823         },
94824
94825         //-------------------------------------------------------------------------
94826         noop: function(cb) {
94827             return cb();
94828         },
94829
94830         //-------------------------------------------------------------------------
94831         platformBits: function() {
94832
94833             // TODO: implement this!...
94834
94835             return 32;
94836         },
94837
94838         //-------------------------------------------------------------------------
94839         getMaxMemorySize: function(context) {
94840
94841             // Returns the maximum size of a memory object. By default this
94842             // is, set to ``sys.maxint``, however the `context` may override
94843             // this behavior.
94844
94845             // NOTE: currently, this is being hardcoded to a maximum of 2GB for
94846             //       compatibility with funambol servers, which croak above that
94847             //       value.
94848
94849             // TODO: allow the context to control this, or implement auto-detect to
94850             //       determine what the remote peer can support...
94851
94852             return Math.min(Math.pow(2, exports.platformBits() - 1) - 1,
94853                     Math.pow(2, 31) - 1);
94854         },
94855
94856         //-------------------------------------------------------------------------
94857         normpath: function(path) {
94858             if ( path == undefined )
94859                 return null;
94860             if ( path.length <= 0 )
94861                 return '';
94862             if ( path.indexOf('/') < 0 )
94863                 path = path.replace('\\', '/');
94864             var ret = [];
94865             var plist = path.split('/');
94866             for ( var idx=0 ; idx<plist.length ; idx++ )
94867             {
94868                 var item = plist[idx];
94869                 if ( item.length <= 0 || item == '.' )
94870                     continue;
94871                 if ( item != '..' || ret.length <= 0 || ret[ret.length - 1] == '..' )
94872                 {
94873                     ret.push(item);
94874                     continue;
94875                 }
94876                 ret.pop();
94877             }
94878             ret = ret.join('/');
94879             if ( path.charAt(0) != '/' )
94880                 return ret;
94881             return '/' + ret;
94882         },
94883
94884         //-------------------------------------------------------------------------
94885         int: function(str, defval) {
94886             if ( ! str )
94887                 return defval;
94888             return parseInt(str, 10);
94889         },
94890
94891         //-------------------------------------------------------------------------
94892         cmp: function(a, b) {
94893             if ( a < b )
94894                 return -1;
94895             if ( a > b )
94896                 return 1;
94897             return 0;
94898         },
94899
94900         //-------------------------------------------------------------------------
94901         // partially emulates python's string.split() method
94902         splitn: function(str, sep, limit) {
94903             var ret = str.split(sep);
94904             if ( ret.length <= ( limit + 1 ) )
94905                 return ret;
94906             var tmp = ret.slice(0, limit);
94907             tmp.push(ret.slice(limit).join(sep));
94908             return tmp;
94909         },
94910
94911         //-------------------------------------------------------------------------
94912         prettyJson: function(obj, indent) {
94913             indent = indent || '';
94914             var ret = '';
94915             if ( _.isArray(obj) )
94916             {
94917                 if ( obj.length <= 0 )
94918                     return '[]';
94919                 ret = '[\n' + indent;
94920                 _.each(obj, function(el, idx) {
94921                     ret += '  ' + exports.prettyJson(el, indent + '  ');
94922                     if ( idx + 1 < obj.length )
94923                     ret += ',';
94924                 ret += '\n' + indent;
94925                 });
94926                 return ret + ']';
94927             }
94928             if ( _.isObject(obj) )
94929             {
94930                 var keys = _.keys(obj);
94931                 if ( keys.length <= 0 )
94932                     return '{}';
94933                 keys.sort();
94934                 ret = '{\n' + indent;
94935                     _.each(keys, function(key, idx) {
94936                         ret += '  ' + exports.prettyJson(key)
94937                         + ': ' + exports.prettyJson(obj[key], indent + '  ');
94938                     if ( idx + 1 < keys.length )
94939                         ret += ',';
94940                     ret += '\n' + indent;
94941                     });
94942                     return ret + ( indent.length <= 0 ? '}\n' : '}' );
94943             }
94944             return JSON.stringify(obj);
94945         },
94946
94947         //-------------------------------------------------------------------------
94948         urlEncode: function(dat) {
94949             return ( dat == undefined ? dat : encodeURIComponent(dat) );
94950         },
94951
94952         //-------------------------------------------------------------------------
94953         /*
94954            rmfr: function(path, cb) {
94955            fs.stat(path, function(err, stats) {
94956            if ( err && err.code == 'ENOENT' )
94957            return cb();
94958            if ( err )
94959            return cb(err);
94960            if ( ! stats.isDirectory() )
94961            return fs.unlink(path, cb);
94962            fs.readdir(path, function(err, files) {
94963            exports.cascade(files, function(file, cb) {
94964            var curpath = pathmod.join(path, file);
94965            return exports.rmfr(curpath, cb);
94966            }, function(err) {
94967            if ( err )
94968            return cb(err);
94969            fs.rmdir(path, cb);
94970            });
94971            });
94972            });
94973            },
94974            */
94975         //-------------------------------------------------------------------------
94976         /*
94977            makedirs: function(path, cb) {
94978         // node sucks. i can't believe it doesn't provide a fs.makedirs(). wtf.
94979         // clean up the path
94980         path = pathmod.normalize(path.split(/[\\\/]/).join('/'));
94981         var paths = path.split('/');
94982         paths = _.map(paths, function(p, idx) {
94983         return paths.slice(0, idx + 1).join('/');
94984         });
94985         if ( path.charAt(0) == '/' )
94986         paths.shift();
94987         exports.cascade(paths, function(path, cb) {
94988         fs.stat(path, function(err, stats) {
94989         if ( err && err.code == 'ENOENT' )
94990         return fs.mkdir(path, cb);
94991         if ( err )
94992         return cb(err);
94993         if ( stats.isDirectory() )
94994         return cb();
94995         // this probably won't work, but let's get the error anyhow...
94996         return fs.mkdir(path, cb);
94997         });
94998         }, cb);
94999         },
95000         */
95001
95002         //-------------------------------------------------------------------------
95003         StringStream: exports.Stream.extend({
95004
95005             constructor: function(initData) {
95006                 this._data = initData || '';
95007             },
95008
95009         write: function(data) {
95010             if ( data == undefined )
95011             return;
95012         this._data += data;
95013         },
95014
95015         getData: function() {
95016             return this._data;
95017         }
95018
95019         }),
95020
95021         //-------------------------------------------------------------------------
95022         IndentStream: exports.Stream.extend({
95023
95024             //-----------------------------------------------------------------------
95025             constructor: function(stream, indent, options) {
95026                 options = options || {};
95027                 this._stream    = stream;
95028                 this._indent    = indent || '  ';
95029                 this._cleared   = true;
95030                 this._stayBlank = !! options.stayBlank;
95031             },
95032
95033         //-----------------------------------------------------------------------
95034         write: function(data) {
95035             var self = this;
95036             if ( data == undefined )
95037             return;
95038         // if ( ! data || ! data.length || data.length <= 0 )
95039         //   return;
95040         var lines = data.split('\n');
95041         if ( self._cleared )
95042             self._stream.write(self._indent);
95043         self._cleared = false;
95044         for ( var idx=0 ; idx<lines.length ; idx++ )
95045         {
95046             var line = lines[idx];
95047             if ( line == '' )
95048             {
95049                 if ( idx + 1 >= lines.length )
95050                     self._cleared = true;
95051                 else
95052                 {
95053                     if ( idx != 0 && ! self._stayBlank )
95054                         self._stream.write(self._indent);
95055                 }
95056             }
95057             else
95058             {
95059                 if ( idx != 0 || self._cleared )
95060                     self._stream.write(self._indent);
95061                 self._stream.write(line);
95062             }
95063             if ( idx + 1 < lines.length )
95064                 self._stream.write('\n');
95065         }
95066         }
95067
95068         })
95069
95070     });
95071
95072     return exports;
95073 })();
95074
95075 module.exports = _self;
95076
95077 });
95078 define('ripple/platform/tizen/2.0/syncml-js-lib/constant', function (require, exports, module) {
95079 // -*- coding: utf-8 -*-
95080 //-----------------------------------------------------------------------------
95081 // file: $Id$
95082 // desc: SyncML constants
95083 // auth: metagriffin <metagriffin@uberdev.org>
95084 // date: 2012/10/13
95085 // copy: (C) CopyLoose 2012 UberDev <hardcore@uberdev.org>, No Rights Reserved.
95086 //-----------------------------------------------------------------------------
95087
95088 var _self = {
95089     // SyncML versions
95090     SYNCML_VERSION_1_0                      : 'SyncML/1.0',
95091     SYNCML_VERSION_1_1                      : 'SyncML/1.1',
95092     SYNCML_VERSION_1_2                      : 'SyncML/1.2',
95093     SYNCML_DTD_VERSION_1_0                  : '1.0',
95094     SYNCML_DTD_VERSION_1_1                  : '1.1',
95095     SYNCML_DTD_VERSION_1_2                  : '1.2',
95096
95097     // SyncML alert/sync codes
95098     ALERT_DISPLAY                           : 100,
95099     ALERT_TWO_WAY                           : 200,
95100     ALERT_SLOW_SYNC                         : 201,
95101     ALERT_ONE_WAY_FROM_CLIENT               : 202,
95102     ALERT_REFRESH_FROM_CLIENT               : 203,
95103     ALERT_ONE_WAY_FROM_SERVER               : 204,
95104     ALERT_REFRESH_FROM_SERVER               : 205,
95105     ALERT_TWO_WAY_BY_SERVER                 : 206,
95106     ALERT_ONE_WAY_FROM_CLIENT_BY_SERVER     : 207,
95107     ALERT_REFRESH_FROM_CLIENT_BY_SERVER     : 208,
95108     ALERT_ONE_WAY_FROM_SERVER_BY_SERVER     : 209,
95109     ALERT_REFRESH_FROM_SERVER_BY_SERVER     : 210,
95110     // alert codes 211-220 are reserved for future use
95111
95112     // SyncML SyncCap SyncTypes
95113     SYNCTYPE_AUTO                           : null,
95114     SYNCTYPE_TWO_WAY                        : 1,
95115     SYNCTYPE_SLOW_SYNC                      : 2,
95116     SYNCTYPE_ONE_WAY_FROM_CLIENT            : 3,
95117     SYNCTYPE_REFRESH_FROM_CLIENT            : 4,
95118     SYNCTYPE_ONE_WAY_FROM_SERVER            : 5,
95119     SYNCTYPE_REFRESH_FROM_SERVER            : 6,
95120     SYNCTYPE_SERVER_ALERTED                 : 7,
95121
95122     // Special syncml-js SyncTypes
95123     SYNCTYPE_DISCOVER                       : 'discover',
95124
95125     // SyncML synctype-to-alertcode mapping
95126     // taking advantage of the fact that 1..7 maps to 200..206
95127     // (more or less... "7" is a bit "nebulous"...)
95128     SyncTypeToAlert: _.object(_.map(_.range(7), function(i) {
95129         return [ i + 1, i + 200 ];
95130     })),
95131
95132     // Conflict handling policies
95133     POLICY_ERROR                            : 1,
95134     POLICY_CLIENT_WINS                      : 2,
95135     POLICY_SERVER_WINS                      : 3,
95136
95137     // SyncML XML namespaces
95138     NAMESPACE_SYNCML_1_0                    : 'syncml:syncml1.0',
95139     NAMESPACE_SYNCML_1_1                    : 'syncml:syncml1.1',
95140     NAMESPACE_SYNCML_1_2                    : 'syncml:syncml1.2',
95141     NAMESPACE_METINF                        : 'syncml:metinf',
95142     NAMESPACE_DEVINF                        : 'syncml:devinf',
95143     NAMESPACE_AUTH_BASIC                    : 'syncml:auth-basic',
95144     NAMESPACE_AUTH_MD5                      : 'syncml:auth-md5',
95145     NAMESPACE_FILTER_CGI                    : 'syncml:filtertype-cgi',
95146
95147     // Commonly used content-types
95148     TYPE_TEXT_PLAIN                         : 'text/plain',
95149     TYPE_VCARD_V21                          : 'text/x-vcard',
95150     TYPE_VCARD_V30                          : 'text/vcard',
95151     TYPE_VCALENDAR                          : 'text/x-vcalendar',
95152     TYPE_ICALENDAR                          : 'text/calendar',
95153     TYPE_MESSAGE                            : 'text/message',
95154     TYPE_SYNCML                             : 'application/vnd.syncml',
95155     TYPE_SYNCML_DEVICE_INFO                 : 'application/vnd.syncml-devinf',
95156     TYPE_SYNCML_ICALENDAR                   : 'application/vnd.syncml-xcal',
95157     TYPE_SYNCML_EMAIL                       : 'application/vnd.syncml-xmsg',
95158     TYPE_SYNCML_BOOKMARK                    : 'application/vnd.syncml-xbookmark',
95159     TYPE_SYNCML_RELATIONAL_OBJECT           : 'application/vnd.syncml-xrelational',
95160     TYPE_OMADS_FOLDER                       : 'application/vnd.omads-folder',
95161     TYPE_OMADS_FILE                         : 'application/vnd.omads-file',
95162     TYPE_OMADS_EMAIL                        : 'application/vnd.omads-email',
95163     TYPE_SQL                                : 'application/sql',
95164     TYPE_LDAP                               : 'text/directory',
95165     TYPE_EMAIL                              : 'message/rfc2822',
95166     TYPE_EMAIL_822                          : 'message/rfc822',
95167     TYPE_SIF_CONTACT                        : 'text/x-s4j-sifc',
95168     TYPE_SIF_NOTE                           : 'text/x-s4j-sifn',
95169     TYPE_SIF_TASK                           : 'text/x-s4j-sift',
95170     TYPE_SIF_EVENT                          : 'text/x-s4j-sife',
95171
95172     // non-agent URI paths
95173     URI_DEVINFO_1_0                         : 'devinf10',
95174     URI_DEVINFO_1_1                         : 'devinf11',
95175     URI_DEVINFO_1_2                         : 'devinf12',
95176
95177     // Response codes - Generic
95178     STATUS_INVALID_CODE                     : 0,
95179     // Response codes - Informational 1xx
95180     STATUS_IN_PROGRESS                      : 101,
95181     // Response codes - Successful 2xx
95182     STATUS_OK                               : 200,
95183     STATUS_ITEM_ADDED                       : 201,
95184     STATUS_ACCEPTED_FOR_PROCESSING          : 202,
95185     STATUS_NONAUTHORIATATIVE_RESPONSE       : 203,
95186     STATUS_NO_CONTENT                       : 204,
95187     STATUS_RESET_CONTENT                    : 205,
95188     STATUS_PARTIAL_CONTENT                  : 206,
95189     STATUS_CONFLICT_RESOLVED_MERGE          : 207,
95190     STATUS_CONFLICT_RESOLVED_CLIENT_DATA    : 208,
95191     STATUS_CONFLICT_RESOLVED_DUPLICATE      : 209,
95192     STATUS_DELETE_WITHOUT_ARCHIVE           : 210,
95193     STATUS_ITEM_NOT_DELETED                 : 211,
95194     STATUS_AUTHENTICATION_ACCEPTED          : 212,
95195     STATUS_CHUNKED_ITEM_ACCEPTED            : 213,
95196     STATUS_OPERATION_CANCELLED_OK           : 214,
95197     STATUS_NOT_EXECUTED                     : 215,
95198     STATUS_ATOMIC_ROLLBACK_OK               : 216,
95199     STATUS_RESULT_ALERT                     : 221,
95200     STATUS_NEXT_MESSAGE                     : 222,
95201     STATUS_NO_END_OF_DATA                   : 223,
95202     STATUS_SUSPEND                          : 224,
95203     STATUS_RESUME                           : 225,
95204     STATUS_DATA_MANAGEMENT                  : 226,
95205     // status codes 227-250 are reserved for future use,
95206     // Response codes - Redirection 3xx
95207     STATUS_MULTIPLE_CHOICES                 : 300,
95208     STATUS_MOVED_PERMANENTLY                : 301,
95209     STATUS_FOUND                            : 302,
95210     STATUS_SEE_ANOTHER_URI                  : 303,
95211     STATUS_NOT_MODIFIED                     : 304,
95212     STATUS_USE_PROXY                        : 305,
95213     // Response codes - Originator Exceptions 4xx
95214     STATUS_BAD_REQUEST                      : 400,
95215     STATUS_INVALID_CREDENTIALS              : 401,
95216     STATUS_PAYMENT_REQUIRED                 : 402,
95217     STATUS_FORBIDDEN                        : 403,
95218     STATUS_NOT_FOUND                        : 404,
95219     STATUS_COMMAND_NOT_ALLOWED              : 405,
95220     STATUS_OPTIONAL_FEATURE_NOT_SUPPORTED   : 406,
95221     STATUS_MISSING_CREDENTIALS              : 407,
95222     STATUS_REQUEST_TIMEOUT                  : 408,
95223     STATUS_UPDATE_CONFLICT                  : 409,
95224     STATUS_GONE                             : 410,
95225     STATUS_SIZE_REQUIRED                    : 411,
95226     STATUS_INCOMPLETE_COMMAND               : 412,
95227     STATUS_REQUESTED_ENTITY_TOO_LARGE       : 413,
95228     STATUS_URI_TOO_LONG                     : 414,
95229     STATUS_UNSUPPORTED_MEDIA_TYPE           : 415,
95230     STATUS_REQUESTED_SIZE_TOO_BIG           : 416,
95231     STATUS_RETRY_LATER                      : 417,
95232     STATUS_ALREADY_EXISTS                   : 418,
95233     STATUS_CONFLICT_RESOLVED_SERVER_DATA    : 419,
95234     STATUS_DEVICE_FULL                      : 420,
95235     STATUS_UNKNOWN_SEARCH_GRAMMAR           : 421,
95236     STATUS_BAD_CGI_SCRIPT                   : 422,
95237     STATUS_SOFT_DELETE_CONFLICT             : 423,
95238     STATUS_OBJECT_SIZE_MISMATCH             : 424,
95239     STATUS_PERMISSION_DENIED                : 425,
95240     // Response codes - Recipient Exceptions 5xx
95241     STATUS_COMMAND_FAILED                   : 500,
95242     STATUS_NOT_IMPLEMENTED                  : 501,
95243     STATUS_BAD_GATEWAY                      : 502,
95244     STATUS_SERVICE_UNAVAILABLE              : 503,
95245     STATUS_GATEWAY_TIMEOUT                  : 504,
95246     STATUS_VERSION_NOT_SUPPORTED            : 505,
95247     STATUS_PROCESSING_ERROR                 : 506,
95248     STATUS_ATOMIC_FAILED                    : 507,
95249     STATUS_REFRESH_REQUIRED                 : 508,
95250     STATUS_RECIPIENT_EXCEPTION_RESERVED1    : 509,
95251     STATUS_DATASTORE_FAILURE                : 510,
95252     STATUS_SERVER_FAILURE                   : 511,
95253     STATUS_SYNCHRONIZATION_FAILED           : 512,
95254     STATUS_PROTOCOL_VERSION_NOT_SUPPORTED   : 513,
95255     STATUS_OPERATION_CANCELLED              : 514,
95256     STATUS_ATOMIC_ROLLBACK_FAILED           : 516,
95257     STATUS_ATOMIC_RESPONSE_TOO_LARGE_TO_FIT : 517,
95258
95259     // SyncML codecs
95260     CODEC_XML                               : 'xml',
95261     CODEC_WBXML                             : 'wbxml',
95262     FORMAT_B64                              : 'b64',
95263     FORMAT_AUTO                             : 'auto',
95264
95265     // SyncML nodes
95266     NODE_SYNCML                             : 'SyncML',
95267     NODE_SYNCBODY                           : 'SyncBody',
95268
95269     // SyncML commands
95270     CMD_SYNCHDR                             : 'SyncHdr',
95271     CMD_SYNC                                : 'Sync',
95272     CMD_ALERT                               : 'Alert',
95273     CMD_STATUS                              : 'Status',
95274     CMD_GET                                 : 'Get',
95275     CMD_PUT                                 : 'Put',
95276     CMD_ADD                                 : 'Add',
95277     CMD_REPLACE                             : 'Replace',
95278     CMD_DELETE                              : 'Delete',
95279     CMD_RESULTS                             : 'Results',
95280     CMD_ATOMIC                              : 'Atomic',
95281     CMD_COPY                                : 'Copy',
95282     CMD_EXEC                                : 'Exec',
95283     CMD_MAP                                 : 'Map',
95284     CMD_MAPITEM                             : 'MapItem',
95285     CMD_SEARCH                              : 'Search',
95286     CMD_SEQUENCE                            : 'Sequence',
95287     CMD_FINAL                               : 'Final',
95288
95289     // SyncML standard device types
95290     DEVTYPE_HANDHELD                        : 'handheld',
95291     DEVTYPE_PAGER                           : 'pager',
95292     DEVTYPE_PDA                             : 'pda',
95293     DEVTYPE_PHONE                           : 'phone',
95294     DEVTYPE_SERVER                          : 'server',
95295     DEVTYPE_SMARTPHONE                      : 'smartphone',
95296     DEVTYPE_WORKSTATION                     : 'workstation',
95297
95298     // Item status codes
95299     ITEM_OK                                 : 0,
95300     ITEM_ADDED                              : 1,
95301     ITEM_MODIFIED                           : 2,
95302     ITEM_DELETED                            : 3,
95303     ITEM_SOFTDELETED                        : 4,
95304 };
95305
95306 module.exports = _self;
95307
95308 });
95309 define('ripple/platform/tizen/2.0/syncml-js-lib/context', function (require, exports, module) {
95310 // -*- coding: utf-8 -*-
95311 //-----------------------------------------------------------------------------
95312 // file: $Id$
95313 // lib:  syncml-js.context
95314 // auth: griffin <griffin@uberdev.org>
95315 // date: 2012/10/22
95316 // copy: (C) CopyLoose 2012 UberDev <hardcore@uberdev.org>, No Rights Reserved.
95317 //-----------------------------------------------------------------------------
95318
95319 var common = require('ripple/platform/tizen/2.0/syncml-js-lib/common'),
95320     constant = require('ripple/platform/tizen/2.0/syncml-js-lib/constant'),
95321     storage = require('ripple/platform/tizen/2.0/syncml-js-lib/storage'),
95322     router = require('ripple/platform/tizen/2.0/syncml-js-lib/router'),
95323     synchronizer = require('ripple/platform/tizen/2.0/syncml-js-lib/synchronizer'),
95324     protocol = require('ripple/platform/tizen/2.0/syncml-js-lib/protocol'),
95325     localadapter = require('ripple/platform/tizen/2.0/syncml-js-lib/localadapter'),
95326     idxdb = {},
95327     _self;
95328
95329 // todo: is this the right place to put this?...
95330 //       the reason that i did not put it in the `define` call is
95331 //       because it needs access to `this.indexedDB`...
95332 var idxdb = {};
95333 if ( typeof(window) != 'undefined' && window.indexedDB )
95334 {
95335     idxdb.indexedDB   = window.indexedDB;
95336     idxdb.IDBKeyRange = window.IDBKeyRange;
95337 }
95338 else
95339 {
95340     idxdb.indexedDB   = this.indexedDB;
95341     idxdb.IDBKeyRange = this.IDBKeyRange;
95342 }
95343
95344 _self = (function () {
95345     var exports = {};
95346
95347     //---------------------------------------------------------------------------
95348     exports.Context = common.Base.extend({
95349
95350         //-------------------------------------------------------------------------
95351         constructor: function(options) {
95352             // options.storage expects the following properties:
95353             //   - indexedDB
95354             //   - IDBKeyRange
95355             options = options || {};
95356             this.storage      = options.storage || idxdb;
95357             this.dbname       = ( options.prefix || '' ) + 'syncml-js';
95358             this.autoCommit   = options.autoCommit == undefined ? true : options.autoCommit;
95359             this.router       = options.router || new router.SmartRouter();
95360             this.synchronizer = options.synchronizer || new synchronizer.Synchronizer();
95361             this.protocol     = options.protocol || new protocol.Protocol();
95362             this.codec        = options.codec || constant.CODEC_XML;
95363             this.listener     = options.listener;
95364             this.ua           = options.ua;
95365             this.config       = _.defaults({}, options.config, {
95366                 trustDevInfo      : false,
95367                 exposeErrorTrace  : false
95368             });
95369             this._db          = null;
95370             this._dbtxn       = null;
95371         },
95372
95373             //-------------------------------------------------------------------------
95374             getAdapter: function(options, devInfo, cb) {
95375                 options = options || {};
95376                 var self = this;
95377                 if ( this._db == undefined )
95378                 {
95379                     storage.openDatabase(this, function(err, db) {
95380                         if ( err ) {
95381                             return cb(err);
95382                         }
95383                         self._db = db;
95384                         self._db.onerror = function(event) {
95385                             // todo: remove this?...
95386                         };
95387                         self._dbtxn = storage.getTransaction(self._db, null, 'readwrite');
95388                         self.getAdapter(options, devInfo, cb);
95389                     });
95390                 }
95391                 else
95392                 {
95393                     var ret = new localadapter.LocalAdapter(this, options, devInfo);
95394                     return ret._load(cb);
95395                 }
95396             },
95397
95398             //-------------------------------------------------------------------------
95399             _txn: function() {
95400                 try {
95401                     // this is a work-around for XPC-based syncml... try to open
95402                     // a store, if it fails, we need a new transaction.
95403                     var store = this._dbtxn.objectStore('mapping');
95404                     return this._dbtxn;
95405                 } catch ( exc ) {
95406                     this._dbtxn = storage.getTransaction(this._db, null, 'readwrite');
95407                     return this._dbtxn;
95408                 }
95409             },
95410
95411             //-------------------------------------------------------------------------
95412             getEasyClientAdapter: function(options, cb) {
95413                 try{
95414                     this._getEasyClientAdapter(options, cb);
95415                 }catch(e){
95416                     cb(e);
95417                 }
95418             },
95419
95420             //-------------------------------------------------------------------------
95421             _getEasyClientAdapter: function(options, cb) {
95422                 // options should be:= {
95423                 //   // devID,
95424                 //   // displayName,
95425                 //   devInfo: {},
95426                 //   stores: [],
95427                 //   peer: {},
95428                 //   routes: [
95429                 //     [ source, target ],
95430                 //   ]
95431                 // }
95432                 // response: cb(err, adapter, stores, peer);
95433
95434                 var self = this;
95435
95436                 var ret = {
95437                     adapter: null,
95438                     stores: [],
95439                     peer: null
95440                 };
95441
95442                 var setupAdapter = function(cb) {
95443                     var adapterOptions = _.omit(options, 'devInfo', 'stores', 'peers', 'routes');
95444                     self.getAdapter(adapterOptions, options.devInfo, function(err, adapter) {
95445                         if ( err ) {
95446                             return cb(err);
95447                         }
95448                         ret.adapter = adapter;
95449                         if ( adapter.devInfo ) {
95450                             return cb();
95451                         }
95452                         adapter.setDevInfo(options.devInfo, cb);
95453                     });
95454                 };
95455
95456                 var setupStores = function(cb) {
95457                     common.cascade(options.stores, function(storeInfo, cb) {
95458                         var store = ret.adapter.getStore(storeInfo.uri);
95459                         if ( store != undefined )
95460                         {
95461                             if ( storeInfo.agent ) {
95462                                 store.agent = storeInfo.agent;
95463                             }
95464                             ret.stores.push(store);
95465                             return cb();
95466                         }
95467                         ret.adapter.addStore(storeInfo, function(err, store) {
95468                             if ( err ) {
95469                                 return cb(err);
95470                             }
95471                             ret.stores.push(store);
95472                             return cb();
95473                         });
95474                     }, cb);
95475                 };
95476
95477                 var setupPeer = function(cb) {
95478                     var peer = _.find(ret.adapter.getPeers(), function(p) {
95479                         return p.url == options.peer.url;
95480                     });
95481                     if ( peer )
95482                     {
95483                         ret.peer = peer;
95484                         return cb();
95485                     }
95486                     ret.adapter.addPeer(options.peer, function(err, peer) {
95487                         if ( err ) {
95488                             return cb(err);
95489                         }
95490                         ret.peer = peer;
95491                         common.cascade(options.routes, function(route, cb) {
95492                             ret.peer.setRoute(route[0], route[1], cb);
95493                         }, cb);
95494                     });
95495                 };
95496                 setupAdapter(function(err) {
95497                     if ( err ) {
95498                         return cb(err);
95499                     }
95500                     setupStores(function(err) {
95501                         if ( err ) {
95502                             return cb(err);
95503                         }
95504                         setupPeer(function(err) {
95505                             if ( err ) {
95506                                 return cb(err);
95507                             }
95508                             cb(null, ret.adapter, ret.stores, ret.peer);
95509                         });
95510                     });
95511                 });
95512             },
95513
95514             //-------------------------------------------------------------------------
95515             close: function(cb) {
95516                 if ( this._db )
95517                     this._db.close();
95518                 this._db = null;
95519                 cb(null);
95520             }
95521
95522     });
95523
95524     return exports;
95525
95526 })();
95527
95528 module.exports = _self;
95529
95530 });
95531 define('ripple/platform/tizen/2.0/syncml-js-lib/ctype', function (require, exports, module) {
95532 // -*- coding: utf-8 -*-
95533 //-----------------------------------------------------------------------------
95534 // file: $Id$
95535 // auth: metagriffin <metagriffin@uberdev.org>
95536 // date: 2012/10/13
95537 // copy: (C) CopyLoose 2012 UberDev <hardcore@uberdev.org>, No Rights Reserved.
95538 //-----------------------------------------------------------------------------
95539 var common = require('ripple/platform/tizen/2.0/syncml-js-lib/common'),
95540     ET = require('ripple/platform/tizen/2.0/syncml-js-lib/elementtree'),
95541     _self;
95542
95543 _self = (function () {
95544
95545     var exports = {};
95546
95547     //---------------------------------------------------------------------------
95548     exports.ContentTypeInfo = common.Base.extend({
95549
95550         //-------------------------------------------------------------------------
95551         constructor: function(ctype, versions, options) {
95552             this.ctype    = ctype;
95553             this.versions = _.isArray(versions) ? versions : [versions];
95554             _.defaults(this, options || {}, {
95555                 preferred: false,
95556                 transmit:  true,
95557                 receive:   true,
95558             });
95559         },
95560
95561         //-------------------------------------------------------------------------
95562         merge: function(other) {
95563             if ( this.ctype != other.ctype
95564                 || ! _.isEqual(this.versions, other.versions)
95565                 || this.preferred != other.preferred )
95566                 return false;
95567             this.transmit = this.transmit || other.transmit;
95568             this.receive  = this.receive  || other.receive;
95569             return true
95570         },
95571
95572         //-------------------------------------------------------------------------
95573         toStruct: function() {
95574             return {
95575                 ctype: this.ctype,
95576                 versions: this.versions,
95577                 preferred: this.preferred,
95578                 transmit:  this.transmit,
95579                 receive:   this.receive
95580             };
95581         },
95582
95583         //-------------------------------------------------------------------------
95584         toSyncML: function(nodeName, uniqueVerCt) {
95585             if ( _.isFunction(nodeName) )
95586             {
95587                 cb = nodeName;
95588                 nodeName = null;
95589             }
95590             else if ( _.isFunction(uniqueVerCt) )
95591             {
95592                 cb = uniqueVerCt;
95593                 uniqueVerCt = null;
95594             }
95595             if ( ! nodeName )
95596             {
95597                 nodeName = this.transmit ? 'Tx' : 'Rx';
95598                 if ( this.preferred )
95599                     nodeName += '-Pref';
95600             }
95601             if ( this.preferred )
95602                 nodeName += '-Pref';
95603
95604             if ( uniqueVerCt )
95605             {
95606                 var ret = _.map(this.versions, function(v) {
95607                     var tmp = ET.Element(nodeName);
95608                     ET.SubElement(tmp, 'CTType').text = this.ctype;
95609                     ET.SubElement(tmp, 'VerCT').text = v;
95610                     return tmp;
95611                 }, this);
95612                 return ret;
95613             }
95614             var ret = ET.Element(nodeName);
95615             ET.SubElement(ret, 'CTType').text = this.ctype;
95616             _.each(this.versions, function(v) {
95617                 ET.SubElement(ret, 'VerCT').text = v;
95618             });
95619             return ret;
95620         },
95621
95622         describe: function(stream, cb) {
95623             stream.write(this.ctype);
95624             stream.write(this.versions.length == 1 ? ' version ' : ' versions ');
95625             stream.write(this.versions.join(', '));
95626             var flags = [];
95627             if ( this.preferred )
95628                 flags.push('preferred');
95629             if ( this.transmit )
95630                 flags.push('tx');
95631             if ( this.receive )
95632                 flags.push('rx');
95633             if ( flags.length > 0 )
95634             {
95635                 stream.write(' (');
95636                         stream.write(flags.join(', '));
95637                         stream.write(')');
95638                         }
95639                         stream.write('\n');
95640                         }
95641
95642                         }, {
95643
95644                             //-------------------------------------------------------------------------
95645                             fromStruct: function(struct) {
95646                                 return new exports.ContentTypeInfo(struct.ctype, struct.versions, struct);
95647                             },
95648
95649                     //-------------------------------------------------------------------------
95650                     fromSyncML: function(xnode) {
95651                         return new exports.ContentTypeInfo(
95652                             xnode.findtext('CTType'),
95653                             _.map(xnode.findall('VerCT'), function(e) { return e.text; }),
95654                             {
95655                                 preferred: xnode.tag.match('-Pref$') != undefined,
95656                         transmit:  xnode.tag.indexOf('Tx') >= 0,
95657                         receive:   xnode.tag.indexOf('Rx') >= 0
95658                             }
95659                             );
95660                     }
95661
95662                         });
95663
95664     return exports;
95665
95666 })();
95667
95668 module.exports = _self;
95669
95670 });
95671 define('ripple/platform/tizen/2.0/syncml-js-lib/devinfo', function (require, exports, module) {
95672 // -*- coding: utf-8 -*-
95673 //-----------------------------------------------------------------------------
95674 // file: $Id$
95675 // lib:  syncml-js.devinfo
95676 // auth: griffin <griffin@uberdev.org>
95677 // date: 2012/11/06
95678 // copy: (C) CopyLoose 2012 UberDev <hardcore@uberdev.org>, No Rights Reserved.
95679 //-----------------------------------------------------------------------------
95680
95681 var common = require('ripple/platform/tizen/2.0/syncml-js-lib/common'),
95682     constant = require('ripple/platform/tizen/2.0/syncml-js-lib/constant'),
95683     storemod = require('ripple/platform/tizen/2.0/syncml-js-lib/store'),
95684     ET = require('ripple/platform/tizen/2.0/syncml-js-lib/elementtree'),
95685     _self;
95686
95687 _self = (function () {
95688
95689     var exports = {};
95690
95691     var strAttributeMap = [
95692     ['manufacturerName',    'Man'],
95693       ['modelName',           'Mod'],
95694       ['oem',                 'OEM'],
95695       ['firmwareVersion',     'FwV'],
95696       ['softwareVersion',     'SwV'],
95697       ['hardwareVersion',     'HwV'],
95698       ['devID',               'DevID'],
95699       ['devType',             'DevTyp']
95700     ];
95701
95702 var boolAttributeMap = [
95703     ['utc',                 'UTC'],
95704       ['largeObjects',        'SupportLargeObjs'],
95705       ['hierarchicalSync',    'SupportHierarchicalSync'],
95706       ['numberOfChanges',     'SupportNumberOfChanges']
95707     ];
95708
95709 //---------------------------------------------------------------------------
95710 exports.DevInfo = common.Base.extend({
95711
95712     //-------------------------------------------------------------------------
95713     constructor: function(adapter, options) {
95714         var self = this;
95715         var options = _.defaults({}, options, {
95716             devType           : constant.DEVTYPE_WORKSTATION,
95717             manufacturerName  : '-',
95718             modelName         : '-',
95719             oem               : '-',
95720             hardwareVersion   : '-',
95721             firmwareVersion   : '-',
95722             softwareVersion   : '-',
95723             utc               : true,
95724             largeObjects      : true,
95725             hierarchicalSync  : true,
95726             numberOfChanges   : true,
95727             extensions        : {}
95728         });
95729
95730         // todo: is there anyway to mark attributes as read-only?...
95731
95732         //: [read-only] these are all read-only attributes
95733         this.devID            = options.devID || common.makeID();
95734         this.devType          = options.devType;
95735         this.manufacturerName = options.manufacturerName;
95736         this.modelName        = options.modelName;
95737         this.oem              = options.oem;
95738         this.hardwareVersion  = options.hardwareVersion;
95739         this.firmwareVersion  = options.firmwareVersion;
95740         this.softwareVersion  = options.softwareVersion;
95741         this.utc              = options.utc;
95742         this.largeObjects     = options.largeObjects;
95743         this.hierarchicalSync = options.hierarchicalSync;
95744         this.numberOfChanges  = options.numberOfChanges;
95745         this.extensions       = {};
95746
95747         _.each(options.extensions, function(values, name) {
95748             self.setExtension(name, values);
95749         });
95750
95751         // --- private attributes
95752         this._a       = adapter;
95753     },
95754
95755         //-------------------------------------------------------------------------
95756         setExtension: function(name, values) {
95757             this.extensions[name] = _.isArray(values) ? values : [values];
95758         },
95759
95760         //-------------------------------------------------------------------------
95761         getExtensionKeys: function() {
95762             return _.keys(this.extensions);
95763         },
95764
95765         //-------------------------------------------------------------------------
95766         getExtension: function(name) {
95767             return this.extensions[name];
95768         },
95769
95770         //-------------------------------------------------------------------------
95771         _load: function(cb) {
95772             cb();
95773         },
95774
95775         //-------------------------------------------------------------------------
95776         _updateModel: function(cb) {
95777             if ( ! this._a._model )
95778                 return cb('devinfo created on un-initialized adapter');
95779             this._a._model.devInfo = {
95780                 devID            : this.devID,
95781                 devType          : this.devType,
95782                 manufacturerName : this.manufacturerName,
95783                 modelName        : this.modelName,
95784                 oem              : this.oem,
95785                 hardwareVersion  : this.hardwareVersion,
95786                 firmwareVersion  : this.firmwareVersion,
95787                 softwareVersion  : this.softwareVersion,
95788                 utc              : this.utc,
95789                 largeObjects     : this.largeObjects,
95790                 hierarchicalSync : this.hierarchicalSync,
95791                 numberOfChanges  : this.numberOfChanges,
95792                 extensions       : this.extensions
95793             };
95794             cb();
95795         },
95796
95797         //-------------------------------------------------------------------------
95798         toSyncML: function(dtdVersion, stores) {
95799             dtdVersion = dtdVersion || constant.SYNCML_DTD_VERSION_1_2;
95800             if ( dtdVersion != constant.SYNCML_DTD_VERSION_1_2 )
95801                 throw new Error('unsupported DTD version "' + dtdVersion + '"')
95802                     var xret = ET.Element('DevInf', {'xmlns': constant.NAMESPACE_DEVINF})
95803                     ET.SubElement(xret, 'VerDTD').text = dtdVersion;
95804             for ( var idx=0 ; idx<strAttributeMap.length ; idx++ )
95805             {
95806                 var map = strAttributeMap[idx];
95807                 // todo: should i enforce the fact that these are all *required*?...
95808                 if ( this[map[0]] != undefined )
95809                     ET.SubElement(xret, map[1]).text = this[map[0]];
95810             }
95811             for ( var idx=0 ; idx<boolAttributeMap.length ; idx++ )
95812             {
95813                 var map = boolAttributeMap[idx];
95814                 if ( this[map[0]] )
95815                     ET.SubElement(xret, map[1])
95816             }
95817             if ( stores && stores.length > 0 )
95818                 for ( var idx=0 ; idx<stores.length ; idx++ )
95819                     xret.append(stores[idx].toSyncML());
95820             var xext = null;
95821             for ( var name in this.extensions )
95822             {
95823                 if ( ! xext )
95824                     xext = ET.SubElement(xret, 'Ext');
95825                 ET.SubElement(xext, 'XNam').text = name;
95826                 var values = this.extensions[name];
95827                 for ( var idx=0 ; idx<values.length ; idx++ )
95828                     ET.SubElement(xext, 'XVal').text = '' + values[idx];
95829             };
95830             return xret;
95831         },
95832
95833 }, {
95834
95835     //-------------------------------------------------------------------------
95836     fromSyncML: function(xnode) {
95837         var options = {};
95838         var stores  = []
95839             var dtdVersion = xnode.findtext('VerDTD')
95840             if ( dtdVersion != constant.SYNCML_DTD_VERSION_1_2 )
95841                 throw new common.ProtocolError('unsupported DTD version "' + dtdVersion + '"');
95842         for ( var idx=0 ; idx<strAttributeMap.length ; idx++ )
95843         {
95844             var map = strAttributeMap[idx];
95845             // todo: should i enforce the fact that these are all *required*?...
95846             options[map[0]] = xnode.findtext(map[1]);
95847         }
95848         for ( var idx=0 ; idx<boolAttributeMap.length ; idx++ )
95849         {
95850             var map = boolAttributeMap[idx];
95851             options[map[0]] = xnode.find(map[1]) != undefined;
95852         }
95853         _.each(xnode.getchildren(), function(child) {
95854             if ( child.tag == 'DataStore' )
95855             return stores.push(storemod.Store.fromSyncML(child));
95856         if ( child.tag == 'Ext' )
95857         {
95858             options.extensions = {};
95859             var elist = child.getchildren();
95860             var ecur  = null;
95861             for ( var idx=0 ; idx<elist.length ; idx++ )
95862         {
95863             var eitem = elist[idx];
95864             if ( eitem.tag == 'XNam' )
95865         {
95866             ecur = eitem.text;
95867             continue;
95868         }
95869         if ( ! ecur )
95870             // paranoia...
95871             continue;
95872         if ( ! options.extensions[ecur] )
95873             options.extensions[ecur] = [];
95874         options.extensions[ecur].push(eitem.text);
95875         }
95876         return;
95877         }
95878         });
95879         return [new exports.DevInfo(null, options), stores];
95880     }
95881
95882 });
95883
95884 return exports;
95885
95886 })();
95887
95888 module.exports = _self;
95889
95890 });
95891 define('ripple/platform/tizen/2.0/syncml-js-lib/elementtree', function (require, exports, module) {
95892 /*
95893  *  Copyright 2013 Intel Corporation
95894  *
95895  * Licensed under the Apache License, Version 2.0 (the "License");
95896  * you may not use this file except in compliance with the License.
95897  * You may obtain a copy of the License at
95898  *
95899  * http://www.apache.org/licenses/LICENSE-2.0
95900  *
95901  * Unless required by applicable law or agreed to in writing, software
95902  * distributed under the License is distributed on an "AS IS" BASIS,
95903  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
95904  * See the License for the specific language governing permissions and
95905  * limitations under the License.
95906  */
95907
95908 var utils = require('ripple/utils'),
95909     _parser,
95910     _serializer,
95911     _self;
95912
95913 function _find(query, element, type) {
95914     var querylist = query.split("/"),
95915         e = element._node,
95916         tag, i, ret;
95917
95918     if (querylist.length === 0) {
95919         return undefined;
95920     }
95921
95922     for(i = 0; i < querylist.length; i++) {
95923         tag = querylist[i];
95924         try {
95925             e = e.getElementsByTagName(tag)[0];
95926         } catch (error) {
95927             e = undefined;
95928             break;
95929         }
95930     }
95931
95932     if (e) {
95933         if (type === "TEXT") {
95934             return e.textContent;
95935         } else if (type === "NODE") {
95936             ret = {
95937                 _doc: element,
95938                 _node: e,
95939                 find: function (query) {
95940                     return _find(query, this, "NODE");
95941                 },
95942                 findtext: function (query) {
95943                     return _find(query, this, "TEXT");
95944                 },
95945                 findall: function (query) {
95946                     return _findall(query, this);
95947                 },
95948                 getchildren: function () {
95949                     return _getchildren(this);
95950                 },
95951                 append: function (node) {
95952                     this._node.appendChild(node._node);
95953                 },
95954                 getroot: function () {
95955                     return this;
95956                 }
95957             };
95958             ret.__defineSetter__("text", function (text) {
95959                 this._node.textContent = text;
95960             });
95961             ret.__defineGetter__("text", function () {
95962                 return this._node.textContent;
95963             });
95964             ret.__defineGetter__("tag", function () {
95965                 return _tag(this);
95966             });
95967             return ret;
95968         }
95969     } else {
95970         return undefined;
95971     }
95972 }
95973
95974 function _findall(query, element) {
95975     var querylist = query.split("/"),
95976         e = element._node,
95977         tag,
95978         array,
95979         tmp,
95980         ret = [],
95981         i;
95982
95983     for(i = 0; i < querylist.length - 1; i++) {
95984         tag = querylist[i];
95985         try {
95986             e = e.getElementsByTagName(tag)[0];
95987         } catch (error) {
95988             return ret;
95989         }
95990     }
95991
95992     tag = querylist[querylist.length - 1];
95993     array = e.getElementsByTagName(tag);
95994     ///return ret;
95995     for(i = 0; i < array.length; i++) {
95996         tmp = {
95997             _doc: element,
95998             _node: array[i],
95999             find: function (query) {
96000                 return _find(query, this, "NODE");
96001             },
96002             findtext: function (query) {
96003                 return _find(query, this, "TEXT");
96004             },
96005             findall: function (query) {
96006                 return _findall(query, this);
96007             },
96008             getchildren: function () {
96009                 return _getchildren(this);
96010             },
96011             append: function (node) {
96012                 this._node.appendChild(node._node);
96013             },
96014             getroot: function () {
96015                 return this;
96016             }
96017         };
96018         tmp.__defineSetter__("text", function (text) {
96019             this._node.textContent = text;
96020         });
96021         tmp.__defineGetter__("text", function () {
96022             return this._node.textContent;
96023         });
96024         tmp.__defineGetter__("tag", function () {
96025             return _tag(this);
96026         });
96027         ret.push(tmp);
96028     }
96029     return ret;
96030 }
96031
96032 function _tag(element) {
96033     var array;
96034     array = element._node.tagName.split(":");
96035     return array[array.length - 1];
96036 }
96037
96038 function _getchildren(element) {
96039     var ret = [], e, i;
96040     for (i = 0; i < element._node.childNodes.length; i++) {
96041         e = {
96042             _doc: element,
96043             _node: element._node.childNodes[i],
96044             find: function (query) {
96045                 return _find(query, this, "NODE");
96046             },
96047             findtext: function (query) {
96048                 return _find(query, this, "TEXT");
96049             },
96050             findall: function (query) {
96051                 return _findall(query, this);
96052             },
96053             getchildren: function () {
96054                 return _getchildren(this);
96055             },
96056             append: function (node) {
96057                 this._node.appendChild(node._node);
96058             },
96059             getroot: function () {
96060                 return this;
96061             }
96062         };
96063         e.__defineSetter__("text", function (text) {
96064             this._node.textContent = text;
96065         });
96066         e.__defineGetter__("text", function () {
96067             return this._node.textContent;
96068         });
96069         e.__defineGetter__("tag", function () {
96070             return _tag(this);
96071         });
96072         ret.push(e);
96073     }
96074
96075     return ret;
96076 }
96077
96078
96079 _self = (function () {
96080     ET = {};
96081
96082     ET.Element = function(name, attributes) {
96083         var element = {},
96084             doc,
96085             node;
96086
96087         doc = _parser.parseFromString("<" + name + "></" + name + ">", "text/xml");
96088         node = doc.childNodes[0];
96089         if (attributes) {
96090             utils.forEach(attributes, function (value, key) {
96091                 node.setAttribute(key, value);
96092             });
96093         }
96094
96095         element = {
96096             _doc: doc,
96097             _node: node,
96098             find: function (query) {
96099                 return _find(query, this, "NODE");
96100             },
96101             findtext: function (query) {
96102                 return _find(query, this, "TEXT");
96103             },
96104             findall: function (query) {
96105                 return _findall(query, this);
96106             },
96107             getchildren: function () {
96108                 return _getchildren(this);
96109             },
96110             append: function (node) {
96111                 this._node.appendChild(node._node);
96112             },
96113             getroot: function () {
96114                 return this;
96115             }
96116         };
96117
96118         element.__defineSetter__("text", function (text) {
96119             this._node.textContent = text;
96120         });
96121
96122         element.__defineGetter__("text", function () {
96123             return this._node.textContent;
96124         });
96125
96126         element.__defineGetter__("tag", function () {
96127             return _tag(this);
96128         });
96129
96130         return element;
96131     };
96132
96133     ET.SubElement = function(element, name, attributes) {
96134         var subElement = {},
96135             node;
96136         node = element._doc.createElement(name);
96137         if (attributes) {
96138             utils.forEach(attributes, function (value, key) {
96139                 node.setAttribute(key, value);
96140             });
96141         }
96142         element._node.appendChild(node);
96143         subElement = {
96144             _doc: element._doc,
96145             _node: node,
96146             find: function (query) {
96147                 return _find(query, this, "NODE");
96148             },
96149             findtext: function (query) {
96150                 return _find(query, this, "TEXT");
96151             },
96152             findall: function (query) {
96153                 return _findall(query, this);
96154             },
96155             getchildren: function () {
96156                 return _getchildren(this);
96157             },
96158             append: function (node) {
96159                 this._node.appendChild(node._node);
96160             },
96161             getroot: function () {
96162                 return this;
96163             }
96164         };
96165         subElement.__defineSetter__("text", function (text) {
96166             this._node.textContent = text;
96167         });
96168         subElement.__defineGetter__("text", function () {
96169             return this._node.textContent;
96170         });
96171         subElement.__defineGetter__("tag", function () {
96172             return _tag(this);
96173         });
96174
96175         return subElement;
96176     };
96177
96178     ET.tostring = function(element) {
96179         return _serializer.serializeToString(element._node);
96180     };
96181     ET.parse = function(doc) {
96182         var element = {};
96183
96184         element = {
96185             _doc: doc,
96186             _node: doc.childNodes[0],
96187             find: function (query) {
96188                 return _find(query, this, "NODE");
96189             },
96190             findtext: function (query) {
96191                 return _find(query, this, "TEXT");
96192             },
96193             findall: function (query) {
96194                 return _findall(query, this);
96195             },
96196             getchildren: function () {
96197                 return _getchildren(this);
96198             },
96199             append: function (node) {
96200                 this._node.appendChild(node._node);
96201             },
96202             getroot: function () {
96203                 return this;
96204             }
96205         };
96206         element.__defineSetter__("text", function (text) {
96207             this._node.textContent = text;
96208         });
96209         element.__defineGetter__("text", function () {
96210             return this._node.textContent;
96211         });
96212         element.__defineGetter__("tag", function () {
96213             return _tag(this);
96214         });
96215
96216         return element;
96217     };
96218
96219     ET.CdataElement = function(str) {
96220         var doc, cdata;
96221         doc = _parser.parseFromString("<data></data>", "text/xml");
96222         cdata = doc.createCDATASection(str);
96223         return cdata;
96224     };
96225
96226     return ET;
96227 })();
96228
96229 _parser = new DOMParser();
96230 _serializer = new XMLSerializer();
96231
96232 module.exports = _self;
96233
96234 });
96235 define('ripple/platform/tizen/2.0/syncml-js-lib/item', function (require, exports, module) {
96236 // -*- coding: utf-8 -*-
96237 //-----------------------------------------------------------------------------
96238 // file: $Id$
96239 // lib:  syncml-js.item
96240 // auth: griffin <griffin@uberdev.org>
96241 // date: 2012/11/30
96242 // copy: (C) CopyLoose 2012 UberDev <hardcore@uberdev.org>, No Rights Reserved.
96243 //-----------------------------------------------------------------------------
96244
96245 var common = require('ripple/platform/tizen/2.0/syncml-js-lib/common');
96246
96247 var _self = (function () {
96248     var exports = {};
96249
96250     //---------------------------------------------------------------------------
96251     exports.Item = common.Base.extend({
96252
96253         //: the unique identifier (within the context of a SyncML datastore)
96254         //: of the current SyncML item.
96255         id: null,
96256
96257         compare: function(other) {
96258             return ( other === this ? 0 : 1 );
96259         }
96260
96261     });
96262
96263     return exports;
96264
96265 })();
96266
96267 module.exports = _self;
96268
96269 });
96270 define('ripple/platform/tizen/2.0/syncml-js-lib/localadapter', function (require, exports, module) {
96271 // -*- coding: utf-8 -*-
96272 //-----------------------------------------------------------------------------
96273 // file: $Id$
96274 // lib:  syncml-js.localadapter
96275 // auth: griffin <griffin@uberdev.org>
96276 // date: 2012/10/22
96277 // copy: (C) CopyLoose 2012 UberDev <hardcore@uberdev.org>, No Rights Reserved.
96278 //-----------------------------------------------------------------------------
96279
96280 var common = require('ripple/platform/tizen/2.0/syncml-js-lib/common'),
96281     constant = require('ripple/platform/tizen/2.0/syncml-js-lib/constant'),
96282     codec = require('ripple/platform/tizen/2.0/syncml-js-lib/codec'),
96283     storage = require('ripple/platform/tizen/2.0/syncml-js-lib/storage'),
96284     remote = require('ripple/platform/tizen/2.0/syncml-js-lib/remoteadapter'),
96285     storemod = require('ripple/platform/tizen/2.0/syncml-js-lib/store'),
96286     devinfomod = require('ripple/platform/tizen/2.0/syncml-js-lib/devinfo'),
96287     adapter = require('ripple/platform/tizen/2.0/syncml-js-lib/adapter'),
96288     state = require('ripple/platform/tizen/2.0/syncml-js-lib/state'),
96289     useragent = require('ripple/platform/tizen/2.0/syncml-js-lib/useragent'),
96290     _self;
96291
96292 _self = (function () {
96293     var exports = {};
96294
96295     //---------------------------------------------------------------------------
96296     exports.LocalAdapter = adapter.Adapter.extend({
96297
96298         //-------------------------------------------------------------------------
96299         constructor: function(context, options, devInfo) {
96300
96301             // todo: is there anyway to mark attributes as read-only?...
96302
96303             //: [read-only] devInfo describes this adapter's device info and
96304             //: capabilities.
96305             this.devInfo = null;
96306
96307             //: [read-only] the device ID of this adapter.
96308             this.devID = options.devID || null;
96309
96310             //: [read-only] specifies whether this Adapter represents a local
96311             //: or remote peer.
96312             this.isLocal = true;
96313
96314             //: [read-only] human-facing name of this adapter
96315             this.displayName = options.displayName || null;
96316
96317             //: [read-only] the adapter-wide default value of the maximum
96318             //: message size.
96319             this.maxMsgSize = options.maxMsgSize || null;
96320
96321             //: [read-only] the adapter-wide default value of the maximum
96322             //: object size.
96323             this.maxObjSize = options.maxObjSize || null;
96324
96325             //: [read-only] specifies default conflict resolution policy for
96326             //: this adapter. if undefined, defaults to constant.POLICY_ERROR.
96327             this.conflictPolicy = options.conflictPolicy || constant.POLICY_ERROR;
96328
96329             // --- private attributes
96330             this.id       = options.id || common.makeID();
96331             this._c       = context;
96332             // TODO: use _.pick() for these options...
96333             this._options = options;
96334             this._devInfo = devInfo;
96335             this._model   = null;
96336             this._stores  = {};
96337             this._peers   = [];
96338         },
96339
96340             //-------------------------------------------------------------------------
96341             _getModel: function() {
96342                 return this._model;
96343             },
96344
96345             //-------------------------------------------------------------------------
96346             setDevInfo: function(devInfo, cb) {
96347                 if ( this._model == undefined )
96348                     this._model = {
96349                         id              : this.id,
96350                         displayName     : this.displayName,
96351                         maxMsgSize      : this.maxMsgSize,
96352                         maxObjSize      : this.maxObjSize,
96353                         conflictPolicy  : this.conflictPolicy,
96354                         devInfo         : null,
96355                         stores          : [],
96356                         peers           : [],
96357                         isLocal         : 1
96358                     };
96359
96360                 var di = new devinfomod.DevInfo(this, devInfo);
96361                 di._updateModel(_.bind(function(err) {
96362                     if ( err )
96363                         return cb(err);
96364
96365                     this._model.devID = this._model.devInfo.devID;
96366                     this.devID        = this._model.devInfo.devID;
96367                     this.devInfo      = di;
96368
96369                 // since the local devinfo has changed, we need to ensure that
96370                 // we rebroadcast it (in case there are any affects...), thus
96371                 // resetting all anchors.
96372                 // TODO: this seems a little heavy-handed, since this will force
96373                 //       a slow-sync for each datastore. is that really the best
96374                 //       thing?...
96375                 this._resetAllAnchors();
96376
96377                 this._save(this._c._txn(), cb);
96378
96379                 }, this));
96380             },
96381
96382             //-------------------------------------------------------------------------
96383             _resetAllAnchors: function() {
96384                 _.each(this._model.peers, function(peer) {
96385                     _.each(peer.stores, function(store) {
96386                         if ( ! store.binding )
96387                         return;
96388                     store.binding.localAnchor  = null;
96389                     store.binding.remoteAnchor = null;
96390                     });
96391                 });
96392             },
96393
96394             //-------------------------------------------------------------------------
96395             getPeers: function() {
96396                 return this._peers;
96397             },
96398
96399             //-------------------------------------------------------------------------
96400             addPeer: function(peerInfo, cb) {
96401                 var self = this;
96402
96403                 // TODO: if there is already a peer for the specified URL, then
96404                 //       we may have a problem!...
96405
96406                 // todo: if we are adding a peer to an adapter that already has
96407                 //       non-client peers, then we may have a problem!...
96408                 //       (this is only true while syncml-js is not capable of truly
96409                 //       operating in peer-to-peer mode)
96410
96411                 var peer = new remote.RemoteAdapter(this, peerInfo);
96412                 peer._updateModel(function(err) {
96413                     if ( err )
96414                     return cb(err);
96415                 self._peers.push(peer);
96416                 cb(null, peer);
96417                 });
96418             },
96419
96420             //-------------------------------------------------------------------------
96421             save: function(cb) {
96422                 this._save(this._c._txn(), cb);
96423             },
96424
96425             //-------------------------------------------------------------------------
96426             _save: function(dbtxn, cb) {
96427                 var self = this;
96428                 self._updateModel(function(err) {
96429                     if ( err )
96430                     return cb(err);
96431                 storage.put(dbtxn.objectStore('adapter'), self._model, cb);
96432                 });
96433             },
96434
96435             //-------------------------------------------------------------------------
96436             _updateModel: function(cb) {
96437                 var self = this;
96438                 var model = self._model;
96439                 model.displayName    = self.displayName;
96440                 model.devID          = self.devID;
96441                 model.maxMsgSize     = self.maxMsgSize;
96442                 model.maxObjSize     = self.maxObjSize;
96443                 model.conflictPolicy = self.conflictPolicy;
96444                 model.isLocal        = 1;
96445                 common.cascade([
96446                         // update the devInfo model
96447                         function(cb) {
96448                             if ( ! self.devInfo )
96449                     return cb();
96450                 return self.devInfo._updateModel(cb);
96451                         },
96452                         // update the stores model
96453                         function(cb) {
96454                             model.stores = [];
96455                             common.cascade(_.values(self._stores), function(store, cb) {
96456                                 store._updateModel(cb);
96457                             }, cb);
96458                         },
96459
96460                         // update the peers model
96461                         function(cb) {
96462                             // NOTE: unlike stores, which can completely regenerate the
96463                             //       model based on the class, the peers store binding
96464                             //       and routing info is only in the model, so cannot be
96465                             //       completely deleted...
96466                             common.cascade(self._peers, function(peer, cb) {
96467                                 peer._updateModel(cb);
96468                             }, cb);
96469                         }
96470
96471                 ], cb);
96472             },
96473
96474             //-------------------------------------------------------------------------
96475             _load: function(cb) {
96476                 var self = this;
96477
96478                 // TODO: if options specifies a devID/name/etc, use that...
96479
96480                 storage.getAll(
96481                     this._c,
96482                     this._c._txn().objectStore('adapter').index('isLocal'),
96483                     {only: 1},
96484                     function(err, adapters) {
96485                         if ( err ) {
96486                             return cb(err);
96487                         }
96488                         if ( adapters.length > 1 )
96489                             return cb('multiple local adapters defined - specify which devID to load');
96490                         if ( adapters.length <= 0 )
96491                             return cb(null, self);
96492                         self._loadModel(adapters[0], function(err) {
96493                             if ( err )
96494                                 return cb(err);
96495                             return cb(null, self);
96496                         });
96497                     }
96498                 );
96499             },
96500
96501             //-------------------------------------------------------------------------
96502             _loadModel: function(model, cb) {
96503                 var self = this;
96504                 self._model         = model;
96505                 self.displayName    = model.displayName;
96506                 self.devID          = model.devID;
96507                 self.maxMsgSize     = model.maxMsgSize;
96508                 self.maxObjSize     = model.maxObjSize;
96509                 self.conflictPolicy = model.conflictPolicy;
96510                 common.cascade([
96511                         // load device info
96512                         function(cb) {
96513                             var di = new devinfomod.DevInfo(self, self._model.devInfo);
96514                             di._load(function(err) {
96515                                 if ( err )
96516                                 return cb(err);
96517                             self.devInfo = di;
96518                             cb();
96519                             });
96520                         },
96521                         // load stores
96522                         function(cb) {
96523                             common.cascade(model.stores, function(e, cb) {
96524                                 var store = new storemod.Store(self, e);
96525                                 store._load(function(err) {
96526                                     if ( err )
96527                                     return cb(err);
96528                                 self._stores[store.uri] = store;
96529                                 return cb();
96530                                 });
96531                             }, cb);
96532                         },
96533                         // load peers
96534                         function(cb) {
96535                             var remotes = _.filter(model.peers, function(e) {
96536                                 return ! e.isLocal;
96537                             });
96538                             self._peers = [];
96539                             common.cascade(remotes, function(e, cb) {
96540                                 var peer = new remote.RemoteAdapter(self, e);
96541                                 peer._load(function(err) {
96542                                     if ( err )
96543                                     return cb(err);
96544                                 self._peers.push(peer);
96545                                 return cb();
96546                                 });
96547                             }, cb);
96548                         }
96549                 ], cb);
96550             },
96551
96552             //-------------------------------------------------------------------------
96553             sync: function(peer, mode, options, cb) {
96554                 // `options` is optional and can have the following properties:
96555                 //   * `ua`
96556
96557                 // TODO: initialize a new context transaction?...
96558                 // todo: or perhaps add a new session.txn?...
96559
96560                 if ( cb == undefined && _.isFunction(options) )
96561                 {
96562                     cb = options;
96563                     options = {};
96564                 }
96565                 options = options || {};
96566
96567                 var self = this;
96568                 var discover = ( mode == constant.SYNCTYPE_DISCOVER );
96569                 if ( discover )
96570                     mode = constant.SYNCTYPE_SLOW_SYNC;
96571
96572                 if ( ! _.find(self._peers, function(p) { return p === peer; }) )
96573                     return cb(new common.InvalidAdapter('invalid peer for adapter'));
96574                 if ( mode != constant.SYNCTYPE_AUTO )
96575                 {
96576                     mode = common.synctype2alert(mode);
96577                     if ( ! mode )
96578                         return cb(new common.TypeError('invalid synctype'));
96579                 }
96580                 if ( ! self.devInfo )
96581                     return cb(new common.InvalidAdapter('cannot synchronize adapter as client: invalid devInfo'));
96582
96583                 var session = state.makeSession({
96584                     context  : self._c,
96585                     ua       : new useragent.UserAgentMultiplexer([options.ua, self._c.ua]),
96586                     txn      : _.bind(self._c._txn, self._c),
96587                     adapter  : self,
96588                     peer     : peer,
96589                     isServer : false,
96590                     discover : discover,
96591                     info     : state.makeSessionInfo({
96592                         id       : ( peer.lastSessionID || 0 ) + 1,
96593                     msgID    : 1,
96594                     codec    : self._c.codec,
96595                     mode     : mode
96596                     })
96597                 });
96598
96599                 session.send = function(contentType, data, cb) {
96600                     session.peer.sendRequest(session, contentType, data, function(err, response) {
96601                         if ( err )
96602                         return cb(err);
96603                     // todo: allow the client to force the server to authorize itself as well...
96604                     self._receive(session, response, null, cb);
96605                     });
96606                 };
96607
96608                 // TODO: should i do a router.calculate() at this point?
96609                 //       the reason is that if there was a sync, then a
96610                 //       .setRoute(), then things may have changed...
96611                 //       corner-case, yes... but still valid.
96612
96613                 var failed = 0;
96614
96615                 var startSession = function() {
96616                     session.context.protocol.initialize(session, null, function(err, commands) {
96617                         if ( err )
96618                         return cb(err);
96619                     self._transmit(session, commands, function(err) {
96620                         if ( err )
96621                     {
96622                         if ( ! ( err instanceof common.InvalidCredentials )
96623                             && ! ( err instanceof common.CredentialsRequired ) )
96624                             return cb(err);
96625                         if ( err instanceof common.InvalidCredentials )
96626                         failed += 1;
96627                     if ( failed > 100 )
96628                     {
96629                         return cb(err);
96630                     }
96631                     var credErr = err;
96632                     var uaEvent = {
96633                         session : session,
96634                         auth    : err.auth,
96635                         count   : failed
96636                     };
96637                     return session.ua.fetchCredentials(uaEvent, function(err, auth) {
96638                         if ( err )
96639                         return cb(err);
96640                     if ( ! auth )
96641                         return cb(credErr);
96642                     if ( auth.persist )
96643                     {
96644                         session.peer.auth = auth.type;
96645                         session.peer.username = auth.username;
96646                         session.peer.password = auth.password;
96647                     }
96648                     else
96649                         session.auth = auth;
96650                     // todo: should i just create a new session?...
96651                     session.info.id += 1;
96652                     session.info.msgID = 1;
96653                     return startSession();
96654                     });
96655                     }
96656                     self._save(session.txn(), function(err) {
96657                         if ( err )
96658                         return cb(err);
96659                     return cb(null, self._session2stats(session));
96660                     });
96661                     });
96662                     });
96663                 };
96664
96665                 session.context.synchronizer.initStoreSync(session, function(err) {
96666                     if ( err )
96667                     return cb(err);
96668                 startSession();
96669                 });
96670
96671             },
96672
96673             //-------------------------------------------------------------------------
96674             _session2stats: function(session) {
96675                 var ret = {};
96676                 _.each(_.values(session.info.dsstates), function(ds) {
96677                     var stats = _.clone(ds.stats);
96678                     stats.mode = common.alert2synctype(ds.mode);
96679                     if ( ds.action == 'error' && ds.error )
96680                     stats.error = ds.error;
96681                 ret[ds.uri] = stats;
96682                 });
96683                 return ret;
96684             },
96685
96686             //-------------------------------------------------------------------------
96687             _transmit: function(session, commands, cb) {
96688                 var self = this;
96689                 if ( session.info.msgID > 20 )
96690                     return cb('too many client/server messages');
96691                 session.context.protocol.negotiate(session, commands, function(err, commands) {
96692                     if ( err )
96693                     return cb(err);
96694                 if ( session.context.protocol.isComplete(session, commands) )
96695                 {
96696                     // we're done! store all the anchors and session IDs and exit...
96697                     var pmodel = session.peer._getModel();
96698                     if ( ! pmodel )
96699                     return cb('unexpected error: could not locate this peer in local adapter');
96700                 _.each(session.info.dsstates, function(ds, uri) {
96701                     var pstore = _.find(pmodel.stores, function(s) { return s.uri == ds.peerUri; });
96702                     if ( ! pstore )
96703                     return cb('unexpected error: could not locate bound peer store in local adapter');
96704                 pstore.binding.localAnchor  = ds.nextAnchor;
96705                 pstore.binding.remoteAnchor = ds.peerNextAnchor;
96706                 });
96707                 session.peer.lastSessionID = session.info.id;
96708                 pmodel.lastSessionID       = session.info.id;
96709                 return cb();
96710                 }
96711                 session.context.protocol.produce(session, commands, function(err, tree) {
96712                     if ( err )
96713                     return cb(err);
96714                 codec.Codec.autoEncode(tree, session.info.codec, function(err, contentType, data) {
96715                     if ( err )
96716                     return cb(err);
96717                 // update the session with the last request commands so
96718                 // that when we receive the response package, it can be
96719                 // compared against that.
96720                 // TODO: should that only be done on successful transmit?...
96721                 session.info.lastCommands = commands;
96722                 session.send(contentType, data, function(err) {
96723                     if ( err )
96724                     return cb(err);
96725                 cb();
96726                 });
96727                 })
96728                 });
96729                 });
96730             },
96731
96732             //-------------------------------------------------------------------------
96733             authorize: function(request, sessionInfo, authorize, cb) {
96734                 var self = this;
96735                 var ct   = request.headers['Content-Type'];
96736                 codec.Codec.autoDecode(ct, request.body, function(err, xtree, codecName) {
96737                     if ( err )
96738                     return cb(err);
96739                 self._c.protocol.authorize(xtree, null, authorize, cb);
96740                 });
96741             },
96742
96743             //-------------------------------------------------------------------------
96744             getTargetID: function(request, sessionInfo, cb) {
96745                 var self = this;
96746                 var ct   = request.headers['Content-Type'];
96747                 codec.Codec.autoDecode(ct, request.body, function(err, xtree, codecName) {
96748                     if ( err )
96749                     return cb(err);
96750                 return cb(null, self._c.protocol.getTargetID(xtree));
96751                 });
96752             },
96753
96754             //-------------------------------------------------------------------------
96755             handleRequest: function(request, sessionInfo, authorize, response, options, cb) {
96756
96757                 // TODO: initialize a new context transaction?...
96758                 // todo: or perhaps add a new session.txn?...
96759
96760                 if ( cb == undefined && _.isFunction(options) )
96761                 {
96762                     cb = options;
96763                     options = {};
96764                 }
96765                 options = options || {};
96766
96767                 var self = this;
96768                 var session = state.makeSession({
96769                     context  : self._c,
96770                     ua       : new useragent.UserAgentMultiplexer([options.ua, self._c.ua]),
96771                     txn      : _.bind(self._c._txn, self._c),
96772                     adapter  : self,
96773                     peer     : null,
96774                     isServer : true,
96775                     info     : sessionInfo
96776                 });
96777                 session.send = response;
96778                 this._receive(session, request, authorize, function(err, stats) {
96779                     if ( err )
96780                     return cb(err);
96781                 self._save(session.txn(), function(err) {
96782                     if ( err )
96783                     return cb(err);
96784                 return cb(null, self._session2stats(session));
96785                 });
96786                 });
96787             },
96788
96789             //-------------------------------------------------------------------------
96790             _receive: function(session, request, authorize, cb) {
96791                 var self = this;
96792                 if ( ! session.isServer )
96793                 {
96794                     session.info.lastMsgID = session.info.msgID;
96795                     session.info.msgID += 1;
96796                 }
96797                 var ct = request.headers['Content-Type'];
96798                 codec.Codec.autoDecode(ct, request.body, function(err, xtree, codecName) {
96799                     if ( err )
96800                     return cb(err);
96801                 session.info.codec = codecName;
96802                 var do_authorize = ( ! authorize ) ? common.noop : function(cb) {
96803                     session.context.protocol.authorize(xtree, null, authorize, function(err) {
96804                         return cb(err);
96805                     });
96806                 };
96807                 do_authorize(function(err) {
96808                     if ( err )
96809                     return cb(err);
96810                 session.context.protocol.consume(
96811                     session, session.info.lastCommands, xtree,
96812                     function(err, commands) {
96813                         if ( err ) {
96814                             return cb(err);
96815                         }
96816                         if ( session.discover && session.peer.devInfo )
96817                     return cb(null, self._session2stats(session));
96818                 self._transmit(session, commands, function(err) {
96819                     if ( err )
96820                     return cb(err);
96821                 if ( ! session.isServer )
96822                     return cb();
96823                 self._save(session.txn(), function(err) {
96824                     if ( err )
96825                     return cb(err);
96826                 return cb(null, self._session2stats(session));
96827                 });
96828                 });
96829                     }
96830                 );
96831                 });
96832                 })
96833             },
96834
96835     });
96836
96837     return exports;
96838
96839 })();
96840
96841 module.exports = _self;
96842
96843 });
96844 define('ripple/platform/tizen/2.0/syncml-js-lib/matcher', function (require, exports, module) {
96845 // -*- coding: utf-8 -*-
96846 //-----------------------------------------------------------------------------
96847 // file: $Id$
96848 // lib:  syncml-js.matcher
96849 // auth: griffin <griffin@uberdev.org>
96850 // date: 2012/12/05
96851 // copy: (C) CopyLoose 2012 UberDev <hardcore@uberdev.org>, No Rights Reserved.
96852 //-----------------------------------------------------------------------------
96853
96854 var common = require('ripple/platform/tizen/2.0/syncml-js-lib/common'),
96855     _self;
96856
96857 _self = (function () {
96858
96859     var exports = {};
96860
96861     //---------------------------------------------------------------------------
96862     exports._cntpref = function(source, target) {
96863         return ( source.preferred ? 1 : 0 ) + ( target.preferred ? 1 : 0 );
96864     };
96865
96866     //---------------------------------------------------------------------------
96867     exports._pickTransmitContentType = function(source, target, prefcnt, checkVersion) {
96868         for ( var sidx=0 ; sidx<source.length ; sidx++ )
96869 {
96870     var sct = source[sidx];
96871     for ( var tidx=0 ; tidx<target.length ; tidx++ )
96872 {
96873     var tct = target[tidx];
96874     if ( sct.ctype != tct.ctype )
96875     continue;
96876 if ( ! checkVersion )
96877 {
96878     if ( exports._cntpref(sct, tct) >= prefcnt )
96879         return [sct.ctype, sct.versions[sct.versions.length - 1]];
96880     continue;
96881 }
96882 for ( var svidx=sct.versions.length ; svidx>0 ; svidx-- )
96883 {
96884     var sv = sct.versions[svidx - 1]
96885         for ( var tvidx=tct.versions.length ; tvidx>0 ; tvidx-- )
96886         {
96887             var tv = tct.versions[tvidx - 1]
96888                 if ( sv != tv )
96889                     continue;
96890             if ( exports._cntpref(sct, tct) >= prefcnt )
96891                 return [sct.ctype, sv];
96892         }
96893 }
96894 }
96895 }
96896 return null;
96897 };
96898
96899 //---------------------------------------------------------------------------
96900 exports.pickTransmitContentType = function(source, target) {
96901
96902     // TODO: this is probably not the most efficient algorithm!...
96903     //       (but it works... ;-)
96904
96905     // order of preference:
96906     //   - transmit => receive, BOTH preferred, VERSION match
96907     //   - transmit => receive, ONE preferred, VERSION match
96908     //   - transmit => receive, neither preferred, VERSION match
96909     //   - transmit => receive, BOTH preferred, no version match
96910     //   - transmit => receive, ONE preferred, no version match
96911     //   - transmit => receive, neither preferred, no version match
96912     //   - tx/rx => tx/rx, BOTH preferred, VERSION match
96913     //   - tx/rx => tx/rx, ONE preferred, VERSION match
96914     //   - tx/rx => tx/rx, neither preferred, VERSION match
96915     //   - tx/rx => tx/rx, BOTH preferred, no version match
96916     //   - tx/rx => tx/rx, ONE preferred, no version match
96917     //   - tx/rx => tx/rx, neither preferred, no version match
96918
96919     // todo: make it explicit (or overrideable) that i am depending on the ordering
96920     //       of the versions supported to give an indicator of preference...
96921
96922     var sct = source.getContentTypes();
96923     var tct = target.getContentTypes();
96924
96925     var fct = function(cts, transmit) {
96926         return _.filter(cts, function(ct) {
96927             return transmit ? ct.transmit : ct.receive;
96928         });
96929     };
96930
96931     return exports._pickTransmitContentType(fct(sct, true), fct(tct, false), 2, true)
96932         || exports._pickTransmitContentType(fct(sct, true), fct(tct, false), 1, true)
96933         || exports._pickTransmitContentType(fct(sct, true), fct(tct, false), 0, true)
96934         || exports._pickTransmitContentType(fct(sct, true), fct(tct, false), 2, false)
96935         || exports._pickTransmitContentType(fct(sct, true), fct(tct, false), 1, false)
96936         || exports._pickTransmitContentType(fct(sct, true), fct(tct, false), 0, false)
96937         || exports._pickTransmitContentType(sct, tct, 2, true)
96938         || exports._pickTransmitContentType(sct, tct, 1, true)
96939         || exports._pickTransmitContentType(sct, tct, 0, true)
96940         || exports._pickTransmitContentType(sct, tct, 2, false)
96941         || exports._pickTransmitContentType(sct, tct, 1, false)
96942         || exports._pickTransmitContentType(sct, tct, 0, false)
96943         || null;
96944
96945 };
96946
96947 // TODO: OH MY GOD.
96948 //       this is insanely inefficient.
96949 //       i'm embarrassed.
96950 //       fortunately, it's hidden really low-level...
96951 //       but now you know, doh! please don't blackmail me!... ;-)
96952
96953 // TODO: this currently requires that both tx and rx match in both
96954 //       directions with the same velocity... it should prioritize
96955 //       that, but then fallback to giving simplex matches priority.
96956
96957 //---------------------------------------------------------------------------
96958 var has_ct = function(a, b, checkVersion, transmit, wildcard) {
96959     a = _.filter(a, function(e) { return transmit ? e.transmit : e.receive });
96960     b = _.filter(b, function(e) { return transmit ? e.transmit : e.receive });
96961     for ( var aidx=0 ; aidx<a.length ; aidx++ )
96962     {
96963         var ct_a = a[aidx];
96964         for ( var bidx=0 ; bidx<b.length ; bidx++ )
96965         {
96966             var ct_b = b[bidx];
96967             if ( ct_a.ctype != ct_b.ctype )
96968                 continue;
96969             if ( ! checkVersion )
96970                 return true;
96971             for ( var vaidx=0 ; vaidx<ct_a.versions.length ; vaidx++ )
96972             {
96973                 var va = ct_a.versions[vaidx];
96974                 for ( var vbidx=0 ; vbidx<ct_b.length ; vbidx++ )
96975                 {
96976                     var vb = ct_b.versions[vbidx];
96977                     if ( va == vb )
96978                         return true;
96979                 }
96980             }
96981         }
96982     } 
96983     return false;
96984 };
96985
96986 //---------------------------------------------------------------------------
96987 var has_ct_both = function(a, b, checkVersion, wildcard) {
96988     return has_ct(a, b, checkVersion, true, wildcard)
96989         && has_ct(a, b, checkVersion, false, wildcard);
96990 };
96991
96992 //---------------------------------------------------------------------------
96993 var cmpStore_ct_set_crit = function(base, ds1, ds2, checkVersion, wildcard) {
96994     var bds1 = has_ct_both(base, ds1, checkVersion, wildcard);
96995     var bds2 = has_ct_both(base, ds2, checkVersion, wildcard);
96996     if ( bds1 && bds2 )
96997         return 0;
96998     if ( bds1 )
96999         return -1;
97000     if ( bds2 )
97001         return 1;
97002     return 0;
97003 };
97004
97005 //---------------------------------------------------------------------------
97006 var cmpStore_ct_set = function(base, ds1, ds2) {
97007     var ret = cmpStore_ct_set_crit(base, ds1, ds2, true, false);
97008     if ( ret != 0 )
97009         return ret;
97010     ret = cmpStore_ct_set_crit(base, ds1, ds2, false, false);
97011     if ( ret != 0 )
97012         return ret;
97013     ret = cmpStore_ct_set_crit(base, ds1, ds2, true, true);
97014     if ( ret != 0 )
97015         return ret;
97016     ret = cmpStore_ct_set_crit(base, ds1, ds2, false, true);
97017     if ( ret != 0 )
97018         return ret;
97019     return 0;
97020 };
97021
97022 //---------------------------------------------------------------------------
97023 var getct = function(store) {
97024     return store.getContentTypes ? store.getContentTypes() : store.contentTypes;
97025 };
97026
97027 //---------------------------------------------------------------------------
97028 var cmpStore_ct_pref = function(base, ds1, ds2) {
97029     var basect = _.filter(getct(base), function(ct) { return ct.preferred; });
97030     var ds1ct  = _.filter(getct(ds1), function(ct) { return ct.preferred; });
97031     var ds2ct  = _.filter(getct(ds2), function(ct) { return ct.preferred; });
97032     return cmpStore_ct_set(basect, ds1ct, ds2ct);
97033 };
97034
97035 //---------------------------------------------------------------------------
97036 var cmpStore_ct_all = function(base, ds1, ds2) {
97037     return cmpStore_ct_set(getct(base), getct(ds1), getct(ds2));
97038 };
97039
97040 //---------------------------------------------------------------------------
97041 var cmpStore_ct = function(base, ds1, ds2) {
97042     var ret = cmpStore_ct_pref(base, ds1, ds2)
97043         if ( ret != 0 )
97044             return ret;
97045     return cmpStore_ct_all(base, ds1, ds2);
97046 };
97047
97048 //---------------------------------------------------------------------------
97049 var cmpStore_uri = function(base, ds1, ds2) {
97050     var ret = difflib.getCloseMatches(base.uri, [ds1.uri, ds2.uri], 1, 0.5);
97051     if ( ret.length <= 0 )
97052         return 0;
97053     if ( ret[0] == ds1.uri )
97054         return -1;
97055     return 1;
97056 };
97057
97058 //---------------------------------------------------------------------------
97059 exports.cmpStore = function(base, ds1, ds2) {
97060     var ret = cmpStore_ct(base, ds1, ds2);
97061     if ( ret != 0 )
97062         return ret;
97063     return cmpStore_uri(base, ds1, ds2);
97064 };
97065
97066 return exports;
97067
97068 })();
97069
97070 module.exports = _self;
97071
97072
97073 });
97074 define('ripple/platform/tizen/2.0/syncml-js-lib/protocol', function (require, exports, module) {
97075 // -*- coding: utf-8 -*-
97076 //-----------------------------------------------------------------------------
97077 // file: $Id$
97078 // lib:  syncml-js.protocol
97079 // auth: griffin <griffin@uberdev.org>
97080 // date: 2012/11/04
97081 // copy: (C) CopyLoose 2012 UberDev <hardcore@uberdev.org>, No Rights Reserved.
97082 //-----------------------------------------------------------------------------
97083
97084 var db = require('ripple/db'),
97085     common = require('ripple/platform/tizen/2.0/syncml-js-lib/common'),
97086     constant = require('ripple/platform/tizen/2.0/syncml-js-lib/constant'),
97087     devinfo = require('ripple/platform/tizen/2.0/syncml-js-lib/devinfo'),
97088     state = require('ripple/platform/tizen/2.0/syncml-js-lib/state'),
97089     base64 = require('ripple/platform/tizen/2.0/syncml-js-lib/base64'),
97090     ET = require('ripple/platform/tizen/2.0/syncml-js-lib/elementtree'),
97091     _firstflag = false,
97092     changednum, _counts;
97093
97094 var _self = (function () {
97095
97096     var exports = {};
97097
97098     //---------------------------------------------------------------------------
97099     var getError = function(xnode) {
97100         var ret = {
97101             message: xnode.findtext('Item/Data')
97102         };
97103         try{
97104             var xerr  = xnode.find('Error');
97105         }catch(e){
97106             var xerr = null;
97107         }
97108         if ( ! xerr )
97109 {
97110     try{
97111         var xerr  = xnode.find('Item/Error');
97112     }catch(e){
97113         var xerr = null;
97114     }
97115 }
97116 if ( ! xerr )
97117 {
97118     if ( ! ret.message )
97119         return null;
97120     return ret;
97121 }
97122 ret.code    = xerr.findtext('Code');
97123 ret.message = xerr.findtext('Message');
97124 ret.trace   = xerr.findtext('Trace');
97125 return ret;
97126 }
97127
97128 //---------------------------------------------------------------------------
97129 var badStatus = function(xnode, kls, attrs) {
97130     if ( ! kls )
97131         kls = common.ProtocolError;
97132     var code  = xnode.findtext('Data');
97133     var cname = xnode.findtext('Cmd');
97134     var msg   = null;
97135     if ( kls == common.ProtocolError )
97136         msg = 'unexpected status code ' + code + ' for command "' + cname + '"';
97137     else
97138         msg = 'received status code ' + code + ' for command "' + cname + '"';
97139     var error = getError(xnode);
97140     if ( error )
97141     {
97142         if ( error.code )
97143             msg += ': [' + error.code + '] ' + error.message;
97144         else
97145             msg += ': ' + error.message;
97146     }
97147     return new kls(msg, undefined, attrs)
97148 };
97149
97150 //---------------------------------------------------------------------------
97151 exports.getError  = getError;
97152 exports.badStatus = badStatus;
97153
97154 //---------------------------------------------------------------------------
97155 exports.Protocol = common.Base.extend({
97156
97157     //-------------------------------------------------------------------------
97158     constructor: function(options) {
97159     },
97160
97161     //-------------------------------------------------------------------------
97162     authorize: function(xtree, uri, authorize, cb) {
97163
97164         // TODO: if this session has been authorized before, don't call authorize
97165         //       ie.:
97166         //         if ( session.info.authAccepted )
97167         //           return cb();
97168         //       BUT this requires the session object... oops.
97169
97170         if ( ! authorize )
97171     authorize = function(uri, data, cb) { return cb(null, data); };
97172 if ( xtree.tag != 'SyncML' )
97173     throw new common.ProtocolError('root element was not "SyncML"');
97174 var xcred = xtree.find('SyncHdr/Cred');
97175 if ( ! xcred )
97176     return authorize(uri, null, cb);
97177 var data = xcred.findtext('Data');
97178 var authtype = xcred.findtext('Meta/Type');
97179 var format = xcred.findtext('Meta/Format');
97180 if ( format == constant.FORMAT_B64 )
97181     data = base64.decode(data);
97182 else if ( format )
97183     throw new common.UnknownFormatType(format);
97184 switch ( authtype )
97185 {
97186     case constant.NAMESPACE_AUTH_BASIC:
97187         {
97188             data = common.splitn(data, ':', 1);
97189             return authorize(uri, {
97190                 auth:     constant.NAMESPACE_AUTH_BASIC,
97191                    username: data[0],
97192                    password: data[1]
97193             }, cb);
97194         }
97195     case constant.NAMESPACE_AUTH_MD5:
97196         {
97197             return authorize(uri, {
97198                 auth:   constant.NAMESPACE_AUTH_BASIC,
97199                    digest: data
97200             }, cb);
97201         }
97202     default:
97203         {
97204             return cb(new common.UnknownAuthType(
97205                         'unknown/unimplemented auth type "' + authtype + '"'));
97206         }
97207 }
97208 },
97209
97210     //-------------------------------------------------------------------------
97211     getTargetID: function(xtree) {
97212         if ( xtree.tag != 'SyncML' )
97213             throw new common.ProtocolError('root element was not "SyncML"');
97214         // todo: do more validity checks?...
97215         return xtree.findtext('SyncHdr/Target/LocURI');
97216     },
97217
97218     //-------------------------------------------------------------------------
97219     isComplete: function(session, commands) {
97220         return (! session.isServer
97221                 && commands.length == 3
97222                 && commands[0].name == constant.CMD_SYNCHDR
97223                 && commands[1].name == constant.CMD_STATUS
97224                 && commands[1].statusOf == constant.CMD_SYNCHDR
97225                 && commands[1].statusCode == constant.STATUS_OK
97226                 && commands[2].name == constant.CMD_FINAL
97227                );
97228     },
97229
97230     //----------------------<---------------------------------------------------
97231     initialize: function(session, xtree, cb) {
97232         var cmd = state.makeCommand({
97233             name        : constant.CMD_SYNCHDR,
97234         cmdID       : 0,
97235         version     : constant.SYNCML_VERSION_1_2,
97236         source      : session.info.effectiveID || session.adapter.devID,
97237         sourceName  : session.adapter.displayName,
97238         respUri     : session.isServer ? session.info.returnUrl : null
97239         });
97240
97241         var checkPeer = ( ! session.isServer ) ? function(cb) {
97242             if ( ! xtree )
97243                 return cb();
97244             var xhdr = xtree.find('SyncHdr');
97245             // todo: check peer id...
97246             if ( session.info.id != common.int(xhdr.findtext('SessionID')) )
97247             {
97248                 return cb(new common.ProtocolError('session ID mismatch "'
97249                             + xhdr.findtext('SessionID')
97250                             + '" (expected: ' + session.info.id + ')'));
97251                         }
97252                         // todo: check message id...
97253                         cb();
97254                         } : function(cb) {
97255                             var xhdr = xtree.find('SyncHdr');
97256                             var peerID = xhdr.findtext('Source/LocURI');
97257                             if ( session.info.peerID && session.info.peerID != peerID )
97258                 {
97259                     return cb(new common.ProtocolError('unexpected peer ID "' + peerID + '"'));
97260                 }
97261                 if ( session.peer && session.peer.devID != peerID )
97262                 {
97263                     return cb(new common.ProtocolError('unacceptable peer ID "' + peerID + '"'));
97264                 }
97265                 session.info.peerID = peerID;
97266                 // check that no session swapping occurred
97267                 if ( session.info.id != undefined
97268                     && session.info.id != common.int(xhdr.findtext('SessionID')) )
97269                 {
97270                     return cb(new common.ProtocolError('session ID mismatch "'
97271                                 + xhdr.findtext('SessionID')
97272                                 + '" (expected: ' + session.info.id + ')'));
97273                             }
97274                             session.info.id     = common.int(xhdr.findtext('SessionID'));
97275                             session.info.msgID  = common.int(xhdr.findtext('MsgID'));
97276                             if ( session.peer && session.peer.devID == peerID )
97277                             return cb();
97278                             // TODO: i should delete unused peers here... ie. anything that
97279                             //       hasn't been used in some configurable number of seconds,
97280                             //       which should probably default to something like a month...
97281                             session.peer = _.find(session.adapter.getPeers(), function(peer) {
97282                                 return ( peer.devID == peerID );
97283                             });
97284                             if ( session.peer )
97285                             {
97286                                 return cb();
97287                             }
97288                             var peerInfo = {
97289                                 devID:        peerID,
97290                            displayName:  xhdr.findtext('Source/LocName'),
97291                            maxMsgSize:   common.int(xhdr.findtext('Meta/MaxMsgSize')),
97292                            maxObjSize:   common.int(xhdr.findtext('Meta/MaxObjSize'))
97293                             };
97294                             session.adapter.addPeer(peerInfo, function(err, peer) {
97295                                 if ( err )
97296                                 return cb(err);
97297                             session.peer = peer;
97298                             return cb();
97299                             });
97300                         };
97301
97302         checkPeer(function(err) {
97303
97304             session.info.cmdID        = 0;
97305             session.info.pendingMsgID = ( session.isServer
97306                 ? session.info.msgID
97307                 : session.info.lastMsgID );
97308             cmd.sessionID   = session.info.id;
97309             cmd.msgID       = session.info.msgID;
97310             cmd.target      = session.peer ? session.peer.devID || null : null;
97311             cmd.targetName  = session.peer ? session.peer.displayName || null : null;
97312             cmd.auth        = session.auth
97313             ? session.auth.type
97314             : session.peer
97315             ? session.peer.auth
97316             : null;
97317
97318         if ( err )
97319             return cb(err, [cmd]);
97320
97321         if ( cmd.msgID == 1 )
97322         {
97323             // NOTE: normally, the "server" would not send this info. however, in
97324             //       the syncml-js world where it is much more peer-oriented
97325             //       instead of client/server, i send this as well... the
97326             //       idea being, if two "client" peers are communicating in
97327             //       the event of server unavailability, then they may need
97328             //       to know each-others limitations...
97329             cmd.maxMsgSize = common.getMaxMemorySize(session.context);
97330             cmd.maxObjSize = common.getMaxMemorySize(session.context);
97331             ///cmd.maxMsgSize = 150000;
97332             ///cmd.maxObjSize = 4000000;
97333         }
97334         cb(null, [cmd]);
97335         });
97336     },
97337
97338     //-------------------------------------------------------------------------
97339     negotiate: function(session, commands, cb) {
97340         // // todo: determine why i decided to clone the commands...
97341         // commands = _.clone(commands);
97342
97343         if ( commands.length > 0 && _.last(commands).name == constant.CMD_FINAL )
97344             return cb(null, commands);
97345
97346         if ( commands.length > 0
97347                 && _.last(commands).name == constant.CMD_ALERT
97348                 && _.last(commands).data == constant.STATUS_NEXT_MESSAGE )
97349             // todo: should i add a "final" here?...
97350             // commands.push(state.makeCommand({name: constant.CMD_FINAL}));
97351             return cb(null, commands);
97352
97353         var createDevInfoCommands = function(commands, cb) {
97354             // todo: this flag is crap. instead, the local devInfo should have
97355             //       a record of which sessionID lead to the recording, and
97356             //       base it on that. maybe timestamp too... (but it must be
97357             //       in the minutes, just in case...)
97358             session.info.gotinfo = true;
97359             if ( ! session.discover )
97360             {
97361                 commands.push(state.makeCommand({
97362                     name       : constant.CMD_PUT,
97363                     cmdID      : session.nextCmdID(),
97364                     type       : constant.TYPE_SYNCML_DEVICE_INFO + '+' + session.info.codec,
97365                     source     : './' + constant.URI_DEVINFO_1_2,
97366                     data       : session.adapter.devInfo.toSyncML(constant.SYNCML_DTD_VERSION_1_2,
97367                         _.values(session.adapter._stores))
97368                 }));
97369             }
97370             commands.push(state.makeCommand({
97371                 name     : constant.CMD_GET,
97372                 cmdID    : session.nextCmdID(),
97373                 type     : constant.TYPE_SYNCML_DEVICE_INFO + '+' + session.info.codec,
97374                 target   : './' + constant.URI_DEVINFO_1_2
97375             }));
97376             return cb(null, commands);
97377         };
97378
97379         var createCommands = function(commands, cb) {
97380             // request the remote device info if not currently available or
97381             // in discover mode or explicitly re-exchanging it (paranoid mode)
97382             var putget = false;
97383             if ( !! session.discover )
97384             {
97385                 return createDevInfoCommands(commands, cb);
97386             }
97387             if ( ! session.peer.devInfo )
97388             {
97389                 var uaEvent = {session: session};
97390                 return session.ua.acceptDevInfoSwap(uaEvent, function(err) {
97391                     if ( err )
97392                 {
97393                     return cb(err);
97394                 }
97395                 return createDevInfoCommands(commands, cb);
97396                 });
97397             }
97398             if ( ! session.context.config.trustDevInfo && ! session.info.gotinfo )
97399             {
97400                 return createDevInfoCommands(commands, cb);
97401             }
97402             // NOTE: in the current handling of "trustDevInfo", i am doing a
97403             //       potentially unnecessary extra request/response phase to
97404             //       confirm that the devInfo has not changed... i *could*
97405             //       issue the put/get as well as the alert, *assuming* that
97406             //       no devInfo is going to change...
97407             return session.context.synchronizer.actions(session, commands, cb);
97408         };
97409
97410         return createCommands(commands, function(err, commands) {
97411             if ( err )
97412             return cb(err);
97413         //Hack: Memotoo service need to send alert command at the beging
97414         var args, tmp;
97415         args = db.retrieveObject("syncml-alert-args");
97416         tmp = {
97417             name       : constant.CMD_ALERT,
97418                cmdID      : session.nextCmdID(),
97419                data       : args.data,
97420                source     : args.source,
97421                target     : args.target,
97422                maxObjSize : "4000000"
97423         };
97424         if (args.lastAnchor) {
97425             tmp.lastAnchor = args.lastAnchor;
97426         }
97427
97428         if (args.nextAnchor) {
97429             tmp.nextAnchor = args.nextAnchor;
97430         }
97431         _firstflag = db.retrieveObject("syncml-first-flag");
97432         if( !_firstflag) {
97433             commands.push(state.makeCommand(tmp));
97434             db.saveObject("syncml-first-flag", true);
97435         }
97436         commands.push(state.makeCommand({name: constant.CMD_FINAL}));
97437         cb(null, commands);
97438         });
97439     },
97440
97441     //-------------------------------------------------------------------------
97442     // NOTE: `produce` is equivalent to the `pysyncml.protocol.commands2tree`...
97443     // Consumes state.Command commands and converts them to an ET protocol tree
97444     produce: function(session, commands, cb) {
97445
97446         if ( commands.length <= 0 )
97447             return cb('protocol.produce received empty commands');
97448
97449         var hdrcmd = commands[0];
97450         commands = _.rest(commands, 1);
97451
97452         if ( hdrcmd.name != constant.CMD_SYNCHDR )
97453             return cb('unexpected first command "' + hdrcmd.name + '"');
97454
97455         if ( hdrcmd.version != constant.SYNCML_VERSION_1_2 )
97456             return cb('unsupported SyncML version "' + hdrcmd.version + '"');
97457
97458         var xsync = ET.Element(constant.NODE_SYNCML);
97459         var xhdr  = ET.SubElement(xsync, hdrcmd.name);
97460         if ( hdrcmd.version == constant.SYNCML_VERSION_1_2 )
97461         {
97462             ET.SubElement(xhdr, 'VerDTD').text = constant.SYNCML_DTD_VERSION_1_2;
97463             ET.SubElement(xhdr, 'VerProto').text = hdrcmd.version;
97464         }
97465
97466         ET.SubElement(xhdr, 'SessionID').text = hdrcmd.sessionID;
97467         ET.SubElement(xhdr, 'MsgID').text = hdrcmd.msgID;
97468         var xsrc = ET.SubElement(xhdr, 'Source');
97469         ET.SubElement(xsrc, 'LocURI').text = hdrcmd.source;
97470         if ( hdrcmd.sourceName )
97471             ET.SubElement(xsrc, 'LocName').text = hdrcmd.sourceName;
97472         var xtgt = ET.SubElement(xhdr, 'Target');
97473         ET.SubElement(xtgt, 'LocURI').text = hdrcmd.target;
97474         if ( hdrcmd.targetName )
97475             ET.SubElement(xtgt, 'LocName').text = hdrcmd.targetName;
97476         if ( hdrcmd.respUri )
97477             ET.SubElement(xhdr, 'RespURI').text = hdrcmd.respUri;
97478
97479         if ( hdrcmd.auth && ! session.info.authAccepted )
97480         {
97481             // TODO: implement other auth schemes...
97482             if ( hdrcmd.auth != constant.NAMESPACE_AUTH_BASIC )
97483                 return cb('auth method "' + hdrcmd.auth + '" not implemented');
97484
97485             if ( hdrcmd.auth == constant.NAMESPACE_AUTH_BASIC )
97486             {
97487                 var xcred = ET.SubElement(xhdr, 'Cred');
97488                 var xmeta = ET.SubElement(xcred, 'Meta');
97489                 ET.SubElement(xmeta, 'Format', {'xmlns': constant.NAMESPACE_METINF}).text = 'b64';
97490                 ET.SubElement(xmeta, 'Type', {'xmlns': constant.NAMESPACE_METINF}).text   = hdrcmd.auth;
97491                 ET.SubElement(xcred, 'Data').text = base64.encode(
97492                         ( session.auth ? session.auth.username : session.peer.username )
97493                         + ':' + ( session.auth ? session.auth.password : session.peer.password ) );
97494             }
97495
97496         }
97497         if ( hdrcmd.maxMsgSize || hdrcmd.maxObjSize )
97498         {
97499             var xmeta = ET.SubElement(xhdr, 'Meta');
97500             if ( hdrcmd.maxMsgSize )
97501                 ET.SubElement(xmeta, 'MaxMsgSize',
97502                         {'xmlns': constant.NAMESPACE_METINF}).text = hdrcmd.maxMsgSize;
97503             if ( hdrcmd.maxObjSize )
97504                 ET.SubElement(xmeta, 'MaxObjSize',
97505                         {'xmlns': constant.NAMESPACE_METINF}).text = hdrcmd.maxObjSize;
97506         }
97507
97508         var xbody = ET.SubElement(xsync, constant.NODE_SYNCBODY);
97509
97510         for ( var idx=0 ; idx<commands.length ; idx++ )
97511         {
97512             var cmd  = commands[idx];
97513             var xcmd = ET.SubElement(xbody, cmd.name);
97514             if ( cmd.cmdID != undefined )
97515                 ET.SubElement(xcmd, 'CmdID').text = cmd.cmdID;
97516             var func = this['_produce_cmd_' + cmd.name.toLowerCase()];
97517             if ( ! func )
97518                 return cb(new common.InternalError('unexpected command "' + cmd.name + '"'));
97519             try{
97520                 func.call(this, session, cmd, xcmd);
97521             }catch(e){
97522                 return cb(new common.InternalError(
97523                             'failed invoking protocol sub-production of "' + cmd.name + '": ' + e, e));
97524             }
97525             if ( cmd.name == constant.CMD_FINAL && idx + 1 != commands.length )
97526                 return cb('command "' + cmd.name + '" not at end of commands');
97527         }
97528
97529         cb(null, xsync);
97530     },
97531
97532     //-------------------------------------------------------------------------
97533     _produce_cmd_alert: function(session, cmd, xcmd) {
97534         ET.SubElement(xcmd, 'Data').text = cmd.data;
97535         var xitem = ET.SubElement(xcmd, 'Item');
97536         ET.SubElement(ET.SubElement(xitem, 'Source'), 'LocURI').text = cmd.source;
97537         ET.SubElement(ET.SubElement(xitem, 'Target'), 'LocURI').text = cmd.target;
97538         if ( cmd.lastAnchor || cmd.nextAnchor || cmd.maxObjSize )
97539         {
97540             var xmeta = ET.SubElement(xitem, 'Meta');
97541             var xanch = ET.SubElement(xmeta, 'Anchor', {'xmlns': constant.NAMESPACE_METINF});
97542             if ( cmd.lastAnchor )
97543                 ET.SubElement(xanch, 'Last').text = cmd.lastAnchor;
97544             if ( cmd.nextAnchor )
97545                 ET.SubElement(xanch, 'Next').text = cmd.nextAnchor;
97546             if ( cmd.maxObjSize )
97547                 ET.SubElement(xmeta, 'MaxObjSize',
97548                         {'xmlns': constant.NAMESPACE_METINF}).text = cmd.maxObjSize;
97549         }
97550     },
97551
97552     //-------------------------------------------------------------------------
97553     _produce_cmd_status: function(session, cmd, xcmd) {
97554         ET.SubElement(xcmd, 'MsgRef').text    = '' + cmd.msgRef;
97555         ET.SubElement(xcmd, 'CmdRef').text    = '' + cmd.cmdRef;
97556         ET.SubElement(xcmd, 'Cmd').text       = cmd.statusOf;
97557         if ( cmd.sourceRef )
97558             ET.SubElement(xcmd, 'SourceRef').text = cmd.sourceRef;
97559         if ( cmd.targetRef )
97560             ET.SubElement(xcmd, 'TargetRef').text = cmd.targetRef;
97561         ET.SubElement(xcmd, 'Data').text      = cmd.statusCode;
97562         var xitem = null;
97563         var xdata = null;
97564         if ( cmd.nextAnchor || cmd.lastAnchor )
97565         {
97566             xitem = ET.SubElement(xcmd, 'Item');
97567             xdata = ET.SubElement(xitem, 'Data');
97568             var xanch = ET.SubElement(xdata, 'Anchor', {'xmlns': constant.NAMESPACE_METINF});
97569             if ( cmd.lastAnchor )
97570                 ET.SubElement(xanch, 'Last').text = cmd.lastAnchor;
97571             if ( cmd.nextAnchor )
97572                 ET.SubElement(xanch, 'Next').text = cmd.nextAnchor;
97573         }
97574         // NOTE: this is NOT standard SyncML...
97575         if ( cmd.errorCode || cmd.errorMsg )
97576         {
97577             xitem = xitem || ET.SubElement(xcmd, 'Item');
97578             xdata = xdata || ET.SubElement(xitem, 'Data');
97579             var xerr = ET.SubElement(xitem, 'Error');
97580             xdata.text = cmd.errorMsg;
97581             if ( cmd.errorCode )
97582                 ET.SubElement(xerr, 'Code').text = cmd.errorCode;
97583             if ( cmd.errorMsg )
97584                 ET.SubElement(xerr, 'Message').text = cmd.errorMsg;
97585             if ( session.context.config.exposeErrorTrace && cmd.errorTrace )
97586                 ET.SubElement(xerr, 'Trace').text = cmd.errorTrace;
97587         }
97588     },
97589
97590     //-------------------------------------------------------------------------
97591     _produce_cmd_get: function(session, cmd, xcmd) {
97592         ET.SubElement(ET.SubElement(xcmd, 'Meta'), 'Type',
97593                 {'xmlns': constant.NAMESPACE_METINF}).text = cmd.type;
97594         if ( cmd.source || cmd.target || cmd.data )
97595         {
97596             var xitem = ET.SubElement(xcmd, 'Item');
97597             if ( cmd.source )
97598             {
97599                 var xsrc = ET.SubElement(xitem, 'Source');
97600                 ET.SubElement(xsrc, 'LocURI').text  = cmd.source;
97601                 ET.SubElement(xsrc, 'LocName').text = cmd.source;
97602             }
97603             if ( cmd.target )
97604             {
97605                 var xtgt = ET.SubElement(xitem, 'Target');
97606                 ET.SubElement(xtgt, 'LocURI').text  = cmd.target;
97607                 ET.SubElement(xtgt, 'LocName').text = cmd.target;
97608             }
97609             if ( cmd.data )
97610             {
97611                 if ( _.isString(cmd.data) )
97612                     ET.SubElement(xitem, 'Data').text = cmd.data;
97613                 else
97614                     // assuming here that it is an ElementTree object...
97615                     ET.SubElement(xitem, 'Data').append(cmd.data);
97616             }
97617         }
97618     },
97619
97620     //-------------------------------------------------------------------------
97621     _produce_cmd_put: function(session, cmd, xcmd) {
97622         return this._produce_cmd_get(session, cmd, xcmd);
97623     },
97624
97625     //-------------------------------------------------------------------------
97626     _produce_cmd_results: function(session, cmd, xcmd) {
97627         ET.SubElement(xcmd, 'MsgRef').text    = cmd.msgRef;
97628         ET.SubElement(xcmd, 'CmdRef').text    = cmd.cmdRef;
97629         ET.SubElement(ET.SubElement(xcmd, 'Meta'), 'Type',
97630                 {'xmlns': constant.NAMESPACE_METINF}).text = cmd.type;
97631         var xitem = ET.SubElement(xcmd, 'Item');
97632         var xsrc  = ET.SubElement(xitem, 'Source');
97633         ET.SubElement(xsrc, 'LocURI').text  = cmd.source;
97634         ET.SubElement(xsrc, 'LocName').text = cmd.source;
97635         if ( cmd.data )
97636         {
97637             if ( _.isString(cmd.data) )
97638                 ET.SubElement(xitem, 'Data').text = cmd.data;
97639             else
97640                 // assuming here that it is an ElementTree object...
97641                 ET.SubElement(xitem, 'Data').append(cmd.data);
97642         }
97643     },
97644
97645     //-------------------------------------------------------------------------
97646     _produce_cmd_sync: function(session, cmd, xcmd) {
97647         ET.SubElement(ET.SubElement(xcmd, 'Source'), 'LocURI').text = cmd.source;
97648         ET.SubElement(ET.SubElement(xcmd, 'Target'), 'LocURI').text = cmd.target;
97649         if ( cmd.noc != undefined )
97650             ET.SubElement(xcmd, 'NumberOfChanges').text = '' + cmd.noc;
97651         if ( ! cmd.data )
97652             return;
97653         for ( var idx=0 ; idx<cmd.data.length ; idx++ )
97654         {
97655             var scmd = cmd.data[idx];
97656             var xscmd = ET.SubElement(xcmd, scmd.name);
97657             if ( scmd.cmdID )
97658                 ET.SubElement(xscmd, 'CmdID').text = scmd.cmdID;
97659             if ( scmd.type
97660                     || ( scmd.format && scmd.format != constant.FORMAT_AUTO ) )
97661             {
97662                 var xsmeta = ET.SubElement(xscmd, 'Meta')
97663                     // todo: implement auto encoding determination...
97664                     //       (the current implementation just lets XML encoding
97665                     //       do it, which is for most things good enough, but
97666                     //       not so good for sequences that need a large amount
97667                     //       of escaping such as binary data...)
97668                     if ( scmd.format && scmd.format != constant.FORMAT_AUTO )
97669                         ET.SubElement(xsmeta, 'Format',
97670                                 {'xmlns': constant.NAMESPACE_METINF}).text = scmd.format;
97671                 if ( scmd.type )
97672                     ET.SubElement(xsmeta, 'Type',
97673                             {'xmlns': constant.NAMESPACE_METINF}).text = scmd.type;
97674             }
97675             var xsitem = ET.SubElement(xscmd, 'Item');
97676             if ( scmd.source )
97677                 ET.SubElement(ET.SubElement(xsitem, 'Source'),
97678                         'LocURI').text = scmd.source;
97679             if ( scmd.sourceParent )
97680                 ET.SubElement(ET.SubElement(xsitem, 'SourceParent'),
97681                         'LocURI').text = scmd.sourceParent;
97682             if ( scmd.target )
97683                 ET.SubElement(ET.SubElement(xsitem, 'Target'),
97684                         'LocURI').text = scmd.target;
97685             if ( scmd.targetParent )
97686                 ET.SubElement(ET.SubElement(xsitem, 'TargetParent'),
97687                         'LocURI').text = scmd.targetParent;
97688             if ( scmd.data )
97689             {
97690                 if ( _.isString(scmd.data) )
97691                     ET.SubElement(xsitem, 'Data').text = scmd.data;
97692                 else
97693                     // assuming here that it is an ElementTree object...
97694                     ET.SubElement(xsitem, 'Data')._node.appendChild(scmd.data);
97695             }
97696         }
97697     },
97698
97699     //-------------------------------------------------------------------------
97700     _produce_cmd_map: function(session, cmd, xcmd) {
97701         ET.SubElement(ET.SubElement(xcmd, 'Source'), 'LocURI').text = cmd.source;
97702         ET.SubElement(ET.SubElement(xcmd, 'Target'), 'LocURI').text = cmd.target;
97703         if ( cmd.sourceItem || cmd.targetItem )
97704         {
97705             var xitem = ET.SubElement(xcmd, constant.CMD_MAPITEM);
97706             if ( cmd.sourceItem )
97707                 ET.SubElement(ET.SubElement(xitem, 'Source'), 'LocURI').text = cmd.sourceItem;
97708             if ( cmd.targetItem )
97709                 ET.SubElement(ET.SubElement(xitem, 'Target'), 'LocURI').text = cmd.targetItem;
97710         }
97711     },
97712
97713     //-------------------------------------------------------------------------
97714     _produce_cmd_final: function(session, cmd, xcmd) {
97715         return;
97716     },
97717
97718     //-------------------------------------------------------------------------
97719     // NOTE: `consume` is equivalent to the `pysyncml.protocol.tree2commands`...
97720     // consume: function...
97721     consume: function(session, lastcmds, xsync, cb) {
97722
97723         // do some preliminary sanity checks...
97724         // todo: do i really want to be returning an error instead of
97725         // generating an error response?...
97726
97727         if ( xsync.tag != constant.NODE_SYNCML
97728                 || xsync.getchildren().length != 2
97729                 || xsync.getchildren()[0].tag != constant.CMD_SYNCHDR
97730                 || xsync.getchildren()[1].tag != constant.NODE_SYNCBODY
97731            )
97732         {
97733             return cb('unexpected SyncML document structure');
97734         }
97735
97736         var version = xsync.getchildren()[0].findtext('VerProto');
97737         if ( version != constant.SYNCML_VERSION_1_2 )
97738             return cb('unsupported SyncML version "' + version + '"');
97739
97740         var verdtd = xsync.getchildren()[0].findtext('VerDTD');
97741         if ( verdtd != constant.SYNCML_DTD_VERSION_1_2 )
97742             return cb('unsupported SyncML DTD version "' + verdtd + '"');
97743
97744         var self = this;
97745
97746         self.initialize(session, xsync, function(err, cmds) {
97747             var hdrcmd = ( cmds && cmds.length > 0 ) ? cmds[0] : null;
97748             var makeErrorCommands = function(err, cb) {
97749
97750                 if ( err.exception )
97751
97752             if ( ! session.isServer )
97753             return cb(err);
97754
97755         var errcmd = state.makeCommand({
97756             name       : constant.CMD_STATUS,
97757             cmdID      : '1',
97758             msgRef     : session.info.pendingMsgID,
97759             cmdRef     : 0,
97760             sourceRef  : xsync.getchildren()[0].findtext('Source/LocURI'),
97761             targetRef  : xsync.getchildren()[0].findtext('Target/LocURI'),
97762             statusOf   : constant.CMD_SYNCHDR,
97763             statusCode : constant.STATUS_COMMAND_FAILED,
97764             errorMsg   : 'an error occurred during processing'
97765         });
97766
97767         // TODO: make this configurable as to whether or not any error
97768         //       is sent back to the peer as a SyncML "standardized" error
97769         //       status...
97770
97771         // TODO: make sure this is doing what is expected/intended...
97772         if ( err.code || err.name )
97773             errcmd.errorCode  = 'syncml-js.' + ( err.code || err.name );
97774         errcmd.errorMsg   = err.message || common.j(err) || '' + err;
97775
97776         return cb(null, [hdrcmd, errcmd,
97777                 state.makeCommand({name: constant.CMD_FINAL})]);
97778             };
97779
97780             if ( err )
97781                 return makeErrorCommands(err, cb);
97782
97783             try {
97784                 self._consume(session, lastcmds, xsync, cmds, function(err, commands) {
97785                     if ( err )
97786                     return makeErrorCommands(err, cb);
97787                 return cb(null, commands);
97788                 });
97789             } catch ( exc ) {
97790                 return makeErrorCommands(exc, cb);
97791             }
97792
97793         });
97794     },
97795
97796     //-------------------------------------------------------------------------
97797     _consume: function(session, lastcmds, xsync, commands, cb) {
97798
97799         var self       = this;
97800         var hdrcmd     = commands[0];
97801         var statusCode = constant.STATUS_OK;
97802
97803         // analyze the SyncHdr
97804         var children = xsync.getchildren()[0].getchildren();
97805         for ( var idx=0 ; idx<children.length ; idx++ )
97806         {
97807             var child = children[idx];
97808
97809
97810             if ( child.tag == 'VerDTD' )
97811             {
97812                 if ( hdrcmd.version == constant.SYNCML_VERSION_1_2 )
97813                 {
97814                     if ( child.text != constant.SYNCML_DTD_VERSION_1_2 )
97815                         return cb(new common.ProtocolError('bad VerDTD "' + child.text + '"'));
97816                 }
97817                 else
97818                     return cb(new common.FeatureNotSupported(
97819                                 'unsupported internal SyncML version "' + hdrcmd.version + '"'));
97820                 continue;
97821             }
97822
97823             if ( child.tag == 'VerProto' )
97824                 // this was checked earlier...
97825                 continue;
97826
97827             if ( child.tag == 'SessionID' )
97828             {
97829                 if ( child.text != hdrcmd.sessionID )
97830                     return cb(new common.ProtocolError(
97831                                 'session ID mismatch: "' + child.text + '" != "' + hdrcmd.sessionID + '"'));
97832                 continue;
97833             }
97834
97835             if ( child.tag == 'MsgID' )
97836             {
97837                 var chkmsg = ( session.isServer ? hdrcmd.msgID : lastcmds[0].msgID );
97838                 if ( child.text != chkmsg )
97839                     return cb(new common.ProtocolError(
97840                                 'message ID mismatch: "' + child.text + '" != "' + chkmsg + '"'));
97841                 continue;
97842             }
97843
97844             if ( child.tag == 'Target' )
97845             {
97846                 var uri = child.findtext('LocURI');
97847
97848                 // TODO... server-side...
97849
97850                 if ( uri != hdrcmd.source )
97851                     return cb(new common.ProtocolError(
97852                                 'incoming target mismatch: "' + uri + '" != "' + hdrcmd.source + '"'));
97853                 continue;
97854             }
97855
97856             if ( child.tag == 'Source' )
97857             {
97858                 var uri = child.findtext('LocURI');
97859                 if ( uri != hdrcmd.target && uri != lastcmds[0].target )
97860                     return cb(new common.ProtocolError(
97861                                 'incoming source mismatch: "' + uri + '" != "' + hdrcmd.target + '"'));
97862                 continue;
97863             }
97864
97865             if ( child.tag == 'RespURI' )
97866             {
97867                 // hdrcmd.target = child.text
97868                 // session.info.respUri = child.text
97869                 if ( ! session.isServer )
97870                     session.info.respUri = child.text;
97871                 continue;
97872             }
97873
97874             if ( child.tag == 'Cred' )
97875             {
97876                 // the responsibility is on the calling framework to ensure this is
97877                 // checked long before we get here... ie. Adapter.authorize(...)
97878                 // or via the Adapter.handleRequest() `authorize` parameter...
97879                 statusCode = constant.STATUS_AUTHENTICATION_ACCEPTED;
97880                 continue;
97881             }
97882
97883             if ( child.tag == 'Meta' )
97884             {
97885                 // this should already have been consumed during the protocol.initialize() call
97886                 continue;
97887             }
97888
97889             return cb(new common.ProtocolError('unexpected header node "' + child.tag + '"'));
97890         };
97891
97892         commands.push(state.makeCommand({
97893             name       : constant.CMD_STATUS,
97894             cmdID      : session.nextCmdID(),
97895             msgRef     : session.info.pendingMsgID,
97896             cmdRef     : 0,
97897             sourceRef  : xsync.getchildren()[0].findtext('Source/LocURI'),
97898             targetRef  : xsync.getchildren()[0].findtext('Target/LocURI'),
97899             statusOf   : constant.CMD_SYNCHDR,
97900             statusCode : statusCode
97901         }));
97902
97903         // and now evaluate the SyncBody
97904
97905         var chkcmds = _.filter(lastcmds, function(e) {
97906             return e.name != constant.CMD_STATUS && e.name != constant.CMD_FINAL;
97907         });
97908
97909         // for each "sync" command, search for sub-commands
97910         // todo: should this be generalized to search for any sub-commands?...
97911         _.each(chkcmds, function(e) {
97912             if ( e.name != constant.CMD_SYNC || ! e.data || e.data.length <= 0 )
97913             return;
97914         _.each(e.data, function(sub) { chkcmds.push(sub); });
97915         });
97916
97917         var children = xsync.getchildren()[1].getchildren();
97918
97919         // first, check all the 'Status' commands
97920
97921         var consumeStatus = function(cb) {
97922
97923             common.cascade(children, function(child, cb) {
97924
97925                 if ( child.tag != constant.CMD_STATUS )
97926                 return cb();
97927
97928             cname = child.findtext('Cmd');
97929
97930             var blen   = chkcmds.length;
97931             var chkcmd = null;
97932             var chkerr = null;
97933
97934             chkcmds = _.filter(chkcmds, function(cmd) {
97935                 if ( chkerr )
97936                 return;
97937             if ( cmd.cmdID != child.findtext('CmdRef')
97938                 || cmd.name != cname
97939                 || lastcmds[0].msgID != child.findtext('MsgRef') )
97940                 return true;
97941             if ( chkcmd )
97942                 chkerr = new Error('unexpected error: multiple check commands match status command');
97943             chkcmd = cmd;
97944             return false;
97945             });
97946
97947             if ( chkerr )
97948                 return cb(chkerr);
97949
97950             if ( chkcmds.length >= blen )
97951                 return cb(new common.ProtocolError(
97952                             'unexpected status node "s' + session.info.id + '.m' + child.findtext('MsgRef')
97953                             + '.c' + child.findtext('CmdRef') + ' cmd=' + cname + '"'));
97954
97955             // TODO: check for unknown elements (and complain?)...
97956
97957             var code = common.int(child.findtext('Data'));
97958
97959             if ( code == constant.STATUS_MISSING_CREDENTIALS )
97960             {
97961                 var authtype = child.findtext('Chal/Meta/Type');
97962                 var attrs = {auth: {type: authtype}};
97963                 return cb(badStatus(child, common.CredentialsRequired, attrs));
97964             }
97965
97966             if ( code == constant.STATUS_INVALID_CREDENTIALS )
97967             {
97968                 // TODO: get the auth type... from where??...
97969                 var authtype = child.findtext('Chal/Meta/Type');
97970                 var attrs = {auth: {type: authtype}};
97971                 return cb(badStatus(child, common.InvalidCredentials, attrs));
97972             }
97973
97974             var targetRef = child.findtext('TargetRef');
97975             if ( targetRef )
97976             {
97977                 // note: doing a normUri on chkcmd.target because it could be "./devinf12"...
97978                 if ( session.peer.normUri(targetRef) != session.peer.normUri(chkcmd.target) )
97979                     return cb(new common.ProtocolError('unexpected target-ref "'
97980                                 + targetRef + '" != "' + chkcmd.target
97981                                 + '" for command "' + cname + '"'));
97982             }
97983
97984             var sourceRef = child.findtext('SourceRef');
97985             if ( sourceRef )
97986             {
97987                 // note: doing a normUri on chkcmd.source because it could be "./devinf12"...
97988                 if ( cname == constant.CMD_SYNCHDR )
97989                 {
97990                     // this is a little odd, but syncevolution strips the sessionid path
97991                     // parameter off for some reason, so compensating here...
97992                     if ( _.indexOf([session.adapter.normUri(chkcmd.source),
97993                                 session.info.effectiveID,
97994                                 session.info.returnUrl],
97995                                 session.adapter.normUri(sourceRef)) < 0
97996                             && session.adapter.normUri(chkcmd.source).indexOf(session.adapter.normUri(sourceRef)) != 0 )
97997                         return cb(new common.ProtocolError('unexpected source-ref "'
97998                                     + sourceRef + '" != "' + chkcmd.source
97999                                     + '" for command "' + cname + '"'));
98000                 }
98001                 else
98002                 {
98003                     if ( session.adapter.normUri(sourceRef) != session.adapter.normUri(chkcmd.source) )
98004                         return cb(new common.ProtocolError('unexpected source-ref "'
98005                                     + sourceRef + '" != "' + chkcmd.source
98006                                     + '" for command "' + cname + '"'));
98007                 }
98008             }
98009
98010             // todo: any other common elements?...
98011
98012             switch ( cname )
98013             {
98014
98015                 case constant.CMD_SYNCHDR:
98016                     {
98017                         if ( code != constant.STATUS_OK && code != constant.STATUS_AUTHENTICATION_ACCEPTED )
98018                             return cb(badStatus(child));
98019                         if ( code == constant.STATUS_AUTHENTICATION_ACCEPTED )
98020                         {
98021                             // TODO: there is currently nothing that can "reset" the
98022                             //       authAccepted flag...  there should be a trap such
98023                             //       that if an auth fails, then authAccepted gets set
98024                             //       to false.
98025                             session.info.authAccepted = true;
98026                         }
98027                         return cb();
98028                     }
98029
98030                 case constant.CMD_ALERT:
98031                     {
98032                         if ( code == constant.STATUS_OK )
98033                             // TODO: do something with the Item/Data/Anchor/Next?...
98034                             return cb();
98035                         if ( code == constant.STATUS_REFRESH_REQUIRED && ! session.isServer )
98036                         {
98037                             // TODO: support the ability for the UA to control which kind of
98038                             //       refresh to do (slow-sync, client-refresh, server-refresh)
98039                             return cb();
98040                         }
98041                         return cb(badStatus(child));
98042                     }
98043
98044                 case constant.CMD_GET:
98045                     {
98046                         if ( code != constant.STATUS_OK )
98047                             return cb(badStatus(child));
98048                         return cb();
98049                     }
98050
98051                 case constant.CMD_PUT:
98052                     {
98053                         if ( code != constant.STATUS_OK )
98054                             return cb(badStatus(child));
98055                         return cb();
98056                     }
98057
98058                 case constant.CMD_RESULTS:
98059                     {
98060                         if ( code != constant.STATUS_OK )
98061                             return cb(badStatus(child));
98062                         return cb();
98063                     }
98064
98065                 case constant.CMD_SYNC:
98066                     {
98067                         // todo: should this be moved into the synchronizer as a "settle" event?...
98068                         var ds = session.info.dsstates[session.adapter.normUri(chkcmd.source)]
98069                             if ( code != constant.STATUS_OK )
98070                             {
98071                                 // check for server-side errors...
98072                                 if ( code >= 500 && code < 600 && child.findtext('Item/Data') )
98073                                 {
98074                                     ds.action = 'error';
98075                                     ds.error  = getError(child);
98076                                     ds.stats.peerErr += 1;
98077                                     return cb();
98078                                 }
98079                                 return cb(badStatus(child));
98080                             }
98081                         if ( ds.action == 'send' )
98082                         {
98083                             if ( session.isServer )
98084                             {
98085                                 ds.action = 'save';
98086                                 return cb();
98087                             }
98088                             ds.action = common.oneWayOut(session, ds.mode) ? 'done' : 'recv';
98089                             return cb();
98090                         }
98091                         return cb(new common.ProtocolError('unexpected sync state for action=' + ds.action));
98092                     }
98093
98094                 case constant.CMD_ADD:
98095                 case constant.CMD_REPLACE:
98096                 case constant.CMD_DELETE:
98097                     {
98098                         var scmd = state.makeCommand({
98099                             name       : cname,
98100                             msgID      : hdrcmd.msgID,
98101                             cmdID      : child.findtext('CmdID'),
98102                             sourceRef  : sourceRef,
98103                             targetRef  : targetRef,
98104                             data       : code
98105                         });
98106
98107                         session.context.synchronizer.settle(
98108                                 session, scmd, chkcmd, child,
98109                                 function(err, cmds) {
98110                                     if ( err )
98111                             return cb(err);
98112                         _.each(cmds, function(cmd) { commands.push(cmd); });
98113                         return cb();
98114                                 });
98115                         return;
98116                     }
98117
98118                 case constant.CMD_MAP:
98119                     {
98120                         if ( session.isServer )
98121                             return cb(new common.ProtocolError(
98122                                         'unexpected server-side status for command "' + cname + '"'));
98123                         if ( code != constant.STATUS_OK )
98124                             return cb(badStatus(child));
98125                         return cb();
98126                     }
98127
98128                 default:
98129                     {
98130                         return cb(new common.ProtocolError('unexpected status for command "' + cname + '"'));
98131                     }
98132
98133             }
98134
98135             }, cb);
98136
98137         };
98138
98139         // second, check all the non-'Status' commands
98140
98141         var consumeCommands = function(cb) {
98142
98143             var gotFinal = false;
98144
98145             common.cascade(children, function(child, cb) {
98146
98147
98148                 if ( child.tag == constant.CMD_STATUS )
98149                 return cb();
98150
98151             if ( child.tag == constant.CMD_FINAL )
98152             {
98153                 gotFinal = true;
98154                 return cb();
98155             }
98156
98157
98158             // todo: restrict this to the following commands?...
98159             //         CMD_ALERT, CMD_GET, CMD_PUT,
98160             //         CMD_SYNC, CMD_RESULTS, CMD_MAP
98161
98162             var func = self['_consume_node_' + child.tag.toLowerCase()];
98163
98164             if ( ! func )
98165                 return cb(new common.ProtocolError('unexpected command node "' + child.tag + '"'));
98166
98167             try{
98168
98169                 func.call(self, session, lastcmds, xsync, child, function(err, cmds) {
98170                     if ( err )
98171                     return cb(err);
98172                 _.each(cmds, function(cmd) { commands.push(cmd); });
98173                 return cb();
98174                 });
98175
98176             }catch(e){
98177                 // log.error('failed invoking protocol sub-consumption of "%s": %s', child.tag, e);
98178                 // log.error('  ' + stacktrace({e: e}).join('\n  '));
98179                 return cb(new common.InternalError(
98180                             'failed invoking protocol sub-consumption of "' + child.tag + '": ' + e, e));
98181             }
98182
98183             }, function(err) {
98184
98185                 if ( err )
98186                     return cb(err);
98187
98188                 if ( ! gotFinal )
98189                 {
98190                     commands.push(state.makeCommand({
98191                         name       : constant.CMD_ALERT,
98192                         cmdID      : session.nextCmdID(),
98193                         data       : constant.STATUS_NEXT_MESSAGE,
98194                         source     : session.adapter.devID,
98195                         target     : session.peer.devID,
98196                     }));
98197                 }
98198
98199                 return cb();
98200
98201             });
98202
98203         };
98204
98205         // do it!
98206
98207         consumeStatus(function(err) {
98208
98209             if ( err )
98210             return cb(err);
98211
98212         // TODO: is this right?... or should i be getting pissed off and
98213         //       raising hell that all my commands were not addressed?...
98214
98215         _.each(chkcmds, function(chkcmd) {
98216             commands.push(chkcmd);
98217         });
98218
98219         return consumeCommands(function(err) {
98220             if ( err )
98221             return cb(err);
98222         return cb(null, commands);
98223         });
98224
98225         });
98226
98227     },
98228
98229     //-------------------------------------------------------------------------
98230     _consume_node_get: function(session, lastcmds, xsync, xnode, cb) {
98231         var cttype = xnode.findtext('Meta/Type');
98232         var target = xnode.findtext('Item/Target/LocURI');
98233         if ( cttype.indexOf(constant.TYPE_SYNCML_DEVICE_INFO) == 0
98234                 && session.adapter.normUri(target) == constant.URI_DEVINFO_1_2 )
98235             return this._consume_node_get_devinf12(session, lastcmds, xsync, xnode, cb);
98236         // todo: make error status node...
98237         cb(new common.ProtocolError(
98238                     'unexpected "' + constant.CMD_GET + '" command for local "' + target + '"'));
98239     },
98240
98241     //-------------------------------------------------------------------------
98242     _consume_node_get_devinf12: function(session, lastcmds, xsync, xnode, cb) {
98243         var ret = [];
98244         ret.push(state.makeCommand({
98245             name       : constant.CMD_STATUS,
98246             cmdID      : session.nextCmdID(),
98247             msgRef     : session.info.pendingMsgID,
98248             cmdRef     : xnode.findtext('CmdID'),
98249             statusOf   : xnode.tag,
98250             statusCode : constant.STATUS_OK,
98251             targetRef  : xnode.findtext('Item/Target/LocURI')
98252         }));
98253         ret.push(state.makeCommand({
98254             name       : constant.CMD_RESULTS,
98255             cmdID      : session.nextCmdID(),
98256             msgRef     : session.info.pendingMsgID,
98257             cmdRef     : xnode.findtext('CmdID'),
98258             type       : constant.TYPE_SYNCML_DEVICE_INFO + '+' + session.info.codec,
98259             source     : './' + constant.URI_DEVINFO_1_2,
98260             data       : session.adapter.devInfo.toSyncML(constant.SYNCML_DTD_VERSION_1_2,
98261                 _.values(session.adapter._stores))
98262
98263         }));
98264         cb(null, ret);
98265     },
98266
98267     //-------------------------------------------------------------------------
98268     _consume_node_put: function(session, lastcmds, xsync, xnode, cb) {
98269         var cttype = xnode.findtext('Meta/Type');
98270         var source = xnode.findtext('Item/Source/LocURI');
98271         if ( cttype.indexOf(constant.TYPE_SYNCML_DEVICE_INFO) == 0
98272                 && session.peer.normUri(source) == constant.URI_DEVINFO_1_2 )
98273             return this._consume_node_put_devinf12(session, lastcmds, xsync, xnode, cb);
98274         // todo: make error status node...
98275         cb(new common.ProtocolError(
98276                     'unexpected "' + constant.CMD_PUT + '" command for remote "' + source + '"'));
98277     },
98278
98279     //-------------------------------------------------------------------------
98280     _consume_node_put_devinf12: function(session, lastcmds, xsync, xnode, cb) {
98281         var xdev = xnode.find('Item/Data/DevInf');
98282         var res  = devinfo.DevInfo.fromSyncML(xdev);
98283         session.peer._setRemoteInfo(res[0], res[1], function(err) {
98284             if ( err )
98285             return cb(err);
98286
98287         var okcmd = state.makeCommand({
98288             name       : constant.CMD_STATUS,
98289             cmdID      : session.nextCmdID(),
98290             msgRef     : xsync.findtext('SyncHdr/MsgID'),
98291             cmdRef     : xnode.findtext('CmdID'),
98292             sourceRef  : xnode.findtext('Item/Source/LocURI'),
98293             statusOf   : xnode.tag,
98294             statusCode : constant.STATUS_OK
98295         });
98296
98297         if ( session.isServer )
98298             return cb(null, [okcmd]);
98299
98300         // TODO: this should only cause a `recalculate` if any
98301         //       meta-information actually changed...
98302
98303         session.context.router.recalculate(session.adapter, session.peer, function(err) {
98304             if ( err )
98305             return cb(err);
98306         session.context.synchronizer.initStoreSync(session, function(err) {
98307             if ( err )
98308             return cb(err);
98309
98310         // TODO: the call to _setRemoteInfo makes the peer
98311         //       "dirty" without saving changes to the model...
98312         //       make sure the `save` executed in Adapter.sync()
98313         //       or Adapter.handleRequest() appropriately causes
98314         //       objects to save themselves to the model...
98315
98316         // session.adapter._save(session.txn(), function(err) {
98317         //   if ( err )
98318         //     return cb(err);
98319
98320         return cb(null, [okcmd]);
98321
98322         // });
98323
98324         });
98325         });
98326         });
98327     },
98328
98329     //-------------------------------------------------------------------------
98330     _consume_node_results: function(session, lastcmds, xsync, xnode, cb) {
98331         var cttype = xnode.findtext('Meta/Type');
98332         var source = xnode.findtext('Item/Source/LocURI');
98333         if ( cttype.indexOf(constant.TYPE_SYNCML_DEVICE_INFO) == 0
98334                 && session.peer.normUri(source) == constant.URI_DEVINFO_1_2 )
98335             return this._consume_node_put_devinf12(session, lastcmds, xsync, xnode, cb);
98336         // todo: make error status node...
98337         return cb(new common.ProtocolError('unexpected "' + constant.CMD_RESULTS
98338                     + '" command for remote "' + source + '"'))
98339     },
98340
98341     //-------------------------------------------------------------------------
98342     _consume_node_alert: function(session, lastcmds, xsync, xnode, cb) {
98343         var code = common.int(xnode.findtext('Data'));
98344         var statusCode = constant.STATUS_OK
98345             switch ( code )
98346             {
98347                 case constant.ALERT_TWO_WAY:
98348                 case constant.ALERT_SLOW_SYNC:
98349                 case constant.ALERT_ONE_WAY_FROM_CLIENT:
98350                 case constant.ALERT_REFRESH_FROM_CLIENT:
98351                 case constant.ALERT_ONE_WAY_FROM_SERVER:
98352                 case constant.ALERT_REFRESH_FROM_SERVER:
98353                     // todo: these should only be received out-of-band: right?...
98354                     // case constant.ALERT_TWO_WAY_BY_SERVER:
98355                     // case constant.ALERT_ONE_WAY_FROM_CLIENT_BY_SERVER:
98356                     // case constant.ALERT_REFRESH_FROM_CLIENT_BY_SERVER:
98357                     // case constant.ALERT_ONE_WAY_FROM_SERVER_BY_SERVER:
98358                     // case constant.ALERT_REFRESH_FROM_SERVER_BY_SERVER:
98359                     {
98360                         break;
98361                     }
98362                 default:
98363                     {
98364                         if ( session.isServer && code == constant.STATUS_RESUME )
98365                         {
98366                             code = constant.ALERT_SLOW_SYNC;
98367                         }
98368                         else
98369                         {
98370                             return cb(new common.FeatureNotSupported(
98371                                         'unimplemented sync mode '
98372                                         + code + ' ("' + common.mode2string(code) + '")'));
98373                         }
98374                     }
98375             }
98376
98377         if ( session.isServer )
98378         {
98379             // TODO: if this is the server, we need to validate that the requested
98380             //       sync mode is actually feasible... i.e. check:
98381             //         - do the anchors match?
98382             //         - have we bound the datastores together?
98383             //         - is there a pending sync?
98384         }
98385
98386         var uri  = session.adapter.normUri(xnode.findtext('Item/Target/LocURI'));
98387         var ruri = session.peer.normUri(xnode.findtext('Item/Source/LocURI'));
98388
98389         // TODO: this should really be done by the synchronizer... as it can
98390         //       then also do a lot of checks - potentially responding with
98391         //       an error...
98392
98393         var getDS = function(cb) {
98394             if ( session.isServer )
98395             {
98396                 var ds = session.info.dsstates[uri];
98397                 if ( ds )
98398                 {
98399                     ds.action = 'alert';
98400                     return cb(null, ds);
98401                 }
98402
98403                 var peerStore = session.peer.getStore(ruri);
98404                 if ( ! peerStore )
98405                     return cb(new common.ProtocolError(
98406                                 'request to synchronize unknown remote client URI "' + ruri
98407                                 + '" (to local server URI "' + uri + '")'));
98408
98409                 // todo: if already correctly bound, then we don't need to re-bind
98410                 // if ( peerStore._getBinding() )
98411                 // {
98412                 //   log.critical('(currently bound)');
98413                 // }
98414                 // else
98415                 //   log.critical('(currently unbound)');
98416
98417                 session.peer.setRoute(uri, ruri, true, function(err) {
98418                     if ( err )
98419                     return cb(err);
98420                 var peerStore = session.peer.getStore(ruri);
98421                 var ds = state.makeStoreSyncState({
98422                     uri        : uri,
98423                     peerUri    : ruri,
98424                     lastAnchor : peerStore._getBinding().localAnchor,
98425                     mode       : null,
98426                     action     : 'alert'
98427                 });
98428                 session.info.dsstates[uri] = ds;
98429                 return cb(null, ds);
98430                 });
98431                 return;
98432             }
98433             else
98434             {
98435                 var ds = session.info.dsstates[uri];
98436                 if ( ! ds )
98437                     return cb(new common.ProtocolError('request for unreflected local datastore "'
98438                                 + uri + '"'));
98439                 ds.action = 'send';
98440                 if ( code == ds.mode )
98441                     return cb(null, ds);
98442
98443                 var uaEvent = {
98444                     session   : session,
98445                     uri       : uri,
98446                     peerUri   : ruri,
98447                     modeReq   : ds.mode,
98448                     modeRes   : code
98449                 };
98450                 session.ua.acceptSyncModeSwitch(uaEvent, function(err) {
98451                     if ( err )
98452                 {
98453                     return cb(err);
98454                 }
98455                 if ( session.context.listener )
98456                     session.context.listener(uaEvent);
98457                 return cb(null, ds);
98458                 });
98459             }
98460         };
98461
98462
98463         getDS(function(err, ds) {
98464
98465             if ( err )
98466             return cb(err);
98467
98468         ds.mode = code;
98469         ds.peerLastAnchor = xnode.findtext('Item/Meta/Anchor/Last', null);
98470         ds.peerNextAnchor = xnode.findtext('Item/Meta/Anchor/Next', null);
98471
98472         if ( ds.peerLastAnchor != session.peer.getStore(ruri)._getBinding().remoteAnchor )
98473         {
98474             ds.peerLastAnchor = null;
98475             switch ( ds.mode )
98476         {
98477             case constant.ALERT_SLOW_SYNC:
98478             case constant.ALERT_REFRESH_FROM_CLIENT:
98479             case constant.ALERT_REFRESH_FROM_SERVER:
98480                 {
98481                     break;
98482                 }
98483             default:
98484                 {
98485                     if ( session.isServer )
98486                     {
98487                         ds.mode = constant.ALERT_SLOW_SYNC;
98488                         statusCode = constant.STATUS_REFRESH_REQUIRED;
98489                     }
98490                     else
98491                     {
98492                         // todo: should i assume that the server knows something
98493                         //       that i don't and just go along with it?...
98494                         return cb(new common.ProtocolError(
98495                                     'server-side requested inappropriate ' + common.mode2string(ds.mode)
98496                                     + ' sync mode on unbound datastore "' + uri + '"'));
98497                     }
98498                 }
98499         }
98500         }
98501
98502         return cb(null, [state.makeCommand({
98503             name       : constant.CMD_STATUS,
98504                cmdID      : session.nextCmdID(),
98505                msgRef     : xsync.findtext('SyncHdr/MsgID'),
98506                cmdRef     : xnode.findtext('CmdID'),
98507                targetRef  : xnode.findtext('Item/Target/LocURI'),
98508                sourceRef  : xnode.findtext('Item/Source/LocURI'),
98509                statusOf   : xnode.tag,
98510                statusCode : statusCode,
98511                // todo: syncevolution does not echo the remote last anchor... why not?
98512                lastAnchor : ds.peerLastAnchor,
98513                nextAnchor : ds.peerNextAnchor
98514         })]);
98515
98516         });
98517
98518     },
98519
98520     //-------------------------------------------------------------------------
98521     _consume_node_sync: function(session, lastcmds, xsync, xnode, cb) {
98522         var self   = this;
98523         var uri    = xnode.findtext('Target/LocURI');
98524         var store  = session.adapter.getStore(session.adapter.normUri(uri));
98525         var ds     = session.info.dsstates[session.adapter.normUri(uri)];
98526         var commands = [state.makeCommand({
98527             name        : constant.CMD_SYNC,
98528             msgID       : xsync.findtext('SyncHdr/MsgID'),
98529             cmdID       : xnode.findtext('CmdID'),
98530             source      : xnode.findtext('Source/LocURI'),
98531             target      : uri,
98532             data        : [],
98533         })];
98534         var noc = common.int(xnode.findtext('NumberOfChanges'));
98535         if (noc !== undefined) {
98536             changednum = noc;
98537             _counts = 0;
98538         }
98539         common.cascade(xnode.getchildren(), function(child, cb) {
98540             switch ( child.tag )
98541         {
98542             case 'CmdID':
98543             case 'Target':
98544             case 'Source':
98545             case 'NumberOfChanges':
98546                 {
98547                     return cb();
98548                 }
98549             case constant.CMD_ADD:
98550             case constant.CMD_REPLACE:
98551             case constant.CMD_DELETE:
98552                 {
98553                     var func = self['_consume_sync_' + child.tag.toLowerCase()];
98554                     func.call(self, session, lastcmds, store, xsync, child, function(err, cmds) {
98555                         if ( err )
98556                         return cb(err);
98557                     _.each(cmds, function(cmd) { commands[0].data.push(cmd); });
98558                     return cb();
98559                     });
98560                     return;
98561                 }
98562             default:
98563                 {
98564                     return cb(new common.ProtocolError('unexpected sync command "' + child.tag + '"'));
98565                 }
98566         }
98567         }, function(err) {
98568             if ( err )
98569                 return cb(err);
98570             // confirm that i received the right number of changes...
98571             /*
98572                if ( noc != undefined && noc != commands[0].data.length )
98573                return cb(new common.ProtocolError('number-of-changes mismatch (received '
98574                + commands[0].data.length + ', expected '
98575                + noc + ')'));
98576                */
98577             _counts =  _counts + commands[0].data.length;
98578             if ( ds.action != 'error' )
98579             {
98580                 if ( ! session.isServer )
98581                 {
98582                     if ( ds.action != 'recv' )
98583                         return cb(new common.ProtocolError('unexpected sync state for URI "'
98584                                     + uri + '": action=' + ds.action));
98585                     if (changednum != undefined && changednum <= _counts)  {
98586                         ds.action = 'done';
98587                         changednum = undefined;
98588                         _counts = 0;
98589                     }
98590                 }
98591                 else
98592                 {
98593                     if ( ds.action != 'alert' )
98594                         return cb(new common.ProtocolError(
98595                                     'unexpected sync state for URI "' + uri + '": action=' + ds.action));
98596                     ds.action = common.oneWayIn(session, ds.mode) ? 'save' : 'send';
98597                 }
98598             }
98599             return session.context.synchronizer.reactions(session, commands, cb);
98600         });
98601     },
98602
98603     //-------------------------------------------------------------------------
98604     _consume_xnode2item: function(session, lastcmds, store, xsync, xnode, cb) {
98605         var ctype  = xnode.findtext('Meta/Type');
98606         // todo: can the version be specified in the Meta tag?... maybe create an
98607         //       extension to SyncML to communicate this?...
98608         var ctver  = null;
98609         var format = xnode.findtext('Meta/Format');
98610         var xitem  = xnode.findall('Item/Data');
98611         if ( xitem.length > 1 )
98612             return cb(new common.ProtocolError(
98613                         '"' + xnode.tag + '" command with non-singular item data nodes'));
98614         if ( xitem.length < 1 )
98615             return cb(new common.ProtocolError(
98616                         '"' + xnode.tag + '" command with missing data node'));
98617         var xitem = xitem[0];
98618         // todo: confirm that getchildren only returns element nodes...
98619         if ( xitem.getchildren().length == 1 )
98620             data = xitem.getchildren()[0];
98621         else
98622         {
98623             data = xitem.text;
98624             if ( format == constant.FORMAT_B64 )
98625                 data = base64.decode(data);
98626         }
98627         return store.agent.loadsItem(data, ctype, ctver, cb);
98628     },
98629
98630     //-------------------------------------------------------------------------
98631     _consume_sync_add: function(session, lastcmds, store, xsync, xnode, cb) {
98632         this._consume_xnode2item(session, lastcmds, store, xsync, xnode, function(err, item) {
98633             if ( err )
98634             return cb(err);
98635         return cb(null, [state.makeCommand({
98636             name          : constant.CMD_ADD,
98637                msgID         : xsync.findtext('SyncHdr/MsgID'),
98638                cmdID         : xnode.findtext('CmdID'),
98639                source        : xnode.findtext('Item/Source/LocURI'),
98640                sourceParent  : xnode.findtext('Item/SourceParent/LocURI'),
98641                targetParent  : xnode.findtext('Item/TargetParent/LocURI'),
98642                data          : item
98643         })]);
98644         });
98645     },
98646
98647     //-------------------------------------------------------------------------
98648     _consume_sync_replace: function(session, lastcmds, store, xsync, xnode, cb) {
98649         this._consume_xnode2item(session, lastcmds, store, xsync, xnode, function(err, item) {
98650             if ( err )
98651             return cb(err);
98652         return cb(null, [state.makeCommand({
98653             name          : constant.CMD_REPLACE,
98654                msgID         : xsync.findtext('SyncHdr/MsgID'),
98655                cmdID         : xnode.findtext('CmdID'),
98656                source        : xnode.findtext('Item/Source/LocURI'),
98657                sourceParent  : xnode.findtext('Item/SourceParent/LocURI'),
98658                target        : xnode.findtext('Item/Target/LocURI'),
98659                targetParent  : xnode.findtext('Item/TargetParent/LocURI'),
98660                data          : item
98661         })]);
98662         });
98663     },
98664
98665     //-------------------------------------------------------------------------
98666     _consume_sync_delete: function(session, lastcmds, store, xsync, xnode, cb) {
98667         return cb(null, [state.makeCommand({
98668             name          : constant.CMD_DELETE,
98669         msgID         : xsync.findtext('SyncHdr/MsgID'),
98670         cmdID         : xnode.findtext('CmdID'),
98671         source        : xnode.findtext('Item/Source/LocURI'),
98672         sourceParent  : xnode.findtext('Item/SourceParent/LocURI'),
98673         target        : xnode.findtext('Item/Target/LocURI'),
98674         targetParent  : xnode.findtext('Item/TargetParent/LocURI')
98675         })]);
98676     },
98677
98678     // #----------------------------------------------------------------------------
98679     // def makeStatus(self, session, xsync, xnode, status=constant.STATUS_OK, **kw):
98680     //   return state.Command(
98681     //     name       = constant.CMD_STATUS,
98682     //     cmdID      = session.nextCmdID(),
98683     //     msgRef     = xsync.findtext('SyncHdr/MsgID'),
98684     //     cmdRef     = xnode.findtext('CmdID'),
98685     //     statusOf   = xnode.tag,
98686     //     statusCode = status,
98687     //     **kw
98688     //     )
98689
98690     //-------------------------------------------------------------------------
98691     _consume_node_map: function(session, lastcmds, xsync, xnode, cb) {
98692         if ( ! session.isServer )
98693             return cb(new common.ProtocolError(
98694                         'unexpected "Map" command received by client-side SyncML peer'));
98695         // TODO: convert the sender-side to support command.items like
98696         //       this as well...
98697         var cmd = state.makeCommand({
98698             name    : constant.CMD_MAP,
98699             msgID   : xsync.findtext('SyncHdr/MsgID'),
98700             cmdID   : xnode.findtext('CmdID'),
98701             source  : xnode.findtext('Source/LocURI'),
98702             target  : xnode.findtext('Target/LocURI'),
98703             items   : []
98704         });
98705         _.each(xnode.findall('MapItem'), function(xnode) {
98706             // todo: support hierarchical sync...
98707             cmd.items.push({
98708                 source        : xnode.findtext('Source/LocURI'),
98709                 // sourceParent  : xnode.findtext('SourceParent/LocURI'),
98710                 target        : xnode.findtext('Target/LocURI'),
98711                 // targetParent  : xnode.findtext('TargetParent/LocURI')
98712             });
98713         });
98714         return session.context.synchronizer.reactions(session, [cmd], cb);
98715     }
98716
98717
98718 });
98719
98720 return exports;
98721
98722 })();
98723
98724 module.exports = _self;
98725
98726 });
98727 define('ripple/platform/tizen/2.0/syncml-js-lib/remoteadapter', function (require, exports, module) {
98728 // -*- coding: utf-8 -*-
98729 //-----------------------------------------------------------------------------
98730 // file: $Id$
98731 // lib:  syncml-js.remoteadapter
98732 // auth: griffin <griffin@uberdev.org>
98733 // date: 2012/11/04
98734 // copy: (C) CopyLoose 2012 UberDev <hardcore@uberdev.org>, No Rights Reserved.
98735 //-----------------------------------------------------------------------------
98736
98737 var common = require('ripple/platform/tizen/2.0/syncml-js-lib/common'),
98738     devinfomod = require('ripple/platform/tizen/2.0/syncml-js-lib/devinfo'),
98739     adapter = require('ripple/platform/tizen/2.0/syncml-js-lib/adapter'),
98740     storemod = require('ripple/platform/tizen/2.0/syncml-js-lib/store'),
98741     _self;
98742
98743 _self = (function () {
98744     var exports = {};
98745
98746     //---------------------------------------------------------------------------
98747     exports.RemoteAdapter = adapter.Adapter.extend({
98748
98749         //-------------------------------------------------------------------------
98750         constructor: function(adapter, options) {
98751
98752             //: [read-only] the URL of the remote syncml peer, acting as a server,
98753             //: to connect to.
98754             this.url = options.url || null;
98755
98756             //: [read-only] specifies whether this Adapter represents a local
98757             //: or remote peer.
98758             this.isLocal = false;
98759
98760             //: [read-only] the DevID of the remote syncml peer (which usually
98761             //: defaults to the URL).
98762             this.devID = options.devID || options.url || null;
98763
98764             //: [read-only] the authentication method to use to identify the local
98765             //: peer to the remote peer.
98766             ///TODO: this.auth = options.auth || null;
98767             this.auth = 'syncml:auth-basic';
98768
98769             //: [read-only] the human-friendly display name of the remote peer.
98770             this.displayName = options.displayName || null;
98771
98772             //: [read-only] the username to use during credential-based authentication.
98773             this.username = options.username || null;
98774
98775             //: [read-only] the password to use during credential-based authentication.
98776             this.password = options.password || null;
98777
98778             //: [read-only] the peer-wide default value of the maximum
98779             //: message size.
98780             this.maxMsgSize = options.maxMsgSize || null;
98781
98782             //: [read-only] the peer-wide default value of the maximum
98783             //: object size.
98784             this.maxObjSize = options.maxObjSize || null;
98785
98786             //: [read-only] the DevInfo object for this remote peer.
98787             this.devInfo = null;
98788
98789             this.lastSessionID = options.lastSessionID || null;
98790
98791             // --- private attributes
98792             this.id       = options.id || common.makeID();
98793             this._a       = adapter;
98794             this._c       = adapter._c;
98795             this._stores  = {};
98796             this._proxy   = null;
98797
98798             // TODO: filter these options for db-valid only properties...
98799             this._options = options;
98800         },
98801
98802             //-------------------------------------------------------------------------
98803             _load: function(cb) {
98804
98805                 var self  = this;
98806                 var model = this._getModel();
98807
98808                 // todo: should this be loading these?...
98809                 // self.displayName = model.displayName;
98810                 // self.devID       = model.devID;
98811
98812                 var loadDevInfo = function(cb) {
98813                     var di = new devinfomod.DevInfo(self, model.devInfo);
98814                     di._load(function(err) {
98815                         if ( err )
98816                         return cb(err);
98817                     self.devInfo = di;
98818                     cb();
98819                     });
98820                 };
98821
98822                 var loadStores = function(cb) {
98823                     common.cascade(model.stores, function(e, cb) {
98824                         var store = new storemod.Store(self, e);
98825                         store._load(function(err) {
98826                             if ( err )
98827                             return cb(err);
98828                         self._stores[store.uri] = store;
98829                         return cb();
98830                         });
98831                     }, cb);
98832                 };
98833
98834                 loadDevInfo(function(err) {
98835                     if ( err )
98836                     return cb(err);
98837                 loadStores(cb);
98838                 });
98839             },
98840
98841             //-------------------------------------------------------------------------
98842             _updateModel: function(cb) {
98843                 var self = this;
98844                 if ( ! this._a._model || ! this._a._model.peers )
98845                     return cb(new common.InternalError('peer created on un-initialized adapter'));
98846                 var model = self._getModel();
98847                 // todo: should this be in this._getModel()?...
98848                 if ( ! model )
98849                 {
98850                     model = {
98851                         id:       self.id,
98852                         devInfo:  null,
98853                         stores:   [],
98854                         routes:   []
98855                     };
98856                     self._a._model.peers.push(model);
98857                 }
98858
98859                 model.isLocal         = 0;
98860                 model.url             = self.url;
98861                 model.devID           = self.devID;
98862                 model.displayName     = self.displayName;
98863                 model.auth            = self.auth;
98864                 model.username        = self.username;
98865                 model.password        = self.password;
98866                 model.lastSessionID   = self.lastSessionID
98867                     model.maxMsgSize      = self.maxMsgSize;
98868                 model.maxObjSize      = self.maxObjSize;
98869
98870                 common.cascade([
98871
98872                         // update the devInfo model
98873                         function(cb) {
98874                             if ( ! self.devInfo )
98875                     return cb();
98876                 return self.devInfo._updateModel(cb);
98877                         },
98878
98879                         // update the stores model
98880                         function(cb) {
98881                             // TODO: this should really be the responsibility of the Store class...
98882                             // NOTE: since bindings are not stored in Store, they need to be saved
98883                             //       and re-applied.
98884                             // TODO: or, perhaps better, i should purge all unwanted stores
98885                             //       instead of doing this brute-force method...
98886                             var bindings = _.object(_.map(model.stores, function(store) {
98887                                 return [store.uri, store.binding];
98888                             }));
98889                             model.stores = [];
98890                             common.cascade(_.values(self._stores), function(store, cb) {
98891                                 store._updateModel(cb);
98892                             }, function(err) {
98893                                 if ( err )
98894                                 return cb(err);
98895                             _.each(bindings, function(binding, uri) {
98896                                 var store = _.find(model.stores, function(s) { return s.uri == uri; });
98897                                 if ( ! store )
98898                                 return;
98899                             store.binding = binding;
98900                             });
98901                             return cb();
98902                             });
98903                         },
98904
98905                         ], cb);
98906
98907             },
98908
98909             //-------------------------------------------------------------------------
98910             _getModel: function() {
98911                 return _.find(this._a._model.peers,
98912                         function(e) { return e.id == this.id; }, this);
98913             },
98914
98915             //-------------------------------------------------------------------------
98916             _setRemoteInfo: function(devInfo, stores, cb) {
98917                 var self      = this;
98918                 self._model   = self._getModel();
98919                 devInfo._a    = self;
98920                 self.devInfo  = devInfo;
98921                 self.devInfo._updateModel(function(err) {
98922                     if ( err )
98923                     return cb(err);
98924                 // merge the new datastore info with any pre-existing store bindings
98925                 // step 1: prepare the new stores (clean up the URIs)
98926                 var lut = _.object(_.map(stores, function(store) {
98927                     store.uri = self.normUri(store.uri);
98928                     return [store.uri, store];
98929                 }));
98930                 // step 2: remove all stores that are no longer mentioned
98931                 self._stores = _.object(
98932                     _.map(
98933                         _.filter(_.keys(self._stores), function(oldUri) {
98934                             return _.indexOf(_.keys(lut), oldUri) >= 0;
98935                         }), function(uri) {
98936                             return [uri, self._stores[uri]];
98937                         }
98938                         )
98939                     );
98940                 // step 3: merge the datastore info for existing stores
98941                 var merge_stores = function(cb) {
98942                     common.cascade(_.values(self._stores), function(store, cb) {
98943                         store.merge(lut[store.uri], function(err) {
98944                             if ( err )
98945                             return cb(err);
98946                         delete lut[store.uri];
98947                         return cb();
98948                         });
98949                     }, cb);
98950                 };
98951                 // step 4: add new datastores
98952                 var add_stores = function(cb) {
98953                     common.cascade(_.values(lut), function(store, cb) {
98954                         self.addStore(store, cb);
98955                     }, cb);
98956                 };
98957                 merge_stores(function(err) {
98958                     if ( err )
98959                     return cb(err);
98960                 add_stores(cb);
98961                 });
98962                 });
98963             },
98964
98965             //-------------------------------------------------------------------------
98966             setRoute: function(localUri, remoteUri, autoMapped, cb) {
98967                 if ( _.isFunction(autoMapped) )
98968                     // defaulting 'autoMapped' to false
98969                     return this.setRoute(localUri, remoteUri, false, autoMapped);
98970                 var pmodel = this._getModel();
98971                 if ( ! pmodel )
98972                     return cb(new common.InternalError('could not locate this peer in local adapter'));
98973                 pmodel.routes = _.filter(pmodel.routes, function(r) {
98974                     return r.localUri != localUri && r.remoteUri != remoteUri;
98975                 });
98976                 pmodel.routes.push({localUri   : localUri,
98977                     remoteUri  : remoteUri,
98978                     autoMapped : autoMapped
98979                 });
98980                 // now search through previous bindings, breaking incorrect ones...
98981                 // NOTE: this requires that a router.recalculate() is called at
98982                 //       some point later since other valid bindings may now be
98983                 //       possible...
98984                 _.each(pmodel.stores, function(store) {
98985                     if ( store.uri != remoteUri
98986                         && ( ! store.binding || store.binding.uri != localUri ) )
98987                     {
98988                         return;
98989                     }
98990                     if ( ! store.binding )
98991                 {
98992                     store.binding = {
98993                         uri          : localUri,
98994                     autoMapped   : autoMapped,
98995                     localAnchor  : null,
98996                     remoteAnchor : null
98997                     };
98998                     return;
98999                 }
99000                 if ( store.uri == remoteUri && store.binding.uri == localUri )
99001                 {
99002                     store.binding.autoMapped = store.binding.autoMapped && autoMapped;
99003                     return;
99004                 }
99005                 store.binding = null;
99006                 return;
99007                 });
99008                 // TODO: this additional route may impact "smart routing" - recalculate?...
99009                 // TODO: saving adapter from peer --- SHOULD IT BE DOING THIS?...
99010                 // TODO: get transaction from a session!...
99011                 this._a._save(this._c._txn(), cb);
99012             },
99013
99014             //-------------------------------------------------------------------------
99015             sendRequest: function(session, contentType, data, cb) {
99016                 var xmlhttp;
99017
99018                 // TODO: shouldn't proxies just overwrite .sendRequest() ?...
99019                 if ( this._proxy )
99020                     return this._proxy.sendRequest(session, contentType, data, cb);
99021
99022                 var req = {
99023                     url     : session.info.respUri || this.url,
99024                     method  : 'POST',
99025                     headers : {'Content-Type': contentType},
99026                     body    : data
99027                 };
99028
99029                 xmlhttp = new XMLHttpRequest();
99030                 xmlhttp.open(req.method, req.url, false);
99031
99032                 xmlhttp.setRequestHeader("Content-Type", contentType);
99033                 xmlhttp.send(req.body);
99034
99035                 var response = {
99036                     headers: {
99037                         "Content-Type": xmlhttp.getResponseHeader("content-type")
99038                     },
99039                     body: xmlhttp.responseXML
99040                 };
99041                 return cb(null, response);
99042             }
99043
99044     });
99045
99046     return exports;
99047
99048 })();
99049
99050 module.exports = _self;
99051
99052 });
99053 define('ripple/platform/tizen/2.0/syncml-js-lib/router', function (require, exports, module) {
99054 // -*- coding: utf-8 -*-
99055 //-----------------------------------------------------------------------------
99056 // file: $Id$
99057 // lib:  syncml-js.router
99058 // auth: griffin <griffin@uberdev.org>
99059 // date: 2012/11/04
99060 // copy: (C) CopyLoose 2012 UberDev <hardcore@uberdev.org>, No Rights Reserved.
99061 //-----------------------------------------------------------------------------
99062
99063 var common = require('ripple/platform/tizen/2.0/syncml-js-lib/common'),
99064     constant = require('ripple/platform/tizen/2.0/syncml-js-lib/constant'),
99065     ctype = require('ripple/platform/tizen/2.0/syncml-js-lib/ctype'),
99066     matcher = require('ripple/platform/tizen/2.0/syncml-js-lib/matcher'),
99067     stablematch = require('ripple/platform/tizen/2.0/syncml-js-lib/stablematch'),
99068     _self;
99069
99070 _self = (function () {
99071
99072     var exports = {};
99073
99074     //---------------------------------------------------------------------------
99075     exports.Router = common.Base.extend({
99076
99077         //-------------------------------------------------------------------------
99078         constructor: function(options) {
99079         },
99080
99081         //-------------------------------------------------------------------------
99082         getTargetUri: function(adapter, peer, sourceUri) {
99083             var pmodel = peer._getModel();
99084             for ( var idx=0 ; idx<pmodel.routes.length ; idx++ )
99085     {
99086         var route = pmodel.routes[idx];
99087         if ( route.localUri == sourceUri )
99088         return route.remoteUri;
99089     }
99090     for ( var idx=0 ; idx<pmodel.stores.length ; idx++ )
99091     {
99092         var store = pmodel.stores[idx];
99093         if ( store.binding && store.binding.uri == sourceUri )
99094         return store.uri;
99095     }
99096     return null;
99097         },
99098
99099         //-------------------------------------------------------------------------
99100         recalculate: function(adapter, peer, cb) {
99101             // the non-"SmartRouter" only connects manually-configured routes...
99102             var routes = _.filter(peer._getModel().routes,
99103                     function(r) { return ! r.autoMapped; });
99104             return this._setupRoutes(adapter, peer, routes, cb);
99105         },
99106
99107         //-------------------------------------------------------------------------
99108         _setupRoutes: function(adapter, peer, routes, cb) {
99109             // available local URIs
99110             var lset = _.map(adapter._getModel().stores,
99111                     function(s) { return adapter.normUri(s.uri); });
99112             // available remote URIs
99113             var rset = _.map(peer._getModel().stores,
99114                     function(s) { return peer.normUri(s.uri); });
99115
99116             // break all routes not listed
99117             var ruris = _.map(routes, function(r) { return r.remoteUri; });
99118             var xrset = _.filter(rset, function(uri) {
99119                 return _.indexOf(ruris, uri) < 0;
99120             });
99121             _.each(xrset, function(uri) {
99122                 var smodel = peer.getStore(uri)._getModel();
99123                 if ( ! smodel.binding )
99124                 return;
99125             smodel.binding = null;
99126             });
99127
99128             var err = null;
99129             _.each(routes, function(route) {
99130                 if ( err )
99131                 return;
99132
99133             route.localUri  = adapter.normUri(route.localUri);
99134             route.remoteUri = peer.normUri(route.remoteUri);
99135             if ( _.indexOf(rset, route.remoteUri) < 0
99136                 || _.indexOf(lset, route.localUri) < 0 )
99137             {
99138                 err = 'unable to route from "' + route.localUri
99139                 + '" (here) to "' + route.remoteUri
99140                 + '" (peer): no such stores or already routed elsewhere';
99141             return;
99142             }
99143
99144             lset = _.filter(lset, function(uri) { return uri != route.localUri; });
99145             rset = _.filter(rset, function(uri) { return uri != route.remoteUri; });
99146
99147
99148             var smodel = peer.getStore(route.remoteUri)._getModel();
99149             if ( smodel.binding && smodel.binding.uri == route.localUri )
99150                 return;
99151             smodel.binding = {
99152                 uri          : route.localUri,
99153                 autoMapped   : route.autoMapped,
99154                 localAnchor  : null,
99155                 remoteAnchor : null
99156             };
99157             });
99158
99159             if ( err )
99160                 return cb(err);
99161
99162             return cb();
99163         },
99164
99165         //-------------------------------------------------------------------------
99166         getBestTransmitContentType: function(adapter, peer, uri) {
99167             var lstore = adapter.getStore(uri);
99168             var rstore = peer.getStore(this.getTargetUri(adapter, peer, uri));
99169             return matcher.pickTransmitContentType(lstore, rstore);
99170         },
99171
99172     });
99173
99174     //---------------------------------------------------------------------------
99175     exports.SmartRouter = exports.Router.extend({
99176
99177         //-------------------------------------------------------------------------
99178         recalculate: function(adapter, peer, cb) {
99179
99180             // note: if you don't want smart routing, assign the non-SmartRouter
99181             //       router (i.e. syncml-js.Router) to the loaded context
99182
99183             // available local URIs
99184             var llut = _.object(
99185                 _.map(adapter._getModel().stores,
99186                     function(s) { return [adapter.normUri(s.uri), s]; }));
99187             var lset = _.keys(llut);
99188
99189             // available remote URIs
99190             var rlut = _.object(
99191                 _.map(peer._getModel().stores,
99192                     function(s) { return [adapter.normUri(s.uri), s]; }));
99193             var rset = _.keys(rlut);
99194
99195             // TODO: i am directly touching the model here.
99196             //       total i-rep violation.
99197             //       i'm embarrassed.
99198             //       fortunately, it's just between syncml-js classes...
99199             //       but now you know, doh! please don't blackmail me!... ;-)
99200
99201             // manual routes
99202             var pmodel = peer._getModel();
99203             pmodel.routes = _.filter(pmodel.routes,
99204                     function(r) { return ! r.autoMapped; });
99205
99206             // remove manual routes from available routes
99207             var uris = _.map(pmodel.routes, function(r) { return r.localUri; });
99208             lset = _.filter(lset, function(uri) {
99209                 return _.indexOf(uris, uri) < 0;
99210             });
99211             uris = _.map(pmodel.routes, function(r) { return r.remoteUri; });
99212             rset = _.filter(rset, function(uri) {
99213                 return _.indexOf(uris, uri) < 0;
99214             });
99215
99216             // match remaining stores
99217             var rankL = function(luri) {
99218                 var ret = _.rest(rset, 0);
99219                 ret.sort(function(a, b) {
99220                     return matcher.cmpStore(llut[luri], rlut[a], rlut[b]);
99221                 });
99222                 return ret;
99223             };
99224             var rankR = function(ruri) {
99225                 var ret = _.rest(lset, 0);
99226                 ret.sort(function(a, b) {
99227                     return matcher.cmpStore(rlut[ruri], llut[a], llut[b]);
99228                 });
99229                 return ret;
99230             };
99231             var matches = stablematch.match(lset, rset, rankL, rankR);
99232
99233             // add them to the routes (as auto-routed)
99234             for ( var idx=0 ; idx<matches.length ; idx++ )
99235             {
99236                 var pair = matches[idx];
99237                 pmodel.routes.push({
99238                     localUri   : pair[0],
99239                     remoteUri  : pair[1],
99240                     autoMapped : true
99241                 });
99242             }
99243
99244             return this._setupRoutes(adapter, peer, pmodel.routes, cb);
99245         },
99246
99247     });
99248
99249     return exports;
99250
99251 })();
99252
99253 module.exports = _self;
99254
99255 });
99256 define('ripple/platform/tizen/2.0/syncml-js-lib/stablematch', function (require, exports, module) {
99257 // -*- coding: utf-8 -*-
99258 //-----------------------------------------------------------------------------
99259 // file: $Id$
99260 // desc: implements a solution to the stable matching problem using a
99261 //       left-optimized algorithm. shamelessly adapted from:
99262 //         https://github.com/paulgb/Python-Gale-Shapley/
99263 // auth: metagriffin <mg.npmjs@uberdev.org>
99264 // date: 2012/12/29
99265 // copy: (C) CopyLoose 2012 UberDev <hardcore@uberdev.org>, No Rights Reserved.
99266 //-----------------------------------------------------------------------------
99267
99268 var _self = (function () {
99269
99270     var exports = {};
99271
99272     // TODO: figure out how to pull this dynamically from package.json...
99273     exports.version = '0.0.4';
99274
99275     //---------------------------------------------------------------------------
99276     exports.match = function(A, B, rankA, rankB) {
99277         if ( ! A || ! B || ! A.length || ! B.length ) {
99278             return [];
99279         }
99280         if ( A.length == B.length ) {
99281             return exports._match(A, B, rankA, rankB);
99282         }
99283
99284         // TODO: this is a brute-force implementation of getting both
99285         //       lists to be of symmetric length... make this "better".
99286         //       for example, build this directly into _match() or use
99287         //       deterministic exclusion of the longer data set.
99288
99289         var sA   = _.rest(A, 0);
99290         var sB   = _.rest(B, 0);
99291         var mlen = Math.max(sA, sB);
99292         while ( sA.length < mlen )
99293             sA.push(null);
99294         while ( sB.length < mlen )
99295             sB.push(null);
99296         var sRA  = function(a) {
99297             var ret = rankA(a);
99298             while ( ret.length < mlen )
99299                 ret.push(null);
99300             return ret;
99301         };
99302         var sRB  = function(b) {
99303             var ret = rankB(b);
99304             while ( ret.length < mlen )
99305                 ret.push(null);
99306             return ret;
99307         };
99308         var ret = exports._match(sA, sB, sRA, sRB);
99309         return _.filter(ret, function(pair) {
99310             return pair[0] != null && pair[1] != null;
99311         });
99312     };
99313
99314     //---------------------------------------------------------------------------
99315     exports._match = function(A, B, rankA, rankB) {
99316         // this translates sets A and B to indeces, since _imatch can only work
99317         // with sets of elements that can be used as the key in a hash (in this
99318         // implementation).
99319         var iA  = _.range(A.length);
99320         var iB  = _.range(B.length);
99321         var iRA = function(ia) {
99322             var ret = rankA(A[ia]);
99323             return _.map(ret, function(item) {
99324                 return _.indexOf(B, item);
99325             });
99326         };
99327         var iRB = function(ib) {
99328             var ret = rankB(B[ib]);
99329             return _.map(ret, function(item) {
99330                 return _.indexOf(A, item);
99331             });
99332         };
99333         var ret = exports._imatch(iA, iB, iRA, iRB);
99334         return _.map(ret, function(item) {
99335             return [A[item[0]], B[item[1]]];
99336         });
99337     };
99338
99339     //---------------------------------------------------------------------------
99340     exports._imatch = function(A, B, rankA, rankB) {
99341         // TODO: improve this... it was a brute-force porting of
99342         //         https://github.com/paulgb/Python-Gale-Shapley
99343         //       without any eye on optimal outcome or performance...
99344         //: `partners` is a paring hash of { a => [b, rank] }
99345         var partners = {};
99346         _.each(A, function(a) {
99347             partners[a] = [rankA(a)[0], 0];
99348         });
99349         //: `stable` indicates stability of the current pairing in `partners`
99350         var stable = false;
99351         while ( ! stable )
99352         {
99353             stable = true;
99354             _.each(B, function(b) {
99355                 var paired = false;
99356                 for ( var n=0 ; n<A.length ; n++ )
99357                 {
99358                     var a = rankB(b)[n];
99359                     var pair = partners[a];
99360                     if ( pair[0] == b )
99361                     {
99362                         if ( paired )
99363                         {
99364                             stable = false;
99365                             partners[a] = [rankA(a)[pair[1] + 1], pair[1] + 1];
99366                         }
99367                         else
99368                             paired = true;
99369                     }
99370                 }
99371             });
99372         }
99373         return _.map(_.keys(partners), function(a) {
99374             return [a, partners[a][0]];
99375         });
99376     };
99377
99378     return exports;
99379 })();
99380
99381 module.exports = _self;
99382
99383 });
99384 define('ripple/platform/tizen/2.0/syncml-js-lib/state', function (require, exports, module) {
99385 // -*- coding: utf-8 -*-
99386 //-----------------------------------------------------------------------------
99387 // file: $Id$
99388 // auth: metagriffin <metagriffin@uberdev.org>
99389 // date: 2012/10/27
99390 // copy: (C) CopyLoose 2012 UberDev <hardcore@uberdev.org>, No Rights Reserved.
99391 //-----------------------------------------------------------------------------
99392
99393 var common = require('ripple/platform/tizen/2.0/syncml-js-lib/common'),
99394     constant = require('ripple/platform/tizen/2.0/syncml-js-lib/constant'),
99395     _self;
99396
99397 _self = (function () {
99398     var exports = {};
99399
99400     //---------------------------------------------------------------------------
99401     exports.makeCommand = function(options) {
99402         return _.defaults({}, options, {
99403             // ?
99404         });
99405     };
99406
99407     //---------------------------------------------------------------------------
99408     exports.makeStats = function(options) {
99409         return _.defaults({}, options, {
99410             mode      : null,
99411                hereAdd   : 0,
99412                hereMod   : 0,
99413                hereDel   : 0,
99414                hereErr   : 0,
99415                peerAdd   : 0,
99416                peerMod   : 0,
99417                peerDel   : 0,
99418                peerErr   : 0,
99419                conflicts : 0,
99420                merged    : 0,
99421         });
99422     };
99423
99424     //---------------------------------------------------------------------------
99425     exports.makeSessionInfo = function(options) {
99426         return _.defaults({}, options, {
99427             id           : null,
99428                msgID        : null,
99429                cmdID        : 0,
99430                dsstates     : {},
99431                lastCommands : [],
99432                stats        : exports.makeStats()
99433         });
99434     };
99435
99436     //---------------------------------------------------------------------------
99437     exports.makeStoreSyncState = function(options) {
99438         return _.defaults({}, options, {
99439             uri        : null,
99440                peerUri    : null,
99441                lastAnchor : null,
99442                nextAnchor : '' + common.ts(),
99443                mode       : constant.ALERT_TWO_WAY,
99444                action     : null,
99445                stats      : exports.makeStats()
99446         });
99447     };
99448
99449     //---------------------------------------------------------------------------
99450     exports.makeSession = function(options) {
99451         return new (function() {
99452             this.context   = options.context || null;
99453             this.ua        = options.ua      || null;
99454             this.txn       = options.txn     || options.context.txn;
99455             this.adapter   = options.adapter || null;
99456             this.peer      = options.peer    || null;
99457             this.info      = options.info    || null;
99458             this.discover  = options.discover ? true : false;
99459             this.isServer  = options.isServer ? true : false;
99460             this.nextCmdID = function() {
99461                 this.info.cmdID += 1;
99462                 return this.info.cmdID;
99463             };
99464         })();
99465
99466         // return _.defaults({}, options, {
99467         //   context : null,
99468         //   adapter : null,
99469         //   peer    : null,
99470         //   info    : null
99471         // });
99472     };
99473
99474     var smult = function(s, count) {
99475         var ret = '';
99476         for ( var idx=0 ; idx<count ; idx++ )
99477             ret += s;
99478         return ret;
99479     };
99480
99481     var num2str = function(num) {
99482         // TODO: i18n...
99483         // TODO: this is *UGLY*
99484         // TODO: OMG, i'm *so* embarrassed
99485         // TODO: but it works... sort of.
99486         if ( num == 0 )
99487             return '-';
99488         var ret = '';
99489         num = '' + num;
99490         for ( var idx=num.length ; idx>0 ; idx-=3 )
99491         {
99492             if ( ret.length > 0 )
99493                 ret = ',' + ret;
99494             ret = num.charAt(idx - 1) + ret;
99495             if ( idx - 1 > 0 )
99496                 ret = num.charAt(idx - 2) + ret;
99497             if ( idx - 2 > 0 )
99498                 ret = num.charAt(idx - 3) + ret;
99499         }
99500         return ret;
99501     };
99502
99503     var center = function(s, wid, pad) {
99504         // todo: is there no way to get sprintf to do this for me???...
99505         pad = pad || ' ';
99506         if ( wid <= s.length )
99507             return s;
99508         var diff = wid - s.length;
99509         return smult(pad, Math.floor(diff / 2)) + s + smult(pad, Math.ceil(diff / 2));
99510     };
99511
99512     var right = function(s, wid, pad) {
99513         // todo: is there no way to get sprintf to do this for me???...
99514         pad = pad || ' ';
99515         if ( wid <= s.length )
99516             return s;
99517         return smult(pad, wid - s.length) + s;
99518     };
99519
99520     //---------------------------------------------------------------------------
99521     // TODO: this should probably be put into another package...
99522     exports.describeStats = function(stats, stream, options) {
99523
99524         // ASCII OBJECTIVE:
99525         // +----------------------------------------------------------------------------------+
99526         // |                                      TITLE                                       |
99527         // +----------+------+-------------------------+--------------------------+-----------+
99528         // |          |      |          Local          |          Remote          | Conflicts |
99529         // |   Source | Mode |  Add  | Mod | Del | Err |   Add  | Mod | Del | Err | Col | Mrg |
99530         // +----------+------+-------+-----+-----+-----+--------+-----+-----+-----+-----+-----+
99531         // | contacts |  <=  |   -   |  -  |  -  |  -  | 10,387 |  -  |  -  |  -  |  -  |  -  |
99532         // |     note |  SS  | 1,308 |  -  |   2 |  -  |    -   |  -  |  -  |  -  |  -  |  -  |
99533         // +----------+------+-------+-----+-----+-----+--------+-----+-----+-----+-----+-----+
99534         // |                  1,310 local changes and 10,387 remote changes.                  |
99535         // +----------------------------------------------------------------------------------+
99536
99537         // UNICODE OBJECTIVE:
99538         // ┌──────────────────────────────────────────────────────────────────────────────────┐
99539         // │                                      TITLE                                       │
99540         // ├──────────┬──────┬─────────────────────────┬──────────────────────────┬───────────┤
99541         // │          │      │          Local          │          Remote          │ Conflicts │
99542         // │   Source │ Mode │  Add    Mod   Del   Err │   Add    Mod   Del   Err │ Col   Mrg │
99543         // ├──────────┼──────┼───────┼─────┼─────┼─────┼────────┼─────┼─────┼─────┼─────┼─────┤
99544         // │ contacts │  <=  │       │     │     │     │ 10,387 │     │     │     │     │     │
99545         // │     note │  SS  │ 1,308 │     │   2 │     │        │     │     │     │     │     │
99546         // ├──────────┴──────┴───────┴─────┴─────┴─────┴────────┴─────┴─────┴─────┴─────┴─────┤
99547         // │                  1,310 local changes and 10,387 remote changes.                  │
99548         // └──────────────────────────────────────────────────────────────────────────────────┘
99549
99550         // todo: perhaps the fancy version should have color-coding as well?...
99551
99552         options = _.defaults({}, options, {
99553             title      : null,
99554                 details    : true,
99555                 totals     : true,
99556                 ascii      : false,
99557                 gettext    : function(text) { return text; }
99558         });
99559
99560         var modeStringLut = _.object([
99561                 [constant.SYNCTYPE_TWO_WAY             , '<>'],
99562                 [constant.SYNCTYPE_SLOW_SYNC           , 'SS'],
99563                 [constant.SYNCTYPE_ONE_WAY_FROM_CLIENT , '->'],
99564                 [constant.SYNCTYPE_REFRESH_FROM_CLIENT , '=>'],
99565                 [constant.SYNCTYPE_ONE_WAY_FROM_SERVER , '<-'],
99566                 [constant.SYNCTYPE_REFRESH_FROM_SERVER , '<=']
99567                 ]);
99568
99569         if ( options.ascii )
99570         {
99571
99572             // unicode graphing characters: ('\xe2\x94\x80' - '\xe2\x94\xc0')
99573             // mapping table unicode ==> ascii
99574
99575             glyphs = {
99576                 '─': '-',
99577                 '━': '-',
99578                 '│': '|',
99579                 '┃': '|',
99580                 '┄': '-',
99581                 '┅': '-',
99582                 '┆': '|',
99583                 '┇': '|',
99584                 '┈': '-',
99585                 '┉': '-',
99586                 '┊': '|',
99587                 '┋': '|',
99588                 '┌': '+',
99589                 '┍': '+',
99590                 '┎': '+',
99591                 '┏': '+',
99592                 '┐': '+',
99593                 '┑': '+',
99594                 '┒': '+',
99595                 '┓': '+',
99596                 '└': '+',
99597                 '┕': '+',
99598                 '┖': '+',
99599                 '┗': '+',
99600                 '┘': '+',
99601                 '┙': '+',
99602                 '┚': '+',
99603                 '┛': '+',
99604                 '├': '+',
99605                 '┝': '+',
99606                 '┞': '+',
99607                 '┟': '+',
99608                 '┠': '+',
99609                 '┡': '+',
99610                 '┢': '+',
99611                 '┣': '+',
99612                 '┤': '+',
99613                 '┥': '+',
99614                 '┦': '+',
99615                 '┧': '+',
99616                 '┨': '+',
99617                 '┩': '+',
99618                 '┪': '+',
99619                 '┫': '+',
99620                 '┬': '+',
99621                 '┭': '+',
99622                 '┮': '+',
99623                 '┯': '+',
99624                 '┰': '+',
99625                 '┱': '+',
99626                 '┲': '+',
99627                 '┳': '+',
99628                 '┴': '+',
99629                 '┵': '+',
99630                 '┶': '+',
99631                 '┷': '+',
99632                 '┸': '+',
99633                 '┹': '+',
99634                 '┺': '+',
99635                 '┻': '+',
99636                 '┼': '+',
99637                 '┽': '+',
99638                 '┾': '+',
99639                 '┿': '+',
99640             };
99641
99642             var UnicodeToAsciiStream = common.Stream.extend({
99643                 constructor: function(stream) {
99644                     this.stream = stream;
99645                 },
99646                 write: function(data) {
99647                     if ( data == undefined )
99648                 return;
99649             var ascii = '';
99650             for ( var idx=0 ; idx<data.length ; idx++ )
99651             {
99652                 var el = data[idx];
99653                 if ( glyphs[el] != undefined )
99654                 ascii += glyphs[el];
99655                 else
99656                 ascii += el;
99657             }
99658             this.stream.write(ascii);
99659                 }
99660             });
99661
99662             stream = new UnicodeToAsciiStream(stream);
99663
99664         }
99665
99666         // todo: this does not handle the case where the title is wider than the table.
99667
99668         var wSrc  = options.gettext('Source').length;
99669         var wMode = options.gettext('Mode').length;
99670         var wCon  = options.gettext('Conflicts').length;
99671         var wCol  = options.gettext('Col').length;
99672         var wMrg  = options.gettext('Mrg').length;
99673         var wHereAdd = wPeerAdd = options.gettext('Add').length;
99674         var wHereMod = wPeerMod = options.gettext('Mod').length;
99675         var wHereDel = wPeerDel = options.gettext('Del').length;
99676         var wHereErr = wPeerErr = options.gettext('Err').length
99677
99678             var totLoc = 0;
99679         var totRem = 0;
99680         var totErr = 0;
99681         var totCol = 0;
99682         var totMrg = 0;
99683
99684         _.each(stats, function(value, key) {
99685             wSrc  = Math.max(wSrc, key.length);
99686             wMode = Math.max(wMode, modeStringLut[value.mode].length);
99687             wCol  = Math.max(wCol, num2str(value.conflicts).length);
99688             wMrg  = Math.max(wMrg, num2str(value.merged).length);
99689             wHereAdd = Math.max(wHereAdd, num2str(value.hereAdd).length);
99690             wPeerAdd = Math.max(wPeerAdd, num2str(value.peerAdd).length);
99691             wHereMod = Math.max(wHereMod, num2str(value.hereMod).length);
99692             wPeerMod = Math.max(wPeerMod, num2str(value.peerMod).length);
99693             wHereDel = Math.max(wHereDel, num2str(value.hereDel).length);
99694             wPeerDel = Math.max(wPeerDel, num2str(value.peerDel).length);
99695             wHereErr = Math.max(wHereErr, num2str(value.hereErr).length);
99696             wPeerErr = Math.max(wPeerErr, num2str(value.peerErr).length);
99697             totLoc += value.hereAdd + value.hereMod + value.hereDel;
99698             totRem += value.peerAdd + value.peerMod + value.peerDel;
99699             totErr += value.hereErr + value.peerErr;
99700             totCol += value.conflicts;
99701             totMrg += value.merged;
99702         });
99703
99704         // TODO: i'm 100% sure there is a python library that can do this for me...
99705
99706         if ( wCon > wCol + 3 + wMrg )
99707         {
99708             diff = wCon - ( wCol + 3 + wMrg );
99709             wCol += diff / 2;
99710             wMrg = wCon - 3 - wCol;
99711         }
99712         else
99713             wCon = wCol + 3 + wMrg;
99714
99715         if ( options.details )
99716             tWid = ( wSrc + 3 + wMode + 3
99717                     + wHereAdd + wHereMod + wHereDel + wHereErr + 9 + 3
99718                     + wPeerAdd + wPeerMod + wPeerDel + wPeerErr + 9 + 3
99719                     + wCon );
99720         else
99721             tWid = options.title ? options.title.length : 0;
99722
99723         if ( options.totals )
99724         {
99725             // TODO: oh dear. from an i18n POV, this is *horrible*!...
99726             sumlist = [];
99727             // for val, singular, plural in [
99728             _.each([
99729                     [totLoc, options.gettext('local change'), options.gettext('local changes')],
99730                     [totRem, options.gettext('remote change'), options.gettext('remote changes')],
99731                     [totErr, options.gettext('error'), options.gettext('errors')]
99732                     ], function(set) {
99733                         if ( set[0] <= 0 )
99734                 return;
99735             sumlist.push(num2str(set[0]) + ' ' + ( set[0] == 1 ? set[1] : set[2] ));
99736                     });
99737             if ( sumlist.length <= 0 )
99738                 sumlist = options.gettext('No changes');
99739             else if ( sumlist.length == 1 )
99740                 sumlist = sumlist[0];
99741             else
99742                 sumlist = ( sumlist.slice(0, -1).join(', ') + ' '
99743                         + options.gettext('and') + ' ' + sumlist[sumlist.length - 1] );
99744             if ( totMrg > 0 || totCol > 0 )
99745             {
99746                 sumlist += ': ';
99747                 if ( totMrg == 1 )
99748                     sumlist += num2str(totMrg) + ' ' + options.gettext('merge');
99749                 else if ( totMrg > 1 )
99750                     sumlist += num2str(totMrg) + ' ' + options.gettext('merges');
99751                 if ( totMrg > 0 && totCol > 0 )
99752                     sumlist += ' ' + options.gettext('and') + ' ';
99753                 if ( totCol == 1 )
99754                     sumlist += num2str(totCol) + ' ' + options.gettext('conflict');
99755                 else if ( totCol > 1 )
99756                     sumlist += num2str(totCol) + ' ' + options.gettext('conflicts');
99757             }
99758             sumlist += '.';
99759             if ( sumlist.length > tWid )
99760             {
99761                 wSrc += sumlist.length - tWid;
99762                 tWid = sumlist.length;
99763             }
99764         }
99765
99766         if ( options.title )
99767         {
99768             stream.write('┏━' + smult('━', tWid) + '━┓\n');
99769             stream.write('┃ ' + center(options.title, tWid) + ' ┃\n');
99770         }
99771
99772         if ( options.details )
99773         {
99774             if ( options.title )
99775                 stream.write('┡━'
99776                         + smult('━', wSrc)
99777                         + '━┯━'
99778                         + smult('━', wMode)
99779                         + '━┯━'
99780                         + smult('━', ( wHereAdd + wHereMod + wHereDel + wHereErr + 9 ))
99781                         + '━┯━'
99782                         + smult('━', ( wPeerAdd + wPeerMod + wPeerDel + wPeerErr + 9 ))
99783                         + '━┯━'
99784                         + smult('━', wCon)
99785                         + '━┩\n'
99786                         );
99787             else
99788                 stream.write('┌─'
99789                         + smult('─', wSrc)
99790                         + '─┬─'
99791                         + smult('─', wMode)
99792                         + '─┬─'
99793                         + smult('─', ( wHereAdd + wHereMod + wHereDel + wHereErr + 9 ))
99794                         + '─┬─'
99795                         + smult('─', ( wPeerAdd + wPeerMod + wPeerDel + wPeerErr + 9 ))
99796                         + '─┬─'
99797                         + smult('─', wCon)
99798                         + '─┐\n'
99799                         );
99800
99801             stream.write('│ ' + smult(' ', wSrc));
99802             stream.write(' │ ' + smult(' ', wMode));
99803             stream.write(' │ ' + center(options.gettext('Local'), wHereAdd + wHereMod + wHereDel + wHereErr + 9 ));
99804             stream.write(' │ ' + center(options.gettext('Remote'), wPeerAdd + wPeerMod + wPeerDel + wPeerErr + 9 ));
99805             stream.write(' │ ' + center(options.gettext('Conflicts'), wCon));
99806             stream.write(' │\n');
99807
99808             stream.write('│ ' + right(options.gettext('Source'), wSrc));
99809             stream.write(' │ ' + center(options.gettext('Mode'), wMode));
99810             stream.write(' │ ' + center(options.gettext('Add'), wHereAdd));
99811             stream.write(( options.ascii ? ' │ ' : '   ' ) + center(options.gettext('Mod'), wHereMod));
99812             stream.write(( options.ascii ? ' │ ' : '   ' ) + center(options.gettext('Del'), wHereDel));
99813             stream.write(( options.ascii ? ' │ ' : '   ' ) + center(options.gettext('Err'), wHereErr));
99814             stream.write(' │ ' + center(options.gettext('Add'), wPeerAdd));
99815             stream.write(( options.ascii ? ' │ ' : '   ' ) + center(options.gettext('Mod'), wPeerMod));
99816             stream.write(( options.ascii ? ' │ ' : '   ' ) + center(options.gettext('Del'), wPeerDel));
99817             stream.write(( options.ascii ? ' │ ' : '   ' ) + center(options.gettext('Err'), wPeerErr));
99818             stream.write(' │ ' + center(options.gettext('Col'), wCol));
99819             stream.write(( options.ascii ? ' │ ' : '   ' ) + center(options.gettext('Mrg'), wMrg));
99820             stream.write(' │\n');
99821
99822             stream.write('├─' + smult('─', wSrc)
99823                     + '─┼─' + smult('─', wMode)
99824                     + '─┼─' + smult('─', wHereAdd)
99825                     + '─┼─' + smult('─', wHereMod)
99826                     + '─┼─' + smult('─', wHereDel)
99827                     + '─┼─' + smult('─', wHereErr)
99828                     + '─┼─' + smult('─', wPeerAdd)
99829                     + '─┼─' + smult('─', wPeerMod)
99830                     + '─┼─' + smult('─', wPeerDel)
99831                     + '─┼─' + smult('─', wPeerErr)
99832                     + '─┼─' + smult('─', wCol)
99833                     + '─┼─' + smult('─', wMrg)
99834                     + '─┤\n'
99835                     );
99836
99837             var numcol = function(val, wid) {
99838                 if ( val == 0 )
99839                     return ' │ ' + center(options.ascii ? '-' : ' ', wid);
99840                 return ' │ ' + right(num2str(val), wid);
99841             };
99842
99843             var keys = _.keys(stats);
99844             // todo: sort case insensitively...
99845             keys.sort();
99846             _.each(keys, function(key) {
99847                 var stat = stats[key];
99848                 stream.write('│ ' + right(key, wSrc));
99849                 stream.write(' │ ' + center(modeStringLut[stat.mode], wMode));
99850                 stream.write(numcol(stat.hereAdd, wHereAdd));
99851                 stream.write(numcol(stat.hereMod, wHereMod));
99852                 stream.write(numcol(stat.hereDel, wHereDel));
99853                 stream.write(numcol(stat.hereErr, wHereErr));
99854                 stream.write(numcol(stat.peerAdd, wPeerAdd));
99855                 stream.write(numcol(stat.peerMod, wPeerMod));
99856                 stream.write(numcol(stat.peerDel, wPeerDel));
99857                 stream.write(numcol(stat.peerErr, wPeerErr));
99858                 stream.write(numcol(stat.conflicts, wCol));
99859                 stream.write(numcol(stat.merged, wMrg));
99860                 stream.write(' │\n');
99861             });
99862
99863             if ( options.totals )
99864                 stream.write('├─');
99865             else
99866                 stream.write('└─');
99867
99868             stream.write(smult('─', wSrc)
99869                     + '─┴─' + smult('─', wMode)
99870                     + '─┴─' + smult('─', wHereAdd)
99871                     + '─┴─' + smult('─', wHereMod)
99872                     + '─┴─' + smult('─', wHereDel)
99873                     + '─┴─' + smult('─', wHereErr)
99874                     + '─┴─' + smult('─', wPeerAdd)
99875                     + '─┴─' + smult('─', wPeerMod)
99876                     + '─┴─' + smult('─', wPeerDel)
99877                     + '─┴─' + smult('─', wPeerErr)
99878                     + '─┴─' + smult('─', wCol)
99879                     + '─┴─' + smult('─', wMrg)
99880                     );
99881
99882             if ( options.totals )
99883                 stream.write('─┤\n');
99884             else
99885                 stream.write('─┘\n');
99886         }
99887
99888         // ─━│┃┄┅┆┇┈┉┊┋┼┽┾┿
99889         // ┌┍┎┏┐┑┒┓└┕┖┗┘┙┚┛
99890         // ├┝┞┟┠┡┢┣┤┥┦┧┨┩┪┫
99891         // ┬┭┮┯┰┱┲┳┴┵┶┷┸┹┺┻
99892
99893         if ( options.totals )
99894         {
99895             if ( !! options.title && ! options.details )
99896                 stream.write('┌─' + smult('─', tWid) + '─┐\n');
99897             stream.write('│ ' + center(sumlist, tWid));
99898             stream.write(' │\n');
99899             stream.write('└─' + smult('─', tWid) + '─┘\n');
99900         }
99901
99902         return;
99903
99904     };
99905
99906     return exports;
99907
99908 })();
99909
99910 module.exports = _self;
99911
99912 });
99913 define('ripple/platform/tizen/2.0/syncml-js-lib/storage', function (require, exports, module) {
99914 // -*- coding: utf-8 -*-
99915 //-----------------------------------------------------------------------------
99916 // file: $Id$
99917 // lib:  syncml-js.storage
99918 // auth: griffin <griffin@uberdev.org>
99919 // date: 2012/10/31
99920 // copy: (C) CopyLoose 2012 UberDev <hardcore@uberdev.org>, No Rights Reserved.
99921 //-----------------------------------------------------------------------------
99922
99923 var common = require('ripple/platform/tizen/2.0/syncml-js-lib/common'),
99924     constant = require('ripple/platform/tizen/2.0/syncml-js-lib/constant');
99925
99926 var _self = (function () {
99927
99928     var exports = {};
99929
99930     //---------------------------------------------------------------------------
99931     _.extend(exports, {
99932
99933         //-------------------------------------------------------------------------
99934         errstr: function(target) {
99935             if ( target.error && typeof(target.error.toString) == 'function' )
99936         return target.error.toString();
99937     var ret = '';
99938     var count = 0;
99939     for ( var key in target.error )
99940         count += 1;
99941     if ( count == 1 && target.error.name )
99942         ret = '' + target.error.name;
99943     else
99944     {
99945         ret = '{';
99946         for ( var key in target.error )
99947     {
99948         ret += key + ': ' + target.error[key];
99949         count -= 1;
99950         if ( count > 0 )
99951         ret += ', ';
99952     }
99953     }
99954     if ( target.errorCode )
99955     {
99956         if ( ret.length <= 0 || ret == '{}' )
99957             ret = '' + target.errorCode;
99958         else
99959             ret = '[' + target.errorCode + '] ' + ret;
99960     }
99961     if ( ret.length <= 0 || ret == '{}' )
99962         // last ditch effort...
99963         ret = common.prettyJson(target);
99964     return ret;
99965         },
99966
99967             //-------------------------------------------------------------------------
99968             openDatabase: function(context, cb) {
99969                 var dbreq = context.storage.indexedDB.open(context.dbname, 1);
99970                 dbreq.onblocked = function(event) {
99971                     cb({code: 'syncml-js.storage.OD.10',
99972                         message: 'database blocked by other process/tab/window'});
99973                 };
99974                 dbreq.onerror = function(event) {
99975                     var errmsg = exports.errstr(event.target);
99976                     cb({code: 'syncml-js.storage.OD.20',
99977                         message: 'failed to open syncml-js database: ' + errmsg});
99978                 };
99979                 dbreq.onupgradeneeded = function(event) {
99980
99981
99982                     var db = event.target.result;
99983
99984                     var adapterTable = db.createObjectStore('adapter', {keyPath: 'id'});
99985                     adapterTable.createIndex('isLocal', 'isLocal', {unique: false});
99986                     adapterTable.createIndex('devID', 'devID', {unique: true});
99987
99988                     var mappingTable = db.createObjectStore(
99989                             'mapping',
99990                             {keyPath: ['store_id', 'guid']});
99991                     mappingTable.createIndex('store_id', 'store_id', {unique: false});
99992                     // mappingTable.createIndex('guid', 'guid', {unique: false});
99993                     // mappingTable.createIndex('luid', 'luid', {unique: false});
99994
99995                     var changeTable = db.createObjectStore(
99996                             'change',
99997                             {keyPath: ['store_id', 'item_id']});
99998                     changeTable.createIndex('store_id', 'store_id', {unique: false});
99999                     // changeTable.createIndex('item_id', 'item_id', {unique: false});
100000
100001                 };
100002                 dbreq.onsuccess = function(event) {
100003                     cb(null, event.target.result);
100004                 };
100005             },
100006
100007             //-------------------------------------------------------------------------
100008             getTransaction: function(db, tables, mode) {
100009                 // NOTE: the spec says passing in null should be valid... but
100010                 //       mozilla's indexedDB seems to barf with:
100011                 //         [Exception... "The operation failed because the
100012                 //         requested database object could not be found. For
100013                 //         example, an object store did not exist but was
100014                 //         being opened."  code: "8" nsresult: "0x80660003
100015                 //         (NotFoundError)"
100016                 if ( ! tables )
100017                     tables = ['adapter','mapping','change'];
100018                 if ( ! mode )
100019                     mode = 'readwrite';
100020                 return db.transaction(tables, mode);
100021             },
100022
100023             //-------------------------------------------------------------------------
100024             dumpDatabase: function(context, cb) {
100025
100026                 var ret = {};
100027                 var txn = context._txn();
100028
100029                 var steps = [
100030                     function(cb) {
100031                         exports.getAll(context, txn.objectStore('adapter'), {}, function(err, adapters) {
100032                             ret.adapter = adapters;
100033                             return cb(err);
100034                         });
100035                     },
100036                     function(cb) {
100037                         exports.getAll(context, txn.objectStore('mapping'), {}, function(err, mappings) {
100038                             ret.mapping = mappings;
100039                             return cb(err);
100040                         });
100041                     },
100042                     function(cb) {
100043                         exports.getAll(context, txn.objectStore('change'), {}, function(err, changes) {
100044                             ret.change = changes;
100045                             return cb(err);
100046                         });
100047                     }
100048                 ];
100049
100050                 common.cascade(steps, function(step, cb) {
100051                     return step(cb);
100052                 }, function(err) {
100053                     return cb(err, ret);
100054                 });
100055             },
100056
100057             //-------------------------------------------------------------------------
100058             clearDatabase: function(context, cb) {
100059                 var dbreq = context.storage.indexedDB.open(context.dbname, 1);
100060                 dbreq.onblocked = function(event) {
100061                     cb({code: 'syncml-js.storage.CD.10',
100062                         message: 'database blocked by other process/tab/window'});
100063                 };
100064                 dbreq.onerror = function(event) {
100065                     var errmsg = exports.errstr(event.target);
100066                     cb({code: 'syncml-js.storage.CD.20',
100067                         message: 'failed to open syncml-js database: ' + errmsg});
100068                 };
100069                 dbreq.onsuccess = function(event) {
100070                     var db = event.target.result;
100071                     db.onerror = dbreq.onerror;
100072                     async.map(['adapter', 'mapping', 'change'], function(name, cb) {
100073                         cb();
100074                     }, function(err) {
100075                         if ( err )
100076                         return cb(err);
100077                     db.close();
100078                     });
100079                 };
100080             },
100081
100082             //-------------------------------------------------------------------------
100083             getAll: function(context, source, options, cb) {
100084                 // supported options:
100085                 //   - range
100086                 //   - only
100087                 options = options || {};
100088                 var range = options.range;
100089                 if ( ! range && options.only )
100090                     range = context.storage.IDBKeyRange.only(options.only);
100091                 var req = source.openCursor(range);
100092                 var ret = [];
100093                 req.onsuccess = function(event) {
100094                     var cursor = event.target.result;
100095                     if ( cursor )
100096                     {
100097                         ret.push(cursor.value);
100098                         // ret.push({key: cursor.key, value: cursor.value});
100099                         return cursor.continue();
100100                     }
100101                     cb(null, ret);
100102                 };
100103                 req.onerror = function(event) {
100104                     cb(exports.errstr(event.target));
100105                 };
100106             },
100107
100108             //-------------------------------------------------------------------------
100109             put: function(store, object, cb) {
100110                 var req = store.put(object);
100111                 req.onsuccess = function(event) { cb(); };
100112                 req.onerror = function(event) {
100113                     cb(exports.errstr(event.target));
100114                 };
100115             },
100116
100117             //-------------------------------------------------------------------------
100118             delete: function(store, objectID, cb) {
100119                 var req = store.delete(objectID);
100120                 req.onsuccess = function(event) { cb(); };
100121                 req.onerror = function(event) {
100122                     cb(exports.errstr(event.target));
100123                 };
100124             },
100125
100126             //-------------------------------------------------------------------------
100127             deleteAll: function(source, matches, cb) {
100128                 var req = source.openCursor();
100129                 req.onsuccess = function(event) {
100130                     var cursor = event.target.result;
100131                     if ( cursor )
100132                     {
100133                         for (key in matches)
100134                             if ( matches[key] != cursor.value[key] )
100135                                 return cursor.continue();
100136                         exports.delete(source, cursor.key, function(err) {
100137                             if ( err )
100138                             return cb(err);
100139                         return cursor.continue();
100140                         });
100141                         return;
100142                     }
100143                     cb(null);
100144                 };
100145                 req.onerror = function(event) {
100146                     cb(exports.errstr(event.target));
100147                 };
100148             },
100149
100150             //-------------------------------------------------------------------------
100151             iterateCursor: function(openCursor, iterator, cb) {
100152                 openCursor.onsuccess = function(event) {
100153                     var cursor = event.target.result;
100154                     if ( ! cursor )
100155                         return cb();
100156                     iterator(cursor.value.value, cursor.value.id, function(err) {
100157                         if ( err )
100158                         return cb(err);
100159                     return cursor.continue();
100160                     });
100161                 };
100162                 openCursor.onerror = function(event) {
100163                     cb(exports.errstr(event.target));
100164                 };
100165             }
100166
100167     });
100168
100169     return exports;
100170
100171 })();
100172
100173 module.exports = _self;
100174
100175 });
100176 define('ripple/platform/tizen/2.0/syncml-js-lib/store', function (require, exports, module) {
100177 // -*- coding: utf-8 -*-
100178 //-----------------------------------------------------------------------------
100179 // file: $Id$
100180 // lib:  syncml-js.store
100181 // auth: griffin <griffin@uberdev.org>
100182 // date: 2012/11/04
100183 // copy: (C) CopyLoose 2012 UberDev <hardcore@uberdev.org>, No Rights Reserved.
100184 //-----------------------------------------------------------------------------
100185
100186
100187 var common = require('ripple/platform/tizen/2.0/syncml-js-lib/common'),
100188     constant = require('ripple/platform/tizen/2.0/syncml-js-lib/constant'),
100189     ctype = require('ripple/platform/tizen/2.0/syncml-js-lib/ctype'),
100190     storage = require('ripple/platform/tizen/2.0/syncml-js-lib/storage'),
100191     ET = require('ripple/platform/tizen/2.0/syncml-js-lib/elementtree');
100192
100193
100194 var _self = (function () {
100195     var exports = {};
100196
100197     //---------------------------------------------------------------------------
100198     exports.Store = common.Base.extend({
100199
100200         //-------------------------------------------------------------------------
100201         constructor: function(adapter, options) {
100202
100203             // todo: some of these attributes should be modifiable...
100204
100205             //: for local stores, specifies the agent that will implement
100206             //: the actual item operations -- it must implement the
100207             //: syncml-js.Agent API.
100208             this.agent = options.agent || null;
100209
100210             //: [read-only] specifies the SyncML URI that this store is bound to.
100211             this.uri = ( adapter ? adapter.normUri(options.uri) : options.uri ) || null;
100212
100213             //: [read-only] specifies the human-readable name for this store.
100214             //: if undefined, defaults to URI.
100215             this.displayName = options.displayName || this.uri || null;
100216
100217             //: [read-only] specifies the maximum GUID size for items in this store.
100218             //: if undefined, defaults to adapter setting.
100219             this.maxGuidSize = options.maxGuidSize || null;
100220
100221             //: [read-only] specifies the maximum object size for items in this store.
100222             //: if undefined, defaults to adapter setting.
100223             this.maxObjSize = options.maxObjSize || null;
100224
100225             //: [read-only] specifies conflict resolution policy for this store.
100226             //: if undefined, defaults to adapter setting.
100227             this.conflictPolicy = options.conflictPolicy || null;
100228
100229             //: [read-only] specifies which syncTypes this store supports.
100230             //: (defaults to all.)
100231             this.syncTypes = options.syncTypes;
100232             if ( this.syncTypes == undefined || this.syncTypes.length <= 0 )
100233             {
100234                 this.syncTypes = [
100235                     constant.SYNCTYPE_TWO_WAY,
100236                     constant.SYNCTYPE_SLOW_SYNC,
100237                     constant.SYNCTYPE_ONE_WAY_FROM_CLIENT,
100238                     constant.SYNCTYPE_REFRESH_FROM_CLIENT,
100239                     constant.SYNCTYPE_ONE_WAY_FROM_SERVER,
100240                     constant.SYNCTYPE_REFRESH_FROM_SERVER,
100241                     constant.SYNCTYPE_SERVER_ALERTED
100242                 ];
100243             }
100244
100245             ctypes = options.contentTypes;
100246             if ( ! ctypes && options.agent )
100247                 ctypes = options.agent.getContentTypes();
100248
100249             this.contentTypes = _.map(ctypes, function(e) {
100250                 if ( e instanceof ctype.ContentTypeInfo ) {
100251                     return e;
100252                 }
100253                 return ctype.ContentTypeInfo.fromStruct(e);
100254             });
100255
100256             // --- private attributes
100257             this.id       = options.id || common.makeID();
100258             this._a       = adapter;
100259         },
100260
100261         //-------------------------------------------------------------------------
100262         _load: function(cb) {
100263             cb();
100264         },
100265
100266         //-------------------------------------------------------------------------
100267         _getModel: function() {
100268             var self = this;
100269             var uri  = self._a.normUri(self.uri);
100270             return _.find(this._a._getModel().stores,
100271                     function(s) { return self._a.normUri(s.uri) == uri; });
100272         },
100273
100274         //-------------------------------------------------------------------------
100275         _updateModel: function(cb) {
100276             if ( ! this._a._model || ! this._a._model.stores )
100277                 return cb('store created on un-initialized adapter');
100278             // TODO: this squashes any data that may already be there, such
100279             //       as *BINDING* info!...
100280             this._a._model.stores = _.filter(this._a._model.stores, function(e) {
100281                 return e.uri != this.uri;
100282             }, this);
100283             this._a._model.stores.push({
100284                 id              : this.id,
100285                 uri             : this.uri,
100286                 displayName     : this.displayName,
100287                 syncTypes       : this.syncTypes,
100288                 maxGuidSize     : this.maxGuidSize,
100289                 maxObjSize      : this.maxObjSize,
100290                 conflictPolicy  : this.conflictPolicy,
100291                 contentTypes    : _.map(this.contentTypes, function(e) { return e.toStruct(); })
100292             });
100293             cb();
100294         },
100295
100296         //-------------------------------------------------------------------------
100297         _getBinding: function() {
100298             return this._getModel().binding;
100299         },
100300
100301         //-------------------------------------------------------------------------
100302         _setBinding: function(binding) {
100303             this._getModel().binding = binding;
100304         },
100305
100306         //-------------------------------------------------------------------------
100307         getContentTypes: function() {
100308             if ( this.agent != undefined ) {
100309                 return this.agent.getContentTypes();
100310             }
100311             return this.contentTypes;
100312         },
100313
100314         //-------------------------------------------------------------------------
100315         getPeerStore: function(peer) {
100316             var peerUri = null;
100317             if ( this._a.isLocal ) {
100318                 peerUri = this._a._c.router.getTargetUri(this._a, peer, this.uri);
100319             }
100320             else {
100321                 var binding = this.getBinding();
100322                 peerUri = binding ? binding.uri : null;
100323             }
100324             if ( ! peerUri ) {
100325                 return null;
100326             }
100327             return peer.getStore(peerUri);
100328         },
100329
100330         //-------------------------------------------------------------------------
100331         merge: function(store, cb) {
100332             if ( this.uri != store.uri )
100333                 return cb(new common.InternalError(
100334                                 'unexpected merging of stores with different URIs ("' + this.uri
100335                                     + '" != "' + store.uri + '")'));
100336             if ( ! _.isEqual(this.contentTypes, store.contentTypes) )
100337             {
100338                 // todo: this is a bit drastic... perhaps have an operational setting
100339                 //       which controls how paranoid to be?...
100340                 this._setBinding(null);
100341             }
100342             this.displayName    = store.displayName;
100343             this.contentTypes   = _.rest(store.contentTypes, 0);
100344             this.syncTypes      = _.rest(store.syncTypes, 0);
100345             this.maxGuidSize    = store.maxGuidSize;
100346             this.maxObjSize     = store.maxObjSize;
100347             this.agent          = store.agent;
100348             this.conflictPolicy = store.conflictPolicy;
100349             return cb();
100350         },
100351
100352         //-------------------------------------------------------------------------
100353         _clearAllMappings: function(cb) {
100354             if ( this._a.isLocal )
100355                 return cb(new common.InternalError(
100356                             'unexpected mapping request for local store'));
100357             var mapping = this._a._c._txn().objectStore('mapping');
100358             storage.deleteAll(mapping, {store_id: this.id}, cb);
100359         },
100360
100361         //-------------------------------------------------------------------------
100362         _setMapping: function(guid, luid, cb) {
100363             var self = this;
100364             if ( this._a.isLocal )
100365                 return cb(new common.InternalError(
100366                             'unexpected mapping request for local store'));
100367             // delete all previous mappings for this guid/store (there should
100368             // be at most one)... but paranoia rules.
100369             var mapping = this._a._c._txn().objectStore('mapping');
100370             storage.deleteAll(mapping, {store_id: this.id, guid: guid}, function(err) {
100371                 if ( err ) {
100372                     return cb(err);
100373                 }
100374                 storage.put(mapping, {store_id: self.id, guid: guid, luid: luid}, function(err) {
100375                     if ( err ) {
100376                         return cb(err);
100377                     }
100378                     cb();
100379                 });
100380             });
100381         },
100382
100383         //-------------------------------------------------------------------------
100384         _getMapping: function(guid, cb) {
100385             if ( this._a.isLocal )
100386                 return cb(new common.InternalError(
100387                             'unexpected mapping request for local store'));
100388             // todo: there must be a way to use IndexedDB since i have everything
100389             //       needed to generate the keyPath!... eg:
100390             //         objectStore.get({store_id:X,guid:Y})?...
100391             var mapdb = this._a._c._txn().objectStore('mapping').index('store_id');
100392             storage.getAll(this._a._c, mapdb, {only: this.id}, function(err, list) {
100393                 if ( err ) {
100394                     return cb(err);
100395                 }
100396                 var item = _.find(list, function(item) {
100397                     return item.guid == guid;
100398                 });
100399                 return cb(null, item ? item.luid : null);
100400             });
100401         },
100402
100403         //-------------------------------------------------------------------------
100404         _getMappings: function(cb) {
100405             if ( this._a.isLocal )
100406                 return cb(new common.InternalError(
100407                             'unexpected mapping request for local store'));
100408             var mapdb = this._a._c._txn().objectStore('mapping').index('store_id');
100409             storage.getAll(this._a._c, mapdb, {only: this.id}, function(err, list) {
100410                 if ( err )
100411                     return cb(err);
100412                 return cb(null, _.map(list, function(item) {
100413                     return [item.guid, item.luid];
100414                 }));
100415             });
100416         },
100417
100418         //-------------------------------------------------------------------------
100419         _getReverseMapping: function(luid, cb) {
100420             if ( this._a.isLocal )
100421                 return cb(new common.InternalError(
100422                             'unexpected mapping request for local store'));
100423             // todo: there must be a way to use IndexedDB since i have everything
100424             //       needed to generate the keyPath!... eg:
100425             //         objectStore.get({store_id:X,guid:Y})?...
100426             var mapdb = this._a._c._txn().objectStore('mapping').index('store_id');
100427             storage.getAll(this._a._c, mapdb, {only: this.id}, function(err, list) {
100428                 if ( err )
100429                     return cb(err);
100430                 var item = _.find(list, function(item) {
100431                     return item.luid == luid;
100432                 });
100433                 return cb(null, item ? item.guid : null);
100434             });
100435         },
100436
100437         //-------------------------------------------------------------------------
100438         registerChange: function(itemID, state, options, cb) {
100439             // options can include:
100440             //   - changeSpec (string)
100441             //   - excludePeerID (string)
100442
100443             if ( ! _.contains([constant.ITEM_ADDED, constant.ITEM_MODIFIED,
100444                         constant.ITEM_DELETED], state) )
100445                 return cb(new common.TypeError(
100446                             'registerChange: invalid state "' + state + '"'));
100447
100448             options = options || {};
100449             var self = this;
100450             if ( self._a.isLocal )
100451             {
100452                 // TODO: THIS NEEDS TO BE SIGNIFICANTLY OPTIMIZED!... either:
100453                 //         a) optimize this reverse lookup, or
100454                 //         b) use a query that targets exactly the set of stores needed
100455                 //       note that a pre-emptive model.session.flush() may be necessary.
100456                 common.cascade(self._a.getPeers(), function(peer, cb) {
100457                     if ( options.excludePeerID && options.excludePeerID == peer.id )
100458                         return cb();
100459                     common.cascade(peer.getStores(), function(store, cb) {
100460                         var binding = store._getBinding()
100461                         if ( ! binding || binding.uri != self.uri )
100462                             return cb();
100463                         store.registerChange(itemID, state, options, cb);
100464                     }, cb);
100465                 }, cb);
100466                 return;
100467             }
100468
100469             // todo: a non-ADD change event for an ID that has never been
100470             // seen does not create an error... should it??? that would mean
100471             // that syncml-js needs to track that. not a good idea.
100472
100473             itemID = '' + itemID;
100474             var handled = false;
100475
100476             // paranoia
100477             if ( options.changeSpec && state != constant.ITEM_MODIFIED )
100478             {
100479                 options.changeSpec = null;
100480             }
100481
100482             var check_update = function(cb) {
100483                 self._getChange(itemID, function(err, change) {
100484                     if ( err )
100485                         return cb(err);
100486                     if ( ! change)
100487                         return cb();
100488                     var badstate = function(action) {
100489                     };
100490                 // note: many of the following change.state / state combinations
100491                 // should never occur. the following tries to recover gracefully.
100492                 // todo: should i raise an error for "illogical" conditions?
100493                     switch ( change.state )
100494                     {
100495                     case constant.ITEM_ADDED:
100496                     {
100497                         if ( state != constant.ITEM_DELETED )
100498                         {
100499                             // ADD + anything except DELETE stays ADD
100500                             handled = true;
100501                             return cb();
100502                         }
100503                         // ADD + DELETE cancels out
100504                         handled = true;
100505                         var changeTab = self._a._c._txn().objectStore('change');
100506                         storage.deleteAll(changeTab, change, function(err) {
100507                             if ( err )
100508                                 return cb(err);
100509                             return cb();
100510                         });
100511                         return;
100512                     }
100513                     case constant.ITEM_MODIFIED:
100514                     {
100515                         if ( state == constant.ITEM_ADDED )
100516                         {
100517                             badstate('squelching changeSpec');
100518                             delete change.changeSpec;
100519                             break;
100520                         }
100521                         if ( state == constant.ITEM_DELETED )
100522                         {
100523                             change.state = state;
100524                             delete change.changeSpec;
100525                             break;
100526                         }
100527                         if ( change.changeSpec )
100528                         {
100529                             if ( options.changeSpec )
100530                                 change.changeSpec += ';' + options.changeSpec;
100531                             else
100532                                 delete change.changeSpec;
100533                         }
100534                         break;
100535                     }
100536                     case constant.ITEM_DELETED:
100537                     {
100538                         if ( state == constant.ITEM_DELETED )
100539                         {
100540                             badstate('ignoring');
100541                             handled = true;
100542                             return cb();
100543                         }
100544                         badstate('reverting to modified');
100545                         change.state = constant.ITEM_MODIFIED;
100546                         delete change.changeSpec;
100547                         break;
100548                     }
100549                     default:
100550                     {
100551                         return cb(new common.InternalError(
100552                                     'unexpected recorded change state "' + change.state
100553                                     + '" for item ID "' + itemID + '"'));
100554                     }
100555                     }
100556                     // update the change
100557                     // todo: do i need to delete it first?
100558                     handled = true;
100559                     return storage.put(
100560                         self._a._c._txn().objectStore('change'),
100561                         change,
100562                         cb);
100563                 });
100564             };
100565
100566             var check_mapping = ( self._a._isMapper() || state == constant.ITEM_ADDED )
100567                 ? common.noop
100568                 : function(cb) {
100569                     // doing a `_getMapping` for non-add events to make sure that
100570                     // the remote peer actually has this object before we tell it
100571                     // to modify or delete an item...
100572                     self._getMapping(itemID, function(err, luid) {
100573                         if ( err )
100574                         return cb(err);
100575                     if ( luid )
100576                         return cb();
100577                     // this item does not exist as (or has not been mapped to) an
100578                     // item on the remote peer and is not an `ADD` event, so can
100579                     // therefore be ignored - mark it as "handled".
100580                     handled = true;
100581                     return cb();
100582                     });
100583                 };
100584
100585             // todo: there is a weirdness here wrt `handled` in the case
100586             //       of check_mapping and deletes... ie. there is a bit of
100587             //       a responsibility violation (handled does not actually
100588             //       mean handled...)
100589
100590             check_update(function(err) {
100591                 if ( err )
100592                     return cb(err);
100593                 if ( handled )
100594                     return cb();
100595                 check_mapping(function(err) {
100596                     if ( err )
100597                         return cb(err);
100598                     if ( handled && state != constant.ITEM_DELETED )
100599                         return cb();
100600                     // note: if it is a delete event, and it has not been mapped
100601                     // yet, so does not yet exist on the peer, therefore
100602                     // propagate nothing -- continuing just to execute the
100603                     // deleteAll().
100604                     var changeTab = self._a._c._txn().objectStore('change');
100605                     change = {store_id: self.id, item_id: itemID};
100606                     // todo: is this deleteAll really necessary?... paranoia rules!
100607                     storage.deleteAll(changeTab, change, function(err) {
100608                         if ( err )
100609                             return cb(err);
100610                         if ( handled )
100611                             return cb();
100612                         change.state = state;
100613                         change.changeSpec = options.changeSpec;
100614                         storage.put(changeTab, change, cb);
100615                     });
100616                 });
100617             });
100618         },
100619
100620         //-------------------------------------------------------------------------
100621         _getChange: function(itemID, cb) {
100622             // returns cb(null, CHANGE)
100623             // change ::= { store_id: ID, item_id: GUID, state: STATE, changeSpec: SPEC }
100624             itemID = '' + itemID;
100625             var self = this;
100626             // todo: there must be a way to use IndexedDB since i have everything
100627             //       needed to generate the keyPath!... eg:
100628             //         objectStore.get({store_id:X,guid:Y})?...
100629             var changedb = self._a._c._txn().objectStore('change').index('store_id');
100630             storage.getAll(self._a._c, changedb, {only: self.id}, function(err, changes) {
100631                 if ( err )
100632                     return cb(err);
100633                 var change = _.find(changes, function(change) {
100634                     return change.item_id == itemID;
100635                 });
100636                 return cb(null, change);
100637             });
100638         },
100639
100640         //-------------------------------------------------------------------------
100641         _delChange: function(options, cb) {
100642             // - if options is null/empty, delete all changes recorded
100643             //   for this store
100644
100645             // // todo: this is *technically* subject to a race condition... but the
100646             // //       same peer should really not be synchronizing at the same time...
100647             // // todo: also potentially check Change.registered...
100648             // // TODO: this could be solved by:
100649             // //         a) never updating a Change record (only deleting and replacing)
100650             // //         b) deleting Change records by ID instead of by store/item/state...
100651
100652             // var objstore = session.context._txn().objectStore('change');
100653             // storage.iterateCursor(
100654             //   objstore.index('store_id').openCursor(peerStore.id),
100655             //   function(value, key, cb) {
100656             //     if ( value.itemID != chkcmd.source || value.state != constant.ITEM_ADDED )
100657             //       return;
100658             //     storage.delete(objstore, key, cb);
100659             //   }, cb);
100660
100661             var dbstore = this._a._c._txn().objectStore('change');
100662             var matches = {store_id: this.id};
100663             if ( options.itemID )
100664                 matches.item_id = options.itemID;
100665             if ( options.state )
100666                 matches.state = options.state;
100667             storage.deleteAll(dbstore, matches, cb);
100668         },
100669
100670         //-------------------------------------------------------------------------
100671         toSyncML: function() {
100672             var xstore = ET.Element('DataStore');
100673             if ( this.uri )
100674                 ET.SubElement(xstore, 'SourceRef').text = this.uri;
100675             if ( this.displayName )
100676                 ET.SubElement(xstore, 'DisplayName').text = this.displayName;
100677             if ( this.maxGuidSize )
100678             {
100679                 // todo: this should ONLY be sent by the client... (according to the
100680                 //       spec, but not according to funambol behavior...)
100681                 ET.SubElement(xstore, 'MaxGUIDSize').text = this.maxGuidSize;
100682             }
100683             if ( this.maxObjSize )
100684                 ET.SubElement(xstore, 'MaxObjSize').text = this.maxObjSize;
100685
100686             var ctypes = this.getContentTypes();
100687
100688             if ( ctypes && ctypes.length > 0 )
100689             {
100690                 var pref = _.filter(ctypes, function(ct) { return ct.receive && ct.preferred; });
100691
100692                 // todo: should i just take the first one?...
100693                 if ( pref.length > 1 )
100694                     throw new Error('agents can prefer at most one receive content-type');
100695
100696                 if ( pref.length == 1 )
100697                 {
100698                     pref = pref[0].toSyncML('Rx', true);
100699                     pref[0].tag = 'Rx-Pref';
100700                     _.each(pref, function(xnode) { xstore.append(xnode); });
100701                 }
100702
100703                 _.each(
100704                         _.filter(ctypes, function(ct) { return ct.receive && ! ct.preferred; }),
100705                         function(ct) {
100706                             _.each(ct.toSyncML('Rx', true), function(xnode) {
100707                                 xstore.append(xnode);
100708                             });
100709                         });
100710
100711                 var pref = _.filter(ctypes, function(ct) { return ct.transmit && ct.preferred; });
100712
100713                 // todo: should i just take the first one?...
100714                 if ( pref.length > 1 )
100715                     throw new Error('agents can prefer at most one transmit content-type');
100716
100717                 if ( pref.length == 1 )
100718                 {
100719                     pref = pref[0].toSyncML('Tx', true);
100720                     pref[0].tag = 'Tx-Pref';
100721                     _.each(pref, function(xnode) { xstore.append(xnode); });
100722                 }
100723
100724                 _.each(
100725                         _.filter(ctypes, function(ct) { return ct.transmit && ! ct.preferred; }),
100726                         function(ct) {
100727                             _.each(ct.toSyncML('Tx', true), function(xnode) {
100728                                 xstore.append(xnode);
100729                             });
100730                         });
100731
100732             }
100733
100734             if ( this.syncTypes && this.syncTypes.length > 0 )
100735             {
100736                 var xcap = ET.SubElement(xstore, 'SyncCap');
100737                 for ( var idx=0 ; idx<this.syncTypes.length ; idx++ )
100738                     ET.SubElement(xcap, 'SyncType').text = this.syncTypes[idx];
100739             }
100740             return xstore;
100741
100742         },
100743
100744         //-------------------------------------------------------------------------
100745         describe: function(stream, cb) {
100746             stream.writeln('URI: ' + this.uri);
100747             stream.writeln('Max ID size: ' + ( this.maxGuidSize || '(none)' ));
100748             stream.writeln('Max object size: ' + ( this.maxObjSize || '(none)' ));
100749             stream.writeln('Sync types: ' + this.syncTypes.join(', '));
100750             var cts = this.getContentTypes();
100751             if ( cts.length <= 0 )
100752             {
100753                 stream.writeln('Capabilities: (none)');
100754                 return cb();
100755             }
100756             stream.writeln('Capabilities:');
100757             var s1 = new common.IndentStream(stream);
100758             common.cascade(cts, function(ct, cb) {
100759                 s1.write('- ');
100760                 ct.describe(s1);
100761                 return cb();
100762             }, cb);
100763         }
100764     }, {
100765
100766         //-------------------------------------------------------------------------
100767         fromSyncML: function(xnode) {
100768             var options = {
100769                 uri          : xnode.findtext('SourceRef'),
100770                 displayName  : xnode.findtext('DisplayName'),
100771                 maxGuidSize  : common.int(xnode.findtext('MaxGUIDSize')),
100772                 maxObjSize   : common.int(xnode.findtext('MaxObjSize')),
100773                 contentTypes : [],
100774                 syncTypes    : _.map(xnode.findall('SyncCap/SyncType'), function(e) {
100775                     return common.int(e.text);
100776                 })
100777             };
100778             _.each(xnode.getchildren(), function(child) {
100779                 if ( _.indexOf(['Rx-Pref', 'Rx', 'Tx-Pref', 'Tx'], child.tag) < 0 )
100780                 return;
100781             var cti = ctype.ContentTypeInfo.fromSyncML(child);
100782             var merged = false;
100783             _.each(options.contentTypes, function(ct) {
100784                 if ( merged )
100785                 return;
100786             if ( ct.merge(cti) )
100787                 merged = true;
100788             });
100789             if ( ! merged )
100790                 options.contentTypes.push(cti);
100791             });
100792             return new exports.Store(null, options);
100793         },
100794     });
100795
100796     return exports;
100797
100798 })();
100799
100800 module.exports = _self;
100801
100802 });
100803 define('ripple/platform/tizen/2.0/syncml-js-lib/synchronizer', function (require, exports, module) {
100804 // -*- coding: utf-8 -*-
100805 //-----------------------------------------------------------------------------
100806 // file: $Id$
100807 // lib:  syncml-js.synchronizer
100808 // auth: griffin <griffin@uberdev.org>
100809 // date: 2012/11/05
100810 // copy: (C) CopyLoose 2012 UberDev <hardcore@uberdev.org>, No Rights Reserved.
100811 //-----------------------------------------------------------------------------
100812
100813 var common = require('ripple/platform/tizen/2.0/syncml-js-lib/common'),
100814     constant = require('ripple/platform/tizen/2.0/syncml-js-lib/constant'),
100815     ctype = require('ripple/platform/tizen/2.0/syncml-js-lib/ctype'),
100816     state = require('ripple/platform/tizen/2.0/syncml-js-lib/state'),
100817     protocol = require('ripple/platform/tizen/2.0/syncml-js-lib/protocol'),
100818     storage = require('ripple/platform/tizen/2.0/syncml-js-lib/storage'),
100819     _self;
100820
100821 _self = (function () {
100822
100823     var exports = {};
100824     var badStatus = protocol.badStatus;
100825
100826     //---------------------------------------------------------------------------
100827     exports.Synchronizer = common.Base.extend({
100828
100829         //-------------------------------------------------------------------------
100830         constructor: function(options) {
100831         },
100832
100833         //-------------------------------------------------------------------------
100834         initStoreSync: function(session, cb) {
100835             async.eachSeries(session.peer._getModel().stores, function(rstore, cb) {
100836                 // TODO: should the server-side be doing this? probably not
100837                 //       since store mapping is a client-side decision...
100838                 var ruri = session.peer.normUri(rstore.uri);
100839                 if ( session.info.dsstates[ruri] || ! rstore.binding )
100840                 return cb();
100841             var lstore = session.adapter.getStore(rstore.binding.uri);
100842             if ( ! lstore || ! lstore.agent )
100843                 return cb();
100844             var ds = state.makeStoreSyncState({
100845                 uri        : lstore.uri,
100846                 peerUri    : ruri,
100847                 lastAnchor : rstore.binding.localAnchor,
100848                 mode       : session.info.mode || constant.ALERT_TWO_WAY,
100849                 action     : 'alert'
100850             });
100851             if ( ! ds.lastAnchor )
100852             {
100853                 switch ( ds.mode )
100854             {
100855                 case constant.ALERT_SLOW_SYNC:
100856                 case constant.ALERT_REFRESH_FROM_CLIENT:
100857                 case constant.ALERT_REFRESH_FROM_SERVER:
100858                     {
100859                         break;
100860                     }
100861                 case constant.ALERT_TWO_WAY:
100862                 case constant.ALERT_ONE_WAY_FROM_CLIENT:
100863                 case constant.ALERT_ONE_WAY_FROM_SERVER:
100864                     {
100865                         if ( session.info.mode == constant.SYNCTYPE_AUTO )
100866                         {
100867                             ds.mode = constant.ALERT_SLOW_SYNC;
100868                             break;
100869                         }
100870                         var uaEvent = {
100871                             session   : session,
100872                             store     : lstore,
100873                             peerStore : rstore,
100874                             modeReq   : ds.mode
100875                         };
100876                         return session.ua.chooseRefreshRequired(uaEvent, function(err, mode) {
100877                             if ( err )
100878                             return cb(err);
100879                         if ( ! _.contains([constant.ALERT_SLOW_SYNC,
100880                                 constant.ALERT_REFRESH_FROM_CLIENT,
100881                                 constant.ALERT_REFRESH_FROM_SERVER], mode) )
100882                             return cb(new common.TypeError(
100883                                     'invalid mode chosen for refresh: ' + common.j(mode)));
100884                         ds.mode = mode;
100885                         session.info.dsstates[ds.uri] = ds;
100886                         return cb();
100887                         });
100888                     }
100889                 default:
100890                     {
100891                         return cb(new common.InternalError(
100892                                     'unexpected sync mode "' + ds.mode + '" requested'));
100893                     }
100894             }
100895             }
100896             session.info.dsstates[ds.uri] = ds;
100897             return cb();
100898             }, cb);
100899         },
100900
100901         //-------------------------------------------------------------------------
100902         // SYNCHRONIZATION PHASE: ACTION
100903         //-------------------------------------------------------------------------
100904
100905         //-------------------------------------------------------------------------
100906         actions: function(session, commands, cb) {
100907             var self = this;
100908             common.cascade(_.keys(session.info.dsstates), function(uri, cb) {
100909                 var ds = session.info.dsstates[uri];
100910                 if ( ds.action == 'done' )
100911                 return cb();
100912             // TODO: is this the right handling of an "error" dsstate?...
100913             if ( ds.action == 'error' )
100914                 return cb();
100915             var func = self['_action_' + ds.action.toLowerCase()];
100916             if ( ! func )
100917                 return cb(new common.InternalError(
100918                         'unexpected store action "' + ds.action + '"'));
100919             try{
100920                 func.call(self, session, ds, function(err, cmds) {
100921                     if ( err )
100922                     return cb(err);
100923                 _.each(cmds, function(cmd) { commands.push(cmd); });
100924                 return cb();
100925                 });
100926             }catch(e){
100927                 return cb(new common.InternalError(
100928                         'failed invoking synchronizer action: ' + e, e));
100929             }
100930             }, function(err) {
100931                 if ( err )
100932                     return cb(err);
100933                 return cb(null, commands);
100934             });
100935         },
100936
100937         //-------------------------------------------------------------------------
100938         _action_alert: function(session, dsstate, cb) {
100939
100940             var src = session.adapter.getStore(dsstate.uri);
100941             var tgt = session.peer.getStore(dsstate.peerUri);
100942
100943             // TODO: ensure that mode is acceptable...
100944
100945             // todo: perhaps i should only specify maxObjSize if it differs from
100946             //       adapter.maxObjSize?...
100947
100948             return cb(null, [state.makeCommand({
100949                 name        : constant.CMD_ALERT,
100950                    cmdID       : session.nextCmdID(),
100951                    data        : dsstate.mode,
100952                    source      : src.uri,
100953                    target      : tgt.uri,
100954                    lastAnchor  : dsstate.lastAnchor,
100955                    nextAnchor  : dsstate.nextAnchor,
100956                    maxObjSize  : src.maxObjSize,
100957             })]);
100958
100959         },
100960
100961         //-------------------------------------------------------------------------
100962         _action_send: function(session, dsstate, cb) {
100963             var store = session.adapter.getStore(dsstate.uri);
100964             var agent = store.agent;
100965             var peerStore = session.peer.getStore(dsstate.peerUri);
100966
100967             var cmd = state.makeCommand({
100968                 name   : constant.CMD_SYNC,
100969                 cmdID  : session.nextCmdID(),
100970                 source : dsstate.uri,
100971                 // target : adapter.router.getTargetUri(uri),
100972                 target : dsstate.peerUri
100973             });
100974
100975             switch ( dsstate.mode )
100976             {
100977                 case constant.ALERT_TWO_WAY:
100978                 case constant.ALERT_SLOW_SYNC:
100979                 case constant.ALERT_ONE_WAY_FROM_CLIENT:
100980                 case constant.ALERT_REFRESH_FROM_CLIENT:
100981                 case constant.ALERT_ONE_WAY_FROM_SERVER:
100982                 case constant.ALERT_REFRESH_FROM_SERVER:
100983                     // todo: these should only be received out-of-band, right?...
100984                     // case constant.ALERT_TWO_WAY_BY_SERVER:
100985                     // case constant.ALERT_ONE_WAY_FROM_CLIENT_BY_SERVER:
100986                     // case constant.ALERT_REFRESH_FROM_CLIENT_BY_SERVER:
100987                     // case constant.ALERT_ONE_WAY_FROM_SERVER_BY_SERVER:
100988                     // case constant.ALERT_REFRESH_FROM_SERVER_BY_SERVER:
100989                     {
100990                         break;
100991                     }
100992                 default:
100993                     {
100994                         return cb(new common.InternalError(
100995                                     'unexpected sync mode "' + common.mode2string(dsstate.mode) + '"'));
100996                     }
100997             }
100998
100999             if ( session.isServer )
101000             {
101001                 if ( dsstate.mode == constant.ALERT_REFRESH_FROM_CLIENT
101002                         || dsstate.mode == constant.ALERT_ONE_WAY_FROM_CLIENT )
101003                 {
101004                     cmd.noc = 0;
101005                     return cb(null, [cmd]);
101006                 }
101007             }
101008
101009             if ( ! session.isServer )
101010             {
101011                 if ( dsstate.mode == constant.ALERT_REFRESH_FROM_SERVER
101012                         || dsstate.mode == constant.ALERT_ONE_WAY_FROM_SERVER )
101013                 {
101014                     cmd.noc = 0;
101015                     return cb(null, [cmd]);
101016                 }
101017             }
101018
101019             switch ( dsstate.mode )
101020             {
101021
101022                 case constant.ALERT_TWO_WAY:
101023                 case constant.ALERT_ONE_WAY_FROM_CLIENT: // when ! session.isServer
101024                 case constant.ALERT_ONE_WAY_FROM_SERVER: // when session.isServer
101025                     {
101026                         // send local changes
101027
101028                         storage.getAll(
101029                                 session.context,
101030                                 session.txn().objectStore('change').index('store_id'),
101031                                 {only: peerStore.id},
101032                                 function(err, changes) {
101033                                     if ( err )
101034                             return cb(err);
101035                         var ctype = session.context.router.getBestTransmitContentType(
101036                             session.adapter, session.peer, dsstate.uri);
101037                         cmd.data = [];
101038
101039                         // TODO: add support for hierarchical operations...
101040                         //       including MOVE, COPY, etc.
101041
101042                         // TODO: this assumes that the entire object set can fit in memory...
101043                         //       perhaps, as a work-around, just keep a reference to the object
101044                         //       and then stream-based serialize it actually gets converted to
101045                         //       XML.
101046
101047                         common.cascade(changes, function(change, cb) {
101048
101049                             if ( dsstate.conflicts && _.indexOf(dsstate.conflicts, change.item_id) >= 0 )
101050                             return cb();
101051
101052                         var scmdtype = null;
101053                         switch ( change.state )
101054                         {
101055                             case constant.ITEM_ADDED:    scmdtype = constant.CMD_ADD;     break;
101056                             case constant.ITEM_MODIFIED: scmdtype = constant.CMD_REPLACE; break;
101057                             case constant.ITEM_DELETED:  scmdtype = constant.CMD_DELETE;  break;
101058                             default:
101059                                                          {
101060                                                              return cb();
101061                                                          }
101062                         }
101063
101064                         // todo: do something with the ctype version (ie. ctype[1])?...
101065                         var scmd = state.makeCommand({
101066                             name    : scmdtype,
101067                             cmdID   : session.nextCmdID(),
101068                             format  : constant.FORMAT_AUTO,
101069                             type    : change.state != constant.ITEM_DELETED ? ctype[0] : null,
101070                             uri     : dsstate.uri
101071                         });
101072
101073                         // TODO: need to add hierarchical addition support here...
101074
101075                         var set_data = scmdtype == constant.CMD_DELETE ? common.noop : function(cb) {
101076
101077                             agent.getItem(change.item_id, function(err, item) {
101078                                 if ( err )
101079                                 return cb(err);
101080                             agent.dumpsItem(item, ctype[0], ctype[1], function(err, data, nct, nv) {
101081                                 if ( err )
101082                                 return cb(err);
101083                             scmd.data = data;
101084                             scmd.type = nct || scmd.type;
101085                             // todo: what to do with the content-type version?... eg.
101086                             //         scmd.version = nv || scmd.version;
101087                             // TODO: support hierarchical sync
101088                             // if ( agent.hierarchicalSync && item.parent )
101089                             //   scmd.sourceParent = '' + item.parent
101090                             return cb();
101091                             });
101092                             });
101093                         };
101094
101095                         var set_target = scmdtype == constant.CMD_ADD ? function(cb) {
101096                             scmd.source = change.item_id;
101097                             cb();
101098                         } : function(cb) {
101099                             if ( ! session.isServer )
101100                             {
101101                                 scmd.source = change.item_id;
101102                                 return cb();
101103                             }
101104                             peerStore._getMapping(change.item_id, function(err, luid) {
101105                                 if ( err )
101106                                 return cb(err);
101107                             if ( luid )
101108                                 scmd.target = luid;
101109                             else
101110                                 scmd.source = change.item_id;
101111                             cb();
101112                             });
101113                         };
101114
101115                         set_data(function(err) {
101116                             if ( err )
101117                             return cb(err);
101118                         set_target(function(err) {
101119                             if ( err )
101120                             return cb(err);
101121                         cmd.data.push(scmd);
101122                         return cb();
101123                         });
101124                         });
101125                         }, function(err) {
101126                             if ( err )
101127                                 return cb(err);
101128                             cmd.noc = cmd.data.length;
101129                             return cb(null, [cmd]);
101130                         });
101131                                 }
101132                         );
101133                         return;
101134                     }
101135                 case constant.ALERT_SLOW_SYNC:
101136                 case constant.ALERT_REFRESH_FROM_SERVER: // when session.isServer
101137                 case constant.ALERT_REFRESH_FROM_CLIENT: // when ! session.isServer
101138                     {
101139                         // todo: this approach assumes that the entire object set can fit
101140                         //       in memory... perhaps move to an iterator-based approach?...
101141                         cmd.data = [];
101142
101143                         agent.getAllItems(function(err, items) {
101144
101145                             if ( err )
101146                             return cb(err);
101147
101148                         // TODO: support hierarchical sync...
101149
101150                         if ( agent.hierarchicalSync )
101151                         {
101152                             return cb(new common.NotImplementedError('hierarchical-sync'));
101153                             //       orditems = []            # the ordered items
101154                             //       dunitems = dict()        # lut of the ordered items
101155                             //       curitems = dict()        # lut of current items (for loop detection)
101156                             //       lutitems = dict([(item.id, item) for item in items])
101157                             //       def appenditem(item):
101158                             //         if item.id in dunitems:
101159                             //           return
101160                             //         if item.id in curitems:
101161                             //           raise common.LogicalError('recursive item hierarchy detected at item %r' % (item,))
101162                             //         curitems[item.id] = True
101163                             //         if item.parent is not None:
101164                             //           appenditem(lutitems[item.parent])
101165                             //         orditems.append(item)
101166                             //         dunitems[item.id] = item
101167                             //       for item in items:
101168                             //         curitems = dict()
101169                             //         appenditem(item)
101170                         }
101171
101172                         var ctype = session.context.router.getBestTransmitContentType(
101173                                 session.adapter, session.peer, dsstate.uri);
101174
101175                         common.cascade(items, function(item, cb) {
101176
101177                             // TODO: these should all be non-deleted items, right?...
101178
101179                             if ( _.indexOf(dsstate.conflicts, '' + item.id) >= 0 )
101180                             return cb();
101181
101182                         // note: need to check for mappings since on slow-sync, the
101183                         // server will already have received the client's "add" commands
101184                         // at this point (and therefore should not send them back...)
101185                         var check_sync = function(cb) {
101186                             if ( ! session.isServer )
101187                             return cb(null, true);
101188                         peerStore._getMapping(item.id, function(err, luid) {
101189                             return cb(err, luid ? false : true);
101190                         });
101191                         };
101192
101193                         check_sync(function(err, dosync) {
101194                             if ( err )
101195                             return cb(err);
101196
101197                         if ( ! dosync )
101198                             return cb();
101199
101200                         agent.dumpsItem(
101201                             item, ctype[0], ctype[1],
101202                             function(err, data, new_ct, new_v) {
101203
101204                                 if ( err )
101205                             return cb(err);
101206
101207                         // todo: do something with the content-type version...
101208                         var scmd = state.makeCommand({
101209                             name    : constant.CMD_ADD,
101210                             cmdID   : session.nextCmdID(),
101211                             format  : constant.FORMAT_AUTO,
101212                             type    : new_ct || ctype[0],
101213                             uri     : dsstate.uri,
101214                             source  : '' + item.id,
101215                             data    : data
101216                         });
101217
101218                         if ( agent.hierarchicalSync )
101219                         {
101220                             // TODO: support hierarchical sync...
101221                             // if agent.hierarchicalSync and item.parent is not None:
101222                             //   scmd.sourceParent = str(item.parent)
101223                             return cb(new common.NotImplementedError('hierarchical-sync'));
101224                         }
101225
101226                         cmd.data.push(scmd);
101227                         return cb();
101228                             });
101229
101230                         });
101231
101232                         }, function(err) {
101233                             if ( err )
101234                                 return cb(err);
101235                             cmd.noc = cmd.data.length;
101236                             return cb(null, [cmd]);
101237                         });
101238
101239                         });
101240                         return;
101241                     }
101242             }
101243
101244             return cb(new common.InternalError(
101245                         'unexpected sync situation (action=' + dsstate.action
101246                             + ', mode=' + common.mode2string(dsstate.mode)
101247                             + ', isServer=' + ( session.isServer ? '1' : '0' ) + ')'));
101248                     },
101249
101250                     //-------------------------------------------------------------------------
101251                     _action_save: function(session, dsstate, cb) {
101252                         if ( ! session.isServer )
101253                 // TODO: for now, only servers should take the "save" action - the client
101254                 //       will explicitly do this at the end of the .sync() method.
101255                 //       ... mostly because clients don't call synchronizer.actions()
101256                 //       one final time ...
101257                 //       *BUT* perhaps that should be changed?... for example, .sync()
101258                 //       could call synchronizer.actions() to cause action_save's to occur
101259                 //       *AND* verify that synchronizer.actions() does not return anything...
101260                 return cb(new common.InternalError(
101261                         'unexpected sync save situation (action=' + dsstate.action
101262                             + ', mode=' + common.mode2string(dsstate.mode)
101263                             + ', isServer=' + ( session.isServer ? '1' : '0' ) + ')'));
101264
101265                     var peerStore = session.peer.getStore(dsstate.peerUri);
101266                     var binding = peerStore._getBinding();
101267                     binding.localAnchor  = dsstate.nextAnchor;
101268                     binding.remoteAnchor = dsstate.peerNextAnchor;
101269                     return cb(null);
101270                     },
101271
101272                     //-------------------------------------------------------------------------
101273                     // SYNCHRONIZATION PHASE: REACTION
101274                     //-------------------------------------------------------------------------
101275
101276                     //-------------------------------------------------------------------------
101277                     reactions: function(session, commands, cb) {
101278                         var self = this;
101279                         var ret  = [];
101280                         session.hierlut = null;
101281                         common.cascade(commands, function(cmd, cb) {
101282                             var func = self['_reaction_' + cmd.name.toLowerCase()];
101283                             if ( ! func )
101284                             return cb(new common.InternalError(
101285                                     'unexpected store reaction "' + cmd.name + '"'));
101286                         try{
101287                             func.call(self, session, cmd, function(err, cmds) {
101288                                 if ( err ) {
101289                                     return cb(err);
101290                                 }
101291                                 _.each(cmds, function(cmd) { ret.push(cmd); });
101292                                 return cb();
101293                             });
101294                         }catch(e){
101295                             return cb(new common.InternalError(
101296                                     'failed invoking synchronizer reaction: ' + e, e));
101297                         }
101298                         }, function(err) {
101299                             session.hierlut = null;
101300                             if ( err )
101301                                 return cb(err);
101302                             return cb(null, ret);
101303                         });
101304                     },
101305
101306                     //-------------------------------------------------------------------------
101307                     _reaction_sync: function(session, command, cb) {
101308                         var self = this;
101309                         var ret  = [state.makeCommand({
101310                             name       : constant.CMD_STATUS,
101311                             cmdID      : session.nextCmdID(),
101312                             msgRef     : command.msgID,
101313                             cmdRef     : command.cmdID,
101314                             targetRef  : command.target,
101315                             sourceRef  : command.source,
101316                             statusOf   : command.name,
101317                             statusCode : constant.STATUS_OK
101318                         })];
101319                         var store = session.adapter.getStore(session.adapter.normUri(command.target));
101320                         var dsstate = session.info.dsstates[store.uri];
101321                         if ( ! store.agent )
101322                         {
101323                             // todo: this is a bit different handling than anywhere else...
101324                             //       should everywhere else be like here, or the other way
101325                             //       round?...
101326                             //       the "REAL BIG ISSUE" is that atomicity of the changes
101327                             //       is a little vague at this point...
101328                             dsstate.stats.hereErr += 1;
101329                             dsstate.action = 'error';
101330                             dsstate.error  = {
101331                                 message:  'Sync agent for store "' + store.uri + '" not available',
101332                                 code:     'syncml-js.TypeError'
101333                             };
101334                             ret[0].statusCode = constant.STATUS_SERVICE_UNAVAILABLE;
101335                             ret[0].errorMsg   = dsstate.error.message;
101336                             ret[0].errorCode  = dsstate.error.code;
101337                             return cb(null, ret);
101338                         }
101339
101340                         if ( store.agent.hierarchicalSync )
101341                             session.hierlut = {};
101342
101343                         var preprocess = common.noop;
101344
101345                         if ( ( ! session.isServer && dsstate.mode == constant.ALERT_REFRESH_FROM_SERVER )
101346                                 || ( session.isServer && dsstate.mode == constant.ALERT_REFRESH_FROM_CLIENT ) )
101347                         {
101348                             // delete all local items
101349                             preprocess = function(cb) {
101350                                 store.agent.getAllItems(function(err, items) {
101351                                     if ( err )
101352                                     return cb(err);
101353                                 common.cascade(items, function(item, cb) {
101354                                     store.agent.deleteItem(item.id, function(err) {
101355                                         if ( err )
101356                                         return cb(err);
101357                                     dsstate.stats.hereDel += 1;
101358                                     if ( ! session.isServer )
101359                                         return cb();
101360                                     store.registerChange(item.id, constant.ITEM_DELETED,
101361                                         {excludePeerID: session.peer.id}, cb);
101362                                     });
101363                                 }, function(err) {
101364                                     if ( err )
101365                                     return cb(err);
101366                                 return store.getPeerStore(session.peer)._delChange({}, cb);
101367                                 });
101368                                 });
101369                             };
101370                         }
101371
101372                         if ( dsstate.mode == constant.ALERT_SLOW_SYNC
101373                                 || ( session.isServer && dsstate.mode == constant.ALERT_REFRESH_FROM_SERVER ) )
101374                         {
101375                             // delete all mappings and pending changes
101376                             var peerStore = store.getPeerStore(session.peer);
101377                             var prepreprocess = preprocess;
101378                             preprocess = function(cb) {
101379                                 prepreprocess(function(err) {
101380                                     if ( err )
101381                                     return cb(err);
101382                                 peerStore._delChange({}, function(err) {
101383                                     if ( err )
101384                                     return cb(err);
101385                                 peerStore._clearAllMappings(cb);
101386                                 });
101387                                 });
101388                             };
101389                         }
101390
101391                         preprocess(function(err) {
101392                             if ( err )
101393                             return cb(err);
101394
101395                         if ( command.data.length <= 0 )
101396                             return cb(null, ret);
101397
101398                         // paranoia: verify that i should be receiving data...
101399                         if ( ! ( dsstate.mode == constant.ALERT_TWO_WAY
101400                                 || dsstate.mode == constant.ALERT_SLOW_SYNC
101401                                 || ( ! session.isServer
101402                                     && ( dsstate.mode == constant.ALERT_ONE_WAY_FROM_SERVER
101403                                         || dsstate.mode == constant.ALERT_REFRESH_FROM_SERVER ) )
101404                                 || ( session.isServer
101405                                     && ( dsstate.mode == constant.ALERT_ONE_WAY_FROM_CLIENT
101406                                         || dsstate.mode == constant.ALERT_REFRESH_FROM_CLIENT ) ) ) )
101407                             return cb(new common.ProtocolError(
101408                                     'unexpected sync data (role="'
101409                                         + ( session.isServer ? 'server' : 'client' )
101410                                         + '", mode="' + common.mode2string(dsstate.mode)
101411                                         + '")'));
101412
101413                         common.cascade(command.data, function(cmd, cb) {
101414
101415                             // NOTE: commented this paranoia setting out, since the server
101416                             //       *may* decide to update/delete a client item...
101417                             //       e.g. conflict-resolved-merge (207)
101418                             // TODO: perhaps i should only allow non-ADDs for those items
101419                             //       that i received a conflict-resolved-merge (207) for?...
101420
101421                             // // paranoia: non-'add' sync commands should only be received in non-refresh modes
101422                             // if ( cmd.name != constant.CMD_ADD
101423                             //      && _.indexOf([constant.ALERT_TWO_WAY,
101424                             //                    constant.ALERT_ONE_WAY_FROM_SERVER,
101425                             //                    constant.ALERT_ONE_WAY_FROM_CLIENT], dsstate.mode) < 0 )
101426                             //   return cb(new common.ProtocolError(
101427                             //     'unexpected non-add sync command (role="'
101428                             //       + ( session.isServer ? 'server' : 'client' )
101429                             //       + '", mode="' + common.mode2string(dsstate.mode)
101430                             //       + '", command="' + cmd.name
101431                             //       + '")'));
101432
101433                             self._reaction_syncdispatch(session, cmd, store, dsstate, function(err, cmds) {
101434                                 if ( err )
101435                                 return cb(err);
101436                             _.each(cmds, function(cmd) { ret.push(cmd); });
101437                             return cb();
101438                             });
101439
101440                         }, function(err) {
101441                             if ( err )
101442                                 return cb(err);
101443                             return cb(null, ret);
101444                         });
101445                         });
101446                     },
101447
101448                     //-------------------------------------------------------------------------
101449                     _reaction_syncdispatch: function(session, cmd, store, dsstate, cb) {
101450
101451                         var self = this;
101452                         var func = self['_reaction_sync_' + cmd.name.toLowerCase()];
101453                         if ( ! func )
101454                             return cb(new common.ProtocolError(
101455                                         'unexpected reaction requested for sync command "' + cmd.name + '"'));
101456
101457                         var check_for_conflicts = common.noop;
101458
101459                         if ( session.isServer
101460                                 && cmd.name != constant.CMD_ADD
101461                                 && dsstate.mode != constant.ALERT_REFRESH_FROM_CLIENT )
101462                         {
101463                             // server, non-add, non-slowsync, non-refresh commands: check for conflicts.
101464                             // note that certain types of content could be a conflict even if it is an
101465                             // "Add" command; for example, two files with the same name cannot be added
101466                             // from separate clients.
101467
101468                             check_for_conflicts = function(cb) {
101469
101470                                 // todo: allow agents to raise a ConflictError...
101471                                 //       ==> perhaps this is already covered by the .matchItem() API?...
101472
101473                                 var policy = store.conflictPolicy || session.adapter.conflictPolicy;
101474                                 var peerStore = session.peer.getStore(dsstate.peerUri);
101475                                 self.getSourceMapping(
101476                                         session, constant.CMD_SYNC, cmd, peerStore, cmd.source,
101477                                         function(err, itemID) {
101478
101479                                             if ( err )
101480                                     return cb(err);
101481                                 if ( ! itemID )
101482                                     // this shouldn't happen...
101483                                     return cb();
101484
101485                                 peerStore._getChange(itemID, function(err, change) {
101486                                     if ( err )
101487                                     return cb(err);
101488                                 if ( ! change )
101489                                     return cb();
101490
101491                                 var retcmd = state.makeCommand({
101492                                     name       : constant.CMD_STATUS,
101493                                     cmdID      : session.nextCmdID(),
101494                                     msgRef     : cmd.msgID,
101495                                     cmdRef     : cmd.cmdID,
101496                                     sourceRef  : cmd.source,
101497                                     targetRef  : cmd.target,
101498                                     statusOf   : cmd.name,
101499                                     // todo: make this error message a bit more descriptive...
101500                                     errorMsg   : 'command "' + cmd.name + '" conflict for item ID "'
101501                                     + itemID + '" (state: ' + common.state2string(change.state) + ')'
101502                                 });
101503
101504
101505                                     // four possible states: mod-mod, mod-del, del-mod, del-del
101506                                     if ( ! dsstate.conflicts )
101507                                     dsstate.conflicts = [];
101508
101509                                     // handle mod-mod (but only if change-tracking is enabled)
101510                                     if ( change.state == constant.ITEM_MODIFIED
101511                                         && cmd.name == constant.CMD_REPLACE )
101512                                     {
101513                                         cmd._conflict = retcmd;
101514                                         cmd._change   = change;
101515                                         return cb();
101516                                     }
101517
101518                                     // handle del-del
101519                                     if ( change.state == constant.ITEM_DELETED
101520                                             && cmd.name == constant.CMD_DELETE )
101521                                     {
101522                                         // both changes are deletes... that's not a conflict.
101523                                         // TODO: should i really be doing all this here?... it does not
101524                                         //       follow the pattern..
101525                                         peerStore._delChange({
101526                                             itemID: change.item_id,
101527                                             state:  change.state
101528                                         }, function(err) {
101529                                             if ( err )
101530                                             return cb(err);
101531                                         dsstate.stats.peerDel   += 1;
101532                                         dsstate.stats.hereDel   += 1;
101533                                         dsstate.stats.merged    += 1;
101534                                         retcmd.statusCode = constant.STATUS_CONFLICT_RESOLVED_MERGE;
101535                                         retcmd.errorCode  = null;
101536                                         retcmd.errorMsg   = null;
101537                                         return cb(null, [retcmd]);
101538                                         });
101539                                         return;
101540                                     }
101541
101542                                     // handle del-mod or mod-del
101543                                     if ( ( change.state == constant.ITEM_DELETED
101544                                                 || cmd.name == constant.CMD_DELETE )
101545                                             && policy != constant.POLICY_ERROR )
101546                                     {
101547                                         // one of them is a delete and a conflict that can be solved
101548                                         // by the framework
101549                                         cmd._conflict = retcmd;
101550                                         cmd._change   = change;
101551                                         return cb();
101552                                     }
101553
101554                                     dsstate.conflicts.push(itemID);
101555                                     dsstate.stats.peerErr   += 1;
101556                                     dsstate.stats.conflicts += 1;
101557                                     retcmd.statusCode = constant.STATUS_UPDATE_CONFLICT;
101558                                     retcmd.errorCode  = 'syncml-js.synchronizer.RSd.10';
101559                                     return cb(null, [retcmd]);
101560                                 });
101561                                         }
101562                                 );
101563                             };
101564                         }
101565
101566                         check_for_conflicts(function(err, cmds) {
101567                             if ( err || cmds )
101568                             return cb(err, cmds);
101569                         try{
101570                             func.call(self, session, cmd, store, dsstate, cb);
101571                         }catch(e){
101572                             return cb(new common.InternalError(
101573                                     'failed invoking synchronizer sync reaction: ' + e, e));
101574                         }
101575                         });
101576
101577                     },
101578
101579                     //-------------------------------------------------------------------------
101580                     _reaction_sync_add: function(session, cmd, store, dsstate, cb) {
101581                         var curitem = null;
101582                         var item    = null;
101583                         if ( store.agent.hierarchicalSync )
101584                         {
101585                             if ( cmd.targetParent )
101586                                 cmd.data.parent = cmd.targetParent;
101587                             else if ( cmd.sourceParent )
101588                                 cmd.data.parent = session.hierlut[cmd.sourceParent];
101589                         }
101590
101591                         var matcher = common.noop;
101592                         if ( session.isServer && dsstate.mode == constant.ALERT_SLOW_SYNC )
101593                         {
101594                             // TODO: if the matched item is already mapped to another client-side
101595                             //       object, then this should cancel the matching...
101596                             matcher = function(cb) {
101597                                 store.agent.matchItem(cmd.data, function(err, match) {
101598                                     if ( err )
101599                                     return cb(err);
101600                                 if ( ! match || ! match.compare )
101601                                     return cb();
101602                                 curitem = match;
101603                                 if ( match.compare(cmd.data) == 0 )
101604                                     return cb();
101605                                 store.agent.mergeItems(curitem, cmd.data, null, function(err) {
101606                                     // TODO: if there is a common.ConflictError, set
101607                                     //       curitem to null and continue without error...
101608                                     if ( err )
101609                                     return cb(err);
101610                                 store.registerChange(curitem.id, constant.ITEM_MODIFIED,
101611                                     {changeSpec: cspec, excludePeerID: session.peer.id},
101612                                     cb);
101613                                 });
101614                                 });
101615                             };
101616                         }
101617
101618                         matcher(function(err) {
101619                             if ( err )
101620                             return cb(err);
101621                         var adder = common.noop;
101622                         if ( ! curitem )
101623                             adder = function(cb) {
101624                                 store.agent.addItem(cmd.data, function(err, newitem) {
101625                                     if ( err )
101626                                     return cb(err);
101627                                 item = newitem;
101628                                 dsstate.stats.hereAdd += 1;
101629                                 store.registerChange(item.id, constant.ITEM_ADDED,
101630                                     {excludePeerID: session.peer.id}, cb);
101631                                 });
101632                             };
101633                         else
101634                             item = curitem;
101635                         return adder(function(err) {
101636                             if ( err )
101637                             return cb(err);
101638
101639                         if ( store.agent.hierarchicalSync )
101640                             session.hierlut[cmd.source] = item.id;
101641
101642                         var ret = [state.makeCommand({
101643                             name       : constant.CMD_STATUS,
101644                             cmdID      : session.nextCmdID(),
101645                             msgRef     : cmd.msgID,
101646                             cmdRef     : cmd.cmdID,
101647                             sourceRef  : cmd.source,
101648                             statusOf   : cmd.name,
101649                             statusCode : ( curitem
101650                                 ? constant.STATUS_ALREADY_EXISTS
101651                                 : constant.STATUS_ITEM_ADDED )
101652                         })];
101653
101654                         if ( ! session.isServer )
101655                         {
101656                             ret.push(state.makeCommand({
101657                                 name       : constant.CMD_MAP,
101658                                 cmdID      : session.nextCmdID(),
101659                                 source     : store.uri,
101660                                 target     : dsstate.peerUri,
101661                                 sourceItem : item.id,
101662                                 targetItem : cmd.source
101663                             }));
101664                             return cb(null, ret);
101665                         }
101666
101667                         var peerStore = session.peer.getStore(dsstate.peerUri);
101668                         peerStore._setMapping(item.id, cmd.source, function(err) {
101669                             if ( err )
101670                             return cb(err);
101671                         return cb(null, ret);
101672                         });
101673
101674                         });
101675                         });
101676
101677                     },
101678
101679                     //-------------------------------------------------------------------------
101680                     getSourceMapping: function(session, cmdctxt, cmd, peerStore, luid, cb) {
101681                         peerStore._getReverseMapping(luid, function(err, guid) {
101682
101683                             if ( err )
101684                             return cb(err);
101685
101686                         if ( guid )
101687                             return cb(null, guid);
101688
101689                         return cb(new common.InvalidItem(
101690                                 'unexpected "' + cmdctxt + '/' + cmd.name
101691                                 + '" request for unmapped item ID "' + luid + '"'));
101692
101693                         // todo: pysyncml generates a nice cmd-specific error node:
101694                         //       (which is probably over-kill)
101695
101696                         //     curmap = adapter._context._model.Mapping.q(store_id=peerStore.id, luid=luid).one()
101697                         //     return str(curmap.guid)
101698                         //   except NoResultFound:
101699                         //     msg = 'unexpected "%s/%s" request for unmapped item ID: %r' % (cmdctxt, cmd.name, luid)
101700                         //     # todo: this is a bit of a hack when cmdctxt == 'Status'...
101701                         //     return state.Command(
101702                         //       name       = constant.CMD_STATUS,
101703                         //       cmdID      = session.nextCmdID(),
101704                         //       msgRef     = cmd.msgID,
101705                         //       cmdRef     = cmd.cmdID,
101706                         //       sourceRef  = cmd.source,
101707                         //       targetRef  = cmd.target,
101708                         //       statusOf   = cmd.name if cmdctxt != constant.CMD_STATUS else cmdctxt,
101709                         //       statusCode = constant.STATUS_COMMAND_FAILED,
101710                         //       errorCode  = __name__ + '.' + self.__class__.__name__ + '.GSM.10',
101711                         //       errorMsg   = msg,
101712                         //       )
101713
101714                         });
101715                     },
101716
101717                     //-------------------------------------------------------------------------
101718                     _reaction_sync_replace: function(session, cmd, store, dsstate, cb) {
101719
101720                         // TODO: handle hierarchical-sync...
101721                         var self = this;
101722                         var item = cmd.data;
101723                         var get_item_id = ( ! session.isServer ) ? function(cb) {
101724                             item.id = cmd.target;
101725                             return cb();
101726                         } : function(cb) {
101727                             var peerStore = session.peer.getStore(dsstate.peerUri);
101728                             self.getSourceMapping(
101729                                     session, constant.CMD_SYNC, cmd, peerStore, cmd.source,
101730                                     function(err, guid) {
101731
101732                                         if ( err )
101733                                 return cb(err);
101734
101735                             // todo: what if guid is null?...
101736
101737                             item.id = guid;
101738                             return cb();
101739                                     }
101740                                     );
101741                         };
101742
101743                         var okcmd = state.makeCommand({
101744                             name       : constant.CMD_STATUS,
101745                             cmdID      : session.nextCmdID(),
101746                             msgRef     : cmd.msgID,
101747                             cmdRef     : cmd.cmdID,
101748                             targetRef  : cmd.target,
101749                             sourceRef  : cmd.source,
101750                             statusOf   : cmd.name,
101751                             statusCode : constant.STATUS_OK
101752                         });
101753
101754                         var handle_conflict = ( ! cmd._conflict ) ? common.noop : function(cb) {
101755
101756                             //   if cmd._conflict is not None:
101757                             //     try:
101758                             //       if cmd._change.state == constant.ITEM_DELETED:
101759                             //         raise common.ConflictError('item deleted')
101760                             //       if cmd._change.changeSpec is None:
101761                             //         raise common.ConflictError('no change tracking enabled - falling back to policy')
101762                             //       cspec = store.agent.mergeItems(store.agent.getItem(item.id), item, cmd._change.changeSpec)
101763                             //       dsstate.stats.hereMod += 1
101764                             //       store.registerChange(item.id, constant.ITEM_MODIFIED,
101765                             //                            changeSpec=cspec, excludePeerID=adapter.peer.id)
101766                             //       okcmd.statusCode = constant.STATUS_CONFLICT_RESOLVED_MERGE
101767                             //       # NOTE: *not* suppressing the change that is registered from server
101768                             //       #       to client, since the merge may have resulted in an item that
101769                             //       #       is not identical to the one on the client.
101770                             //       return [okcmd]
101771                             //     except common.ConflictError, e:
101772                             //       # conflict types: client=mod/server=mod or client=mod/server=del
101773                             //       if store.conflictPolicy == constant.POLICY_CLIENT_WINS:
101774                             //         adapter._context._model.session.delete(cmd._change)
101775                             //         dsstate.stats.merged += 1
101776                             //         okcmd.statusCode = constant.STATUS_CONFLICT_RESOLVED_CLIENT_DATA
101777                             //         if cmd._change.state == constant.ITEM_DELETED:
101778                             //           # todo: this "re-creation" of a new item is detrimental to
101779                             //           #       clients that are tracking changes to an item (for
101780                             //           #       example, a SyncML svn client bridge...). but then, to
101781                             //           #       them, this item may already have been deleted. ugh.
101782                             //           dsstate.stats.hereMod += 1
101783                             //           item = store.agent.addItem(item)
101784                             //           peerStore = store.peer
101785                             //           adapter._context._model.Mapping.q(store_id=peerStore.id, guid=item.id).delete()
101786                             //           newmap = adapter._context._model.Mapping(store_id=peerStore.id,
101787                             //                                                    guid=item.id,
101788                             //                                                    luid=cmd.source)
101789                             //           adapter._context._model.session.add(newmap)
101790                             //           store.registerChange(item.id, constant.ITEM_ADDED,
101791                             //                                excludePeerID=adapter.peer.id)
101792                             //           return [okcmd]
101793                             //         # falling back to standard handling...
101794                             //       elif store.conflictPolicy == constant.POLICY_SERVER_WINS:
101795                             //         dsstate.stats.merged += 1
101796                             //         okcmd.statusCode = constant.STATUS_CONFLICT_RESOLVED_SERVER_DATA
101797                             //         return [okcmd]
101798                             //       else:
101799                             //         # store.conflictPolicy == constant.POLICY_ERROR or other...
101800                             //         dsstate.stats.peerErr    += 1
101801                             //         dsstate.stats.conflicts  += 1
101802                             //         cmd._conflict.errorMsg   += ', agent failed merge: ' + str(e)
101803                             //         cmd._conflict.statusCode = constant.STATUS_UPDATE_CONFLICT
101804                             //         cmd._conflict.errorCode  = common.fullClassname(self) + '.RSR.10'
101805                             //         dsstate.conflicts.append(str(item.id))
101806                             //         return [cmd._conflict]
101807
101808                             cb();
101809
101810                         };
101811
101812                         // TODO: support hierarchical-sync...
101813                         // if ( store.agent.hierarchicalSync )
101814                         //   session.hierlut[cmd.source] = item.id;
101815
101816                         get_item_id(function(err) {
101817                             if ( err )
101818                             return cb(err);
101819                         handle_conflict(function(err) {
101820                             if ( err )
101821                             return cb(err);
101822                         store.agent.replaceItem(item, session.isServer, function(err, cspec) {
101823                             if ( err )
101824                             return cb(err);
101825                         dsstate.stats.hereMod += 1;
101826                         store.registerChange(
101827                             item.id, constant.ITEM_MODIFIED,
101828                             {changeSpec: cspec, excludePeerID: session.peer.id},
101829                             function(err) {
101830                                 if ( err )
101831                             return cb(err);
101832                         return cb(null, [okcmd]);
101833                             }
101834                             );
101835                         });
101836                         });
101837                         });
101838
101839                     },
101840
101841                     //-------------------------------------------------------------------------
101842                     _reaction_sync_delete: function(session, cmd, store, dsstate, cb) {
101843
101844                         var self   = this;
101845                         var status = constant.STATUS_OK;
101846                         var itemID = null;
101847
101848                         var get_item_id = ( ! session.isServer ) ? function(cb) {
101849                             itemID = cmd.target;
101850                             return cb();
101851                         } : function(cb) {
101852                             var peerStore = session.peer.getStore(dsstate.peerUri);
101853                             self.getSourceMapping(
101854                                     session, constant.CMD_SYNC, cmd, peerStore, cmd.source,
101855                                     function(err, guid) {
101856
101857                                         // if not isinstance(itemID, basestring):
101858                                         //   return [itemID]
101859
101860                                         if ( err )
101861                                 return cb(err);
101862
101863                             // todo: what if guid is null?...
101864
101865                             itemID = guid;
101866                             if ( ! cmd._conflict )
101867                                 return cb();
101868                             var policy = store.conflictPolicy || session.adapter.conflictPolicy;
101869                             switch ( policy )
101870                             {
101871
101872                                 case constant.POLICY_CLIENT_WINS:
101873                                     {
101874
101875
101876                                         // TODO ::: implement these...
101877
101878                                         //   //     adapter._context._model.session.delete(cmd._change)
101879                                         //   //     status = constant.STATUS_CONFLICT_RESOLVED_CLIENT_DATA
101880                                         //   //     session.dsstates[store.uri].stats.merged += 1
101881                                         //   //     # falling back to standard handling...
101882
101883                                         //   break;
101884
101885                                     }
101886                                 case constant.POLICY_SERVER_WINS:
101887                                     {
101888
101889
101890                                         //   //     adapter._context._model.session.delete(cmd._change)
101891                                         //   //     store.peer.registerChange(itemID, constant.ITEM_ADDED)
101892                                         //   //     session.dsstates[store.uri].stats.merged += 1
101893                                         //   //     cmd._conflict.statusCode = constant.STATUS_CONFLICT_RESOLVED_SERVER_DATA
101894                                         //   //     cmd._conflict.errorCode  = None
101895                                         //   //     cmd._conflict.errorMsg   = None
101896                                         //   //     return [cmd._conflict]
101897
101898                                         //   break;
101899
101900                                     }
101901
101902                                 default:
101903                                     {
101904                                         // a constant.POLICY_ERROR policy should have been handled by the dispatch
101905                                         return cb(new common.InternalError(
101906                                                     'unexpected conflictPolicy: %s', '' + policy));
101907                                     }
101908                             }
101909                                     }
101910                             );
101911
101912                         };
101913
101914                         get_item_id(function(err) {
101915                             if ( err )
101916                             return cb(err);
101917                         store.agent.deleteItem(itemID, function(err) {
101918                             if ( err )
101919                             return cb(err);
101920                         dsstate.stats.hereDel += 1;
101921                         store.registerChange(
101922                             itemID, constant.ITEM_DELETED, {excludePeerID: session.peer.id},
101923                             function(err) {
101924                                 if ( err )
101925                             return cb(err);
101926                         return cb(null, [state.makeCommand({
101927                             name       : constant.CMD_STATUS,
101928                                cmdID      : session.nextCmdID(),
101929                                msgRef     : cmd.msgID,
101930                                cmdRef     : cmd.cmdID,
101931                                targetRef  : cmd.target,
101932                                sourceRef  : cmd.source,
101933                                statusOf   : cmd.name,
101934                                // todo: should this return DELETE_WITHOUT_ARCHIVE instead of OK?...
101935                                // statusCode = constant.STATUS_DELETE_WITHOUT_ARCHIVE,
101936                                statusCode : status
101937                         })]);
101938                             }
101939                             );
101940                         });
101941                         });
101942
101943                     },
101944
101945                     //-------------------------------------------------------------------------
101946                     _reaction_map: function(session, command, cb) {
101947                         var peerStore = session.peer.getStore(command.source);
101948                         if ( command.target != peerStore._getBinding().uri )
101949                             return cb(new common.NoSuchRoute(
101950                                         'unexpected "Map" event for unbound stores (local: "'
101951                                             + command.target + ', remote: "' + command.source + '")'));
101952                         common.cascade(command.items, function(item, cb) {
101953                             // todo: support hierarchical sync...
101954                             peerStore._setMapping(item.target, item.source, cb);
101955                         }, function(err) {
101956                             if ( err )
101957                             return cb(err);
101958                         return cb(null, [state.makeCommand({
101959                             name       : constant.CMD_STATUS,
101960                                cmdID      : session.nextCmdID(),
101961                                msgRef     : command.msgID,
101962                                cmdRef     : command.cmdID,
101963                                targetRef  : command.target,
101964                                sourceRef  : command.source,
101965                                statusOf   : command.name,
101966                                statusCode : constant.STATUS_OK
101967                         })]);
101968                         });
101969                     },
101970
101971                     //-------------------------------------------------------------------------
101972                     // SYNCHRONIZATION PHASE: SETTLE
101973                     //-------------------------------------------------------------------------
101974
101975                     //-------------------------------------------------------------------------
101976                     settle: function(session, cmd, chkcmd, xnode, cb) {
101977
101978                         // TODO: remove the "xnode" parameter... it is a hack so that i can
101979                         //       call badStatus() the same way as in protocol.js
101980                         // todo: there is a bit of a disconnect between how action and reaction
101981                         //       phases are called (for a list of commands), whereas the settle
101982                         //       phase is called on a per-item basis... not ideal, but the protocol
101983                         //       is really set up that way :(
101984                         // TODO: check all valid values of ``data``...
101985                         // todo: anything else in common?...
101986                         // todo: trap errors...
101987
101988                         var func = this['_settle_' + cmd.name.toLowerCase()];
101989                         if ( ! func )
101990                             return cb(new common.ProtocolError('unexpected settle command "' + cmd.name + '"'));
101991                         return func.call(this, session, cmd, chkcmd, xnode, cb);
101992                     },
101993
101994                     //-------------------------------------------------------------------------
101995                     _settle_add: function(session, cmd, chkcmd, xnode, cb) {
101996                         switch ( cmd.data )
101997                         {
101998                             default:
101999                                 {
102000                                     return cb(badStatus(xnode));
102001                                 }
102002                             case constant.STATUS_OK:
102003                             case constant.STATUS_ITEM_ADDED:
102004                             case constant.STATUS_CONFLICT_RESOLVED_DUPLICATE:
102005                                 {
102006                                     session.info.dsstates[chkcmd.uri].stats.peerAdd += 1;
102007                                     break;
102008                                 }
102009                             case constant.STATUS_ALREADY_EXISTS:
102010                             case constant.STATUS_CONFLICT_RESOLVED_MERGE:
102011                                 // todo: should this conflict-resolved-merge status be stored so
102012                                 //       that only this item can have a non-"ADD" during initial
102013                                 //       sync?...
102014                             case constant.STATUS_CONFLICT_RESOLVED_CLIENT_DATA:
102015                                 {
102016                                     session.info.dsstates[chkcmd.uri].stats.merged += 1;
102017                                     break;
102018                                 }
102019                         }
102020
102021                         var peerStore = session.peer.getStore(
102022                                 session.context.router.getTargetUri(
102023                                     session.adapter, session.peer, chkcmd.uri));
102024
102025                         peerStore._delChange({
102026                             itemID: chkcmd.source,
102027                             state: constant.ITEM_ADDED
102028                         }, cb);
102029                     },
102030
102031                     //-------------------------------------------------------------------------
102032                     _settle_replace: function(session, cmd, chkcmd, xnode, cb) {
102033
102034                         var self = this;
102035                         var dsstate = session.info.dsstates[chkcmd.uri];
102036
102037                         if ( ! session.isServer && cmd.data == constant.STATUS_UPDATE_CONFLICT )
102038                         {
102039                             dsstate.stats.hereErr   += 1;
102040                             dsstate.stats.conflicts += 1;
102041                             return cb();
102042                         }
102043                         if ( cmd.data != constant.STATUS_OK
102044                                 && cmd.data != constant.STATUS_CONFLICT_RESOLVED_MERGE
102045                                 && cmd.data != constant.STATUS_CONFLICT_RESOLVED_CLIENT_DATA
102046                                 && cmd.data != constant.STATUS_CONFLICT_RESOLVED_SERVER_DATA )
102047                             return cb(badStatus(xnode));
102048                         if ( cmd.data == constant.STATUS_CONFLICT_RESOLVED_MERGE
102049                                 || cmd.data == constant.STATUS_CONFLICT_RESOLVED_CLIENT_DATA
102050                                 || cmd.data == constant.STATUS_CONFLICT_RESOLVED_SERVER_DATA )
102051                             dsstate.stats.merged += 1;
102052                         if ( cmd.data != constant.STATUS_CONFLICT_RESOLVED_SERVER_DATA )
102053                             dsstate.stats.peerMod += 1;
102054
102055                         var peerStore = session.peer.getStore(
102056                                 session.context.router.getTargetUri(
102057                                     session.adapter, session.peer, chkcmd.uri));
102058
102059                         var get_item_id = ( ! session.isServer ) ? function(cb) {
102060                             return cb(null, chkcmd.source);
102061                         } : function(cb) {
102062                             // if not isinstance(locItemID, basestring):
102063                             //   return locItemID
102064
102065                             self.getSourceMapping(
102066                                     session, constant.CMD_STATUS, cmd, peerStore, chkcmd.target,
102067                                     function(err, guid) { return cb(err, guid); }
102068                                     );
102069                         };
102070
102071                         get_item_id(function(err, locItemID) {
102072
102073                             if ( err )
102074                             return cb(err);
102075
102076                         // todo: this is *technically* subject to a race condition... but the
102077                         //       same peer should really not be synchronizing at the same time...
102078                         // todo: also potentially check Change.registered...
102079                         // TODO: this could be solved by:
102080                         //         a) never updating a Change record (only deleting and replacing)
102081                         //         b) deleting Change records by ID instead of by store/item/state...
102082
102083                         peerStore._delChange({
102084                             itemID    : locItemID,
102085                             state     : constant.ITEM_MODIFIED,
102086                         }, cb);
102087
102088                         });
102089
102090                     },
102091
102092                     //-------------------------------------------------------------------------
102093                     _settle_delete: function(session, cmd, chkcmd, xnode, cb) {
102094                         var self    = this;
102095                         var dsstate = session.info.dsstates[chkcmd.uri];
102096                         if ( ! session.isServer && cmd.data == constant.STATUS_UPDATE_CONFLICT )
102097                         {
102098                             dsstate.stats.hereErr   += 1;
102099                             dsstate.stats.conflicts += 1;
102100                             return cb();
102101                         }
102102                         if ( ! session.isServer && cmd.data == constant.STATUS_CONFLICT_RESOLVED_MERGE )
102103                         {
102104                             dsstate.stats.hereDel   += 1;
102105                             dsstate.stats.peerDel   += 1;
102106                             dsstate.stats.merged    += 1;
102107                         }
102108                         else if ( ! session.isServer && cmd.data == constant.STATUS_CONFLICT_RESOLVED_CLIENT_DATA )
102109                         {
102110                             dsstate.stats.peerDel   += 1;
102111                             dsstate.stats.merged    += 1;
102112                         }
102113                         else if ( ! session.isServer && cmd.data == constant.STATUS_CONFLICT_RESOLVED_SERVER_DATA )
102114                             dsstate.stats.merged    += 1;
102115                         else if ( cmd.data == constant.STATUS_ITEM_NOT_DELETED )
102116                         {
102117                             // note: the reason that this *may* be ok is that some servers (funambol)
102118                             //       will report ITEM_NOT_DELETED when the item did not exist, thus this
102119                             //       is "alright"...
102120                             // todo: perhaps this should be raised as an error if the
102121                             //       remote peer != funambol?...
102122                         }
102123                         else if ( cmd.data == constant.STATUS_OK )
102124                             dsstate.stats.peerDel += 1;
102125                         else
102126                             return cb(badStatus(xnode));
102127
102128                         var peerStore = session.peer.getStore(
102129                                 session.context.router.getTargetUri(
102130                                     session.adapter, session.peer, chkcmd.uri));
102131
102132                         // todo: handle hierarchical sync...
102133                         var get_locItemID = ( ! chkcmd.target ) ? function(cb) {
102134                             cb(null, chkcmd.source);
102135                         } : function(cb) {
102136                             self.getSourceMapping(
102137                                     session, constant.CMD_STATUS, cmd, peerStore, chkcmd.target,
102138                                     function(err, guid) { return cb(err, guid); }
102139                                     );
102140                         };
102141
102142                         // todo: this is *technically* subject to a race condition... but the
102143                         //       same peer should really not be synchronizing at the same time...
102144                         // todo: also potentially check Change.registered...
102145                         // TODO: this could be solved by:
102146                         //         a) never updating a Change record (only deleting and replacing)
102147                         //         b) deleting Change records by ID instead of by store/item/state...
102148
102149                         get_locItemID(function(err, locItemID) {
102150                             if ( err )
102151                             return cb(err);
102152                         peerStore._delChange({
102153                             itemID    : locItemID,
102154                             state     : constant.ITEM_DELETED,
102155                         }, cb);
102156                         });
102157
102158                     }
102159
102160     });
102161
102162     return exports;
102163
102164 })();
102165
102166 module.exports = _self;
102167
102168 });
102169 define('ripple/platform/tizen/2.0/syncml-js-lib/useragent', function (require, exports, module) {
102170 // -*- coding: utf-8 -*-
102171 //-----------------------------------------------------------------------------
102172 // file: $Id$
102173 // lib:  syncml-js.useragent
102174 // auth: griffin <griffin@uberdev.org>
102175 // date: 2013/06/07
102176 // copy: (C) CopyLoose 2013 UberDev <hardcore@uberdev.org>, No Rights Reserved.
102177 //-----------------------------------------------------------------------------
102178
102179 var common = require('ripple/platform/tizen/2.0/syncml-js-lib/common'),
102180     constant = require('ripple/platform/tizen/2.0/syncml-js-lib/constant'),
102181     _self;
102182
102183 _self = (function () {
102184     var exports = {};
102185
102186     //---------------------------------------------------------------------------
102187     exports.UserAgent = common.Base.extend({
102188         // primary handlers:
102189         acceptSyncModeSwitch:  null, // function(EVENT, CALLBACK(ERR))
102190             acceptDevInfoSwap:     null, // function(EVENT, CALLBACK(ERR))
102191             chooseRefreshRequired: null, // function(EVENT, CALLBACK(ERR, TYPE))
102192             fetchCredentials:      null, // function(EVENT, CALLBACK(ERR, AUTH))
102193             // fallback handlers:
102194             accept:                null, // function(TYPE, EVENT, CALLBACK(ERR))
102195             choose:                null, // function(TYPE, EVENT, CALLBACK(ERR, CHOICE))
102196             fetch:                 null, // function(TYPE, EVENT, CALLBACK(ERR, STRUCT))
102197             // catchall handler:
102198             handle:                null  // function(ACTION, TYPE, EVENT, CALLBACK(ERR, RESULT...))
102199     });
102200
102201     //---------------------------------------------------------------------------
102202     exports.UserAgentMultiplexer = common.Base.extend({
102203
102204         //-------------------------------------------------------------------------
102205         constructor: function(uaList) {
102206             this.ualist = uaList;
102207         },
102208
102209         //-------------------------------------------------------------------------
102210         _getHandler: function(name) {
102211             for ( var idx=0 ; idx<this.ualist.length ; idx++ )
102212     {
102213         var ua = this.ualist[idx];
102214         if ( ua && _.isFunction(ua[name]) )
102215         return ua[name];
102216     }
102217     return null;
102218         },
102219
102220         //-------------------------------------------------------------------------
102221         hasHandler: function(name) {
102222             return !! this._getHandler(name);
102223         },
102224
102225         //-------------------------------------------------------------------------
102226         acceptSyncModeSwitch: function(event, cb) {
102227             return this._handle({
102228                 handler: 'acceptSyncModeSwitch',
102229             action:  'accept',
102230             type:    'sync.mode.switch'
102231             }, event, cb);
102232         },
102233
102234         //-------------------------------------------------------------------------
102235         acceptDevInfoSwap: function(event, cb) {
102236             return this._handle({
102237                 handler: 'acceptDevInfoSwap',
102238             action:  'accept',
102239             type:    'dev.info.swap'
102240             }, event, cb);
102241         },
102242
102243         //-------------------------------------------------------------------------
102244         chooseRefreshRequired: function(event, cb) {
102245             return this._handle({
102246                 handler: 'chooseRefreshRequired',
102247             action:  'choose',
102248             type:    'refresh.required',
102249             choices: [
102250             {value: constant.SYNCTYPE_SLOW_SYNC, default: true},
102251             {value: constant.SYNCTYPE_REFRESH_FROM_CLIENT},
102252             {value: constant.SYNCTYPE_REFRESH_FROM_SERVER}
102253             ]
102254             }, event, function(err, choice) {
102255                 if ( err )
102256                 return cb(err);
102257             // todo: catch the condition where `choice` is not a valid synctype
102258             return cb(err, common.synctype2alert(choice));
102259             });
102260         },
102261
102262         //-------------------------------------------------------------------------
102263         fetchCredentials: function(event, cb) {
102264             return this._handle({
102265                 handler: 'fetchCredentials',
102266             action:  'fetch',
102267             type:    'auth.challenge',
102268             choices: [
102269             {value: constant.SYNCTYPE_SLOW_SYNC, default: true},
102270             {value: constant.SYNCTYPE_REFRESH_FROM_CLIENT},
102271             {value: constant.SYNCTYPE_REFRESH_FROM_SERVER}
102272             ]
102273             }, event, cb);
102274         },
102275
102276         //-------------------------------------------------------------------------
102277         _handle: function(spec, event, cb) {
102278             event = _.extend({}, spec, event, {
102279                 type         : spec.type,
102280             context      : event.session.context,
102281             adapter      : event.session.adapter,
102282             peer         : event.session.peer,
102283             ua_handler   : spec.handler,
102284             ua_action    : spec.action
102285             });
102286             var handler = this._getHandler(spec.handler);
102287             if ( handler )
102288                 return handler(event, cb);
102289             handler = this._getHandler(spec.action);
102290             if ( handler )
102291                 return handler(spec.type, event, cb);
102292             handler = this._getHandler('handle');
102293             if ( handler )
102294                 return handler(spec.action, spec.type, event, cb);
102295             if ( spec.action == 'accept' )
102296             {
102297                 return cb();
102298             }
102299             if ( spec.action == 'choose'
102300                     && event.choices && event.choices.length > 0 )
102301             {
102302                 var choice = _.find(event.choices, function(c) { return c.default; });
102303                 if ( ! choice )
102304                     choice = event.choices[0];
102305                 if ( choice.value )
102306                     choice = choice.value;
102307                 return cb(null, choice);
102308             }
102309             if ( spec.type == 'auth.challenge' )
102310                 return cb();
102311             return cb(new common.NotImplementedError(
102312                         'user-agent handler for event type "' + spec.type + '" (action: "'
102313                             + spec.action + '") not found or defined'));
102314         }
102315
102316     });
102317
102318     return exports;
102319
102320 })();
102321
102322 module.exports = _self;
102323
102324 });
102325 define('ripple/platform/tizen/2.0/systeminfo', function (require, exports, module) {
102326 /*
102327  *  Copyright 2011 Intel Corporation.
102328  *
102329  * Licensed under the Apache License, Version 2.0 (the "License");
102330  * you may not use this file except in compliance with the License.
102331  * You may obtain a copy of the License at
102332  *
102333  * http://www.apache.org/licenses/LICENSE-2.0
102334  *
102335  * Unless required by applicable law or agreed to in writing, software
102336  * distributed under the License is distributed on an "AS IS" BASIS,
102337  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
102338  * See the License for the specific language governing permissions and
102339  * limitations under the License.
102340  */
102341
102342 var deviceSettings = require('ripple/deviceSettings'),
102343     db = require('ripple/db'),
102344     t = require('ripple/platform/tizen/2.0/typedef'),
102345     TypeCoerce = require('ripple/platform/tizen/2.0/typecoerce'),
102346     constants = require('ripple/constants'),
102347     event = require('ripple/event'),
102348     tizen_utils = require('ripple/platform/tizen/2.0/tizen1_utils'),
102349     errorcode = require('ripple/platform/tizen/2.0/errorcode'),
102350     WebAPIError = require('ripple/platform/tizen/2.0/WebAPIError'),
102351     WebAPIException = require('ripple/platform/tizen/2.0/WebAPIException'),
102352     _systemInfoProperties = ["BATTERY", "CPU", "STORAGE", "DISPLAY", "DEVICE_ORIENTATION", "BUILD", "LOCALE", "NETWORK", "WIFI_NETWORK", "CELLULAR_NETWORK", "SIM", "PERIPHERAL"],
102353     _propertyMap = {}, // Object like: {"BATTERY": ["level", "isCharging"], ...}
102354     _batteryEvent = ["BatteryLevelChanged", "BatteryChargingChanged"],
102355     _watches = {},
102356     _powerData = {},
102357     _security = {
102358         "http://tizen.org/privilege/system": ["SystemInfoSIM", "webApiVersion", "nativeApiVersion", "platformVersion"],
102359         "http://tizen.org/privilege/systemmanager": ["NetworkImei"]
102360     },
102361     _self;
102362
102363 function  _prepareObj(obj, aspect, property, value) {
102364     if ((aspect === "CELLULAR_NETWORK") && (property === "imei")) {
102365         obj.__defineGetter__("imei", function () {
102366             if (!_security.NetworkImei) {
102367                 throw new WebAPIError(errorcode.SECURITY_ERR);
102368             }
102369             return deviceSettings.retrieve("CELLULAR_NETWORK.imei");
102370         });
102371     } else {
102372         if (aspect === "WIFI_NETWORK" || aspect === "CELLULAR_NETWORK") {
102373             if (property === 'status') {
102374                 if (value === true) {
102375                     value = "ON";
102376                 } else {
102377                     value = "OFF";
102378                 }
102379             }
102380         }
102381         obj.__defineGetter__(property, function () {
102382             return value;
102383         });
102384     }
102385 }
102386
102387 function _getValue(aspect, successCallback) {
102388     var properties = [], value, index = 0, property, obj = {};
102389
102390     if ((aspect === "SIM") && !_security.SystemInfoSIM) {
102391         throw new WebAPIError(errorcode.SECURITY_ERR);
102392     }
102393
102394     if (aspect === "BATTERY") {
102395         successCallback(_powerData);
102396         return;
102397     }
102398
102399     properties = _propertyMap[aspect];
102400     for (; index < properties.length; index++) {
102401         property = properties[index];
102402         value = deviceSettings.retrieve(aspect + "." + property);
102403         _prepareObj(obj, aspect, property, value);
102404     }
102405
102406     if (aspect === "STORAGE") {
102407         obj.__defineGetter__("units", function () {
102408             return [obj];
102409         });
102410     }
102411
102412     successCallback(obj);
102413 }
102414
102415 function _initialize() {
102416     var aspectName, index, i, vol;
102417
102418     for (index = 0; index < _systemInfoProperties.length; index++) {
102419         aspectName = _systemInfoProperties[index];
102420         _propertyMap[aspectName] = [];
102421         for (i in deviceSettings.retrieve(aspectName)) {
102422             _propertyMap[aspectName].push(i);
102423         }
102424     }
102425
102426     _propertyMap.BATTERY.push("level");
102427     _propertyMap.BATTERY.push("isCharging");
102428
102429     _powerData.__defineGetter__("isCharging", function () {
102430         return false;
102431     });
102432
102433     vol = db.retrieve(constants.BATTERY.VOLUME) || 100.0;
102434     _powerData.__defineGetter__("level", function () {
102435         return Number((vol / 100.0).toFixed(4));
102436     });
102437
102438     event.on("BatteryEvent", function (status) {
102439         _powerData.__defineGetter__("isCharging", function () {
102440             return status.charging;
102441         });
102442         _powerData.__defineGetter__("level", function () {
102443             return Number(status.level.toFixed(4));
102444         });
102445     });
102446 }
102447
102448 function _isPropertyFound(propertyId) {
102449     if (tizen_utils.isEmptyObject(_propertyMap)) {
102450         _initialize();
102451     }
102452
102453     if (_propertyMap[propertyId]) {
102454         return true;
102455     }
102456
102457     return false;
102458 }
102459
102460 function _rtnCapability() {
102461     var _self = {};
102462
102463     _self.__defineGetter__("bluetooth", function () {
102464         return true;
102465     });
102466     _self.__defineGetter__("nfc", function () {
102467         return true;
102468     });
102469     _self.__defineGetter__("nfcReservedPush", function () {
102470         return false;
102471     });
102472     _self.__defineGetter__("multiTouchCount", function () {
102473         return 5;
102474     });
102475     _self.__defineGetter__("inputKeyboard", function () {
102476         return false;
102477     });
102478     _self.__defineGetter__("inputKeyboardLayout", function () {
102479         return false;
102480     });
102481     _self.__defineGetter__("wifi", function () {
102482         return true;
102483     });
102484     _self.__defineGetter__("wifiDirect", function () {
102485         return true;
102486     });
102487     _self.__defineGetter__("opengles", function () {
102488         return false;
102489     });
102490     _self.__defineGetter__("openglestextureFormat", function () {
102491         return "3dc";
102492     });
102493     _self.__defineGetter__("openglesVersion1_1", function () {
102494         return false;
102495     });
102496     _self.__defineGetter__("openglesVersion2_0", function () {
102497         return false;
102498     });
102499     _self.__defineGetter__("fmRadio", function () {
102500         return false;
102501     });
102502     _self.__defineGetter__("platformVersion", function () {
102503         if (!_security.platformVersion) {
102504             throw new WebAPIError(errorcode.SECURITY_ERR);
102505         }
102506         return "2.2";
102507     });
102508     _self.__defineGetter__("webApiVersion", function () {
102509         if (!_security.webApiVersion) {
102510             throw new WebAPIError(errorcode.SECURITY_ERR);
102511         }
102512         return "2.2";
102513     });
102514     _self.__defineGetter__("nativeApiVersion", function () {
102515         if (!_security.nativeApiVersion) {
102516             throw new WebAPIError(errorcode.SECURITY_ERR);
102517         }
102518         return "2.2";
102519     });
102520     _self.__defineGetter__("platformName", function () {
102521         return "Tizen";
102522     });
102523     _self.__defineGetter__("camera", function () {
102524         return false;
102525     });
102526     _self.__defineGetter__("cameraFront", function () {
102527         return false;
102528     });
102529     _self.__defineGetter__("cameraFrontFlash", function () {
102530         return false;
102531     });
102532     _self.__defineGetter__("cameraBack", function () {
102533         return false;
102534     });
102535     _self.__defineGetter__("cameraBackFlash", function () {
102536         return false;
102537     });
102538     _self.__defineGetter__("location", function () {
102539         return true;
102540     });
102541     _self.__defineGetter__("locationGps", function () {
102542         return true;
102543     });
102544     _self.__defineGetter__("locationWps", function () {
102545         return false;
102546     });
102547     _self.__defineGetter__("microphone", function () {
102548         return false;
102549     });
102550     _self.__defineGetter__("usbHost", function () {
102551         return false;
102552     });
102553     _self.__defineGetter__("usbAccessory", function () {
102554         return false;
102555     });
102556     _self.__defineGetter__("screenOutputRca", function () {
102557         return false;
102558     });
102559     _self.__defineGetter__("screenOutputHdmi", function () {
102560         return false;
102561     });
102562     _self.__defineGetter__("platformCoreCpuArch", function () {
102563         return "x86";
102564     });
102565     _self.__defineGetter__("platformCoreFpuArch", function () {
102566         return "ssse3";
102567     });
102568     _self.__defineGetter__("sipVoip", function () {
102569         return false;
102570     });
102571     _self.__defineGetter__("duid", function () {
102572         return "device unique ID";
102573     });
102574     _self.__defineGetter__("speechRecognition", function () {
102575         return false;
102576     });
102577     _self.__defineGetter__("speechSynthesis", function () {
102578         return false;
102579     });
102580     _self.__defineGetter__("accelerometer", function () {
102581         return true;
102582     });
102583     _self.__defineGetter__("accelerometerWakeup", function () {
102584         return false;
102585     });
102586     _self.__defineGetter__("barometer", function () {
102587         return false;
102588     });
102589     _self.__defineGetter__("barometerWakeup", function () {
102590         return false;
102591     });
102592     _self.__defineGetter__("gyroscope", function () {
102593         return true;
102594     });
102595     _self.__defineGetter__("gyroscopeWakeup", function () {
102596         return false;
102597     });
102598     _self.__defineGetter__("magnetometer", function () {
102599         return false;
102600     });
102601     _self.__defineGetter__("magnetometerWakeup", function () {
102602         return false;
102603     });
102604     _self.__defineGetter__("photometer", function () {
102605         return false;
102606     });
102607     _self.__defineGetter__("photometerWakeup", function () {
102608         return false;
102609     });
102610     _self.__defineGetter__("proximity", function () {
102611         return false;
102612     });
102613     _self.__defineGetter__("proximityWakeup", function () {
102614         return false;
102615     });
102616     _self.__defineGetter__("tiltmeter", function () {
102617         return false;
102618     });
102619     _self.__defineGetter__("tiltmeterWakeup", function () {
102620         return false;
102621     });
102622     _self.__defineGetter__("dataEncryption", function () {
102623         return false;
102624     });
102625     _self.__defineGetter__("graphicsAcceleration", function () {
102626         return false;
102627     });
102628     _self.__defineGetter__("push", function () {
102629         return true;
102630     });
102631     _self.__defineGetter__("telephony", function () {
102632         return true;
102633     });
102634     _self.__defineGetter__("telephonyMms", function () {
102635         return true;
102636     });
102637     _self.__defineGetter__("telephonySms", function () {
102638         return true;
102639     });
102640     _self.__defineGetter__("screenSizeNormal", function () {
102641         return true;
102642     });
102643     _self.__defineGetter__("screenSize480_800", function () {
102644         return true;
102645     });
102646     _self.__defineGetter__("screenSize720_1280", function () {
102647         return true;
102648     });
102649     _self.__defineGetter__("autoRotation", function () {
102650         return true;
102651     });
102652     _self.__defineGetter__("shellAppWidget", function () {
102653         return false;
102654     });
102655     _self.__defineGetter__("visionImageRecognition", function () {
102656         return false;
102657     });
102658     _self.__defineGetter__("visionQrcodeGeneration", function () {
102659         return false;
102660     });
102661     _self.__defineGetter__("visionQrcodeRecognition", function () {
102662         return false;
102663     });
102664     _self.__defineGetter__("visionFaceRecognition", function () {
102665         return false;
102666     });
102667     _self.__defineGetter__("secureElement", function () {
102668         return false;
102669     });
102670     _self.__defineGetter__("nativeOspCompatible", function () {
102671         return false;
102672     });
102673     _self.__defineGetter__("inputKeyBack", function () {
102674         return true;
102675     });
102676     _self.__defineGetter__("inputKeyMenu", function () {
102677         return true;
102678     });
102679     return _self;
102680 }
102681
102682
102683 function _delayGetValue(timeout, propertyId, successCallback, errorCallback) {
102684     return setInterval(function () {
102685         _getValue(propertyId, successCallback, errorCallback);
102686     }, timeout);
102687 }
102688
102689 _self = function () {
102690     function getCapabilities() {
102691         return _rtnCapability();
102692     }
102693
102694     function getPropertyValue(propertyId, successCallback, errorCallback) {
102695         if (arguments.length === 2) {
102696             errorCallback = null;
102697         }
102698         if (!(new TypeCoerce(t.DOMString)).match(propertyId)) {
102699             throw new WebAPIException(errorcode.TYPE_MISMATCH_ERR);
102700         }
102701         if (_isPropertyFound(propertyId) === false) {
102702             throw new WebAPIException(errorcode.TYPE_MISMATCH_ERR);
102703         }
102704         if (!(new TypeCoerce(t.SuccessCallback)).match(successCallback)) {
102705             throw new WebAPIException(errorcode.TYPE_MISMATCH_ERR);
102706         }
102707         if (!(new TypeCoerce(t.ErrorCallback)).match(errorCallback) && (arguments.length !== 2)) {
102708             throw new WebAPIException(errorcode.TYPE_MISMATCH_ERR);
102709         }
102710
102711         return tizen_utils.validateTypeMismatch(successCallback, errorCallback, "getPropertyValue", function () {
102712
102713             setTimeout(_getValue(propertyId, successCallback, errorCallback), 1); // Simulate a async operation
102714
102715             return null;
102716         });
102717     }
102718
102719     function addPropertyValueChangeListener(propertyId, successCallback, options) {
102720     // no error callback in spec, as of 2.0.0 RC7.
102721         var WatchOBJ;
102722         if (arguments.length === 2) {
102723             options = null;
102724         }
102725         if (!(new TypeCoerce(t.DOMString)).match(propertyId)) {
102726             throw new WebAPIException(errorcode.TYPE_MISMATCH_ERR);
102727         }
102728         if (_isPropertyFound(propertyId) === false) {
102729             throw new WebAPIException(errorcode.TYPE_MISMATCH_ERR);
102730         }
102731         if (!(new TypeCoerce(t.SuccessCallback)).match(successCallback)) {
102732             throw new WebAPIException(errorcode.TYPE_MISMATCH_ERR);
102733         }
102734         if (options !== null) {
102735             if ((typeof options !== 'object') ||
102736                (options.hasOwnProperty("timeout") && typeof options.timeout !== 'number') ||
102737                (options.hasOwnProperty("highThrashold") && typeof options.highThrashold !== 'number') ||
102738                (options.hasOwnProperty("lowThrashold") && typeof options.lowThrashold !== 'number'))
102739             {
102740                 throw new WebAPIException(errorcode.TYPE_MISMATCH_ERR);
102741             }
102742         }
102743         WatchOBJ = function (deviceEventType, propertyId, successCallback) {
102744             var obj = this;
102745             this.eventType = deviceEventType;
102746             this.onEvent = function (newValue) {
102747                 if (obj.timeout) {
102748                     clearInterval(obj.intervalId);
102749                     obj.intervalId = setInterval(function () {
102750                         _getValue(propertyId, successCallback, null);
102751                     }, obj.timeout);
102752                 }
102753
102754                 if ((obj.highThreshold && (newValue < obj.highThreshold)) ||
102755                     (obj.lowThreshold && (newValue > obj.lowThreshold))) {
102756                     return;
102757                 }
102758
102759                 _getValue(propertyId, successCallback, null);
102760             };
102761         };
102762
102763         return tizen_utils.validateTypeMismatch(successCallback, null, "addPropertyValueChangeListener", function () {
102764             var watchId = (new Date()).getTime(),
102765                 _options = new Object(options),
102766                 properties, property, index = 0, deviceEventType, watchObj;
102767
102768             // A listener will listen all the properties of one aspect, each of the property
102769             // will have an internal watchObj to record the information.
102770             _watches[watchId] = [];
102771
102772             if (propertyId === "BATTERY") {
102773                 properties = _batteryEvent;
102774             } else {
102775                 properties = _propertyMap[propertyId];
102776             }
102777
102778             for (; index < properties.length; index++) {
102779                 property = properties[index];
102780                 if (propertyId === "BATTERY") {
102781                     deviceEventType = property;
102782                 } else {
102783                     deviceEventType = deviceSettings.retrieve(propertyId)[property].event;
102784                 }
102785
102786                 if (deviceEventType === undefined) continue;
102787                 // These two items are needed when delete an event listener.
102788                 watchObj = new WatchOBJ(deviceEventType, propertyId, successCallback);
102789
102790                 if (options && _options.timeout) {
102791                     watchObj.intervalId = _delayGetValue(_options.timeout, propertyId, successCallback, null);
102792                 }
102793
102794                 if (watchObj.eventType === "CpuLoadChanged" || watchObj.eventType === "DisplayBrightnessChanged" || watchObj.eventType === "BatteryLevelChanged") {
102795                     if (options && _options.highThreshold) {
102796                         watchObj.highThreshold = _options.highThreshold;
102797                     }
102798
102799                     if (options && _options.lowThreshold) {
102800                         watchObj.lowThreshold = _options.lowThreshold;
102801                     }
102802                 }
102803
102804                 _watches[watchId].push(watchObj);
102805                 if (watchObj.eventType) {
102806                     event.on(watchObj.eventType, watchObj.onEvent);
102807                 }
102808             }
102809
102810             setTimeout(function () {
102811                 _getValue(propertyId, successCallback, null);
102812             }, 1);
102813
102814             return watchId;
102815         });
102816     }
102817
102818     function removePropertyValueChangeListener(listenerID) {
102819         var _handler = listenerID, index = 0, watchObjs = [], watchObj;
102820
102821         if (typeof listenerID !== 'number') {
102822             throw new WebAPIException(errorcode.TYPE_MISMATCH_ERR);
102823         }
102824         if (!_watches[_handler]) {
102825             throw new WebAPIException(errorcode.INVALID_VALUES_ERR);
102826         }
102827         watchObjs = _watches[_handler];
102828         if (watchObjs) {
102829             for (; index < watchObjs.length; index++) {
102830                 watchObj = watchObjs[index];
102831                 event.deleteEventHandler(watchObj.eventType, watchObj.onEvent);
102832                 if (watchObj.intervalId) {
102833                     clearInterval(watchObj.intervalId);
102834                 }
102835             }
102836             delete(_watches[_handler]);
102837         }
102838         return null;
102839     }
102840
102841     function handleSubFeatures(subFeatures) {
102842         var i, subFeature;
102843
102844         for (subFeature in subFeatures) {
102845             for (i in _security[subFeature]) {
102846                 _security[_security[subFeature][i]] = true;
102847             }
102848         }
102849     }
102850
102851     var systeminfo = {
102852         getCapabilities: getCapabilities,
102853         getPropertyValue: getPropertyValue,
102854         addPropertyValueChangeListener: addPropertyValueChangeListener,
102855         removePropertyValueChangeListener: removePropertyValueChangeListener,
102856         handleSubFeatures: handleSubFeatures
102857     };
102858
102859     return systeminfo;
102860 };
102861
102862 module.exports = _self;
102863
102864
102865 });
102866 define('ripple/platform/tizen/2.0/systemsetting', function (require, exports, module) {
102867 /*
102868  *  Copyright 2013 Intel Corporation.
102869  *
102870  * Licensed under the Apache License, Version 2.0 (the "License");
102871  * you may not use this file except in compliance with the License.
102872  * You may obtain a copy of the License at
102873  *
102874  * http://www.apache.org/licenses/LICENSE-2.0
102875  *
102876  * Unless required by applicable law or agreed to in writing, software
102877  * distributed under the License is distributed on an "AS IS" BASIS,
102878  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
102879  * See the License for the specific language governing permissions and
102880  * limitations under the License.
102881  */
102882
102883 var db = require('ripple/db'),
102884     event = require('ripple/event'),
102885     t = require('ripple/platform/tizen/2.0/typedef'),
102886     TypeCoerce = require('ripple/platform/tizen/2.0/typecoerce'),
102887     errorcode = require('ripple/platform/tizen/2.0/errorcode'),
102888     WebAPIException = require('ripple/platform/tizen/2.0/WebAPIException'),
102889     _systemSettingTypes = ["HOME_SCREEN", "LOCK_SCREEN", "INCOMING_CALL", "NOTIFICATION_EMAIL"],
102890     _systemSettings = {},
102891     DBSYSTEMSETTING_KEY = "tizen2-systemsetting",
102892      _security = {
102893         "http://tizen.org/privilege/setting": ["setProperty"]
102894     },
102895     _self = {};
102896
102897 function _isTypeFound(type) {
102898     if (_systemSettingTypes.indexOf(type) !== -1) {
102899         return true;
102900     }
102901     return false;
102902 }
102903
102904 function _initialize() {
102905     _systemSettings = db.retrieveObject(DBSYSTEMSETTING_KEY);
102906     if (!_systemSettings) {
102907         _systemSettings = {"HOME_SCREEN": "images/home_screen.jpg", "LOCK_SCREEN": "images/lock_screen.jpg", "INCOMING_CALL": "sounds/incoming.wav", "NOTIFICATION_EMAIL": "sounds/notification.wav"};
102908         db.saveObject(DBSYSTEMSETTING_KEY, _systemSettings);
102909         event.trigger("SystemSettingChanged");
102910     }
102911 }
102912
102913 _self = function () {
102914     function setProperty(type, value, successCallback, errorCallback) {
102915         if (!_security.setProperty) {
102916             throw new WebAPIException(errorcode.SECURITY_ERR);
102917         }
102918         if (!(new TypeCoerce(t.DOMString)).match(type)) {
102919             throw new WebAPIException(errorcode.TYPE_MISMATCH_ERR);
102920         }
102921         if (!_isTypeFound(type)) {
102922             throw new WebAPIException(errorcode.TYPE_MISMATCH_ERR);
102923         }
102924         if (!(new TypeCoerce(t.DOMString)).match(value)) {
102925             throw new WebAPIException(errorcode.TYPE_MISMATCH_ERR);
102926         }
102927         if (!(new TypeCoerce(t.SuccessCallback)).match(successCallback)) {
102928             throw new WebAPIException(errorcode.TYPE_MISMATCH_ERR);
102929         }
102930         if (!(new TypeCoerce(t.ErrorCallback)).match(errorCallback) && (arguments.length !== 3)) {
102931             throw new WebAPIException(errorcode.TYPE_MISMATCH_ERR);
102932         }
102933
102934         _systemSettings = db.retrieveObject(DBSYSTEMSETTING_KEY);
102935         _systemSettings[type] = value;
102936         db.saveObject(DBSYSTEMSETTING_KEY, _systemSettings);
102937         event.trigger("SystemSettingChanged");
102938         setTimeout(function () {
102939             successCallback();
102940         }, 1);
102941     }
102942     function getProperty(type, successCallback, errorCallback) {
102943         if (arguments.length === 2) {
102944             errorCallback = null;
102945         }
102946         if (!(new TypeCoerce(t.DOMString)).match(type)) {
102947             throw new WebAPIException(errorcode.TYPE_MISMATCH_ERR);
102948         }
102949         if (!_isTypeFound(type)) {
102950             throw new WebAPIException(errorcode.TYPE_MISMATCH_ERR);
102951         }
102952
102953         if (!(new TypeCoerce(t.SuccessCallback)).match(successCallback)) {
102954             throw new WebAPIException(errorcode.TYPE_MISMATCH_ERR);
102955         }
102956
102957         if (!(new TypeCoerce(t.ErrorCallback)).match(errorCallback) && (arguments.length !== 2)) {
102958             throw new WebAPIException(errorcode.TYPE_MISMATCH_ERR);
102959         }
102960
102961         _systemSettings = db.retrieveObject(DBSYSTEMSETTING_KEY);
102962         setTimeout(function () {
102963             successCallback(_systemSettings[type]);
102964         }, 1);
102965     }
102966
102967     function handleSubFeatures(subFeatures) {
102968         var i, subFeature;
102969
102970         for (subFeature in subFeatures) {
102971             for (i in _security[subFeature]) {
102972                 _security[_security[subFeature][i]] = true;
102973             }
102974         }
102975     }
102976
102977     var systemsetting = {
102978         setProperty: setProperty,
102979         getProperty: getProperty,
102980         handleSubFeatures: handleSubFeatures
102981     };
102982     return systemsetting;
102983 };
102984
102985 _initialize();
102986
102987 module.exports = _self;
102988
102989 });
102990 define('ripple/platform/tizen/2.0/time', function (require, exports, module) {
102991 /*
102992  *  Copyright 2012 Intel Corporation.
102993  *
102994  * Licensed under the Apache License, Version 2.0 (the "License");
102995  * you may not use this file except in compliance with the License.
102996  * You may obtain a copy of the License at
102997  *
102998  * http://www.apache.org/licenses/LICENSE-2.0
102999  *
103000  * Unless required by applicable law or agreed to in writing, software
103001  * distributed under the License is distributed on an "AS IS" BASIS,
103002  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
103003  * See the License for the specific language governing permissions and
103004  * limitations under the License.
103005  */
103006
103007 var TZDate = require('ripple/platform/tizen/2.0/TZDate'),
103008     errorcode = require('ripple/platform/tizen/2.0/errorcode'),
103009     WebAPIException = require('ripple/platform/tizen/2.0/WebAPIException'),
103010     db = require('ripple/db'),
103011     tz = require('ripple/platform/tizen/2.0/timezone_info'),
103012     _timeFormat = "h:m:s ap", _shortDateFormat = "d/m/y",
103013     _longDateFormat = "D, M d y", _self;
103014
103015 _self = {
103016     getCurrentDateTime: function () {
103017         return new TZDate();
103018     },
103019     getLocalTimezone: function () {
103020         var localtz = db.retrieve("tizen-timezone") || "UTC";
103021         return localtz;
103022     },
103023     getAvailableTimezones: function () {
103024         var ret = tz.getAllTimezone();
103025         return ret;
103026     },
103027     getDateFormat: function (shortformat) {
103028         if (shortformat !== undefined && shortformat !== null &&
103029             typeof shortformat !== 'boolean') {
103030             throw new WebAPIException(errorcode.TYPE_MISMATCH_ERR);
103031         }
103032         if (shortformat) {
103033             return _shortDateFormat;
103034         } else {
103035             return _longDateFormat;
103036         }
103037     },
103038     getTimeFormat: function () {
103039         return _timeFormat;
103040     },
103041     isLeapYear: function (year) {
103042         if (typeof year !== 'number') {
103043             throw new WebAPIException(errorcode.TYPE_MISMATCH_ERR);
103044         }
103045         return ((year % 4 === 0) && (year % 100 !== 0 || year % 400 === 0));
103046     }
103047 };
103048
103049 module.exports = _self;
103050
103051 });
103052 define('ripple/platform/tizen/2.0/timezone_info', function (require, exports, module) {
103053 /*
103054  *  Copyright 2012 Intel Corporation.
103055  *
103056  * Licensed under the Apache License, Version 2.0 (the "License");
103057  * you may not use this file except in compliance with the License.
103058  * You may obtain a copy of the License at
103059  *
103060  * http://www.apache.org/licenses/LICENSE-2.0
103061  *
103062  * Unless required by applicable law or agreed to in writing, software
103063  * distributed under the License is distributed on an "AS IS" BASIS,
103064  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
103065  * See the License for the specific language governing permissions and
103066  * limitations under the License.
103067  */
103068
103069 var _timezone_data = {
103070     "UTC": {diff: 0, abbr: "UTC"},
103071     "Africa/Cairo": {diff: 2, abbr: "EET"},
103072     "Africa/Casablanca": {diff: 0, abbr: "UTC"},
103073     "Africa/Dakar": {diff: 0, abbr: "UTC"},
103074     "Africa/Freetown": {diff: 0, abbr: "UTC"},
103075     "Africa/Johannesburg": {diff: 2, abbr: "SAST"},
103076     "Africa/Luanda": {diff: 1, abbr: "WAT"},
103077     "America/Anchorage": {diff: -9, abbr: "AKDT"},
103078     "America/Antigua": {diff: -4, abbr: "AST"},
103079     "America/Aruba": {diff: -4, abbr: "AST"},
103080     "America/Barbados": {diff: -4, abbr: "AST"},
103081     "America/Belize": {diff: -6, abbr: "CST"},
103082     "America/Bogota": {diff: -5, abbr: "COT"},
103083     "America/Buenos_Aires": {diff: -3, abbr: "ART"},
103084     "America/Cancun": {diff: -6, abbr: "CDT"},
103085     "America/Cayenne": {diff: -3, abbr: "GFT"},
103086     "America/Cayman": {diff: -5, abbr: "EST"},
103087     "America/Chicago": {diff: -6, abbr: "CST"},
103088     "America/Chihuahua": {diff: -7, abbr: "MST"},
103089     "America/Costa_Rica": {diff: -6, abbr: "CST"},
103090     "America/Denver": {diff: -7, abbr: "MST"},
103091     "America/Detroit": {diff: -5, abbr: "EST"},
103092     "America/Dominica": {diff: -4, abbr: "AST"},
103093     "America/Edmonton": {diff: -7, abbr: "MST"},
103094     "America/El_Salvador": {diff: -6, abbr: "CST"},
103095     "America/Guatemala": {diff: -6, abbr: "CST"},
103096     "America/Havana": {diff: -5, abbr: "CST"},
103097     "America/Indianapolis": {diff: -5, abbr: "EST"},
103098     "America/Jamaica": {diff: -5, abbr: "EST"},
103099     "America/Lima": {diff: -5, abbr: "PET"},
103100     "America/Los_Angeles": {diff: -8, abbr: "PST"},
103101     "America/Louisville": {diff: -5, abbr: "EST"},
103102     "America/Mexico_City": {diff: -6, abbr: "CST"},
103103     "America/Montevideo": {diff: -2, abbr: "UYST"},
103104     "America/Montreal": {diff: -5, abbr: "EST"},
103105     "America/New_York": {diff: -5, abbr: "EST"},
103106     "America/Panama": {diff: -5, abbr: "EST"},
103107     "America/Phoenix": {diff: -7, abbr: "MST"},
103108     "America/Puerto_Rico": {diff: -4, abbr: "AST"},
103109     "America/Santiago": {diff: -3, abbr: "CLST"},
103110     "America/Santo_Domingo": {diff: -4, abbr: "AST"},
103111     "America/Sao_Paulo": {diff: -4, abbr: "AST"},
103112     "America/Tijuana": {diff: -8, abbr: "PST"},
103113     "America/Vancouver": {diff: -8, abbr: "PST"},
103114     "America/Winnipeg": {diff: -6, abbr: "CST"},
103115     "Antarctica/South_Pole": {diff: 13, abbr: "NZDT"},
103116     "Arctic/Longyearbyen": {diff: 13, abbr: "CET"},
103117     "Asia/Amman": {diff: 2, abbr: "EET"},
103118     "Asia/Baghdad": {diff: 3, abbr: "AST"},
103119     "Asia/Bahrain": {diff: 3, abbr: "AST"},
103120     "Asia/Bangkok": {diff: 7, abbr: "ICT"},
103121     "Asia/Beirut": {diff: 2, abbr: "EET"},
103122     "Asia/Chungking": {diff: 8, abbr: "CST"},
103123     "Asia/Dubai": {diff: 4, abbr: "GST"},
103124     "Asia/Harbin": {diff: 8, abbr: "CST"},
103125     "Asia/Ho_Chi_Minh": {diff: 7, abbr: "IST"},
103126     "Asia/Hong_Kong": {diff: 8, abbr: "HKT"},
103127     "Asia/Istanbul": {diff: 2, abbr: "EET"},
103128     "Asia/Jakarta": {diff: 7, abbr: "WIT"},
103129     "Asia/Jerusalem": {diff: 2, abbr: "IST"},
103130     "Asia/Karachi": {diff: 5, abbr: "PKT"},
103131     "Asia/Kuala_Lumpur": {diff: 8, abbr: "MYT"},
103132     "Asia/Kuwait": {diff: 3, abbr: "AST"},
103133     "Asia/Macao": {diff: 8, abbr: "CST"},
103134     "Asia/Manila": {diff: 8, abbr: "PHT"},
103135     "Asia/Pyongyang": {diff: 9, abbr: "KST"},
103136     "Asia/Qatar": {diff: 3, abbr: "AST"},
103137     "Asia/Saigon": {diff: 7, abbr: "ICT"},
103138     "Asia/Seoul": {diff: 9, abbr: "KST"},
103139     "Asia/Shanghai": {diff: 8, abbr: "CST"},
103140     "Asia/Singapore": {diff: 8, abbr: "SGT"},
103141     "Asia/Taipei": {diff: 8, abbr: "CST"},
103142     "Asia/Tel_Aviv": {diff: 2, abbr: "IST"},
103143     "Asia/Tokyo": {diff: 9, abbr: "JST"},
103144     "Asia/Urumqi": {diff: 8, abbr: "CST"},
103145     "Atlantic/Bermuda": {diff: -4, abbr: "AST"},
103146     "Atlantic/Canary": {diff: 0, abbr: "WET"},
103147     "Atlantic/Cape_Verde": {diff: -1, abbr: "CVT"},
103148     "Atlantic/Reykjavik": {diff: 0, abbr: "GMT"},
103149     "Australia/Brisbane": {diff: 10, abbr: "EST"},
103150     "Australia/Canberra": {diff: 11, abbr: "EST"},
103151     "Australia/Darwin": {diff: 9.5, abbr: "CST"},
103152     "Australia/Melbourne": {diff: 11, abbr: "EST"},
103153     "Australia/North": {diff: 9.5, abbr: "CST"},
103154     "Australia/Perth": {diff: 8, abbr: "WST"},
103155     "Australia/Queensland": {diff: 10, abbr: "EST"},
103156     "Australia/South": {diff: 10.5, abbr: "CST"},
103157     "Australia/Sydney": {diff: 11, abbr: "EST"},
103158     "Australia/West": {diff: 8, abbr: "WST"},
103159     "Australia/Victoria": {diff: 11, abbr: "EST"},
103160     "Europe/Amsterdam": {diff: 1, abbr: "CET"},
103161     "Europe/Athens": {diff: 2, abbr: "EET"},
103162     "Europe/Belgrade": {diff: 1, abbr: "CET"},
103163     "Europe/Berlin": {diff: 1, abbr: "CET"},
103164     "Europe/Brussels": {diff: 1, abbr: "CET"},
103165     "Europe/Bucharest": {diff: 2, abbr: "EET"},
103166     "Europe/Budapest": {diff: 1, abbr: "CET"},
103167     "Europe/Copenhagen": {diff: 1, abbr: "CET"},
103168     "Europe/Dublin": {diff: 0, abbr: "GMT"},
103169     "Europe/Helsinki": {diff: 2, abbr: "EET"},
103170     "Europe/Istanbul": {diff: 2, abbr: "EET"},
103171     "Europe/Kaliningrad": {diff: 3, abbr: "FET"},
103172     "Europe/Kiev": {diff: 2, abbr: "EET"},
103173     "Europe/Lisbon": {diff: 0, abbr: "WET"},
103174     "Europe/London": {diff: 0, abbr: "GMT"},
103175     "Europe/Luxembourg": {diff: 1, abbr: "CET"},
103176     "Europe/Madrid": {diff: 1, abbr: "CET"},
103177     "Europe/Minsk": {diff: 3, abbr: "FET"},
103178     "Europe/Monaco": {diff: 1, abbr: "CET"},
103179     "Europe/Moscow": {diff: 4, abbr: "MSK"},
103180     "Europe/Oslo": {diff: 1, abbr: "CET"},
103181     "Europe/Paris": {diff: 1, abbr: "CET"},
103182     "Europe/Prague": {diff: 1, abbr: "CET"},
103183     "Europe/Rome": {diff: 1, abbr: "CET"},
103184     "Europe/San_Marino": {diff: 1, abbr: "CET"},
103185     "Europe/Sarajevo": {diff: 1, abbr: "CET"},
103186     "Europe/Stockholm": {diff: 1, abbr: "CET"},
103187     "Europe/Vatican": {diff: 1, abbr: "CET"},
103188     "Europe/Vienna": {diff: 1, abbr: "CET"},
103189     "Europe/Warsaw": {diff: 1, abbr: "CET"},
103190     "Europe/Zurich": {diff: 2, abbr: "EET"},
103191     "Indian/Christmas": {diff: 7, abbr: "CXT"},
103192     "Indian/Maldives": {diff: 5, abbr: "MVT"},
103193     "Pacific/Auckland": {diff: 12, abbr: "NZST"},
103194     "Pacific/Easter": {diff: -6, abbr: "EAST"},
103195     "Pacific/Fiji": {diff: 12, abbr: "FJT"},
103196     "Pacific/Guam": {diff: 10, abbr: "ChST"},
103197     "Pacific/Honolulu": {diff: -10, abbr: "HST"},
103198     "Pacific/Midway": {diff: -11, abbr: "SST"},
103199     "Pacific/Saipan": {diff: 10, abbr: "ChST"},
103200     "Pacific/Samoa": {diff: -11, abbr: "SST"},
103201     "Pacific/Tahiti": {diff: -10, abbr: "TAHT"},
103202     "UCT": {diff: 0, abbr: "UCT"},
103203     "SST": {diff: 0, abbr: "SST"},
103204     "GMT": {diff: 0, abbr: "GMT"},
103205     "Greenwich": {diff: 0, abbr: "GMT"},
103206     "US/Alaska": {diff: -9, abbr: "AKST"},
103207     "US/Eastern": {diff: -5, abbr: "EST"},
103208     "US/Central": {diff: -6, abbr: "CST"},
103209     "US/Mountain": {diff: -7, abbr: "MST"},
103210     "US/Pacific": {diff: -8, abbr: "PST"},
103211     "Universal": {diff: 0, abbr: "UTC"},
103212     "Zulu": {diff: 0, abbr: "UTC"},
103213     "Etc/GMT": {diff: 0, abbr: "Etc/GMT"},
103214     "Etc/GMT+0": {diff: 0, abbr: "Etc/GMT+0"},
103215     "Etc/GMT+1": {diff: -1, abbr: "Etc/GMT+1"},
103216     "Etc/GMT+10": {diff: -10, abbr: "Etc/GMT+10"},
103217     "Etc/GMT+11": {diff: -11, abbr: "Etc/GMT+11"},
103218     "Etc/GMT+12": {diff: -12, abbr: "Etc/GMT+12"},
103219     "Etc/GMT+2": {diff: -2, abbr: "Etc/GMT+2"},
103220     "Etc/GMT+3": {diff: -3, abbr: "Etc/GMT+3"},
103221     "Etc/GMT+4": {diff: -4, abbr: "Etc/GMT+4"},
103222     "Etc/GMT+5": {diff: -5, abbr: "Etc/GMT+5"},
103223     "Etc/GMT+6": {diff: -6, abbr: "Etc/GMT+6"},
103224     "Etc/GMT+7": {diff: -7, abbr: "Etc/GMT+7"},
103225     "Etc/GMT+8": {diff: -8, abbr: "Etc/GMT+8"},
103226     "Etc/GMT+9": {diff: -9, abbr: "Etc/GMT+9"},
103227     "Etc/GMT-0": {diff: 0, abbr: "Etc/GMT-0"},
103228     "Etc/GMT-1": {diff: 1, abbr: "Etc/GMT-1"},
103229     "Etc/GMT-10": {diff: 10, abbr: "Etc/GMT-10"},
103230     "Etc/GMT-11": {diff: 11, abbr: "Etc/GMT-11"},
103231     "Etc/GMT-12": {diff: 12, abbr: "Etc/GMT-12"},
103232     "Etc/GMT-13": {diff: 13, abbr: "Etc/GMT-13"},
103233     "Etc/GMT-14": {diff: 14, abbr: "Etc/GMT-14"},
103234     "Etc/GMT-2": {diff: 2, abbr: "Etc/GMT-2"},
103235     "Etc/GMT-3": {diff: 3, abbr: "Etc/GMT-3"},
103236     "Etc/GMT-4": {diff: 4, abbr: "Etc/GMT-4"},
103237     "Etc/GMT-5": {diff: 5, abbr: "Etc/GMT-5"},
103238     "Etc/GMT-6": {diff: 6, abbr: "Etc/GMT-6"},
103239     "Etc/GMT-7": {diff: 7, abbr: "Etc/GMT-7"},
103240     "Etc/GMT-8": {diff: 8, abbr: "Etc/GMT-8"},
103241     "Etc/GMT-9": {diff: 9, abbr: "Etc/GMT-9"},
103242     "Etc/GMT0": {diff: 0, abbr: "Etc/GMT0"},
103243     "Etc/Greenwich": {diff: 0, abbr: "GMT"}
103244 };
103245
103246 module.exports = {
103247     getAllTimezone: function () {
103248         var i, ret = [];
103249         for (i in _timezone_data)
103250             ret.push(i);
103251         return ret;
103252     },
103253     getTimezoneDiff: function (zone) {
103254         return _timezone_data[zone].diff;
103255     },
103256     getTimezoneAbbr: function (zone) {
103257         return _timezone_data[zone].abbr;
103258     },
103259     isValidTimezone: function (zone) {
103260         return (_timezone_data[zone] === undefined) ? false : true;
103261     }
103262 };
103263
103264
103265 });
103266 define('ripple/platform/tizen/2.0/tizen1_utils', function (require, exports, module) {
103267 /*
103268  *  Copyright 2011 Intel Corporation.
103269  *
103270  * Licensed under the Apache License, Version 2.0 (the "License");
103271  * you may not use this file except in compliance with the License.
103272  * You may obtain a copy of the License at
103273  *
103274  * http://www.apache.org/licenses/LICENSE-2.0
103275  *
103276  * Unless required by applicable law or agreed to in writing, software
103277  * distributed under the License is distributed on an "AS IS" BASIS,
103278  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
103279  * See the License for the specific language governing permissions and
103280  * limitations under the License.
103281  */
103282
103283 var self,
103284     utils = require('ripple/utils'),
103285     errorcode = require('ripple/platform/tizen/2.0/errorcode'),
103286     WebAPIException = require('ripple/platform/tizen/2.0/WebAPIException');
103287
103288 self = module.exports = {
103289     _wac2_regexSanitize: function (regexString) {
103290         var escapePattern = /([^\\]|^)(%)/g, percentPattern = /\\%/g;
103291         return regexString.replace("^", "\\^")
103292                 .replace("$", "\\$")
103293                 .replace("(", "\\(")
103294                 .replace(")", "\\)")
103295                 .replace("<", "\\<")
103296                 .replace("[", "\\[")
103297                 .replace("{", "\\{")
103298                 .replace(/\\([^%])/, "\\\\$1")    /* don't replace \\% */
103299                 .replace("|", "\\|")
103300                 .replace(">", "\\>")
103301                 .replace(".", "\\.")
103302                 .replace("*", "\\*")
103303                 .replace("+", "\\+")
103304                 .replace("?", "\\?")
103305                 .replace(escapePattern, "$1.*")  /* replace % with .* */
103306                 .replace(percentPattern, "%");   /* strip excape of % */
103307     },
103308
103309     isValidDate: function (d) {
103310         if (Object.prototype.toString.call(d) !== "[object Date]")
103311             return false;
103312         return !isNaN(d.getTime());
103313     },
103314     isValidTZDate: function (d) {
103315         if (Object.prototype.toString.call(d) !== "[object Object]")
103316             return false;
103317         return d.getTimezone && !isNaN(d.getDate());//getTimezone() belongs to TZDate
103318     },
103319     isValidArray: function (a) {
103320         return (Object.prototype.toString.call(a) === "[object Array]");
103321     },
103322
103323     matchOptionArrayString: function (src, attr, pattern) {
103324         /* src.obj[attr] is a StringArray */
103325         var _pattern, re, _stringMatch;
103326         _pattern = this._wac2_regexSanitize(pattern);
103327         re = new RegExp("^" + _pattern + "$", "i");
103328
103329         _stringMatch = function (obj, index) {
103330             if (pattern.search(/^%*$/i) === 0)
103331                 return true;
103332             if (obj[attr] === undefined || obj[attr] === null)
103333                 return false;
103334             return obj[attr].some(function (f) {
103335                 return f.search(re) !== -1;
103336             });
103337         };
103338         return utils.filter(src, _stringMatch);
103339     },
103340
103341     matchAttributeBooleanFilter: function (src, attr, value) {
103342         // only support EXACTLY matchFlag
103343         var _booleanMatch, atr = attr.split(".");
103344
103345         if (atr.length === 2) {
103346             _booleanMatch = function (obj, index) {
103347                 return (obj[atr[0]][atr[1]] === value);
103348             };
103349         } else {
103350             _booleanMatch = function (obj, index) {
103351                 return (obj[attr] === value);
103352             };
103353         }
103354
103355         return utils.filter(src, _booleanMatch);
103356     },
103357
103358     matchAttributeArrayFilter: function (src, attr, matchFlag, value) {
103359         var _re, _arrayMatch, atr = attr.split("."), _existMatch;
103360
103361         if (atr.length === 2) {
103362             _existMatch = function (obj, index) {
103363                 return (obj[atr[0]][atr[1]] !== undefined);
103364             };
103365         } else {
103366             _existMatch = function (obj, index) {
103367                 return (obj[attr] !== undefined);
103368             };
103369         }
103370
103371         if (value === undefined) {
103372             return utils.filter(src, _existMatch);
103373         }
103374
103375         switch (matchFlag)
103376         {
103377         case "EXACTLY":
103378             _re = new RegExp("^" + value + "$");
103379             break;
103380         case "FULLSTRING":
103381             _re = new RegExp("^" + value + "$", "i");
103382             break;
103383         case "CONTAINS":
103384             _re = new RegExp(value, "i");
103385             break;
103386         case "STARTSWITH":
103387             _re = new RegExp("^" + value, "i");
103388             break;
103389         case "ENDSWITH":
103390             _re = new RegExp(value + "$", "i");
103391             break;
103392         case "EXISTS":
103393             return utils.filter(src, _existMatch);
103394         default:
103395             return [];
103396         }
103397
103398         if (atr.length === 2) {
103399             _arrayMatch = function (obj, index) {
103400                 return (obj[atr[0]][atr[1]] && obj[atr[0]][atr[1]].some(function (o) {
103401                     return (o.search(_re) !== -1);
103402                 }));
103403             };
103404         } else {
103405             _arrayMatch = function (obj, index) {
103406                 return (obj[attr] && obj[attr].some(function (o) {
103407                     return (o.search(_re) !== -1);
103408                 }));
103409             };
103410         }
103411
103412         return utils.filter(src, _arrayMatch);
103413     },
103414
103415     matchAttributeRangeFilter: function (src, attr, low, high) {
103416         var _rangeMatch, atr = attr.split(".");
103417
103418         if (atr.length === 2) {
103419             _rangeMatch = function (obj, index) {
103420                 var matched = true;
103421                 if (low !== null && low !== undefined) {
103422                     matched = (obj[atr[0]][atr[1]] >= low);
103423                 }
103424                 if (matched && (high !== null && high !== undefined)) {
103425                     matched = (obj[atr[0]][atr[1]] <= high);
103426                 }
103427                 return matched;
103428             };
103429         } else {
103430             _rangeMatch = function (obj, index) {
103431                 var matched = true;
103432                 if (low !== null && low !== undefined) {
103433                     matched = (obj[attr] >= low);
103434                 }
103435                 if (matched && (high !== null && high !== undefined)) {
103436                     matched = (obj[attr] <= high);
103437                 }
103438                 return matched;
103439             };
103440         }
103441         return utils.filter(src, _rangeMatch);
103442     },
103443
103444     matchAttributeFilter: function (src, attr, matchFlag, value) {
103445         var _re, _stringMatch, atr = attr.split("."),
103446             _existMatch;
103447
103448         if (atr.length === 2) {
103449             _existMatch = function (obj, index) {
103450                 return (obj[atr[0]][atr[1]] !== undefined);
103451             };
103452         } else {
103453             _existMatch = function (obj, index) {
103454                 return (obj[attr] !== undefined);
103455             };
103456         }
103457
103458         if (value === undefined) {
103459             return utils.filter(src, _existMatch);
103460         }
103461
103462         switch (matchFlag)
103463         {
103464         case "EXACTLY":
103465             _re = new RegExp("^" + value + "$");
103466             break;
103467         case "FULLSTRING":
103468             _re = new RegExp("^" + value + "$", "i");
103469             break;
103470         case "CONTAINS":
103471             _re = new RegExp(value, "i");
103472             break;
103473         case "STARTSWITH":
103474             _re = new RegExp("^" + value, "i");
103475             break;
103476         case "ENDSWITH":
103477             _re = new RegExp(value + "$", "i");
103478             break;
103479         case "EXISTS":
103480             return utils.filter(src, _existMatch);
103481         default:
103482             return [];
103483         }
103484         if (atr.length === 2) {
103485             _stringMatch = function (obj, index) {
103486                 if (matchFlag === "EXACTLY") {
103487                     return (obj[atr[0]][atr[1]] === value);
103488                 } else if (typeof obj[atr[0]][atr[1]] !== 'string') {
103489                     return false;
103490                 }
103491
103492                 return (obj[atr[0]][atr[1]].search(_re) !== -1);
103493             };
103494         } else {
103495             _stringMatch = function (obj, index) {
103496                 if (matchFlag === "EXACTLY") {
103497                     return (obj[attr] === value);
103498                 } else if (typeof obj[attr] !== 'string') {
103499                     return false;
103500                 }
103501
103502                 return (obj[attr].search(_re) !== -1);
103503             };
103504         }
103505         return utils.filter(src, _stringMatch);
103506     },
103507
103508     matchOptionString: function (src, attr, pattern) {
103509         /* src.obj[attr] is a string */
103510         var _stringMatch, _pattern, _re;
103511         _pattern = this._wac2_regexSanitize(pattern);
103512         _re = new RegExp("^" + _pattern + "$", "mi");
103513
103514         _stringMatch = function (obj, index) {
103515             return (obj[attr].search(_re) !== -1);
103516         };
103517         return utils.filter(src, _stringMatch);
103518     },
103519
103520     matchOptionDate: function (src, attr, filterStart, filterEnd) {
103521         var _dateMatch;
103522         _dateMatch = function (obj, index) {
103523             var matched = true, valueDate = obj[attr];
103524
103525             if (filterStart !== undefined && filterStart !== null) {
103526                 matched = (valueDate.getTime() >= filterStart.getTime());
103527             }
103528             if (matched && (filterEnd !== undefined && filterEnd !== null)) {
103529                 matched = (valueDate.getTime() <= filterEnd.getTime());
103530             }
103531             return matched;
103532         };
103533         return utils.filter(src, _dateMatch);
103534     },
103535
103536     matchOptionShortArray: function (src, attr, filterArray) {
103537         /* src.obj[attr] is a short, filterArray is an array
103538            i.e. find status is [CONFRIMED or TENTATIVE] */
103539         var arraySome = function (obj, index) {
103540             return filterArray.some(function (f) {
103541                 return f === obj[attr];
103542             });
103543         };
103544         return utils.filter(src, arraySome);
103545     },
103546
103547     validateArgumentType: function (arg, argType, errorObj) {
103548         var invalidArg = false;
103549
103550         switch (argType) {
103551         case "array":
103552             if (!arg instanceof Array) {
103553                 invalidArg = true;
103554             }
103555             break;
103556         case "date":
103557             if (!arg instanceof Date) {
103558                 invalidArg = true;
103559             }
103560             break;
103561         case "integer":
103562             if (typeof Number(arg) !== "number" || Number(arg) !== Math.floor(arg)) {
103563                 invalidArg = true;
103564             }
103565             break;
103566         default:
103567             if (typeof arg !== argType) {
103568                 invalidArg = true;
103569             }
103570             break;
103571         }
103572
103573         if (invalidArg) {
103574             throw errorObj;
103575         }
103576     },
103577
103578     validateCallbackType: function (successCallback, errorCallback) {
103579         if (successCallback) {
103580             this.validateArgumentType(successCallback, "function",
103581                 new WebAPIException(errorcode.TYPE_MISMATCH_ERR));
103582         }
103583         if (errorCallback) {
103584             this.validateArgumentType(errorCallback, "function",
103585                 new WebAPIException(errorcode.TYPE_MISMATCH_ERR));
103586         }
103587     },
103588
103589     validateEqualArrays: function (arrayOne, arrayTwo) {
103590         var isEqual = false, i;
103591
103592         if (Object.prototype.toString.call(arrayTwo) === "[object Array]" &&
103593             Object.prototype.toString.call(arrayTwo) === "[object Array]" &&
103594             arrayOne.length === arrayTwo.length) {
103595             isEqual = true;
103596             for (i in arrayOne) {
103597                 if (arrayOne[i] !== arrayTwo[i]) {
103598                     isEqual = false;
103599                     break;
103600                 }
103601             }
103602         }
103603         return isEqual;
103604     },
103605
103606     validateTypeMismatch: function (onSuccess, onError, name, callback) {
103607
103608         if (onSuccess === undefined || onSuccess === null) {
103609             throw new WebAPIException(errorcode.TYPE_MISMATCH_ERR);
103610         }
103611         this.validateArgumentType(onSuccess, "function",
103612                                   new WebAPIException(errorcode.TYPE_MISMATCH_ERR));
103613         if (onError !== null && onError !== undefined) {
103614             this.validateArgumentType(onError, "function",
103615                                       new WebAPIException(errorcode.TYPE_MISMATCH_ERR));
103616         }
103617
103618         return callback && callback();
103619     },
103620
103621     isEmptyObject: function (obj) {
103622         var prop;
103623
103624         for (prop in obj) {
103625             return false;
103626         }
103627         return true;
103628     },
103629
103630     arrayComposite: function (mode, arrayA, arrayB) {
103631         var combinedArray = arrayA.concat(arrayB),
103632             intersectionArray = arrayA.filter(function (value) {
103633                 if (utils.arrayContains(arrayB, value)) {
103634                     return true;
103635                 }
103636
103637                 return false;
103638             });
103639
103640         switch (mode) {
103641         case "AND":
103642         case "INTERSECTION":
103643             return intersectionArray;
103644         case "OR":
103645         case "UNION":
103646             return intersectionArray.concat(combinedArray.filter(function (value) {
103647                 if (utils.arrayContains(intersectionArray, value)) {
103648                     return false;
103649                 }
103650
103651                 return true;
103652             }));
103653         default:
103654             return undefined;
103655         }
103656     },
103657
103658     isEqual: function (srcObj, aimObj) {
103659         var i;
103660
103661         if (typeof srcObj !== typeof aimObj) {
103662             return false;
103663         }
103664
103665         if (srcObj === null || srcObj === undefined || typeof srcObj === 'number' ||
103666             typeof srcObj === 'string' || typeof srcObj === 'boolean') {
103667             return srcObj === aimObj;
103668         }
103669
103670         for (i in srcObj) {
103671             if (!aimObj.hasOwnProperty(i) || !self.isEqual(srcObj[i], aimObj[i])) {
103672                 return false;
103673             }
103674         }
103675
103676         return true;
103677     },
103678
103679     query: function (objects, filter, sortMode, count, offset) {
103680         function isCompositeFilter(filter) {
103681             return (filter.type) ? true : false;
103682         }
103683
103684         function isAttributeFilter(filter) {
103685             return (filter.matchFlag) ? true : false;
103686         }
103687
103688         function getValue(obj, key) {
103689             var keys = key.split("."),
103690                 value = obj[keys[0]],
103691                 i;
103692
103693             for (i = 1; i < keys.length; i++) {
103694                 if (value[keys[i]]) {
103695                     value = value[keys[i]];
103696                 }
103697             }
103698
103699             return value;
103700         }
103701
103702         function _filter(objects, filter) {
103703             var i, results, eachResult, filterFunc;
103704
103705             if (isCompositeFilter(filter)) {
103706                 for (i in filter.filters) {
103707                     eachResult = _filter(objects, filter.filters[i]);
103708                     results = (results === undefined) ? eachResult : self.arrayComposite(filter.type, results, eachResult);
103709                 }
103710                 return results;
103711             }
103712
103713             if (isAttributeFilter(filter)) {
103714                 for (i in objects) {
103715                     if (filter.attributeName in objects[i])
103716                         break;
103717                 }
103718                 filterFunc = self.isValidArray(objects[i][filter.attributeName]) ? self.matchAttributeArrayFilter : self.matchAttributeFilter;
103719                 results = filterFunc(objects, filter.attributeName, filter.matchFlag, filter.matchValue);
103720             } else {
103721                 results = self.matchAttributeRangeFilter(objects, filter.attributeName, filter.initialValue, filter.endValue);
103722             }
103723
103724             return results;
103725         }
103726
103727         function _sort(objects, sortMode) {
103728             objects.sort(function (a, b) {
103729                 return (sortMode.order === "ASC") ?
103730                     (getValue(a, sortMode.attributeName) < getValue(b, sortMode.attributeName) ? -1 : 1):
103731                     (getValue(a, sortMode.attributeName) > getValue(b, sortMode.attributeName) ? -1 : 1);
103732             });
103733
103734             return objects;
103735         }
103736
103737         var res = objects;
103738
103739         if (filter) {
103740             res = _filter(res, filter);
103741         }
103742
103743         if (sortMode) {
103744             _sort(res, sortMode);
103745         }
103746
103747         if (offset || count) {
103748             offset = (offset > 0) ? offset : 0;
103749             res = (count > 0) ? res.slice(offset, offset + count) : res.slice(offset);
103750         }
103751
103752         return res;
103753     },
103754
103755     copyString: function (str) {
103756         var newStr, charConvert = [], i;
103757
103758         if (typeof str !== 'string') {
103759             return str;
103760         }
103761         for (i = 0; i < str.length; i++) {
103762             charConvert[i] = str.charAt(i);
103763         }
103764         newStr = charConvert.join("");
103765
103766         return newStr;
103767     },
103768
103769     copy: function (obj) {
103770         var i,
103771             newObj = jQuery.isArray(obj) ? [] : {};
103772
103773         if (typeof obj === 'number' ||
103774             typeof obj === 'string' ||
103775             typeof obj === 'boolean' ||
103776             obj === null ||
103777             obj === undefined) {
103778             return obj;
103779         }
103780
103781         if (obj instanceof Date) {
103782             return new Date(obj);
103783         }
103784
103785         if (obj instanceof RegExp) {
103786             return new RegExp(obj);
103787         }
103788
103789         for (i in obj) {
103790             if (obj.hasOwnProperty(i)) {
103791                 if (obj.__lookupGetter__(i)) {
103792                     newObj.__defineGetter__(i, (function (key) {
103793                         return function () {
103794                             return self.copy(obj[key]);
103795                         };
103796                     }(i)));
103797                 }
103798                 else {
103799                     newObj[i] = self.copy(obj[i]);
103800                 }
103801             }
103802         }
103803
103804         return newObj;
103805     }
103806 };
103807
103808 });
103809 define('ripple/platform/tizen/2.0/touchEvent', function (require, exports, module) {
103810 /*
103811  *  Copyright 2012 Intel Corporation
103812  *
103813  * Licensed under the Apache License, Version 2.0 (the "License");
103814  * you may not use this file except in compliance with the License.
103815  * You may obtain a copy of the License at
103816  *
103817  * http://www.apache.org/licenses/LICENSE-2.0
103818  *
103819  * Unless required by applicable law or agreed to in writing, software
103820  * distributed under the License is distributed on an "AS IS" BASIS,
103821  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
103822  * See the License for the specific language governing permissions and
103823  * limitations under the License.
103824  */
103825
103826 var emulatorBridge = require('ripple/emulatorBridge'),
103827     event = require('ripple/event'),
103828     tizen1_utils = require('ripple/platform/tizen/2.0/tizen1_utils'),
103829     Touch,
103830     TouchList,
103831     TouchEvent,
103832     _touchCanvasElements = [],
103833     _dataEnlargeRatio = 4,
103834     _self;
103835
103836 function _isValidTouch(touches) {
103837     var touche, _touches = [], i;
103838     if (!touches) {
103839         return false;
103840     }
103841     if (!tizen1_utils.isValidArray(touches)) {
103842         _touches = [touches];
103843     }
103844
103845     for (i = 0; i < _touches.length; i++) {
103846         touche = _touches[i];
103847         if ((touche !== undefined) &&
103848             ((typeof touche !== "object") ||
103849             (typeof touche.target !== "object") ||
103850             (touche.identifier !== undefined) && (typeof touche.identifier !== "number") ||
103851             (touche.screenX !== undefined) && (typeof touche.screenX !== "number") ||
103852             (touche.screenY !== undefined) && (typeof touche.screenY !== "number") ||
103853             (touche.clientX !== undefined) && (typeof touche.clientX !== "number") ||
103854             (touche.clientY !== undefined) && (typeof touche.clientY !== "number") ||
103855             (touche.pageX !== undefined) && (typeof touche.pageX !== "number") ||
103856             (touche.pageY !== undefined) && (typeof touche.pageY !== "number")))
103857             return false;
103858     }
103859     return true;
103860 }
103861
103862 function _dispatchAllEvents(event) {
103863     _touchCanvasElements.forEach(function (value) {
103864         if (value !== undefined) {
103865             value.dispatchEvent(event);
103866         }
103867     });
103868 }
103869
103870 function _touchMove(event) {
103871     var data = event.data,
103872         touches = [],
103873         removedTouches = [],
103874         touchList,
103875         simulatedEvent,
103876         dataId,
103877         ids = [],
103878         intervalId,
103879         currentIndex,
103880         item = {};
103881
103882     if (_touchCanvasElements.length === 0)
103883         return;
103884
103885     for (dataId in data) {
103886         if (!data[dataId].length || data[dataId].length === 0)
103887             return;
103888
103889         ids.push(dataId);
103890         item = data[dataId][0];
103891         touches.push(new Touch(item.target, dataId, item.pageX * _dataEnlargeRatio, item.pageY * _dataEnlargeRatio, item.screenX * _dataEnlargeRatio,
103892                                item.screenY * _dataEnlargeRatio, item.offsetX * _dataEnlargeRatio, item.offsetY * _dataEnlargeRatio));
103893     }
103894
103895     // touch start
103896     touchList = new TouchList(touches);
103897     simulatedEvent = new TouchEvent("touchstart", true, true, touchList, touchList, touchList, event.altKey, event.metaKey, event.ctrlKey, event.shiftKey);
103898     _dispatchAllEvents(simulatedEvent);
103899     currentIndex = 0;
103900
103901     // touch move and touch end
103902     intervalId = setInterval(function () {
103903         touches = [];
103904         removedTouches = [];
103905
103906         ids.forEach(function (id) {
103907             var points = data[id],
103908                 touchItem, removedItem;
103909
103910             if (currentIndex < points.length) {
103911                 touchItem = points[currentIndex];
103912             } else {
103913                 removedItem = points[points.length - 1];
103914             }
103915
103916             if (touchItem)
103917                 touches.push(new Touch(touchItem.target, id, touchItem.pageX * _dataEnlargeRatio, touchItem.pageY * _dataEnlargeRatio, touchItem.screenX * _dataEnlargeRatio,
103918                                        touchItem.screenY * _dataEnlargeRatio, touchItem.offsetX * _dataEnlargeRatio, touchItem.offsetY * _dataEnlargeRatio));
103919             if (removedItem)
103920                 removedTouches.push(new Touch(removedItem.target, id, removedItem.pageX * _dataEnlargeRatio, removedItem.pageY * _dataEnlargeRatio, removedItem.screenX * _dataEnlargeRatio,
103921                                     removedItem.screenY * _dataEnlargeRatio, removedItem.offsetX * _dataEnlargeRatio, removedItem.offsetY * _dataEnlargeRatio));
103922         });
103923
103924         if (touches.length > 0) {
103925             simulatedEvent = new TouchEvent("touchmove", true, true, new TouchList(touches), new TouchList(touches), new TouchList(touches),
103926                 event.altKey, event.metaKey, event.ctrlKey, event.shiftKey);
103927             _dispatchAllEvents(simulatedEvent);
103928         } else {
103929             clearInterval(intervalId);
103930         }
103931
103932         if (removedTouches.length > 0) {
103933             simulatedEvent = new TouchEvent("touchend", true, true, new TouchList(removedTouches), new TouchList(removedTouches), new TouchList(removedTouches),
103934                 event.altKey, event.metaKey, event.ctrlKey, event.shiftKey);
103935             _dispatchAllEvents(simulatedEvent);
103936         }
103937         currentIndex++;
103938     }, 50);
103939 }
103940
103941 function _touchCancel(event) {
103942     var mousedownEvent = event.touchEvent,
103943         simulatedEvent;
103944
103945     simulatedEvent = new TouchEvent("touchcancel", true, true, new TouchList([]), new TouchList([]), new TouchList([]),
103946         event.altKey, event.metaKey, event.ctrlKey, event.shiftKey);
103947     _dispatchAllEvents(simulatedEvent);
103948 }
103949
103950 function _initialize() {
103951     event.on("touchCancel", _touchCancel);
103952     event.on("touchEvent", _touchMove);
103953 }
103954
103955 Touch = function (target, identifier, pageX, pageY, screenX, screenY, clientX, clientY) {
103956     var _identifier = Number(identifier) || 0,
103957         _screenX = Number(screenX) || 0,
103958         _screenY = Number(screenY) || 0,
103959         _clientX = Number(clientX) || 0,
103960         _clientY = Number(clientY) || 0,
103961         _pageX = Number(pageX) || 0,
103962         _pageY = Number(pageY) || 0;
103963
103964     this.__defineGetter__("identifier", function () {
103965         return _identifier;
103966     });
103967     this.__defineGetter__("target", function () {
103968         return target;
103969     });
103970     this.__defineGetter__("screenX", function () {
103971         return _screenX;
103972     });
103973     this.__defineGetter__("screenY", function () {
103974         return _screenY;
103975     });
103976     this.__defineGetter__("clientX", function () {
103977         return _clientX;
103978     });
103979     this.__defineGetter__("clientY", function () {
103980         return _clientY;
103981     });
103982     this.__defineGetter__("pageX", function () {
103983         return _pageX;
103984     });
103985     this.__defineGetter__("pageY", function () {
103986         return _pageY;
103987     });
103988 };
103989
103990 TouchList = function (touches) {
103991     var _touches = _isValidTouch(touches) ? tizen1_utils.copy(touches) : [],
103992         i, _self;
103993
103994     _self = {
103995         item : function (index) {
103996             if (typeof index !== "number") {
103997                 return null;
103998             }
103999             if (index.toString().indexOf(".") !== -1) {
104000                 return null;
104001             }
104002             if (/^\\d+$/.test(index) || index >= _touches.length) {
104003                 return null;
104004             }
104005             if (!_touches) {
104006                 return null;
104007             }
104008             return _touches[index];
104009         },
104010
104011         identifiedTouch : function (identifier) {
104012             if (typeof identifier !== "number") {
104013                 return null;
104014             }
104015             if (!_touches) {
104016                 return null;
104017             }
104018             for (var i in _touches) {
104019                 if (_touches[i].identifier === identifier) {
104020                     return _touches[i];
104021                 }
104022             }
104023             return null;
104024         }
104025     };
104026
104027     for (i = 0; i < _touches.length; i++) {
104028         _self.__defineGetter__(i, (function (index) {
104029             return function () {
104030                 return _touches[index];
104031             };
104032         }(i)));
104033     }
104034
104035     _self.__defineGetter__("length", function () {
104036         return _touches.length;
104037     });
104038
104039     return _self;
104040 };
104041
104042 TouchEvent = function (type, canBubble, cancelable, touches, targetTouches, changedTouches, altKey, metaKey, ctrlKey, shiftKey) {
104043     var touchEvent = emulatorBridge.document().createEvent("UIEvents");
104044     touchEvent.initUIEvent(type, canBubble, cancelable, emulatorBridge.window(), 1);
104045
104046     touchEvent.__defineGetter__("touches", function () {
104047         return touches;
104048     });
104049     touchEvent.__defineGetter__("targetTouches", function () {
104050         return targetTouches;
104051     });
104052     touchEvent.__defineGetter__("changedTouches", function () {
104053         return changedTouches;
104054     });
104055     touchEvent.__defineGetter__("altKey", function () {
104056         return altKey;
104057     });
104058     touchEvent.__defineGetter__("metaKey", function () {
104059         return metaKey;
104060     });
104061     touchEvent.__defineGetter__("ctrlKey", function () {
104062         return ctrlKey;
104063     });
104064     touchEvent.__defineGetter__("shiftKey", function () {
104065         return shiftKey;
104066     });
104067     return touchEvent;
104068 };
104069
104070 _self = {
104071     mask: function (frame) {
104072         frame.addEventListener("DOMContentLoaded", function () {
104073             /*
104074             var widgetDocument = frame.contentDocument,
104075                 getElementByIdOri = widgetDocument.getElementById;
104076
104077             widgetDocument.getElementById = function () {
104078                 var element, addEventListenerOri;
104079
104080                 element = getElementByIdOri.apply(widgetDocument, Array.prototype.slice.call(arguments));
104081
104082                 if (element) {
104083                     addEventListenerOri = element.addEventListener;
104084                     element.addEventListener = function (event, callback, useCapture) {
104085                         if (event === "touchstart") {
104086                             _touchCanvasElements.push(element);
104087                         }
104088                         addEventListenerOri.apply(element, arguments);
104089                     };
104090                 }
104091                 return element;
104092             };
104093
104094             widgetDocument.createTouch = function (view, target, identifier, pageX, pageY, screenX, screenY) {
104095                 return new Touch(view, target, identifier, pageX, pageY, screenX, screenY);
104096             };
104097
104098             widgetDocument.createTouchList = function (pattern) {
104099                 if (arguments.length !== 1) {
104100                     return null;
104101                 }
104102                 return new TouchList(pattern);
104103             };
104104             */
104105         });
104106     }
104107 };
104108
104109 _initialize();
104110
104111 module.exports = _self;
104112
104113 });
104114 define('ripple/platform/tizen/2.0/typecast', function (require, exports, module) {
104115 /*
104116  *  Copyright 2013 Intel Corporation.
104117  *
104118  * Licensed under the Apache License, Version 2.0 (the "License");
104119  * you may not use this file except in compliance with the License.
104120  * You may obtain a copy of the License at
104121  *
104122  * http://www.apache.org/licenses/LICENSE-2.0
104123  *
104124  * Unless required by applicable law or agreed to in writing, software
104125  * distributed under the License is distributed on an "AS IS" BASIS,
104126  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
104127  * See the License for the specific language governing permissions and
104128  * limitations under the License.
104129  */
104130
104131 var typedef = require('ripple/platform/tizen/2.0/typedef'),
104132     errorcode = require('ripple/platform/tizen/2.0/errorcode'),
104133     WebAPIException = require('ripple/platform/tizen/2.0/WebAPIException'),
104134     TypeCoerce = require('ripple/platform/tizen/2.0/typecoerce'),
104135     _self;
104136
104137 function cast(pattern) {
104138     /*
104139      * Type cast for each known type. The function name is the exact name of the
104140      * corresponding type.
104141      *
104142      * obj
104143      *    Variable to be casted
104144      *
104145      * aux
104146      *    Auxiliary descriptor of obj. It can be any one or combination of below
104147      *    strings, or ignored in most cases.
104148      *
104149      *    "?"     Nullable types
104150      *    "[]"    Arrays
104151      *
104152      * arbitrary
104153      *    A boolean parameter, which indicates that whether obj requires to be
104154      *    verified. It can be ignored in most cases.
104155      *
104156      *    true    Indicates obj may contain invalid values
104157      *    false   Indicates obj must be verified constrainedly
104158      *
104159      * Return
104160      *    Casted object.
104161      */
104162
104163     return function (obj, aux, arbitrary) {
104164         var tc, isNullable;
104165
104166         aux = aux ? String(aux) : "";
104167         tc = new TypeCoerce((aux.indexOf("[]") !== -1) ? [pattern] : pattern);
104168         isNullable = (aux.indexOf("?") !== -1);
104169
104170         if ((isNullable && obj) || !isNullable) {
104171             if ((obj = tc.cast(obj)) === null) {
104172                 throw new WebAPIException(errorcode.TYPE_MISMATCH_ERR);
104173             }
104174         }
104175
104176         if (!arbitrary) {
104177             if (((isNullable && obj) || !isNullable) && !tc.validate(obj)) {
104178                 throw new WebAPIException(errorcode.INVALID_VALUES_ERR);
104179             }
104180         }
104181
104182         return obj;
104183     };
104184 }
104185
104186 function castArgs(pattern) {
104187     /*
104188      * Type cast for each known method of interface. The function name is the
104189      * exact name of the corresponding interface.
104190      *
104191      * method
104192      *    String of method name
104193      *
104194      * argv
104195      *    arguments. The keyword 'arguments' will be always passed in.
104196      */
104197
104198     return function (method, argv) {
104199         var argvType, argvTypeLength, argc, i, tc, isNullable;
104200
104201         argvType = pattern[method];
104202
104203         if (argvType === null)
104204             return;
104205
104206         argvTypeLength = argv.callee.length;
104207         argc = (argv.length < argvTypeLength) ? argv.length : argvTypeLength;
104208
104209         for (i = 0; i < argvTypeLength; ++i) {
104210             isNullable = !!(argvType._optional && argvType._optional[i]);
104211
104212             if (i > argc - 1) {
104213                 if (!isNullable) {
104214                     throw new WebAPIException(errorcode.TYPE_MISMATCH_ERR);
104215                 }
104216                 argv[i] = null;
104217                 continue;
104218             }
104219
104220             tc = new TypeCoerce(argvType[i]);
104221
104222             if ((argv[i] === null) || (argv[i] === undefined)) {
104223                 if (!isNullable || (argv[i] !== null)) {
104224                     throw new WebAPIException(errorcode.TYPE_MISMATCH_ERR);
104225                 }
104226             } else if ((argv[i] = tc.cast(argv[i])) === null) {
104227                 throw new WebAPIException(errorcode.TYPE_MISMATCH_ERR);
104228             }
104229         }
104230     };
104231 }
104232
104233 _self = (function () {
104234     var typecast = {}, i;
104235
104236     for (i in typedef) {
104237         typecast[i] = cast(typedef[i]);
104238     }
104239
104240     for (i in typedef.interface) {
104241         typecast[i] = castArgs(typedef.interface[i]);
104242     }
104243
104244     return typecast;
104245 }());
104246
104247 module.exports = _self;
104248
104249 });
104250 define('ripple/platform/tizen/2.0/typecoerce', function (require, exports, module) {
104251 /*
104252  *  Copyright 2013 Intel Corporation.
104253  *
104254  * Licensed under the Apache License, Version 2.0 (the "License");
104255  * you may not use this file except in compliance with the License.
104256  * You may obtain a copy of the License at
104257  *
104258  * http://www.apache.org/licenses/LICENSE-2.0
104259  *
104260  * Unless required by applicable law or agreed to in writing, software
104261  * distributed under the License is distributed on an "AS IS" BASIS,
104262  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
104263  * See the License for the specific language governing permissions and
104264  * limitations under the License.
104265  */
104266
104267 var t = require('ripple/platform/tizen/2.0/typedef'),
104268     _self;
104269
104270 _self = function (pattern) {
104271     var typeCoerce, typeOfPattern;
104272
104273     // private
104274     function getExtendedType(val) {
104275         var type;
104276
104277         switch (val) {
104278         case "any": // Any type
104279             type = "any";
104280             break;
104281
104282         case "double":
104283         case "float":
104284             type = "float";
104285             break;
104286
104287         default:    // Derivative type name: e.g., "AbstractFilter"
104288             type = "";
104289             break;
104290         }
104291
104292         return type;
104293     }
104294
104295     function getType(val, isPattern) {
104296         var type = Object.prototype.toString.call(val);
104297
104298         switch (type) {
104299         case "[object Array]":
104300             type = (isPattern && (val.length > 1) &&
104301                 (typeof val[0] === "string")) ? "enum" : "Array";
104302             break;
104303
104304         case "[object Boolean]":
104305             type = "boolean";
104306             break;
104307
104308         case "[object Date]":
104309             type = "Date";
104310             break;
104311
104312         case "[object Function]":
104313             type = "Function";
104314             break;
104315
104316         case "[object Number]":
104317             type = "Number";
104318             break;
104319
104320         case "[object Object]":
104321             type = "Object";
104322             break;
104323
104324         case "[object String]":
104325             type = (isPattern && !!val) ? getExtendedType(val) : "DOMString";
104326             break;
104327         }
104328
104329         return type;
104330     }
104331
104332     function isInstance(base, derived, obj) {
104333         var attr;
104334
104335         for (attr in derived) {
104336             switch (attr) {
104337             case "_optional":
104338             case "_derived":
104339                 break;
104340
104341             default:
104342                 if ((!derived._optional || !derived._optional[attr]) &&
104343                     !(attr in obj)) {
104344                     return false;
104345                 }
104346                 break;
104347             }
104348         }
104349
104350         for (attr in obj) {
104351             if (!(attr in base) && !(attr in derived)) {
104352                 return false;
104353             }
104354         }
104355
104356         return true;
104357     }
104358
104359     // public
104360     function cast(obj) {
104361         var typeMap,
104362             typeOfObj = getType(obj, false);
104363
104364         typeMap = {
104365             "Array": function () {
104366                 var arr = [], elementType, i;
104367
104368                 if (typeOfObj !== typeOfPattern) {
104369                     return null;
104370                 }
104371
104372                 elementType = _self(pattern[0]);
104373                 for (i in obj) {
104374                     arr[i] = elementType.cast(obj[i]);
104375                     if (arr[i] === null)
104376                         return null;
104377                 }
104378
104379                 return arr;
104380             },
104381
104382             "DOMString": function () {
104383                 switch (typeOfObj) {
104384                 case "Date":
104385                 case "DOMString":
104386                 case "Number":
104387                     obj = String(obj).trim();
104388                     break;
104389
104390                 default:
104391                     obj = null;
104392                     break;
104393                 }
104394
104395                 return obj;
104396             },
104397
104398             "Date": function () {
104399                 return (typeOfObj === typeOfPattern) ? obj : null;
104400             },
104401
104402             "Function": function () {
104403                 return (typeOfObj === typeOfPattern) ? obj : null;
104404             },
104405
104406             "Number": function () {
104407                 var n = parseInt(obj, 10);
104408
104409                 if (isNaN(n))
104410                     return null;
104411
104412                 return (obj === n) ? n : parseFloat(obj);
104413             },
104414
104415             "Object": function () {
104416                 var ret = {}, attr, i, isMatched = false;
104417
104418                 if (typeOfObj !== typeOfPattern) {
104419                     return null;
104420                 }
104421
104422                 for (attr in pattern) {
104423                     switch (attr) {
104424                     case "_optional":
104425                         break;
104426
104427                     case "_derived":
104428                         for (i in pattern._derived) {
104429                             if (isInstance(pattern, pattern._derived[i], obj)) {
104430                                 isMatched = true;
104431                                 break;
104432                             }
104433                         }
104434                         ret = _self(pattern._derived[isMatched ? i : 0])
104435                             .cast(obj);
104436                         break;
104437
104438                     default:
104439                         if (!pattern._optional || !pattern._optional[attr] ||
104440                             (obj[attr] !== undefined) && (obj[attr] !== null)) {
104441                             ret[attr] = _self(pattern[attr]).cast(obj[attr]);
104442                             if (ret[attr] === null) {
104443                                 return null;
104444                             }
104445                         }
104446                         break;
104447                     }
104448                 }
104449
104450                 return ret;
104451             },
104452
104453             "any": function () {
104454                 return obj;
104455             },
104456
104457             "boolean": function () {
104458                 return (typeOfObj === typeOfPattern) ? obj : null;
104459             },
104460
104461             "enum": function () {
104462                 var i;
104463
104464                 obj = String(obj).trim();
104465                 for (i in pattern) {
104466                     if (obj === pattern[i]) {
104467                         return obj;
104468                     }
104469                 }
104470
104471                 return null;
104472             },
104473
104474             "float": function () {
104475                 var f = parseFloat(obj, 10);
104476
104477                 return (isNaN(f) ? null : f);
104478             },
104479
104480             "": function () {
104481                 return _self(t[pattern]).cast(obj);
104482             }
104483         };
104484
104485         return typeMap[typeOfPattern]();
104486     }
104487
104488     function match(obj) {
104489         var typeMap,
104490             typeOfObj = getType(obj, false);
104491
104492         typeMap = {
104493             "Array": function () {
104494                 var elementType, i;
104495
104496                 if (typeOfObj !== typeOfPattern)
104497                     return false;
104498
104499                 elementType = _self(pattern[0]);
104500                 for (i in obj) {
104501                     if (!elementType.match(obj[i])) {
104502                         return false;
104503                     }
104504                 }
104505
104506                 return true;
104507             },
104508
104509             "DOMString": function () {
104510                 return (typeOfObj === typeOfPattern);
104511             },
104512
104513             "Date": function () {
104514                 return (typeOfObj === typeOfPattern);
104515             },
104516
104517             "Function": function () {
104518                 return (typeOfObj === typeOfPattern);
104519             },
104520
104521             "Number": function () {
104522                 return (typeOfObj === typeOfPattern);
104523             },
104524
104525             "Object": function () {
104526                 var attr, i, isMatched = false;
104527
104528                 if (typeOfObj !== typeOfPattern)
104529                     return false;
104530
104531                 for (attr in pattern) {
104532                     switch (attr) {
104533                     case "_optional":
104534                         break;
104535
104536                     case "_derived":
104537                         isMatched = false;
104538
104539                         for (i in pattern._derived) {
104540                             isMatched = _self(pattern._derived[i]).match(obj);
104541                             if (isMatched)
104542                                 break;
104543                         }
104544                         break;
104545
104546                     default:
104547                         if (pattern._optional && pattern._optional[attr]) {
104548                             isMatched = ((obj[attr] === null) ||
104549                                 (obj[attr] === undefined) ||
104550                                 _self(pattern[attr]).match(obj[attr]));
104551                         } else {
104552                             isMatched = (obj[attr] !== undefined) &&
104553                                 _self(pattern[attr]).match(obj[attr]);
104554                         }
104555                         break;
104556                     }
104557
104558                     if (!isMatched)
104559                         break;
104560                 }
104561
104562                 /*// Check if verbose attributes are present
104563                 if (isMatched) {
104564                     for (attr in obj) {
104565                         if (pattern[attr] === undefined) {
104566                             isMatched = false;
104567                             break;
104568                         }
104569                     }
104570                 }*/
104571
104572                 return isMatched;
104573             },
104574
104575             "any": function () {
104576                 return true;
104577             },
104578
104579             "boolean": function () {
104580                 return (typeOfObj === typeOfPattern);
104581             },
104582
104583             "enum": function () {
104584                 for (var i in pattern) {
104585                     if (obj === pattern[i]) {
104586                         return true;
104587                     }
104588                 }
104589
104590                 return false;
104591             },
104592
104593             "float": function () {
104594                 return (typeOfObj === "Number");
104595             },
104596
104597             "": function () {
104598                 return _self(t[pattern]).match(obj);
104599             }
104600         };
104601
104602         return typeMap[typeOfPattern]();
104603     }
104604
104605     function validate(obj) {
104606         var typeMap,
104607             typeOfObj = getType(obj, false);
104608
104609         typeMap = {
104610             "Array": function () {
104611                 var elementType, i;
104612
104613                 if (typeOfObj !== typeOfPattern)
104614                     return false;
104615
104616                 elementType = _self(pattern[0]);
104617                 for (i in obj) {
104618                     if (!elementType.validate(obj[i])) {
104619                         return false;
104620                     }
104621                 }
104622
104623                 return true;
104624             },
104625
104626             "DOMString": function () {
104627                 return (obj !== "");
104628             },
104629
104630             "Number": function () {
104631                 return (obj !== 0);
104632             },
104633
104634             "Object": function () {
104635                 var attr, i, isValid = false, isMatched = false;
104636
104637                 if (typeOfObj !== typeOfPattern)
104638                     return false;
104639
104640                 for (attr in pattern) {
104641                     switch (attr) {
104642                     case "_optional":
104643                         break;
104644
104645                     case "_derived":
104646                         for (i in pattern._derived) {
104647                             if (isInstance(pattern, pattern._derived[i], obj)) {
104648                                 isMatched = true;
104649                                 break;
104650                             }
104651                         }
104652                         isValid = _self(pattern._derived[isMatched ? i : 0])
104653                             .validate(obj);
104654                         break;
104655
104656                     default:
104657                         if (pattern._optional && pattern._optional[attr]) {
104658                             isValid = true;
104659                         } else {
104660                             isValid = _self(pattern[attr]).validate(obj[attr]);
104661                         }
104662                         break;
104663                     }
104664
104665                     if (!isValid)
104666                         break;
104667                 }
104668
104669                 return isValid;
104670             },
104671
104672             "enum": function () {
104673                 for (var i in pattern) {
104674                     if (obj === pattern[i]) {
104675                         return true;
104676                     }
104677                 }
104678
104679                 return false;
104680             },
104681
104682             "float": function () {
104683                 return (obj !== 0);
104684             },
104685
104686             "": function () {
104687                 return _self(t[pattern]).validate(obj);
104688             }
104689         };
104690
104691         return !typeMap[typeOfPattern] || typeMap[typeOfPattern]();
104692     }
104693
104694     typeOfPattern = getType(pattern, true);
104695
104696     typeCoerce = {
104697         cast:     cast,
104698         match:    match,
104699         validate: validate
104700     };
104701
104702     return typeCoerce;
104703 };
104704
104705 module.exports = _self;
104706
104707 });
104708 define('ripple/platform/tizen/2.0/typedef', function (require, exports, module) {
104709 /*
104710  *  Copyright 2013 Intel Corporation.
104711  *
104712  * Licensed under the Apache License, Version 2.0 (the "License");
104713  * you may not use this file except in compliance with the License.
104714  * You may obtain a copy of the License at
104715  *
104716  * http://www.apache.org/licenses/LICENSE-2.0
104717  *
104718  * Unless required by applicable law or agreed to in writing, software
104719  * distributed under the License is distributed on an "AS IS" BASIS,
104720  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
104721  * See the License for the specific language governing permissions and
104722  * limitations under the License.
104723  */
104724
104725 var _t, _i;
104726
104727 /*
104728  * Primitive type definition
104729  */
104730
104731 _t = {
104732     // Basic
104733     DOMString:                    "",
104734     Date:                         new Date(),
104735     Function:                     function () {},
104736     any:                          "any",
104737     boolean:                      false,
104738     double:                       "double",
104739     float:                        "float",
104740     long:                         0,
104741     "unsigned long":              0,
104742     "unsigned long long":         0,
104743     "unsigned short":             0,
104744
104745     // Common
104746     FilterMatchFlag:              ["EXACTLY", "FULLSTRING", "CONTAINS",
104747                                    "STARTSWITH", "ENDSWITH", "EXISTS"],
104748     SortModeOrder:                ["ASC", "DESC"],
104749     CompositeFilterType:          ["UNION", "INTERSECTION"],
104750
104751     // Calendar
104752     ByDayValue:                   ["MO", "TU", "WE", "TH", "FR", "SA", "SU"],
104753
104754     // Contact
104755     ContactTextFormat:            ["VCARD_30", "VCARD_30"],    // Enum must has more than one value
104756
104757     // Content
104758     ContentDirectoryStorageType:  ["INTERNAL", "EXTERNAL"],
104759     ContentType:                  ["IMAGE", "VIDEO", "AUDIO", "OTHER"],
104760     AudioContentLyricsType:       ["SYNCHRONIZED", "UNSYNCHRONIZED"],
104761     ImageContentOrientation:      ["NORMAL", "FLIP_HORIZONTAL", "ROTATE_180",
104762                                    "FLIP_VERTICAL", "TRANSPOSE", "ROTATE_90",
104763                                    "TRANSVERSE", "ROTATE_270"],
104764
104765     // Data Control
104766     DataType:                     ["MAP", "SQL"],
104767
104768     // Data Sync
104769     SyncMode:                     ["MANUAL", "PERIODIC", "PUSH"],
104770     SyncType:                     ["TWO_WAY", "SLOW", "ONE_WAY_FROM_CLIENT", "REFRESH_FROM_CLIENT", "ONE_WAY_FROM_SERVER", "REFRESH_FROM_SERVER"],
104771     SyncInterval:                 ["5_MINUTES", "15_MINUTES", "1_HOUR", "4_HOURS", "12_HOURS", "1_DAY", "1_WEEK", "1_MONTH"],
104772     SyncServiceType:              ["CONTACT", "EVENT"],
104773     SyncStatus:                   ["SUCCESS", "FAIL", "STOP", "NONE"],
104774
104775     // Messaging
104776     MessageServiceTag:            ["messaging.sms", "messaging.mms", "messaging.email"],
104777
104778     // Network Bearer Selection
104779     NetworkType:                  ["CELLULAR", "UNKNOWN"]
104780 };
104781
104782 /*
104783  * Derivative type definition
104784  */
104785
104786 /*
104787  * Object attributes
104788  *     Contruct a prototype of an object. Specify a primitive type for each attribute.
104789  *
104790  * _optional
104791  *     Optional attributes table, which consists of two types of attributes,
104792  *
104793  *     nullable
104794  *         Nullable attributes, marked as '?' in IDL.
104795  *
104796  *     undefined
104797  *         Array type attributes, that not definitely specified to be
104798  *         initialized as an empty array, i.e., undefined-initialized array.
104799  *
104800  * _derived
104801  *     Derived types, which used in two cases of definition,
104802  *
104803  *     Subtype list
104804  *         An array consists of derived subtypes. It exists in the definition of
104805  *         a base type.
104806  *
104807  *     Union types
104808  *         An array consists of member types. It exists in the definition of
104809  *         a union type.
104810  */
104811
104812 /*
104813  * Common
104814  */
104815
104816 _t.CompositeFilter = {
104817     type:    _t.CompositeFilterType,
104818     filters: ["AbstractFilter"]     // Recursive expansion
104819 };
104820
104821 _t.AttributeFilter = {
104822     attributeName: _t.DOMString,
104823     matchFlag:     _t.FilterMatchFlag,
104824     matchValue:    _t.any
104825 };
104826
104827 _t.AttributeRangeFilter = {
104828     attributeName: _t.DOMString,
104829     initialValue:  _t.any,
104830     endValue:      _t.any
104831 };
104832
104833 _t.AbstractFilter = {
104834     _derived: [_t.CompositeFilter, _t.AttributeFilter, _t.AttributeRangeFilter]
104835 };
104836
104837 _t.SortMode = {
104838     attributeName: _t.DOMString,
104839     order:         _t.SortModeOrder
104840 };
104841
104842 _t.SimpleCoordinates = {
104843     latitude:  _t.double,
104844     longitude: _t.double
104845 };
104846
104847 _t.SuccessCallback = _t.Function;
104848 _t.ErrorCallback   = _t.Function;
104849
104850 /*
104851  * Alarm
104852  */
104853
104854 _t.AlarmId = _t.DOMString;
104855
104856 _t.AlarmRelative = {
104857     delay:               _t["unsigned long long"],
104858     period:              _t["unsigned long long"],
104859     getRemainingSeconds: _t.Function,
104860
104861     _optional: {
104862         // nullable
104863         period:              true,
104864         getRemainingSeconds: true
104865     }
104866 };
104867
104868 _t.AlarmAbsolute = {
104869     date:                 _t.Date,
104870     period:               _t["unsigned long long"],
104871     daysOfTheWeek:        [_t.ByDayValue],
104872     getNextScheduledDate: _t.Function,
104873
104874     _optional: {
104875         // nullable
104876         period:               true,
104877         getNextScheduledDate: true
104878     }
104879 };
104880
104881 _t.Alarm = {
104882     id: _t.AlarmId,
104883
104884     _optional: {
104885         // nullable
104886         id: true
104887     },
104888
104889     _derived: [_t.AlarmRelative, _t.AlarmAbsolute]
104890 };
104891
104892 /*
104893  * Application
104894  */
104895
104896 _t.ApplicationId = _t.DOMString;
104897
104898 _t.ApplicationControlData = {
104899     key:   _t.DOMString,
104900     value: [_t.DOMString]
104901 };
104902
104903 _t.ApplicationControl = {
104904     operation: _t.DOMString,
104905     uri:       _t.DOMString,
104906     mime:      _t.DOMString,
104907     category:  _t.DOMString,
104908     data:      [_t.ApplicationControlData],
104909
104910     _optional: {
104911         // nullable
104912         uri:      true,
104913         mime:     true,
104914         category: true
104915     }
104916 };
104917
104918 /*
104919  * Bookmark
104920  */
104921
104922 _t.BookmarkFolder = {
104923     parent: "BookmarkFolder",
104924     title:  _t.DOMString,
104925
104926     _optional: {
104927         // nullable
104928         parent: true
104929     }
104930 };
104931
104932 _t.BookmarkItem = {
104933     parent: _t.BookmarkFolder,
104934     title:  _t.DOMString,
104935     url:    _t.DOMString,
104936
104937     _optional: {
104938         // nullable
104939         parent: true
104940     }
104941 };
104942
104943 _t.Bookmark = {
104944     _derived: [_t.BookmarkItem, _t.BookmarkFolder]
104945 };
104946
104947 /*
104948  * Contact
104949  */
104950
104951 _t.AddressBookId  = _t.DOMString;
104952 _t.ContactId      = _t.DOMString;
104953 _t.PersonId       = _t.DOMString;
104954 _t.ContactGroupId = _t.DOMString;
104955
104956 _t.Person = {
104957     id:               _t.PersonId,
104958     displayName:      _t.DOMString,
104959     contactCount:     _t.long,
104960     hasPhoneNumber:   _t.boolean,
104961     hasEmail:         _t.boolean,
104962     isFavorite:       _t.boolean,
104963     photoURI:         _t.DOMString,
104964     ringtoneURI:      _t.DOMString,
104965     displayContactId: _t.ContactId,
104966
104967     _optional: {
104968         // nullable
104969         photoURI:    true,
104970         ringtoneURI: true
104971     }
104972 };
104973
104974 _t.ContactRef = {
104975     addressBookId: _t.AddressBookId,
104976     contactId:     _t.ContactId
104977 };
104978
104979 _t.ContactName = {
104980     prefix:            _t.DOMString,
104981     suffix:            _t.DOMString,
104982     firstName:         _t.DOMString,
104983     middleName:        _t.DOMString,
104984     lastName:          _t.DOMString,
104985     nicknames:         [_t.DOMString],
104986     phoneticFirstName: _t.DOMString,
104987     phoneticLastName:  _t.DOMString,
104988     displayName:       _t.DOMString,
104989
104990     _optional: {
104991         // nullable
104992         prefix:            true,
104993         suffix:            true,
104994         firstName:         true,
104995         middleName:        true,
104996         lastName:          true,
104997         phoneticFirstName: true,
104998         phoneticLastName:  true,
104999         displayName:       true
105000     }
105001 };
105002
105003 _t.ContactOrganization = {
105004     name:       _t.DOMString,
105005     department: _t.DOMString,
105006     title:      _t.DOMString,
105007     role:       _t.DOMString,
105008     logoURI:    _t.DOMString,
105009
105010     _optional: {
105011         // nullable
105012         name:       true,
105013         department: true,
105014         title:      true,
105015         role:       true,
105016         logoURI:    true
105017     }
105018 };
105019
105020 _t.ContactWebSite = {
105021     url:  _t.DOMString,
105022     type: _t.DOMString,
105023
105024     _optional: {
105025         // nullable
105026         type: true
105027     }
105028 };
105029
105030 _t.ContactAnniversary = {
105031     date:  _t.Date,
105032     label: _t.DOMString,
105033
105034     _optional: {
105035         // nullable
105036         label: true
105037     }
105038 };
105039
105040 _t.ContactAddress = {
105041     country:               _t.DOMString,
105042     region:                _t.DOMString,
105043     city:                  _t.DOMString,
105044     streetAddress:         _t.DOMString,
105045     additionalInformation: _t.DOMString,
105046     postalCode:            _t.DOMString,
105047     isDefault:             _t.boolean,
105048     types:                 [_t.DOMString],
105049
105050     _optional: {
105051         // nullable
105052         country:               true,
105053         region:                true,
105054         city:                  true,
105055         streetAddress:         true,
105056         additionalInformation: true,
105057         postalCode:            true,
105058         // undefined
105059         types:                 true
105060     }
105061 };
105062
105063 _t.ContactPhoneNumber = {
105064     number:    _t.DOMString,
105065     isDefault: _t.boolean,
105066     types:     [_t.DOMString],
105067
105068     _optional: {
105069         // undefined
105070         types: true
105071     }
105072 };
105073
105074 _t.ContactEmailAddress = {
105075     email:     _t.DOMString,
105076     isDefault: _t.boolean,
105077     types:     [_t.DOMString],
105078
105079     _optional: {
105080         // undefined
105081         types: true
105082     }
105083 };
105084
105085 _t.Contact = {
105086     id:              _t.ContactId,
105087     personId:        _t.PersonId,
105088     addressBookId:   _t.AddressBookId,
105089     lastUpdated:     _t.Date,
105090     isFavorite:      _t.boolean,
105091     name:            _t.ContactName,
105092     addresses:       [_t.ContactAddress],
105093     photoURI:        _t.DOMString,
105094     phoneNumbers:    [_t.ContactPhoneNumber],
105095     emails:          [_t.ContactEmailAddress],
105096     birthday:        _t.Date,
105097     anniversaries:   [_t.ContactAnniversary],
105098     organizations:   [_t.ContactOrganization],
105099     notes:           [_t.DOMString],
105100     urls:            [_t.ContactWebSite],
105101     ringtoneURI:     _t.DOMString,
105102     groupIds:        [_t.ContactGroupId],
105103     convertToString: _t.Function,
105104     clone:           _t.Function,
105105
105106     _optional: {
105107         // nullable
105108         id:            true,
105109         personId:      true,
105110         addressBookId: true,
105111         lastUpdated:   true,
105112         name:          true,
105113         photoURI:      true,
105114         birthday:      true,
105115         ringtoneURI:   true
105116     }
105117 };
105118
105119 _t.ContactGroup = {
105120     id:            _t.ContactGroupId,
105121     addressBookId: _t.AddressBookId,
105122     name:          _t.DOMString,
105123     ringtoneURI:   _t.DOMString,
105124     photoURI:      _t.DOMString,
105125     readOnly:      _t.boolean,
105126
105127     _optional: {
105128         // nullable
105129         id:            true,
105130         addressBookId: true,
105131         ringtoneURI:   true,
105132         photoURI:      true
105133     }
105134 };
105135
105136 _t.PersonArraySuccessCallback      = _t.Function;
105137 _t.ContactArraySuccessCallback     = _t.Function;
105138 _t.AddressBookArraySuccessCallback = _t.Function;
105139
105140 _t.AddressBookChangeCallback = {
105141     oncontactsadded:   _t.Function,
105142     oncontactsupdated: _t.Function,
105143     oncontactsremoved: _t.Function
105144 };
105145
105146 _t.PersonsChangeCallback = {
105147     onpersonsadded:   _t.Function,
105148     onpersonsupdated: _t.Function,
105149     onpersonsremoved: _t.Function
105150 };
105151
105152 /*
105153  * Content
105154  */
105155
105156 _t.ContentId                            = _t.DOMString;
105157 _t.ContentDirectoryId                   = _t.DOMString;
105158 _t.ContentArraySuccessCallback          = _t.Function;
105159 _t.ContentDirectoryArraySuccessCallback = _t.Function;
105160 _t.ContentScanSuccessCallback           = _t.Function;
105161
105162 _t.ContentChangeCallback = {
105163     oncontentadded:   _t.Function,
105164     oncontentupdated: _t.Function,
105165     oncontentremoved: _t.Function
105166 };
105167
105168 _t.VideoContent = {
105169     geolocation: _t.SimpleCoordinates,
105170     album:       _t.DOMString,
105171     artists:     [_t.DOMString],
105172     duration:    _t["unsigned long"],
105173     width:       _t["unsigned long"],
105174     height:      _t["unsigned long"],
105175
105176     _optional: {
105177         // nullable
105178         geolocation: true,
105179         album:       true,
105180         artists:     true
105181     }
105182 };
105183
105184 _t.AudioContentLyrics = {
105185     type:       _t.AudioContentLyricsType,
105186     timestamps: [_t["unsigned long"]],
105187     texts:      [_t.DOMString]
105188 };
105189
105190 _t.AudioContent = {
105191     album:       _t.DOMString,
105192     genres:      [_t.DOMString],
105193     artists:     [_t.DOMString],
105194     composers:   [_t.DOMString],
105195     lyrics:      _t.AudioContentLyrics,
105196     copyright:   _t.DOMString,
105197     bitrate:     _t["unsigned long"],
105198     trackNumber: _t["unsigned short"],
105199     duration:    _t["unsigned long"],
105200
105201     _optional: {
105202         // nullable
105203         album:       true,
105204         genres:      true,
105205         artists:     true,
105206         composers:   true,
105207         lyrics:      true,
105208         copyright:   true,
105209         trackNumber: true
105210     }
105211 };
105212
105213 _t.ImageContent = {
105214     geolocation: _t.SimpleCoordinates,
105215     width:       _t["unsigned long"],
105216     height:      _t["unsigned long"],
105217     orientation: _t.ImageContentOrientation,
105218
105219     _optional: {
105220         // nullable
105221         geolocation: true
105222     }
105223 };
105224
105225 _t.Content = {
105226     editableAttributes: [_t.DOMString],
105227     id:                 _t.ContentId,
105228     name:               _t.DOMString,
105229     type:               _t.ContentType,
105230     mimeType:           _t.DOMString,
105231     title:              _t.DOMString,
105232     contentURI:         _t.DOMString,
105233     thumbnailURIs:      [_t.DOMString],
105234     releaseDate:        _t.Date,
105235     modifiedDate:       _t.Date,
105236     size:               _t["unsigned long"],
105237     description:        _t.DOMString,
105238     rating:             _t.float,
105239
105240     _optional: {
105241         // nullable
105242         thumbnailURIs: true,
105243         releaseDate:   true,
105244         modifiedDate:  true,
105245         description:   true
105246     },
105247
105248     _derived: [_t.VideoContent, _t.AudioContent, _t.ImageContent]
105249 };
105250
105251 /*
105252  * Data Control
105253  */
105254
105255 _t.DataControlSuccessCallback         = _t.Function;
105256 _t.DataControlErrorCallback           = _t.Function;
105257 _t.DataControlInsertSuccessCallback   = _t.Function;
105258 _t.DataControlSelectSuccessCallback   = _t.Function;
105259 _t.DataControlGetValueSuccessCallback = _t.Function;
105260
105261 _t.RowData = {
105262     columns: [_t.DOMString],
105263     values:  [_t.DOMString]
105264 };
105265
105266 /*
105267  * Data Sync
105268  */
105269
105270 _t.SyncProfileId = _t.DOMString;
105271
105272 _t.SyncInfo = {
105273     url:                _t.DOMString,
105274     mode:               _t.SyncMode,
105275     type:               _t.SyncType,
105276     interval:           _t.SyncInterval,
105277
105278     _optional: {
105279         // nullable
105280         type:       true,
105281         interval:   true
105282     }
105283 };
105284
105285 _t.SyncServiceInfo = {
105286     enable:             _t.boolean,
105287     serviceType:        _t.SyncServiceType,
105288     serverDatabaseUri:  _t.DOMString
105289 };
105290
105291 _t.SyncProfileInfo = {
105292     profileName:    _t.DOMString,
105293     syncInfo:       _t.SyncInfo,
105294     serviceInfo:    [_t.SyncServiceInfo],
105295
105296     _optional: {
105297         // nullable
105298         serviceInfo:    true
105299     }
105300 };
105301
105302 /*
105303  * Messaging
105304  */
105305
105306 _t.MessageId                               = _t.DOMString;
105307 _t.MessageAttachmentId                     = _t.DOMString;
105308 _t.MessageConvId                           = _t.DOMString;
105309 _t.MessageFolderId                         = _t.DOMString;
105310 _t.MessageServiceArraySuccessCallback      = _t.Function;
105311 _t.MessageRecipientsCallback               = _t.Function;
105312 _t.MessageBodySuccessCallback              = _t.Function;
105313 _t.MessageAttachmentSuccessCallback        = _t.Function;
105314 _t.MessageArraySuccessCallback             = _t.Function;
105315 _t.MessageConversationArraySuccessCallback = _t.Function;
105316 _t.MessageFolderArraySuccessCallback       = _t.Function;
105317
105318 _t.MessageFolder = {
105319     id:             _t.MessageFolderId,
105320     parentId:       _t.MessageFolderId,
105321     serviceId:      _t.DOMString,
105322     contentType:    _t.MessageServiceTag,
105323     name:           _t.DOMString,
105324     path:           _t.DOMString,
105325     type:           _t.DOMString,
105326     synchronizable: _t.boolean,
105327
105328     _optional: {
105329         // nullable
105330         parentId: true
105331     }
105332
105333 };
105334
105335 _t.MessagesChangeCallback = {
105336     messagesadded:   _t.Function,
105337     messagesupdated: _t.Function,
105338     messagesremoved: _t.Function
105339 };
105340
105341 _t.MessageConversationsChangeCallback = {
105342     conversationsadded:   _t.Function,
105343     conversationsupdated: _t.Function,
105344     conversationsremoved: _t.Function
105345 };
105346
105347 _t.MessageFoldersChangeCallback = {
105348     foldersadded:   _t.Function,
105349     foldersupdated: _t.Function,
105350     foldersremoved: _t.Function
105351 };
105352
105353 /*
105354  * Network Bearer Selection
105355  */
105356
105357 _t.NetworkSuccessCallback = {
105358     onsuccess:      _t.Function,
105359     ondisconnected: _t.Function
105360 };
105361
105362 /*
105363  * Push
105364  */
105365
105366 _t.PushRegistrationId          = _t.DOMString;
105367 _t.PushRegisterSuccessCallback = _t.Function;
105368 _t.PushNotificationCallback    = _t.Function;
105369
105370 /*
105371  * Package
105372  */
105373
105374 _t.PackageId = _t.DOMString;
105375 _t.PackageProgressCallback = {
105376     onprogress: _t.Function,
105377     oncomplete: _t.Function,
105378
105379     _optional: {
105380         onprogress: true,
105381         oncomplete: true
105382     }
105383 };
105384 _t.PackageInformationArraySuccessCallback = _t.Function;
105385 _t.PackageInfomationEventCallback = {
105386     oninstalled:   _t.Function,
105387     onupdated:     _t.Function,
105388     onuninstalled: _t.Function,
105389
105390     _optional: {
105391         oninstalled:   true,
105392         onupdated:     true,
105393         onuninstalled: true
105394     }
105395 };
105396
105397 /*
105398  * Interface prototype definition
105399  */
105400
105401 _i = {
105402     // Contact
105403     ContactManager:            {},
105404     AddressBook:               {},
105405     Person:                    {},
105406
105407     // Content
105408     ContentManager:            {},
105409
105410     // Data Control
105411     DataControlManager:        {},
105412     SQLDataControlConsumer:    {},
105413     MappedDataControlConsumer: {}
105414 };
105415
105416 /*
105417  * Contact
105418  */
105419
105420 // ContactManager
105421 _i.ContactManager.getAddressBooks = {
105422     0: _t.AddressBookArraySuccessCallback,
105423     1: _t.ErrorCallback,
105424
105425     _optional: {
105426         1: true
105427     }
105428 };
105429
105430 _i.ContactManager.getUnifiedAddressBook = null;
105431 _i.ContactManager.getDefaultAddressBook = null;
105432
105433 _i.ContactManager.getAddressBook = {
105434     0: _t.AddressBookId
105435 };
105436
105437 _i.ContactManager.get = {
105438     0: _t.PersonId
105439 };
105440
105441 _i.ContactManager.update = {
105442     0: _t.Person
105443 };
105444
105445 _i.ContactManager.updateBatch = {
105446     0: [_t.Person],
105447     1: _t.SuccessCallback,
105448     2: _t.ErrorCallback,
105449
105450     _optional: {
105451         1: true,
105452         2: true
105453     }
105454 };
105455
105456 _i.ContactManager.remove = {
105457     0: _t.PersonId
105458 };
105459
105460 _i.ContactManager.removeBatch = {
105461     0: [_t.PersonId],
105462     1: _t.SuccessCallback,
105463     2: _t.ErrorCallback,
105464
105465     _optional: {
105466         1: true,
105467         2: true
105468     }
105469 };
105470
105471 _i.ContactManager.find = {
105472     0: _t.PersonArraySuccessCallback,
105473     1: _t.ErrorCallback,
105474     2: _t.AbstractFilter,
105475     3: _t.SortMode,
105476
105477     _optional: {
105478         1: true,
105479         2: true,
105480         3: true
105481     }
105482 };
105483
105484 _i.ContactManager.addChangeListener = {
105485     0: _t.PersonsChangeCallback
105486 };
105487
105488 _i.ContactManager.removeChangeListener = {
105489     0: _t.long
105490 };
105491
105492 // AddressBook
105493 _i.AddressBook.get = {
105494     0: _t.ContactId
105495 };
105496
105497 _i.AddressBook.add = {
105498     0: _t.Contact
105499 };
105500
105501 _i.AddressBook.addBatch = {
105502     0: [_t.Contact],
105503     1: _t.ContactArraySuccessCallback,
105504     2: _t.ErrorCallback,
105505
105506     _optional: {
105507         1: true,
105508         2: true
105509     }
105510 };
105511
105512 _i.AddressBook.update = {
105513     0: _t.Contact
105514 };
105515
105516 _i.AddressBook.updateBatch = {
105517     0: [_t.Contact],
105518     1: _t.SuccessCallback,
105519     2: _t.ErrorCallback,
105520
105521     _optional: {
105522         1: true,
105523         2: true
105524     }
105525 };
105526
105527 _i.AddressBook.remove = {
105528     0: _t.ContactId
105529 };
105530
105531 _i.AddressBook.removeBatch = {
105532     0: [_t.ContactId],
105533     1: _t.SuccessCallback,
105534     2: _t.ErrorCallback,
105535
105536     _optional: {
105537         1: true,
105538         2: true
105539     }
105540 };
105541
105542 _i.AddressBook.find = {
105543     0: _t.ContactArraySuccessCallback,
105544     1: _t.ErrorCallback,
105545     2: _t.AbstractFilter,
105546     3: _t.SortMode,
105547
105548     _optional:{
105549         1: true,
105550         2: true,
105551         3: true
105552     }
105553 };
105554
105555 _i.AddressBook.addChangeListener = {
105556     0: _t.AddressBookChangeCallback,
105557     1: _t.ErrorCallback,
105558
105559     _optional: {
105560         1: true
105561     }
105562 };
105563
105564 _i.AddressBook.removeChangeListener = {
105565     0: _t.long
105566 };
105567
105568 _i.AddressBook.getGroup = {
105569     0: _t.ContactGroupId
105570 };
105571
105572 _i.AddressBook.addGroup = {
105573     0: _t.ContactGroup
105574 };
105575
105576 _i.AddressBook.updateGroup = {
105577     0: _t.ContactGroup
105578 };
105579
105580 _i.AddressBook.removeGroup = {
105581     0: _t.ContactGroupId
105582 };
105583
105584 _i.AddressBook.getGroups = null;
105585
105586 // Person
105587 _i.Person.link = {
105588     0: _t.PersonId
105589 };
105590
105591 _i.Person.unlink = {
105592     0: _t.ContactId
105593 };
105594
105595 /*
105596  * Content
105597  */
105598
105599 // ContentManager
105600 _i.ContentManager.update = {
105601     0: _t.Content
105602 };
105603
105604 _i.ContentManager.updateBatch = {
105605     0: [_t.Content],
105606     1: _t.SuccessCallback,
105607     2: _t.ErrorCallback,
105608
105609     _optional: {
105610         1: true,
105611         2: true
105612     }
105613 };
105614
105615 _i.ContentManager.getDirectories = {
105616     0: _t.ContentDirectoryArraySuccessCallback,
105617     1: _t.ErrorCallback,
105618
105619     _optional: {
105620         1: true
105621     }
105622 };
105623
105624 _i.ContentManager.find = {
105625     0: _t.ContentArraySuccessCallback,
105626     1: _t.ErrorCallback,
105627     2: _t.ContentDirectoryId,
105628     3: _t.AbstractFilter,
105629     4: _t.SortMode,
105630     5: _t["unsigned long"],
105631     6: _t["unsigned long"],
105632
105633     _optional: {
105634         1: true,
105635         2: true,
105636         3: true,
105637         4: true,
105638         5: true,
105639         6: true
105640     }
105641 };
105642
105643 _i.ContentManager.scanFile = {
105644     0: _t.DOMString,
105645     1: _t.ContentScanSuccessCallback,
105646     2: _t.ErrorCallback,
105647
105648     _optional: {
105649         1: true,
105650         2: true
105651     }
105652 };
105653
105654 _i.ContentManager.setChangeListener = {
105655     0: _t.ContentChangeCallback
105656 };
105657
105658 _i.ContentManager.unsetChangeListener = null;
105659
105660 /*
105661  * Data Control
105662  */
105663
105664 // DataControlManager
105665 _i.DataControlManager.getDataControlConsumer = {
105666     0: _t.DOMString,
105667     1: _t.DOMString,
105668     2: _t.DataType
105669 };
105670
105671 // SQLDataControlConsumer
105672 _i.SQLDataControlConsumer.insert = {
105673     0: _t["unsigned long"],
105674     1: _t.RowData,
105675     2: _t.DataControlInsertSuccessCallback,
105676     3: _t.DataControlErrorCallback,
105677
105678     _optional: {
105679         2: true,
105680         3: true
105681     }
105682 };
105683
105684 _i.SQLDataControlConsumer.update = {
105685     0: _t["unsigned long"],
105686     1: _t.RowData,
105687     2: _t.DOMString,
105688     3: _t.DataControlSuccessCallback,
105689     4: _t.DataControlErrorCallback,
105690
105691     _optional: {
105692         3: true,
105693         4: true
105694     }
105695 };
105696
105697 _i.SQLDataControlConsumer.remove = {
105698     0: _t["unsigned long"],
105699     1: _t.DOMString,
105700     2: _t.DataControlSuccessCallback,
105701     3: _t.DataControlErrorCallback,
105702
105703     _optional: {
105704         2: true,
105705         3: true
105706     }
105707 };
105708
105709 _i.SQLDataControlConsumer.select = {
105710     0: _t["unsigned long"],
105711     1: [_t.DOMString],
105712     2: _t.DOMString,
105713     3: _t.DataControlSelectSuccessCallback,
105714     4: _t.DataControlErrorCallback,
105715     5: _t["unsigned long"],
105716     6: _t["unsigned long"],
105717
105718     _optional: {
105719         4: true,
105720         5: true,
105721         6: true
105722     }
105723 };
105724
105725 // MappedDataControlConsumer
105726 _i.MappedDataControlConsumer.addValue = {
105727     0: _t["unsigned long"],
105728     1: _t.DOMString,
105729     2: _t.DOMString,
105730     3: _t.DataControlSuccessCallback,
105731     4: _t.DataControlErrorCallback,
105732
105733     _optional: {
105734         3: true,
105735         4: true
105736     }
105737 };
105738
105739 _i.MappedDataControlConsumer.removeValue = {
105740     0: _t["unsigned long"],
105741     1: _t.DOMString,
105742     2: _t.DOMString,
105743     3: _t.DataControlSuccessCallback,
105744     4: _t.DataControlErrorCallback,
105745
105746     _optional: {
105747         4: true
105748     }
105749 };
105750
105751 _i.MappedDataControlConsumer.getValue = {
105752     0: _t["unsigned long"],
105753     1: _t.DOMString,
105754     2: _t.DataControlGetValueSuccessCallback,
105755     3: _t.DataControlErrorCallback,
105756
105757     _optional: {
105758         3: true
105759     }
105760 };
105761
105762 _i.MappedDataControlConsumer.updateValue = {
105763     0: _t["unsigned long"],
105764     1: _t.DOMString,
105765     2: _t.DOMString,
105766     3: _t.DOMString,
105767     4: _t.DataControlSuccessCallback,
105768     5: _t.DataControlErrorCallback,
105769
105770     _optional: {
105771         5: true
105772     }
105773 };
105774
105775 _t.interface = _i;
105776
105777 module.exports = _t;
105778
105779 });
105780 define('ripple/platform/tizen/2.0/vibration', function (require, exports, module) {
105781 /*
105782  *  Copyright 2012 Intel Corporation.
105783  *
105784  * Licensed under the Apache License, Version 2.0 (the "License");
105785  * you may not use this file except in compliance with the License.
105786  * You may obtain a copy of the License at
105787  *
105788  * http://www.apache.org/licenses/LICENSE-2.0
105789  *
105790  * Unless required by applicable law or agreed to in writing, software
105791  * distributed under the License is distributed on an "AS IS" BASIS,
105792  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
105793  * See the License for the specific language governing permissions and
105794  * limitations under the License.
105795  */
105796
105797 var event = require('ripple/event'),
105798     deviceSettings = require('ripple/deviceSettings'),
105799     constants = require('ripple/constants'),
105800     tizen1_utils = require('ripple/platform/tizen/2.0/tizen1_utils'),
105801     emulatorBridge = require('ripple/emulatorBridge'),
105802     curPost,
105803     _self;
105804
105805 function isVibratorOn() {
105806     return deviceSettings.retrieve("Config.vibratingMode");
105807 }
105808
105809 var vibrator = (function () {
105810     var vibratorPattern,
105811         isVibrating = false,
105812         runTime = 0,
105813         vibrateTimeout = null,
105814         MILLILSECONDS_OF_ONE_VIBRATION = 100,
105815         node = jQuery("#" + constants.COMMON.DEVICE_CONTAINER),
105816         movementIndex = 0,
105817         movement = [{ left: -10 }, { left: 0 }, { left: 10 }, { left: 0 },
105818                     {top: -10 }, { top: 0 }, {top: 10 }, { top: 0 }];
105819
105820     function _clearTimeout() {
105821         if (vibrateTimeout) {
105822             clearInterval(vibrateTimeout);
105823             vibrateTimeout = null;
105824         }
105825     }
105826
105827     function stopVibrate() {
105828         isVibrating = false;
105829         _clearTimeout();
105830         node.css({left: 0, top: 0}, MILLILSECONDS_OF_ONE_VIBRATION);
105831     }
105832
105833     function vibrate() {
105834         node.css(movement[movementIndex]);
105835         movementIndex = (movementIndex + 1) % 8;
105836     }
105837
105838     function changePulse() {
105839         if (emulatorBridge.document().hidden) {
105840             return;
105841         }
105842
105843         //run time
105844         runTime = runTime + MILLILSECONDS_OF_ONE_VIBRATION;
105845         if (curPost >= vibratorPattern.length) {
105846             setTimeout(stopVibrate, 1);
105847         }
105848         if (runTime > vibratorPattern[curPost]) {
105849             curPost = curPost + 1;
105850             runTime = 0;
105851         } else {
105852             if ((curPost % 2) === 0) {
105853                 vibrate();
105854             }
105855         }
105856     }
105857
105858     function startVibrate(_pattern) {
105859         if (!isVibratorOn())
105860             return;
105861
105862         vibratorPattern = _pattern;
105863         _clearTimeout();
105864         movementIndex = 0;
105865         if (_pattern) {
105866             runTime = 0;
105867             vibrateTimeout = setInterval(changePulse, MILLILSECONDS_OF_ONE_VIBRATION);
105868         }
105869         isVibrating = true;
105870     }
105871
105872     return {
105873         isVibrating: isVibrating,
105874         startVibrate: startVibrate,
105875         stopVibrate: stopVibrate
105876     };
105877 }());
105878
105879 _self = {
105880     vibrate: function () {
105881         var pattern = arguments[0],
105882             i;
105883
105884         // If vibrator is off, stop the vibration
105885         event.on("VibratingModeChanged", function (value) {
105886             if (value === false) {
105887                 vibrator.stopVibrate();
105888             }
105889         });
105890
105891         //1. If the hidden attribute [PAGE-VISIBILITY] is set to true, abort these steps.
105892         if (emulatorBridge.document().hidden) {
105893             return;
105894         }
105895
105896         //2. Let pattern be the value of the first argument.
105897         if (!tizen1_utils.isValidArray(pattern)) {
105898             pattern |= 0;
105899         } else {
105900             for (i = 0; i < pattern.length; i++) {
105901                 pattern[i] |= 0;
105902             }
105903         }
105904
105905         //3. If pattern is 0, or an empty list, cancel the pre-existing instance of the processing vibration patterns algorithm, if any, and abort these steps.
105906         if (pattern === 0 || (tizen1_utils.isValidArray(pattern) && pattern.length === 0)) {
105907             vibrator.stopVibrate();
105908             return;
105909         }
105910
105911         //4. If pattern is a list, proceed to the next step. Otherwise run the following substeps:
105912         //a. Let list be an initially empty list, and add pattern to list.
105913         //b. Let pattern be list.
105914         if (!tizen1_utils.isValidArray(pattern)) {
105915             pattern = [pattern];
105916         }
105917
105918         //5. If any entry of pattern exceeds an implementation-dependent limit, then the user agent may throw a NotSupportedError exception and abort these steps.
105919
105920         //6. If the length of pattern is even, then remove the last entry in pattern.
105921         if (pattern.length % 2 === 0) {
105922             pattern.pop();
105923         }
105924
105925         //7. Cancel the pre-existing instance of the processing vibration patterns algorithm, if any.
105926         if (vibrator.isVibrating) {
105927             vibrator.stopVibrate();
105928         }
105929
105930         curPost = 0;
105931         vibrator.startVibrate(pattern);
105932     }
105933 };
105934
105935 module.exports = _self;
105936
105937 });
105938 define('ripple/platform/w3c/1.0/Acceleration', function (require, exports, module) {
105939 module.exports = function (x, y, z) {
105940     return {
105941         x: x || 0,    //Acceleration in the 'x' expressed in m/s^2. (Number)
105942         y: y || 0,    //Acceleration in the 'y' expressed in m/s^2. (Number)
105943         z: z || 0     //Acceleration in the 'z' expressed in m/s^2. (Number)
105944     };
105945 };
105946
105947 });
105948 define('ripple/platform/w3c/1.0/Coordinates', function (require, exports, module) {
105949 /*
105950  *  Copyright 2011 Research In Motion Limited.
105951  *
105952  * Licensed under the Apache License, Version 2.0 (the "License");
105953  * you may not use this file except in compliance with the License.
105954  * You may obtain a copy of the License at
105955  *
105956  * http://www.apache.org/licenses/LICENSE-2.0
105957  *
105958  * Unless required by applicable law or agreed to in writing, software
105959  * distributed under the License is distributed on an "AS IS" BASIS,
105960  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
105961  * See the License for the specific language governing permissions and
105962  * limitations under the License.
105963  */
105964 module.exports = function (latitude, longitude, altitude, accuracy, altitudeAccuracy, heading, speed) {
105965     return {
105966         latitude: latitude || 0,                    //Latitude in decimal degrees. (Number)
105967         longitude: longitude || 0,                  //Longitude in decimal degrees. (Number)
105968         altitude: altitude || 0,                    //Height of the position in meters above the ellipsoid. (Number)
105969         accuracy: accuracy || 0,                    //Accuracy level of the latitude and longitude coordinates in meters. (Number)
105970         altitudeAccuracy: altitudeAccuracy || 0,    //Accuracy level of the altitude coordinate in meters. (Number)
105971         heading: heading || 0,                      //Direction of travel, specified in degrees counting clockwise relative to the true north. (Number)
105972         speed: speed || 0                           //Current ground speed of the device, specified in meters per second. (Number)
105973     };
105974 };
105975
105976 });
105977 define('ripple/platform/w3c/1.0/Position', function (require, exports, module) {
105978 /*
105979  *  Copyright 2011 Research In Motion Limited.
105980  *
105981  * Licensed under the Apache License, Version 2.0 (the "License");
105982  * you may not use this file except in compliance with the License.
105983  * You may obtain a copy of the License at
105984  *
105985  * http://www.apache.org/licenses/LICENSE-2.0
105986  *
105987  * Unless required by applicable law or agreed to in writing, software
105988  * distributed under the License is distributed on an "AS IS" BASIS,
105989  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
105990  * See the License for the specific language governing permissions and
105991  * limitations under the License.
105992  */
105993 var Coordinates = require('ripple/platform/w3c/1.0/Coordinates');
105994
105995 module.exports = function () {
105996     return {
105997         coords: new Coordinates(),
105998         timestamp: new Date().getTime()
105999     };
106000 };
106001
106002 });
106003 define('ripple/platform/w3c/1.0/PositionError', function (require, exports, module) {
106004 /*
106005  *  Copyright 2011 Research In Motion Limited.
106006  *
106007  * Licensed under the Apache License, Version 2.0 (the "License");
106008  * you may not use this file except in compliance with the License.
106009  * You may obtain a copy of the License at
106010  *
106011  * http://www.apache.org/licenses/LICENSE-2.0
106012  *
106013  * Unless required by applicable law or agreed to in writing, software
106014  * distributed under the License is distributed on an "AS IS" BASIS,
106015  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
106016  * See the License for the specific language governing permissions and
106017  * limitations under the License.
106018  */
106019 var _self = function () {
106020     return {
106021         code: undefined,
106022         message: undefined
106023     };
106024 };
106025
106026 _self.PERMISSION_DENIED = "PERMISSION_DENIED";
106027 _self.POSITION_UNAVAILABLE = "POSITION_UNAVAILABLE";
106028 _self.TIMEOUT = "TIMEOUT";
106029
106030 module.exports = _self;
106031
106032 });
106033 define('ripple/platform/w3c/1.0/Rotation', function (require, exports, module) {
106034 module.exports = function (alpha, beta, gamma) {
106035     return {
106036         alpha: alpha || 0,    //Rotation about the 'z' axis expressed in degrees [0, 360].    (Number)
106037         beta: beta || 0,      //Rotation about the 'x' axis expressed in degrees [-180, 180]. (Number)
106038         gamma: gamma || 0     //Rotation about the 'y' axis expressed in degrees [-90, 90].   (Number)
106039     };
106040 };
106041
106042 });
106043 define('ripple/platform/w3c/1.0/SensorConnection', function (require, exports, module) {
106044 /*
106045  *  Copyright 2012 Intel Corporation.
106046  *
106047  * Licensed under the Apache License, Version 2.0 (the "License");
106048  * you may not use this file except in compliance with the License.
106049  * You may obtain a copy of the License at
106050  *
106051  * http://www.apache.org/licenses/LICENSE-2.0
106052  *
106053  * Unless required by applicable law or agreed to in writing, software
106054  * distributed under the License is distributed on an "AS IS" BASIS,
106055  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
106056  * See the License for the specific language governing permissions and
106057  * limitations under the License.
106058  */
106059
106060 var utils = require('ripple/utils'),
106061     platform = require('ripple/platform'),
106062     event = require('ripple/event'),
106063     sensorSettings = require('ripple/sensorSettings'),
106064     accelerometer = require('ripple/accelerometer'),
106065     exception = require('ripple/exception'),
106066
106067     _permission = true,
106068     _self;
106069
106070 function ErrorMsg() {
106071     this.__defineGetter__("UNKNOWN_ERROR", function () {
106072         return "An unknown error has occurred.";
106073     });
106074
106075     this.__defineGetter__("TYPE_MISMATCH_ERROR", function () {
106076         return "The object type is incompatible with the expected type.";
106077     });
106078
106079     this.__defineGetter__("INVALID_VALUES_ERROR", function () {
106080         return "The content of an object does not contain valid values.";
106081     });
106082
106083     this.__defineGetter__("ILLEGAL_STATE", function () {
106084         return "The status of connection is illegal.";
106085     });
106086 }
106087
106088 // TODO: Should be replaced by a global object in tizen 1.0
106089 function ErrorCode() {
106090     this.__defineGetter__("UNKNOWN_ERR", function () {
106091         return 0;
106092     });
106093
106094     this.__defineGetter__("INVALID_VALUES_ERROR", function () {
106095         return 1;
106096     });
106097
106098     this.__defineGetter__("TYPE_MISMATCH_ERROR", function () {
106099         return 2;
106100     });
106101
106102     this.__defineGetter__("ILLEGAL_STATE", function () {
106103         return 3;
106104     });
106105 }
106106
106107 function SensorError(code, msg) {
106108     this.__defineGetter__("message", function () {
106109         return msg;
106110     });
106111     this.__defineGetter__("code", function () {
106112         return code;
106113     });
106114
106115     this.PERMISSION_DENIED = -100;
106116 }
106117
106118 function Event() {
106119     var _self = {
106120         CAPTURING_PHASE: 1,
106121         AT_TARGET:  2,
106122         BUBBLING_PHASE: 3,
106123
106124         type: '',
106125         target: null, //new EventTarget(),
106126         currentTarget: null, //new EventTarget(),
106127         eventPhase: 0,
106128         bubbles: false,
106129         cancelable: false,
106130         timeStamp: 0
106131     };
106132         
106133     this.__defineGetter__("type", function () {
106134         return _self.type;
106135     });
106136
106137     this.__defineGetter__("target", function () {
106138         return _self.target;
106139     });
106140
106141     this.__defineGetter__("currentTarget", function () {
106142         return _self.currentTarget;
106143     });
106144
106145     this.__defineGetter__("eventPhase", function () {
106146         return _self.eventPhase;
106147     });    
106148
106149     this.__defineGetter__("bubbles", function () {
106150         return _self.bubbles;
106151     });
106152
106153     this.__defineGetter__("cancelable", function () {
106154         return _self.cancelable;
106155     });
106156     
106157     this.__defineGetter__("timeStamp", function () {
106158         return _self.timeStamp;
106159     });
106160
106161     this.stopPropagation = function () {};
106162
106163     this.preventDefault = function () {};
106164
106165     this.initEvent = function (eventTypeArg, canBubbleArg, cancelableArg) {
106166         _self.type = eventTypeArg;
106167         _self.bubbles = canBubbleArg;
106168         _self.cancelable = cancelableArg;
106169     };
106170
106171     return _self;
106172 }
106173
106174 function SensorDataEvent() {
106175     var _self = {
106176         data: 0,
106177         accuracy: 0,
106178         timestamp: 0,
106179         reason: ''
106180     };
106181
106182     // This type of event inherit from Event
106183     Event.call(this);
106184
106185     this.__defineGetter__("data", function () {
106186         return _self.data;
106187     });
106188
106189     this.__defineGetter__("accuracy", function () {
106190         return _self.accuracy;
106191     });
106192
106193     this.__defineGetter__("timestamp", function () {
106194         return _self.timestamp;
106195     });
106196
106197     this.__defineGetter__("reason", function () {
106198         return _self.reason;
106199     });
106200
106201     this.initSensorDataEvent = function (type, bubbles, cancelable, reason, timestamp, accuracy, data) {
106202         this.initEvent(type, bubbles, cancelable);
106203
106204         _self.reason = reason;
106205         _self.timestamp = timestamp;
106206         _self.accuracy = accuracy;
106207         
106208         // If the data has only one part, just return the value, not the data object    
106209         if (utils.count(data) === 1) {
106210             utils.forEach(data, function (section, key) {
106211                 _self.data = data[key];
106212             });
106213         }
106214         else {
106215             _self.data = utils.copy(data);
106216         }
106217     };
106218 }
106219
106220 // As only one sensor will be used during the simulation with a SensorConnection object,
106221 // we can get that sensor object first and then the following read or write operations will be simplified
106222 function _getSensorObj(type, name) {
106223     var settings = platform.current().sensor, _sensor;
106224
106225     utils.forEach(settings, function (settingSection, settingType) {
106226         if (settingSection.type === type) {
106227
106228             if (settingSection.name && settingSection.name !== name) {
106229                 return;
106230             }
106231
106232             _sensor = utils.copy(settingSection);
106233         }
106234     });
106235
106236     return _sensor;
106237 }
106238
106239 function _getAccelerometerData(dataType) {
106240     var accelerometerData, data = {};
106241
106242     switch (dataType) {
106243     case "Accelerometer":
106244         accelerometerData = accelerometer.getInfo();
106245         data = {
106246             x: accelerometerData.acceleration.x,
106247             y: accelerometerData.acceleration.y,
106248             z: accelerometerData.acceleration.z
106249         };
106250         break;
106251     case "Rotation":
106252         accelerometerData = accelerometer.getInfo();
106253         data = {
106254             x: accelerometerData.orientation.alpha,
106255             y: accelerometerData.orientation.beta,
106256             z: accelerometerData.orientation.gamma
106257         };
106258         break;
106259     case "Orientation":
106260         accelerometerData = accelerometer.getInfo();
106261         data = {
106262             alpha: accelerometerData.orientation.alpha,
106263             beta: accelerometerData.orientation.beta,
106264             gamma: accelerometerData.orientation.gamma
106265         };
106266         break;
106267     default:
106268         break;
106269     }
106270
106271     return data;
106272 }
106273
106274 // The parameter of event callback is an object that contains the latest value, not the value itself,
106275 // so we need a function to create such object.
106276 function _getSensorData(sensorType, sensor, onerror) {
106277     var data = {}, value;
106278
106279     if (sensorType === "Accelerometer" || sensorType === "Rotation" || sensorType === "Orientation") {
106280         return _getAccelerometerData(sensorType);
106281     }
106282
106283     utils.forEach(sensor, function (sensorSection, key) {
106284         try {
106285             value = sensorSettings.retrieve(sensorType + "." + key);
106286         }
106287         catch (e) {
106288             if (onerror) {
106289                 onerror(e);
106290             }
106291         }
106292         
106293         if (value) {
106294             data[key] = value;
106295         }                    
106296     });
106297     
106298     return data;
106299 }
106300
106301 // As the event type in sensor.js file are named in this way, so we can get it with this function.
106302 function _getSensorEventTypes(type, sensor) {
106303     var types = [];
106304
106305     if (type === "Accelerometer" || type === "Rotation" || type === "Orientation") {
106306         return ["AccelerometerInfoChangedEvent"];
106307     }
106308
106309     utils.forEach(sensor, function (sensorSection, sensorType) {
106310         if (typeof sensorSection === "object") {
106311             types.push(type + "-" + sensorType + "Changed");
106312         }
106313     });
106314
106315     return types;
106316 }
106317
106318 function _onEventCallback(type, options, currentSensor, length, eventCallback, onerror) {
106319     return function (values) {
106320         var sensorEvent = new SensorDataEvent();
106321
106322         // Only the sensor that has one attribute could be compared with the threshold
106323         if (options && options.threshold && length === 1 && values[0] < options.threshold) {
106324             return;
106325         }
106326
106327         if (eventCallback) {
106328             sensorEvent.initSensorDataEvent(type, false, false, "read", (new Date()).getTime(), 
106329                                             currentSensor.resolution, _getSensorData(type, currentSensor, onerror));
106330
106331             eventCallback(sensorEvent);
106332         }
106333     };
106334 }
106335
106336 function _bind(name, obj) {
106337     var callback = null;
106338
106339     obj.__defineGetter__(name, function () {
106340         return callback;
106341     });
106342
106343     obj.__defineSetter__(name, function (cb) {
106344         callback = cb;
106345     });
106346
106347     return {
106348         get: function () {
106349             return callback;
106350         },
106351         set: function (value) {
106352             callback = value;
106353         },
106354         exec: function (arg) {
106355             return callback && callback(arg);
106356         },
106357         unbind: function (cb) {
106358             callback = cb === callback ? null : callback;
106359         }
106360     };
106361 }
106362
106363 function SensorConnection(type, name) {
106364     var _self,
106365         currentSensor = _getSensorObj(type, name),
106366         sensorEvent = new SensorDataEvent(),
106367         sensorEventTypes = _getSensorEventTypes(type, currentSensor),
106368         watches = [],
106369         _errorCode = new ErrorCode(),
106370         _errorMsg = new ErrorMsg(),
106371         sensorListener;
106372
106373     if (currentSensor) {
106374         _self = {
106375             sensor: {
106376                 resolution: currentSensor.resolution,
106377                 minDelay: currentSensor.minDelay,
106378                 range: currentSensor.range,
106379                 name: currentSensor.name,
106380                 type: currentSensor.type
106381             },
106382             status: "open",
106383             error: null,
106384             read: function () {
106385
106386                 if (_self.status !== "open" && _self.status !== "watching") {
106387                     exception.raise(exception.types.Argument, "illegal state", new SensorError(_errorCode.ILLEGAL_STATE, _errorMsg.ILLEGAL_STATE));
106388                     return;
106389                 }                
106390
106391                 setTimeout(function () {
106392                     if (sensorListener.get()) {
106393                         sensorEvent.initSensorDataEvent(type, false, false, "read", (new Date()).getTime(), 
106394                                                         currentSensor.resolution, _getSensorData(type, currentSensor, _self.onerror));
106395
106396                         sensorListener.exec(sensorEvent);
106397                     }
106398                 }, 1);  
106399
106400                 return;
106401             },
106402
106403             startWatch: function (options) {
106404                 var index, watchId, watchObj = {};
106405
106406                 if (_self.status !== "open") {
106407                     exception.raise(exception.types.Argument, "illegal state", new SensorError(_errorCode.ILLEGAL_STATE, _errorMsg.ILLEGAL_STATE));
106408                     return;
106409                 }
106410                     
106411                 if (typeof options !== "object") {
106412                     if (_self.onerror) {
106413                         _self.onerror(new SensorError(_errorCode.TYPE_MISMATCH_ERROR, _errorMsg.TYPE_MISMATCH_ERROR));
106414                     }
106415                 }
106416
106417                 setTimeout(function () {
106418                     watchId = (new Date()).getTime();   
106419
106420                     // As there will be many attributes for some sensor, each of them is needed to be watched.
106421                     for (index = 0; index < sensorEventTypes.length; index++) {
106422                         watchObj = {
106423                             eventType: sensorEventTypes[index],
106424                             onEvent: _onEventCallback(type, options, currentSensor, sensorEventTypes.length, sensorListener.get(), _self.onerror),
106425                         };
106426
106427                         watches.push(watchObj);
106428                         if (watchObj.eventType) {
106429                             event.on(watchObj.eventType, watchObj.onEvent);                                               
106430                         }
106431                     }
106432
106433                     
106434                     if (options && options.interval) {
106435                         watchObj.intervalId = setInterval(_onEventCallback(type, options, currentSensor, sensorEventTypes.length, sensorListener.get(), _self.onerror), 
106436                                                           options.interval);
106437                     }
106438
106439                     _self.status = "watching";
106440                     if (_self.onstatuschange) {
106441                         _self.onstatuschange();
106442                     }
106443                                                                                                         
106444                 }, 1);  
106445
106446                 return;
106447             },
106448
106449             endWatch: function () {
106450                 var index, watchObj;
106451
106452                 if (_self.status !== "watching") {
106453                     exception.raise(exception.types.Argument, "illegal state", new SensorError(_errorCode.ILLEGAL_STATE, _errorMsg.ILLEGAL_STATE));
106454                     return;
106455                 }
106456
106457                 for (index = 0; index < watches.length; index++) {
106458                     watchObj = watches[index];
106459
106460                     try {
106461                         event.deleteEventHandler(watchObj.eventType, watchObj.onEvent);  
106462                     }
106463                     catch (e) {
106464                         if (_self.onerror) {
106465                             _self.onerror(e);
106466                         }
106467                     }
106468
106469                     if (watchObj.intervalId) {
106470                         clearInterval(watchObj.intervalId);
106471                     }                
106472                 }
106473
106474                 watches = [];
106475
106476                 _self.status = "open";
106477                 if (_self.onstatuschange) {
106478                     _self.onstatuschange();
106479                 }
106480             },
106481
106482             // These functions are inherited from the EventTarget object
106483             addEventListener: function (eventType, callback, useCapture) {
106484                 var sensorEvent;
106485                 
106486                 if (eventType === "sensordata") {
106487                     sensorListener.set(callback);  
106488
106489                     event.on("sensordata", function (data) {
106490                         sensorEvent = new SensorDataEvent();        
106491                         sensorEvent.initSensorDataEvent("sensordata", false, false, "read", (new Date()).getTime(), 
106492                                                         currentSensor.resolution, _getSensorData(type, currentSensor, _self.onerror));           
106493
106494                         sensorListener.exec(sensorEvent);
106495                     });             
106496                 }               
106497             },
106498
106499             removeEventListener: function (eventType, callback) {
106500                 event.clear(eventType, callback);
106501                 sensorListener.unbind(callback);                                
106502             },
106503
106504             dispatchEvent: function (evt) {
106505                 event.trigger("sensordata", evt);
106506             }
106507         };
106508
106509         sensorListener = _bind("onsensordata", _self);
106510     }    
106511
106512     return _self;
106513 }
106514
106515 module.exports = function (option) {
106516  
106517     var connectionObj,
106518         _errorCode = new ErrorCode(),
106519         _errorMsg = new ErrorMsg();
106520
106521     if (option === null || option === undefined) {
106522         return null;
106523     }
106524
106525     // There are two ways to construct an object
106526     if (typeof option === "object") {
106527         if ((option.type === null || option.type === undefined) &&
106528             (option.name === null || option.name === undefined)) {
106529             // Spec: If none of the dictionary members are defined then raise an instantiation exception    
106530             exception.raise(exception.types.Argument, "type illegal", new SensorError(_errorCode.ILLEGAL_TYPE, _errorMsg.ILLEGAL_TYPE));             
106531         }
106532
106533         connectionObj = new SensorConnection(option.type, option.name);
106534     }
106535     else if (typeof option === "string") {
106536         connectionObj = new SensorConnection(option, option);
106537     }
106538
106539     return connectionObj;
106540 };
106541
106542 });
106543 define('ripple/platform/w3c/1.0/geolocation', function (require, exports, module) {
106544 /*
106545  *  Copyright 2011 Research In Motion Limited.
106546  *
106547  * Licensed under the Apache License, Version 2.0 (the "License");
106548  * you may not use this file except in compliance with the License.
106549  * You may obtain a copy of the License at
106550  *
106551  * http://www.apache.org/licenses/LICENSE-2.0
106552  *
106553  * Unless required by applicable law or agreed to in writing, software
106554  * distributed under the License is distributed on an "AS IS" BASIS,
106555  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
106556  * See the License for the specific language governing permissions and
106557  * limitations under the License.
106558  */
106559 var geo = require('ripple/geo'),
106560     Position = require('ripple/platform/w3c/1.0/Position'),
106561     PositionError = require('ripple/platform/w3c/1.0/PositionError'),
106562     _watches = {},
106563     _self;
106564
106565 function createPosition() {
106566     var position = new Position(),
106567         positionInfo = geo.getPositionInfo();
106568
106569     position.coords.latitude = positionInfo.latitude;
106570     position.coords.longitude = positionInfo.longitude;
106571     position.coords.altitude = positionInfo.altitude;
106572     position.coords.altitudeAccuracy = positionInfo.altitudeAccuracy;
106573     position.coords.accuracy = positionInfo.accuracy;
106574     position.coords.heading = positionInfo.heading;
106575     position.coords.speed = positionInfo.speed;
106576     position.timestamp = positionInfo.timeStamp.getTime();
106577
106578     return position;
106579 }
106580
106581 _self = {
106582     getCurrentPosition: function (onSuccess, onError) {
106583         var delay = ((geo.delay || 0) * 1000) || 1,
106584             timeout = geo.timeout;
106585
106586         window.setTimeout(function () {
106587             if (timeout) {
106588                 var error = new PositionError();
106589                 error.code = PositionError.TIMEOUT;
106590                 error.message = "postion timed out";
106591
106592                 onError(error);
106593             }
106594             else {
106595                 // TODO: build facility to trigger onError() from emulator
106596                 // see pivotal item: https://www.pivotaltracker.com/story/show/7040343
106597                 _self.lastPosition = createPosition();
106598                 onSuccess(_self.lastPosition);
106599             }
106600         }, delay);
106601     },
106602
106603     watchPosition: function (geolocationSuccess, geolocationError, geolocationOptions) {
106604         var watchId = (new Date()).getTime().toString(),
106605             watchObj = {},
106606             timeout;
106607
106608         if (geolocationOptions) {
106609             timeout = geolocationOptions.timeout || 10000;
106610
106611             watchObj = {
106612                 onSuccess: geolocationSuccess,
106613                 onError: geolocationError,
106614                 interval: timeout
106615             };
106616
106617             _watches[watchId] = watchObj;
106618
106619             _watches[watchId].intervalId = window.setInterval(function () {
106620                 _self.getCurrentPosition(_watches[watchId].onSuccess, _watches[watchId].onError);
106621             }, timeout);
106622
106623         }
106624         else {
106625             if (typeof geolocationError === "function") {
106626                 window.setTimeout(function () {
106627                     geolocationError();
106628                 }, 1);
106629             }
106630         }
106631
106632         return watchId;
106633     },
106634
106635     lastPosition: null,
106636
106637     clearWatch: function (watchId) {
106638         window.clearInterval(_watches[watchId].intervalId);
106639         delete _watches[watchId];
106640     }
106641 };
106642
106643 module.exports = _self;
106644
106645 });
106646 define('ripple/platform/w3c/1.0/navigator', function (require, exports, module) {
106647 /*
106648  *  Copyright 2011 Research In Motion Limited.
106649  *
106650  * Licensed under the Apache License, Version 2.0 (the "License");
106651  * you may not use this file except in compliance with the License.
106652  * You may obtain a copy of the License at
106653  *
106654  * http://www.apache.org/licenses/LICENSE-2.0
106655  *
106656  * Unless required by applicable law or agreed to in writing, software
106657  * distributed under the License is distributed on an "AS IS" BASIS,
106658  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
106659  * See the License for the specific language governing permissions and
106660  * limitations under the License.
106661  */
106662 var _original = window.navigator,
106663     utils = require('ripple/utils'),
106664     devices = require('ripple/devices'),
106665     constants = require('ripple/constants'),
106666     _self = {};
106667
106668 (function () {
106669     var key,
106670         nav = window.navigator;
106671
106672     function _handle(obj, key) {
106673         return typeof obj[key] !== "function" ? obj[key] : function () {
106674             return obj[key].apply(obj, Array.prototype.slice.call(arguments));
106675         };
106676     }
106677
106678     for (key in nav) {
106679         _self[key] = _handle(nav, key);
106680     }
106681 }());
106682
106683 _self.__defineGetter__('userAgent', function () {
106684     var currentUserAgent = devices.getCurrentDevice().userAgent;
106685
106686     return currentUserAgent === constants.COMMON.USER_AGENT_DEFAULT ?
106687         _original.userAgent : currentUserAgent;
106688 });
106689
106690 module.exports = _self;
106691
106692 });
106693 define('ripple/platform/wac/1.0/AccelerometerInfo', function (require, exports, module) {
106694 /*
106695  *  Copyright 2011 Research In Motion Limited.
106696  *
106697  * Licensed under the Apache License, Version 2.0 (the "License");
106698  * you may not use this file except in compliance with the License.
106699  * You may obtain a copy of the License at
106700  *
106701  * http://www.apache.org/licenses/LICENSE-2.0
106702  *
106703  * Unless required by applicable law or agreed to in writing, software
106704  * distributed under the License is distributed on an "AS IS" BASIS,
106705  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
106706  * See the License for the specific language governing permissions and
106707  * limitations under the License.
106708  */
106709 var accelerometer = require('ripple/accelerometer'),
106710     _self = {};
106711
106712 _self.__defineGetter__("xAxis", function () {
106713     return accelerometer.getInfo().accelerationIncludingGravity.x;
106714 });
106715
106716 _self.__defineGetter__("yAxis", function () {
106717     return accelerometer.getInfo(true).accelerationIncludingGravity.y;
106718 });
106719
106720 _self.__defineGetter__("zAxis", function () {
106721     return accelerometer.getInfo(true).accelerationIncludingGravity.z;
106722 });
106723
106724 module.exports = _self;
106725
106726 });
106727 define('ripple/platform/wac/1.0/Account', function (require, exports, module) {
106728 /*
106729  *  Copyright 2011 Research In Motion Limited.
106730  *
106731  * Licensed under the Apache License, Version 2.0 (the "License");
106732  * you may not use this file except in compliance with the License.
106733  * You may obtain a copy of the License at
106734  *
106735  * http://www.apache.org/licenses/LICENSE-2.0
106736  *
106737  * Unless required by applicable law or agreed to in writing, software
106738  * distributed under the License is distributed on an "AS IS" BASIS,
106739  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
106740  * See the License for the specific language governing permissions and
106741  * limitations under the License.
106742  */
106743 var deviceSettings = require('ripple/deviceSettings'),
106744     _self;
106745
106746 _self = {
106747     accountName: undefined,
106748     accountId: undefined
106749 };
106750
106751 _self.__defineGetter__("accountName", function () {
106752     return deviceSettings.retrieve("Account.accountName");
106753 });
106754
106755 _self.__defineGetter__("accountId", function () {
106756     return deviceSettings.retrieve("Account.accountId");
106757 });
106758
106759 module.exports = _self;
106760
106761 });
106762 define('ripple/platform/wac/1.0/AccountInfo', function (require, exports, module) {
106763 /*
106764  *  Copyright 2011 Research In Motion Limited.
106765  *
106766  * Licensed under the Apache License, Version 2.0 (the "License");
106767  * you may not use this file except in compliance with the License.
106768  * You may obtain a copy of the License at
106769  *
106770  * http://www.apache.org/licenses/LICENSE-2.0
106771  *
106772  * Unless required by applicable law or agreed to in writing, software
106773  * distributed under the License is distributed on an "AS IS" BASIS,
106774  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
106775  * See the License for the specific language governing permissions and
106776  * limitations under the License.
106777  */
106778 var deviceSettings = require('ripple/deviceSettings'),
106779     _self = {
106780         phoneUserUniqueId: undefined,
106781         phoneMSISDN: undefined,
106782         phoneOperatorName: undefined,
106783         userAccountBalance: undefined,
106784         userSubscriptionType: undefined
106785     };
106786
106787 _self.__defineGetter__("phoneUserUniqueId", function () {
106788     return deviceSettings.retrieve("AccountInfo.phoneUserUniqueId");
106789 });
106790
106791 _self.__defineGetter__("phoneMSISDN", function () {
106792     return deviceSettings.retrieve("AccountInfo.phoneMSISDN");
106793 });
106794
106795 _self.__defineGetter__("phoneOperatorName", function () {
106796     return deviceSettings.retrieve("AccountInfo.phoneOperatorName");
106797 });
106798
106799 _self.__defineGetter__("userAccountBalance", function () {
106800     return deviceSettings.retrieve("AccountInfo.userAccountBalance");
106801 });
106802
106803 _self.__defineGetter__("userSubscriptionType", function () {
106804     return deviceSettings.retrieve("AccountInfo.userSubscriptionType");
106805 });
106806
106807 module.exports = _self;
106808
106809 });
106810 define('ripple/platform/wac/1.0/AddressBookItem', function (require, exports, module) {
106811 /*
106812  *  Copyright 2011 Research In Motion Limited.
106813  *
106814  * Licensed under the Apache License, Version 2.0 (the "License");
106815  * you may not use this file except in compliance with the License.
106816  * You may obtain a copy of the License at
106817  *
106818  * http://www.apache.org/licenses/LICENSE-2.0
106819  *
106820  * Unless required by applicable law or agreed to in writing, software
106821  * distributed under the License is distributed on an "AS IS" BASIS,
106822  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
106823  * See the License for the specific language governing permissions and
106824  * limitations under the License.
106825  */
106826 var utils = require('ripple/utils'),
106827     exception = require('ripple/exception'),
106828     db = require('ripple/db'),
106829     constants = require('ripple/constants'),
106830     Exception = require('ripple/platform/wac/1.0/Exception'),
106831     ExceptionTypes = require('ripple/platform/wac/1.0/ExceptionTypes');
106832
106833 function _validateArgs(min, max, len) {
106834     utils.validateNumberOfArguments(min, max, len,
106835         ExceptionTypes.INVALID_PARAMETER, "invalid number of parameters", new Exception());
106836 }
106837
106838 function _validateType(arg, argType) {
106839     utils.validateArgumentType(arg, argType,
106840         ExceptionTypes.INVALID_PARAMETER,  "argument of wrong type provided",
106841         new Exception());
106842 }
106843
106844 module.exports = function () {
106845     function _throwUnsupportedException(method) {
106846         exception.raise(ExceptionTypes.UNSUPPORTED, "Method not supported." + (method || ""), new Exception());
106847     }
106848
106849     this.addressBookItemId = undefined;
106850     this.fullName = undefined;
106851     this.mobilePhone = undefined;
106852     this.homePhone = undefined;
106853     this.workPhone = undefined;
106854     this.eMail = undefined;
106855     this.company = undefined;
106856     this.title = undefined;
106857     this.address = undefined;
106858
106859     this.setAttributeValue = function (attribute, value) {
106860         _validateArgs(2, 2, arguments.length);
106861         _validateType(attribute, "string");
106862         this[attribute] = value;
106863     };
106864     this.setAddressGroupNames = function (groups) {
106865         _throwUnsupportedException("PIM.AddressBookItem.setAddressGroupNames");
106866     };
106867     this.getAttributeValue = function (attribute) {
106868         _validateArgs(1, 1, arguments.length);
106869         _validateType(attribute, "string");
106870         return this[attribute];
106871     };
106872     this.getAddressGroupNames = function () {
106873         _throwUnsupportedException("PIM.AddressBookItem.getAddressGroupNames");
106874     };
106875     this.getAvailableAttributes = function () {
106876         return utils.reduce(this, function (attributes, value, key) {
106877             if (typeof(value) !== 'function') {
106878                 attributes.push(key);
106879             }
106880             return attributes;
106881         }, []).sort();
106882     };
106883     this.update = function () {
106884         var items = db.retrieveObject(constants.PIM.ADDRESS_LIST_KEY),
106885             that = this,
106886             itemIndex = items.reduce(function (current, value, i) {
106887                 return value.addressBookItemId === that.addressBookItemId ?
106888                     i : current;
106889             }, -1);
106890
106891         if (itemIndex >= 0) {
106892             items[itemIndex] = this;
106893             db.saveObject(constants.PIM.ADDRESS_LIST_KEY, items);
106894         }
106895         else {
106896             exception.raise(ExceptionTypes.INVALID_PARAMETER, "Address Book Item not found: " + (this.addressBookItemId || ""), new Exception());
106897         }
106898
106899     };
106900 };
106901
106902 });
106903 define('ripple/platform/wac/1.0/ApplicationTypes', function (require, exports, module) {
106904 /*
106905  *  Copyright 2011 Research In Motion Limited.
106906  *
106907  * Licensed under the Apache License, Version 2.0 (the "License");
106908  * you may not use this file except in compliance with the License.
106909  * You may obtain a copy of the License at
106910  *
106911  * http://www.apache.org/licenses/LICENSE-2.0
106912  *
106913  * Unless required by applicable law or agreed to in writing, software
106914  * distributed under the License is distributed on an "AS IS" BASIS,
106915  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
106916  * See the License for the specific language governing permissions and
106917  * limitations under the License.
106918  */
106919 var utils = require('ripple/utils'),
106920     constants = require('ripple/constants'),
106921     _self = {};
106922
106923 utils.forEach(constants.PLATFORMS.WAC.APPLICATIONS, function (application) {
106924     _self.__defineGetter__(application, function () {
106925         return application;
106926     });
106927 });
106928
106929 module.exports = _self;
106930
106931 });
106932 define('ripple/platform/wac/1.0/Attachment', function (require, exports, module) {
106933 /*
106934  *  Copyright 2011 Research In Motion Limited.
106935  *
106936  * Licensed under the Apache License, Version 2.0 (the "License");
106937  * you may not use this file except in compliance with the License.
106938  * You may obtain a copy of the License at
106939  *
106940  * http://www.apache.org/licenses/LICENSE-2.0
106941  *
106942  * Unless required by applicable law or agreed to in writing, software
106943  * distributed under the License is distributed on an "AS IS" BASIS,
106944  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
106945  * See the License for the specific language governing permissions and
106946  * limitations under the License.
106947  */
106948 module.exports = function () {
106949     this.fileName = "";
106950     this.MIMEType = "";
106951     this.size = 0;
106952 };
106953
106954 });
106955 define('ripple/platform/wac/1.0/AudioPlayer', function (require, exports, module) {
106956 /*
106957  *  Copyright 2011 Research In Motion Limited.
106958  *
106959  * Licensed under the Apache License, Version 2.0 (the "License");
106960  * you may not use this file except in compliance with the License.
106961  * You may obtain a copy of the License at
106962  *
106963  * http://www.apache.org/licenses/LICENSE-2.0
106964  *
106965  * Unless required by applicable law or agreed to in writing, software
106966  * distributed under the License is distributed on an "AS IS" BASIS,
106967  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
106968  * See the License for the specific language governing permissions and
106969  * limitations under the License.
106970  */
106971 var constants = require('ripple/constants'),
106972     event = require('ripple/event'),
106973     exception = require('ripple/exception'),
106974     utils = require('ripple/utils'),
106975     fileSystem = require('ripple/fileSystem'),
106976     _console = require('ripple/console'),
106977     Exception = require('ripple/platform/wac/1.0/Exception'),
106978     ExceptionTypes = require('ripple/platform/wac/1.0/ExceptionTypes'),
106979     _self,
106980     _state = null,
106981     _STATES = constants.MULTIMEDIA.AUDIO_STATES,
106982     _currentAudioFile,
106983     _audio, _loopCount;
106984
106985 event.on("MultimediaAudioStateChanged", function updateAudioState(state) {
106986     _state = state;
106987     if (typeof _self.onStateChange === 'function') {
106988         _self.onStateChange.apply(_self, arguments);
106989     }
106990 });
106991
106992 _audio = utils.createElement("audio", {
106993     "id": "multimedia-audio"
106994 });
106995
106996 _audio.addEventListener('error', function () {
106997     _console.warn("AudioPlayer encountered an error: " + _audio.error.code);
106998     if (_audio.error.code === 4) {
106999         _console.warn("AudioPlayer error 4 could be caused by missing codecs");
107000     }
107001     _state = null;
107002     event.trigger("MultimediaAudioStateChanged", [null], true);
107003 });
107004
107005 _audio.addEventListener('ended', function handleAudioEnded() {
107006     event.trigger("MultimediaAudioStateChanged", [_STATES.COMPLETED], true);
107007     if (_loopCount > 1) {
107008         _self.open(_currentAudioFile);
107009         _self.play(_loopCount--);
107010     }
107011 });
107012
107013 document.getElementById("ui").appendChild(_audio);
107014
107015 function _validateAndSet(state, validStates, callbackBeforeSuccess) {
107016     var i, valid = false;
107017
107018     for (i = 0; i < validStates.length; i++) {
107019         if (validStates[i] === _state) {
107020             valid = true;
107021         }
107022     }
107023
107024     if (!valid) {
107025         _console.warn("Attempted to initiate AudioPlayer." + state +
107026             " in invalid state. current state: " + _state);
107027     } else {
107028         if (typeof(callbackBeforeSuccess) === "function") {
107029             callbackBeforeSuccess.apply();
107030         }
107031         event.trigger("MultimediaAudioStateChanged", [state], true);
107032     }
107033
107034     return valid;
107035 }
107036
107037 function _validateAudioType(fileUrl) {
107038     var matched = fileUrl.match(/\.(\w*)$/),
107039         type = matched ? matched[1] : "";
107040
107041     if (_audio && _audio.canPlayType("audio/" + type) === "") {
107042         _console.warn("Attempting to load an audio that might not work in the current browser [" + fileUrl + "]");
107043     }
107044 }
107045
107046 _self = {
107047     onStateChange: undefined,
107048
107049     open: function (fileUrl) {
107050         utils.validateNumberOfArguments(1, 1, arguments.length, ExceptionTypes.INVALID_PARAMETER, "Multimedia.js.AudioPlayer.open wrong number of arguments", new Exception());
107051         utils.validateArgumentType(fileUrl, "string", ExceptionTypes.INVALID_PARAMETER, "Multimedia.js.AudioPlayer.open invalid parameter! expected string, fileUrl: " +
107052             fileUrl, new Exception());
107053
107054         if (fileUrl.match(/^rtsp:\/\//)) {
107055             exception.raise(exception.types.MethodNotImplemented, "rtsp:// scheme not yet supported. sorry :(");
107056         }
107057
107058         _validateAndSet(_STATES.OPENED, [_STATES.OPENED, _STATES.STOPPED, _STATES.COMPLETED, null], function () {
107059             _validateAudioType(fileUrl);
107060             _currentAudioFile = fileSystem.getURI(fileUrl);
107061             _audio.setAttribute("src", _currentAudioFile);
107062             _audio.load();
107063         });
107064     },
107065
107066     play: function (repeatTimes) {
107067         utils.validateNumberOfArguments(1, 1, arguments.length, ExceptionTypes.INVALID_PARAMETER, "Multimedia.js.AudioPlayer.play wrong number of arguments", new Exception());
107068         utils.validateArgumentType(repeatTimes, "integer", ExceptionTypes.INVALID_PARAMETER, "Multimedia.js.AudioPlayer.play invalid parameter! expected integer, repeatTimes: " + repeatTimes, new Exception());
107069
107070         if (repeatTimes < 0) {
107071             exception.raise(ExceptionTypes.INVALID_PARAMETER, "value of repeatTimes must be greater than 0", new Exception());
107072         }
107073
107074         if (repeatTimes !== 0) {
107075             _validateAndSet(_STATES.PLAYING, [_STATES.OPENED, _STATES.STOPPED, _STATES.COMPLETED], function () {
107076                 _loopCount = repeatTimes;
107077                 _audio.play();
107078             });
107079         }
107080     },
107081
107082     pause: function () {
107083         _validateAndSet(_STATES.PAUSED, [_STATES.PLAYING], function () {
107084             _audio.pause();
107085         });
107086     },
107087
107088     resume: function () {
107089         _validateAndSet(_STATES.PLAYING, [_STATES.PAUSED], function () {
107090             _audio.play();
107091         });
107092     },
107093
107094     stop: function () {
107095         _validateAndSet(_STATES.STOPPED, [_STATES.PAUSED, _STATES.PLAYING], function () {
107096             try {
107097                 _audio.pause();
107098                 _audio.currentTime = 0;
107099             } catch (e) {
107100                 //HACK: do nothing, this could throw a dom exception 11 sometimes when playing an mp3 or before the file has loaded.
107101                 //see http://developer.palm.com/distribution/viewtopic.php?f=11&t=7568
107102             }
107103         });
107104     }
107105 };
107106
107107 module.exports = _self;
107108
107109 });
107110 define('ripple/platform/wac/1.0/CalendarItem', function (require, exports, module) {
107111 /*
107112  *  Copyright 2011 Research In Motion Limited.
107113  *
107114  * Licensed under the Apache License, Version 2.0 (the "License");
107115  * you may not use this file except in compliance with the License.
107116  * You may obtain a copy of the License at
107117  *
107118  * http://www.apache.org/licenses/LICENSE-2.0
107119  *
107120  * Unless required by applicable law or agreed to in writing, software
107121  * distributed under the License is distributed on an "AS IS" BASIS,
107122  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
107123  * See the License for the specific language governing permissions and
107124  * limitations under the License.
107125  */
107126 var constants = require('ripple/constants'),
107127     db = require('ripple/db'),
107128     exception = require('ripple/exception'),
107129     Exception = require('ripple/platform/wac/1.0/Exception'),
107130     ExceptionTypes = require('ripple/platform/wac/1.0/ExceptionTypes');
107131
107132 module.exports = function () {
107133     this.calendarItemId = undefined;
107134     this.alarmDate = undefined;
107135     this.eventStartTime = undefined;
107136     this.eventEndTime = undefined;
107137     this.eventName = undefined;
107138     this.eventNotes = undefined;
107139     this.alarmed = undefined;
107140
107141     this.update = function () {
107142         var events = db.retrieveObject(constants.PIM.CALENDAR_LIST_KEY) || [],
107143             that = this,
107144             eventIndex = events.reduce(function (match, value, i) {
107145                 return value.calendarItemId === that.calendarItemId ?
107146                     i : match;
107147             }, -1);
107148
107149
107150         if (eventIndex >= 0) {
107151             events[eventIndex] = this;
107152             db.saveObject(constants.PIM.CALENDAR_LIST_KEY, events);
107153         }
107154         else {
107155             exception.raise(ExceptionTypes.INVALID_PARAMETER, "Calendar Item not found: " + (this.calendarItemId || ""), new Exception());
107156         }
107157     };
107158 };
107159
107160 });
107161 define('ripple/platform/wac/1.0/CallRecord', function (require, exports, module) {
107162 /*
107163  *  Copyright 2011 Research In Motion Limited.
107164  *
107165  * Licensed under the Apache License, Version 2.0 (the "License");
107166  * you may not use this file except in compliance with the License.
107167  * You may obtain a copy of the License at
107168  *
107169  * http://www.apache.org/licenses/LICENSE-2.0
107170  *
107171  * Unless required by applicable law or agreed to in writing, software
107172  * distributed under the License is distributed on an "AS IS" BASIS,
107173  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
107174  * See the License for the specific language governing permissions and
107175  * limitations under the License.
107176  */
107177 module.exports = function () {
107178     this.callRecordType = undefined;
107179     this.callRecordId = undefined;
107180     this.callRecordAddress = undefined;
107181     this.callRecordName = undefined;
107182     this.durationSeconds = undefined;
107183     this.startTime = undefined;
107184 };
107185
107186 });
107187 define('ripple/platform/wac/1.0/CallRecordTypes', function (require, exports, module) {
107188 /*
107189  *  Copyright 2011 Research In Motion Limited.
107190  *
107191  * Licensed under the Apache License, Version 2.0 (the "License");
107192  * you may not use this file except in compliance with the License.
107193  * You may obtain a copy of the License at
107194  *
107195  * http://www.apache.org/licenses/LICENSE-2.0
107196  *
107197  * Unless required by applicable law or agreed to in writing, software
107198  * distributed under the License is distributed on an "AS IS" BASIS,
107199  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
107200  * See the License for the specific language governing permissions and
107201  * limitations under the License.
107202  */
107203 module.exports = {
107204     RECEIVED: "received",
107205     OUTGOING: "outgoing",
107206     MISSED: "missed"
107207 };
107208
107209 });
107210 define('ripple/platform/wac/1.0/Camera', function (require, exports, module) {
107211 /*
107212  *  Copyright 2011 Research In Motion Limited.
107213  *
107214  * Licensed under the Apache License, Version 2.0 (the "License");
107215  * you may not use this file except in compliance with the License.
107216  * You may obtain a copy of the License at
107217  *
107218  * http://www.apache.org/licenses/LICENSE-2.0
107219  *
107220  * Unless required by applicable law or agreed to in writing, software
107221  * distributed under the License is distributed on an "AS IS" BASIS,
107222  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
107223  * See the License for the specific language governing permissions and
107224  * limitations under the License.
107225  */
107226 var exception = require('ripple/exception'),
107227     Exception = require('ripple/platform/wac/1.0/Exception'),
107228     ExceptionTypes = require('ripple/platform/wac/1.0/ExceptionTypes'),
107229     constants = require('ripple/constants'),
107230     _console = require('ripple/console'),
107231     utils = require('ripple/utils'),
107232     notifications = require('ripple/notifications'),
107233     _currentlySet,
107234     _img,
107235     _buttons,
107236     _self,
107237     _videoCapture;
107238
107239
107240 function _populateWindow(domObject) {
107241     var record = document.createElement("button"),
107242         pause = document.createElement("button"),
107243         stop = document.createElement("button");
107244
107245     _img = document.createElement("img");
107246     _img.setAttribute("id", "jil-camera-window");
107247     //_img.setAttribute("src", document.querySelector("#extension-url").innerHTML + constants.CAMERA.WINDOW_ANIMATION);
107248     _img.setAttribute("src", document.documentURI.replace(/index\.html$/, "") + constants.CAMERA.WINDOW_ANIMATION);
107249     _img.setAttribute("width", "100%");
107250     _currentlySet = domObject;
107251     domObject.appendChild(_img);
107252
107253     _buttons = document.createElement("div");
107254     _buttons.setAttribute("id", "jil-camera-window-buttons");
107255     _buttons.setAttribute("style", "display: none");
107256
107257     record.setAttribute("id", "jil-camera-window-buttons-record");
107258     record.innerHTML = "Record";
107259     pause.setAttribute("id", "jil-camera-window-buttons-pause");
107260     pause.innerHTML = "Pause";
107261     stop.setAttribute("id", "jil-camera-window-buttons-stop");
107262     stop.innerHTML = "Stop";
107263     stop.addEventListener("click", _self.stopVideoCapture);
107264
107265     _buttons.appendChild(record);
107266     _buttons.appendChild(pause);
107267     _buttons.appendChild(stop);
107268
107269     domObject.appendChild(_buttons);
107270
107271 }
107272
107273 function _verifySetWindow(method) {
107274     if (!_img) {
107275         exception.raise(ExceptionTypes.UNKNOWN, "Camera." +
107276           method + " was (most likely) called before using the setWindow method.", new Exception());
107277     }
107278 }
107279
107280 _self = {
107281     onCameraCaptured: undefined, //function (fileName) { }
107282
107283     captureImage: function (fileName, lowRes) {
107284         utils.validateNumberOfArguments(2, 2, arguments.length, ExceptionTypes.INVALID_PARAMETER, "captureImage invalid number of parameters", new Exception());
107285         utils.validateMultipleArgumentTypes([fileName, lowRes], ['string', 'boolean'], ExceptionTypes.INVALID_PARAMETER, "invalid parameter type", new Exception());
107286
107287         _verifySetWindow("captureImage");
107288         var msg = constants.CAMERA.WARNING_TEXT;
107289         msg = msg.replace("{file}", fileName);
107290         notifications.openNotification("normal", msg);
107291         _console.log("simulated saved image as: " + fileName);
107292         if (_self.onCameraCaptured) {
107293             _self.onCameraCaptured.apply(_self, [fileName]);
107294         }
107295
107296         return fileName;
107297     },
107298     setWindow: function (domObject) {
107299
107300         if (_currentlySet) {
107301             _currentlySet.removeChild(_img);
107302             _currentlySet.removeChild(_buttons);
107303             _currentlySet = null;
107304             _img = null;
107305             _buttons = null;
107306         }
107307         if (domObject !== null) {
107308             _populateWindow(domObject);
107309         }
107310     },
107311     startVideoCapture: function (fileName, lowRes, maxDurationSeconds, showDefaultControls) {
107312         _verifySetWindow("startVideoCapture");
107313         utils.validateNumberOfArguments(1, 4, arguments.length, ExceptionTypes.INVALID_PARAMETER, "startVideoCapture invalid number of parameters", new Exception());
107314         utils.validateMultipleArgumentTypes(
107315             [fileName, lowRes, maxDurationSeconds, showDefaultControls],
107316             ['string', 'boolean', 'integer', 'boolean'],
107317             ExceptionTypes.INVALID_PARAMETER,
107318             "invalid parameter type", new Exception());
107319         _console.log("started recording video");
107320         var interval = window.setTimeout(function () {
107321             _self.stopVideoCapture();
107322         }, maxDurationSeconds * 1000);
107323
107324         if (showDefaultControls) {
107325             _buttons.removeAttribute("style");
107326         }
107327
107328         _videoCapture = {
107329             fileName: fileName,
107330             stop: function () {
107331                 window.clearInterval(interval);
107332                 var msg = constants.CAMERA.WARNING_TEXT;
107333                 msg = msg.replace("{file}", fileName);
107334                 notifications.openNotification("normal", msg);
107335                 if (_self.onCameraCaptured) {
107336                     _self.onCameraCaptured.apply(_self, [fileName]);
107337                 }
107338             }
107339         };
107340
107341         return fileName;
107342     },
107343     stopVideoCapture: function () {
107344         utils.validateNumberOfArguments(0, 0, arguments.length, ExceptionTypes.INVALID_PARAMETER, "stopVideoCapture invalid number of parameters", new Exception());
107345         if (_videoCapture) {
107346             _console.log("simulated saving a video as: " + _videoCapture.fileName);
107347             if (_buttons) {
107348                 _buttons.setAttribute("style", "display: none");
107349             }
107350             _videoCapture.stop();
107351             _videoCapture = null;
107352         }
107353     }
107354
107355 };
107356
107357 module.exports = _self;
107358
107359 });
107360 define('ripple/platform/wac/1.0/Config', function (require, exports, module) {
107361 /*
107362  *  Copyright 2011 Research In Motion Limited.
107363  *
107364  * Licensed under the Apache License, Version 2.0 (the "License");
107365  * you may not use this file except in compliance with the License.
107366  * You may obtain a copy of the License at
107367  *
107368  * http://www.apache.org/licenses/LICENSE-2.0
107369  *
107370  * Unless required by applicable law or agreed to in writing, software
107371  * distributed under the License is distributed on an "AS IS" BASIS,
107372  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
107373  * See the License for the specific language governing permissions and
107374  * limitations under the License.
107375  */
107376 var utils = require('ripple/utils'),
107377     notifications = require('ripple/notifications'),
107378     constants = require('ripple/constants'),
107379     deviceSettings = require('ripple/deviceSettings'),
107380     ExceptionTypes = require('ripple/platform/wac/1.0/ExceptionTypes'),
107381     Exception = require('ripple/platform/wac/1.0/Exception'),
107382     _self = {
107383         ringtoneVolume: undefined,
107384         msgRingtoneVolume: undefined,
107385         vibrationSetting: undefined,
107386
107387         setDefaultRingtone: function (ringtoneUrl) {
107388             utils.validateArgumentType(ringtoneUrl, "string", ExceptionTypes.INVALID_PARAMETER, "ringtoneUrl paramter is not a string", new Exception());
107389             notifications.openNotification("normal", "Setting default ringtone to: " + ringtoneUrl);
107390         },
107391
107392         setAsWallpaper: function (wallpaperUrl) {
107393             utils.validateArgumentType(wallpaperUrl, "string", ExceptionTypes.INVALID_PARAMETER, "wallpaperUrl paramter is not a string", new Exception());
107394             notifications.openNotification("normal", "Setting wallpaper to: " + wallpaperUrl);
107395         }
107396     };
107397
107398 _self.__defineGetter__("ringtoneVolume", function () {
107399     return deviceSettings.retrieve("Config.ringtoneVolume");
107400 });
107401
107402 _self.__defineGetter__("msgRingtoneVolume", function () {
107403     return deviceSettings.retrieve("Config.msgRingtoneVolume");
107404 });
107405
107406 _self.__defineGetter__("vibrationSetting", function () {
107407     return deviceSettings.retrieve("Config.vibrationSetting");
107408 });
107409
107410 module.exports = _self;
107411
107412 });
107413 define('ripple/platform/wac/1.0/DataNetworkConnectionTypes', function (require, exports, module) {
107414 /*
107415  *  Copyright 2011 Research In Motion Limited.
107416  *
107417  * Licensed under the Apache License, Version 2.0 (the "License");
107418  * you may not use this file except in compliance with the License.
107419  * You may obtain a copy of the License at
107420  *
107421  * http://www.apache.org/licenses/LICENSE-2.0
107422  *
107423  * Unless required by applicable law or agreed to in writing, software
107424  * distributed under the License is distributed on an "AS IS" BASIS,
107425  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
107426  * See the License for the specific language governing permissions and
107427  * limitations under the License.
107428  */
107429 var utils = require('ripple/utils'),
107430     _self = {
107431         "BLUETOOTH": undefined,
107432         "EDGE": undefined,
107433         "EVDO": undefined,
107434         "GPRS": undefined,
107435         "IRDA": undefined,
107436         "LTE": undefined,
107437         "ONEXRTT": undefined,
107438         "WIFI": undefined
107439     };
107440
107441 utils.forEach(_self, function (value, property) {
107442     _self.__defineGetter__(property, function () {
107443         return property;
107444     });
107445 });
107446
107447 module.exports = _self;
107448
107449 });
107450 define('ripple/platform/wac/1.0/DataNetworkInfo', function (require, exports, module) {
107451 /*
107452  *  Copyright 2011 Research In Motion Limited.
107453  *
107454  * Licensed under the Apache License, Version 2.0 (the "License");
107455  * you may not use this file except in compliance with the License.
107456  * You may obtain a copy of the License at
107457  *
107458  * http://www.apache.org/licenses/LICENSE-2.0
107459  *
107460  * Unless required by applicable law or agreed to in writing, software
107461  * distributed under the License is distributed on an "AS IS" BASIS,
107462  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
107463  * See the License for the specific language governing permissions and
107464  * limitations under the License.
107465  */
107466 var event = require('ripple/event'),
107467     utils = require('ripple/utils'),
107468     _console = require('ripple/console'),
107469     deviceSettings = require('ripple/deviceSettings'),
107470     DataNetworkConnectionTypes = require('ripple/platform/wac/1.0/DataNetworkConnectionTypes'),
107471     Exception = require('ripple/platform/wac/1.0/Exception'),
107472     ExceptionTypes = require('ripple/platform/wac/1.0/ExceptionTypes'),
107473
107474 _self = {
107475     isDataNetworkConnected: undefined,
107476     networkConnectionType: undefined,
107477     onNetworkConnectionChanged: undefined,
107478
107479     getNetworkConnectionName: function (networkConnectionType) {
107480         var foundConnectionType;
107481         utils.validateArgumentType(networkConnectionType, "string", ExceptionTypes.INVALID_PARAMETER, "networkConnectionType is invalid, expected a string", new Exception());
107482         foundConnectionType = DataNetworkConnectionTypes[networkConnectionType.toUpperCase()];
107483         return foundConnectionType || null;
107484     }
107485 };
107486
107487 event.on("DataNetworkConnectionChanged", function (newConnectionName) {
107488     var callback = _self.onNetworkConnectionChanged,
107489         msg = "Fired onNetworkConnectionChanged with newConnectionName: " + newConnectionName;
107490
107491     if (callback && typeof callback === "function") {
107492         callback.apply(null, [newConnectionName]);
107493     }
107494     else {
107495         msg += " --> BUT there was no registered callback found.";
107496     }
107497
107498     _console.log(msg);
107499 });
107500
107501 _self.__defineGetter__("isDataNetworkConnected", function () {
107502     return deviceSettings.retrieveAsBoolean("DataNetworkInfo.isDataNetworkConnected");
107503 });
107504
107505 _self.__defineGetter__("networkConnectionType", function () {
107506     var value = deviceSettings.retrieve("DataNetworkInfo.networkConnectionType");
107507     return value instanceof Array ? value : [value];
107508 });
107509
107510 module.exports = _self;
107511
107512 });
107513 define('ripple/platform/wac/1.0/Device', function (require, exports, module) {
107514 /*
107515  *  Copyright 2011 Research In Motion Limited.
107516  *
107517  * Licensed under the Apache License, Version 2.0 (the "License");
107518  * you may not use this file except in compliance with the License.
107519  * You may obtain a copy of the License at
107520  *
107521  * http://www.apache.org/licenses/LICENSE-2.0
107522  *
107523  * Unless required by applicable law or agreed to in writing, software
107524  * distributed under the License is distributed on an "AS IS" BASIS,
107525  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
107526  * See the License for the specific language governing permissions and
107527  * limitations under the License.
107528  */
107529 var constants = require('ripple/constants'),
107530     exception = require('ripple/exception'),
107531     _console = require('ripple/console'),
107532     utils = require('ripple/utils'),
107533     notifications = require('ripple/notifications'),
107534     ApplicationTypes = require('ripple/platform/wac/1.0/ApplicationTypes'),
107535     Exception = require('ripple/platform/wac/1.0/Exception'),
107536     ExceptionTypes = require('ripple/platform/wac/1.0/ExceptionTypes'),
107537     _applicationTypes = {
107538         FILES: "FILES",
107539         MEDIAPLAYER: "MEDIAPLAYER",
107540         PHONECALL: "PHONECALL",
107541         PICTURES: "PICTURES"
107542     },
107543     _self;
107544
107545 function _throwUnsupportedException(method) {
107546     exception.raise(ExceptionTypes.UNSUPPORTED, "Method not supported." + (method || ""), new Exception());
107547 }
107548
107549 _self = {
107550     // Properties
107551     clipboardString: undefined,
107552     widgetEngineName: undefined,
107553     widgetEngineProvider: undefined,
107554     widgetEngineVersion: undefined,
107555
107556     // Methods
107557     getAvailableApplications: function () {
107558         return constants.PLATFORMS.WAC.APPLICATIONS || [];
107559     },
107560
107561     getDirectoryFileNames: function () {
107562         _throwUnsupportedException("Device.getDirectoryFileNames");
107563     },
107564     getFile: function () {
107565         _throwUnsupportedException("Device.getFile");
107566     },
107567
107568     launchApplication: function launchApplication(application, startParameter) {
107569         if (!application || typeof(application) !== "string") {
107570             exception.raise(ExceptionTypes.INVALID_PARAMETER,
107571                     "Invalid argument 'application' at Device.launchApplication(): expected to be of type 'string' but was of type: " + (application ? typeof(application) : "null"),
107572                     Exception);
107573         }
107574
107575         if (startParameter && typeof(startParameter) !== "string") {
107576             exception.raise(ExceptionTypes.INVALID_PARAMETER,
107577                     "Invalid argument 'startParameter' at Device.launchApplication(): expected to be 'string' but was : " + typeof(startParameter),
107578                     Exception);
107579         }
107580
107581         // rudimentary implementation for now
107582         var message = "The widget has requested application: '" + application + "' to be launched. \n\n";
107583
107584         if (startParameter) {
107585             message += "The following start parameter was sent in: " + startParameter + "\n\n";
107586         }
107587
107588         if (_applicationTypes[application] && !startParameter) {
107589             message += "Launching this application can also be done with an optional startParameter which was not provided" + "\n\n";
107590         }
107591
107592         if (!ApplicationTypes[application]) {
107593             message += "Note: the application requested is not part of the common values specified by the WAC API.";
107594         }
107595
107596         notifications.openNotification("normal", message);
107597         _console.log(message);
107598     },
107599
107600     copyFile: function () {
107601         _throwUnsupportedException("Device.copyFile");
107602     },
107603     deleteFile: function () {
107604         _throwUnsupportedException("Device.deleteFile");
107605     },
107606     findFiles: function () {
107607         _throwUnsupportedException("Device.findFiles");
107608     },
107609     getFileSystemRoots: function () {
107610         _throwUnsupportedException("Device.getFileSystemRoots");
107611     },
107612     getFileSystemSize: function () {
107613         _throwUnsupportedException("Device.getFileSystemSize");
107614     },
107615     moveFile: function () {
107616         _throwUnsupportedException("Device.moveFile");
107617     },
107618     onFilesFound: function () {
107619         _throwUnsupportedException("Device.onFilesFound");
107620     },
107621     setRingtone: function () {
107622         _throwUnsupportedException("Device.setRingtone");
107623     },
107624
107625     vibrate: function (duration) {
107626         utils.validateArgumentType(duration, "number", ExceptionTypes.INVALID_PARAMETER, "duration paramter is not a number", new Exception());
107627         notifications.openNotification("normal", "Vibrating for " + duration + " second(s).");
107628     }
107629
107630 };
107631
107632 _self.__defineGetter__("widgetEngineName", function () {
107633     return constants.PLATFORMS.WAC.DEVICE.WIDGET_ENGINE_NAME;
107634 });
107635
107636 _self.__defineGetter__("widgetEngineProvider", function () {
107637     return constants.PLATFORMS.WAC.DEVICE.WIDGET_ENGINE_PROVIDER;
107638 });
107639
107640 _self.__defineGetter__("widgetEngineVersion", function () {
107641     return constants.PLATFORMS.WAC.DEVICE.WIDGET_ENGINE_VERSION;
107642 });
107643
107644 module.exports = _self;
107645
107646 });
107647 define('ripple/platform/wac/1.0/DeviceInfo', function (require, exports, module) {
107648 /*
107649  *  Copyright 2011 Research In Motion Limited.
107650  *
107651  * Licensed under the Apache License, Version 2.0 (the "License");
107652  * you may not use this file except in compliance with the License.
107653  * You may obtain a copy of the License at
107654  *
107655  * http://www.apache.org/licenses/LICENSE-2.0
107656  *
107657  * Unless required by applicable law or agreed to in writing, software
107658  * distributed under the License is distributed on an "AS IS" BASIS,
107659  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
107660  * See the License for the specific language governing permissions and
107661  * limitations under the License.
107662  */
107663 var utils = require('ripple/utils'),
107664     deviceSettings = require('ripple/deviceSettings'),
107665     platform = require('ripple/platform'),
107666     devices = require('ripple/devices'),
107667     _self;
107668
107669 _self = {
107670     ownerInfo: undefined, // return AddressBookItem
107671     phoneColorDepthDefault: undefined,
107672     phoneFirmware: undefined,
107673     phoneManufacturer: undefined,
107674     phoneModel: undefined,
107675     phoneOS: undefined,
107676     phoneSoftware: undefined,
107677     phoneScreenHeightDefault: undefined,
107678     phoneScreenWidthDefault: undefined,
107679     totalMemory: undefined
107680 };
107681
107682 function _getDeviceAttribute(attr) {
107683     var devicePointer = devices.getCurrentDevice();
107684     utils.forEach(attr.split("."), function (dot) {
107685         devicePointer = devicePointer[dot];
107686     });
107687     return devicePointer;
107688 }
107689
107690 _self.__defineGetter__("phoneColorDepthDefault", function () {
107691     return deviceSettings.retrieveAsInt("DeviceInfo.phoneColorDepthDefault");
107692 });
107693
107694 _self.__defineGetter__("phoneFirmware", function () {
107695     return _getDeviceAttribute("firmware");
107696 });
107697
107698 _self.__defineGetter__("phoneManufacturer", function () {
107699     return _getDeviceAttribute("manufacturer");
107700 });
107701
107702 _self.__defineGetter__("phoneOS", function () {
107703     return _getDeviceAttribute("osName") + " " + _getDeviceAttribute("osVersion");
107704 });
107705
107706 _self.__defineGetter__("phoneModel", function () {
107707     return _getDeviceAttribute("model");
107708 });
107709
107710 _self.__defineGetter__("phoneSoftware", function () {
107711     return _getDeviceAttribute("osVersion");
107712 });
107713
107714 _self.__defineGetter__("phoneScreenHeightDefault", function () {
107715     return _getDeviceAttribute("screen.height");
107716 });
107717
107718 _self.__defineGetter__("phoneScreenWidthDefault", function () {
107719     return _getDeviceAttribute("screen.width");
107720 });
107721
107722 _self.__defineGetter__("totalMemory", function () {
107723     return deviceSettings.retrieveAsInt("DeviceInfo.totalMemory");
107724 });
107725
107726 module.exports = _self;
107727
107728 });
107729 define('ripple/platform/wac/1.0/DeviceStateInfo', function (require, exports, module) {
107730 /*
107731  *  Copyright 2011 Research In Motion Limited.
107732  *
107733  * Licensed under the Apache License, Version 2.0 (the "License");
107734  * you may not use this file except in compliance with the License.
107735  * You may obtain a copy of the License at
107736  *
107737  * http://www.apache.org/licenses/LICENSE-2.0
107738  *
107739  * Unless required by applicable law or agreed to in writing, software
107740  * distributed under the License is distributed on an "AS IS" BASIS,
107741  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
107742  * See the License for the specific language governing permissions and
107743  * limitations under the License.
107744  */
107745 var utils = require('ripple/utils'),
107746     exception = require('ripple/exception'),
107747     _console = require('ripple/console'),
107748     geo = require('ripple/geo'),
107749     event = require('ripple/event'),
107750     deviceSettings = require('ripple/deviceSettings'),
107751     PositionInfo = require('ripple/platform/wac/1.0/PositionInfo'),
107752     Exception = require('ripple/platform/wac/1.0/Exception'),
107753     ExceptionTypes = require('ripple/platform/wac/1.0/ExceptionTypes'),
107754     _self;
107755
107756 event.on("ScreenChangeDimensions", function (width, height) {
107757     try {
107758         if (typeof _self.onScreenChangeDimensions === 'function') {
107759             _self.onScreenChangeDimensions(width, height);
107760         }
107761         _console.log("called DeviceStateInfo.onScreenChangeDimensions callback function with width = " + width + " and height = " + height);
107762     } catch (e) {
107763         exception.handle(e, false);
107764     }
107765 });
107766
107767 _self = {
107768     availableMemory: undefined,
107769     language: undefined,
107770     keypadLightOn: undefined,
107771     backLightOn: undefined,
107772     processorUtilizationPercent: undefined,
107773     audioPath: undefined,
107774
107775     onPositionRetrieved: undefined,
107776
107777     requestPositionInfo: function (method) {
107778         utils.validateNumberOfArguments(1, 1, arguments.length,
107779             ExceptionTypes.INVALID_PARAMETER, "requestPositionInfo invalid number of parameters", new Exception());
107780         utils.validateArgumentType(method, "string",
107781             ExceptionTypes.INVALID_PARAMETER, "requestPositionInfo invalid parameter", new Exception());
107782
107783         if (!(method.match(/gps|agps|cellid/))) {
107784             exception.raise(ExceptionTypes.INVALID_PARAMETER,
107785                     "Invalid method, expected (gps, agps or cellid)", Exception);
107786         }
107787
107788         if (typeof _self.onPositionRetrieved === "function") {
107789             var delay = geo.delay * 1000,
107790                 timeout = geo.timeout;
107791             setTimeout(function () {
107792                 var pos = PositionInfo,
107793                     errorObj = {};
107794
107795                 if (timeout) {
107796                     //create
107797                     utils.forEach(pos, function (val, key) {
107798                         errorObj[key] = undefined;
107799                     });
107800                     pos = errorObj;
107801                 }
107802                 _self.onPositionRetrieved(pos, method);
107803             }, delay);
107804         }
107805     },
107806
107807     onScreenChangeDimensions: undefined,
107808
107809     onFlipEvent: undefined
107810 };
107811
107812 _self.__defineGetter__("availableMemory", function () {
107813     return deviceSettings.retrieveAsInt("DeviceStateInfo.availableMemory");
107814 });
107815
107816 _self.__defineGetter__("language", function () {
107817     return deviceSettings.retrieve("DeviceStateInfo.language");
107818 });
107819
107820 _self.__defineGetter__("keypadLightOn", function () {
107821     return deviceSettings.retrieveAsBoolean("DeviceStateInfo.keypadLightOn");
107822 });
107823
107824 _self.__defineGetter__("backLightOn", function () {
107825     return deviceSettings.retrieveAsBoolean("DeviceStateInfo.backLightOn");
107826 });
107827
107828 _self.__defineGetter__("audioPath", function () {
107829     return deviceSettings.retrieve("DeviceStateInfo.audioPath");
107830 });
107831
107832 _self.__defineGetter__("processorUtilizationPercent", function () {
107833     return deviceSettings.retrieve("DeviceStateInfo.processorUtilizationPercent");
107834 });
107835
107836 module.exports = _self;
107837
107838
107839 });
107840 define('ripple/platform/wac/1.0/EventRecurrenceTypes', function (require, exports, module) {
107841 /*
107842  *  Copyright 2011 Research In Motion Limited.
107843  *
107844  * Licensed under the Apache License, Version 2.0 (the "License");
107845  * you may not use this file except in compliance with the License.
107846  * You may obtain a copy of the License at
107847  *
107848  * http://www.apache.org/licenses/LICENSE-2.0
107849  *
107850  * Unless required by applicable law or agreed to in writing, software
107851  * distributed under the License is distributed on an "AS IS" BASIS,
107852  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
107853  * See the License for the specific language governing permissions and
107854  * limitations under the License.
107855  */
107856 module.exports = {
107857     NOT_REPEAT: "NOT_REPEAT",
107858     DAILY: "DAILY",
107859     EVERY_WEEKDAY: "EVERY_WEEKDAY",
107860     WEEKLY_ON_DAY: "WEEKLY_ON_DAY",
107861     MONTHLY_ON_DAY: "MONTHLY_ON_DAY",
107862     MONTHLY_ON_DAY_COUNT: "MONTHLY_ON_DAY_COUNT",
107863     YEARLY: "YEARLY"
107864 };
107865
107866 });
107867 define('ripple/platform/wac/1.0/Exception', function (require, exports, module) {
107868 /*
107869  *  Copyright 2011 Research In Motion Limited.
107870  *
107871  * Licensed under the Apache License, Version 2.0 (the "License");
107872  * you may not use this file except in compliance with the License.
107873  * You may obtain a copy of the License at
107874  *
107875  * http://www.apache.org/licenses/LICENSE-2.0
107876  *
107877  * Unless required by applicable law or agreed to in writing, software
107878  * distributed under the License is distributed on an "AS IS" BASIS,
107879  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
107880  * See the License for the specific language governing permissions and
107881  * limitations under the License.
107882  */
107883 module.exports = function () {
107884     this.message = "";
107885     this.type =  "";
107886
107887     this.toString = function () {
107888         var result = this.type + ': "' + this.message + '"';
107889
107890         if (this.stack) {
107891             result += "\n" + this.stack;
107892         }
107893         return result;
107894     };
107895 };
107896
107897 });
107898 define('ripple/platform/wac/1.0/ExceptionTypes', function (require, exports, module) {
107899 /*
107900  *  Copyright 2011 Research In Motion Limited.
107901  *
107902  * Licensed under the Apache License, Version 2.0 (the "License");
107903  * you may not use this file except in compliance with the License.
107904  * You may obtain a copy of the License at
107905  *
107906  * http://www.apache.org/licenses/LICENSE-2.0
107907  *
107908  * Unless required by applicable law or agreed to in writing, software
107909  * distributed under the License is distributed on an "AS IS" BASIS,
107910  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
107911  * See the License for the specific language governing permissions and
107912  * limitations under the License.
107913  */
107914 var _self =  {};
107915
107916 _self.__defineGetter__("INVALID_PARAMETER", function () {
107917     return "invalid_parameter";
107918 });
107919
107920 _self.__defineGetter__("SECURITY", function () {
107921     return "security";
107922 });
107923
107924 _self.__defineGetter__("UNKNOWN", function () {
107925     return "unknown";
107926 });
107927
107928 _self.__defineGetter__("UNSUPPORTED", function () {
107929     return "unsupported";
107930 });
107931
107932 module.exports = _self;
107933
107934 });
107935 define('ripple/platform/wac/1.0/File', function (require, exports, module) {
107936 /*
107937  *  Copyright 2011 Research In Motion Limited.
107938  *
107939  * Licensed under the Apache License, Version 2.0 (the "License");
107940  * you may not use this file except in compliance with the License.
107941  * You may obtain a copy of the License at
107942  *
107943  * http://www.apache.org/licenses/LICENSE-2.0
107944  *
107945  * Unless required by applicable law or agreed to in writing, software
107946  * distributed under the License is distributed on an "AS IS" BASIS,
107947  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
107948  * See the License for the specific language governing permissions and
107949  * limitations under the License.
107950  */
107951 module.expots = function () {
107952     this.createDate = undefined;
107953     this.fileName = undefined;
107954     this.filePath = undefined;
107955     this.fileSize = undefined;
107956     this.isDirectory = undefined;
107957     this.lastModifyDate = undefined;
107958 };
107959
107960 });
107961 define('ripple/platform/wac/1.0/Message', function (require, exports, module) {
107962 /*
107963  *  Copyright 2011 Research In Motion Limited.
107964  *
107965  * Licensed under the Apache License, Version 2.0 (the "License");
107966  * you may not use this file except in compliance with the License.
107967  * You may obtain a copy of the License at
107968  *
107969  * http://www.apache.org/licenses/LICENSE-2.0
107970  *
107971  * Unless required by applicable law or agreed to in writing, software
107972  * distributed under the License is distributed on an "AS IS" BASIS,
107973  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
107974  * See the License for the specific language governing permissions and
107975  * limitations under the License.
107976  */
107977 var exception = require('ripple/exception'),
107978     Attachment = require('ripple/platform/wac/1.0/Attachment'),
107979     ExceptionTypes = require('ripple/platform/wac/1.0/ExceptionTypes'),
107980     Exception = require('ripple/platform/wac/1.0/Exception');
107981
107982 function _throwUnsupportedException(method) {
107983     exception.raise(ExceptionTypes.UNSUPPORTED, "Method not supported." + (method || ""), new Exception());
107984 }
107985
107986 module.exports = function () {
107987     this.messageId = Math.uuid(undefined, 16);
107988     this.callbackNumber = undefined;
107989     this.destinationAddress = [];
107990     this.isRead = undefined;
107991     this.messagePriority = undefined;
107992     this.messageType = undefined;
107993     this.subject = undefined;
107994     this.body = undefined;
107995     this.sourceAddress = undefined;
107996     this.validityPeriodHours = undefined;
107997     this.time = undefined;
107998     this.ccAddress = [];
107999     this.bccAddress = [];
108000     this.attachments = [];
108001
108002     this.addAttachment = function (fileFullName) {
108003         var attachment = new Attachment();
108004         attachment.fileName = fileFullName;
108005         this.attachments.push(attachment);
108006     };
108007     this.deleteAttachment = function (attachment) {
108008
108009         for (var i = this.attachments.length - 1; i >= 0; i--) {
108010             if (this.attachments[i].fileName === attachment.fileName) {
108011                 this.attachments.splice(i, 1);
108012             }
108013         }
108014     };
108015     this.saveAttachment = function (fileFullName, attachment) {
108016         _throwUnsupportedException("Widget.Messaging.Message.addAddress");
108017     };
108018     this.addAddress = function (type, address) {
108019
108020         var addresses = address.split(";");
108021
108022         switch (type) {
108023         case "destination":
108024             this.destinationAddress = this.destinationAddress.concat(addresses);
108025             break;
108026         case "cc":
108027             this.ccAddress = this.ccAddress.concat(addresses);
108028             break;
108029         case "bcc":
108030             this.bccAddress = this.bccAddress.concat(addresses);
108031             break;
108032         }
108033     };
108034
108035     this.deleteAddress = function (type, address) {
108036         var addresses = address.split(";"),
108037             filter = function (orig) {
108038                 return orig.filter(function (address) {
108039                     return !addresses.some(function (x) {
108040                         return address === x;
108041                     });
108042                 });
108043             };
108044
108045         switch (type) {
108046         case "destination":
108047             this.destinationAddress = filter(this.destinationAddress);
108048             break;
108049         case "cc":
108050             this.ccAddress = filter(this.ccAddress);
108051             break;
108052         case "bcc":
108053             this.bccAddress = filter(this.bccAddress);
108054             break;
108055         }
108056     };
108057
108058 };
108059
108060 });
108061 define('ripple/platform/wac/1.0/MessageFolderTypes', function (require, exports, module) {
108062 /*
108063  *  Copyright 2011 Research In Motion Limited.
108064  *
108065  * Licensed under the Apache License, Version 2.0 (the "License");
108066  * you may not use this file except in compliance with the License.
108067  * You may obtain a copy of the License at
108068  *
108069  * http://www.apache.org/licenses/LICENSE-2.0
108070  *
108071  * Unless required by applicable law or agreed to in writing, software
108072  * distributed under the License is distributed on an "AS IS" BASIS,
108073  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
108074  * See the License for the specific language governing permissions and
108075  * limitations under the License.
108076  */
108077 module.exports = {
108078     DRAFTS: "drafts",
108079     INBOX: "inbox",
108080     OUTBOX: "outbox",
108081     SENTBOX: "sentbox"
108082 };
108083
108084 });
108085 define('ripple/platform/wac/1.0/MessageQuantities', function (require, exports, module) {
108086 /*
108087  *  Copyright 2011 Research In Motion Limited.
108088  *
108089  * Licensed under the Apache License, Version 2.0 (the "License");
108090  * you may not use this file except in compliance with the License.
108091  * You may obtain a copy of the License at
108092  *
108093  * http://www.apache.org/licenses/LICENSE-2.0
108094  *
108095  * Unless required by applicable law or agreed to in writing, software
108096  * distributed under the License is distributed on an "AS IS" BASIS,
108097  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
108098  * See the License for the specific language governing permissions and
108099  * limitations under the License.
108100  */
108101 module.exports = {
108102     totalMessageCnt: undefined,
108103     totalMessageReadCnt: undefined,
108104     totalMessageUnreadCnt: undefined
108105 };
108106
108107 });
108108 define('ripple/platform/wac/1.0/MessageTypes', function (require, exports, module) {
108109 /*
108110  *  Copyright 2011 Research In Motion Limited.
108111  *
108112  * Licensed under the Apache License, Version 2.0 (the "License");
108113  * you may not use this file except in compliance with the License.
108114  * You may obtain a copy of the License at
108115  *
108116  * http://www.apache.org/licenses/LICENSE-2.0
108117  *
108118  * Unless required by applicable law or agreed to in writing, software
108119  * distributed under the License is distributed on an "AS IS" BASIS,
108120  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
108121  * See the License for the specific language governing permissions and
108122  * limitations under the License.
108123  */
108124 module.exports = {
108125     EmailMessage: "email",
108126     MMSMessage: "mms",
108127     SMSMessage: "sms"
108128 };
108129
108130 });
108131 define('ripple/platform/wac/1.0/Messaging', function (require, exports, module) {
108132 /*
108133  *  Copyright 2011 Research In Motion Limited.
108134  *
108135  * Licensed under the Apache License, Version 2.0 (the "License");
108136  * you may not use this file except in compliance with the License.
108137  * You may obtain a copy of the License at
108138  *
108139  * http://www.apache.org/licenses/LICENSE-2.0
108140  *
108141  * Unless required by applicable law or agreed to in writing, software
108142  * distributed under the License is distributed on an "AS IS" BASIS,
108143  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
108144  * See the License for the specific language governing permissions and
108145  * limitations under the License.
108146  */
108147 var exception = require('ripple/exception'),
108148     utils = require('ripple/utils'),
108149     constants = require('ripple/constants'),
108150     notifications = require('ripple/notifications'),
108151     _console = require('ripple/console'),
108152     Message = require('ripple/platform/wac/1.0/Message'),
108153     MessageTypes = require('ripple/platform/wac/1.0/MessageTypes'),
108154     Exception = require('ripple/platform/wac/1.0/Exception'),
108155     ExceptionTypes = require('ripple/platform/wac/1.0/ExceptionTypes');
108156
108157 function _throwUnsupportedException(method) {
108158     exception.raise(ExceptionTypes.UNSUPPORTED, "Method not supported." + (method || ""), new Exception());
108159 }
108160
108161 module.exports = {
108162     onMessageArrived: undefined,
108163     onMessageSendingFailure: undefined,
108164     onMessagesFound: undefined,
108165
108166     createMessage: function (messageType) {
108167         utils.validateNumberOfArguments(1, 1, arguments.length, ExceptionTypes.INVALID_PARAMETER, "createMessage invalid number of arguments", new Exception());
108168         utils.validateArgumentType(messageType, "string", ExceptionTypes.INVALID_PARAMETER, "createMessage invalid arguments", new Exception());
108169
108170         if (!utils.some(MessageTypes, function (value) {
108171                 return value === messageType;
108172             })) {
108173             exception.raise(ExceptionTypes.INVALID_PARAMETER, "createMessage invalid arguments", new Exception());
108174         }
108175
108176         var message = new Message();
108177         message.messageType = messageType;
108178
108179         return message;
108180     },
108181     deleteMessage: function () {
108182         _throwUnsupportedException("Messaging.deleteMessage");
108183     },
108184     getMessage: function () {
108185         _throwUnsupportedException("Messaging.getMessage");
108186     },
108187     getMessageQuantities: function () {
108188         _throwUnsupportedException("Messaging.getMessageQuantities");
108189     },
108190     sendMessage: function (msg) {
108191         utils.validateNumberOfArguments(1, 1, arguments.length, ExceptionTypes.UNSUPPORTED, "sendMessage invalid number of arguments", new Exception());
108192         if (msg instanceof Message === false) {
108193             exception.raise(ExceptionTypes.INVALID_PARAMETER, "expected a valid Message object", new Exception());
108194         }
108195
108196         //TODO: Must be modded to fail and to then call the onMessageSendingFailure callback
108197         var message = "Sent " + msg.messageType + " " + msg.messageId + " to " + msg.destinationAddress;
108198
108199         // insert fail check here
108200         notifications.openNotification("normal", message);
108201         _console.log(message);
108202     },
108203     moveMessageToFolder: function () {
108204         _throwUnsupportedException("Messaging.moveMessageToFolder");
108205     },
108206     copyMessageToFolder: function () {
108207         _throwUnsupportedException("Messaging.copyMessageToFolder");
108208     },
108209     createFolder: function () {
108210         _throwUnsupportedException("Messaging.createFolder");
108211     },
108212     deleteFolder: function () {
108213         _throwUnsupportedException("Messaging.deleteFolder");
108214     },
108215     getFolderNames: function () {
108216         _throwUnsupportedException("Messaging.getFolderNames");
108217     },
108218     findMessages: function () {
108219         _throwUnsupportedException("Messaging.findMessages");
108220     },
108221     getCurrentEmailAccount: function () {
108222         _throwUnsupportedException("Messaging.getCurrentEmailAccount");
108223     },
108224     getEmailAccounts: function () {
108225         _throwUnsupportedException("Messaging.getEmailAccounts");
108226     },
108227     setCurrentEmailAccount: function () {
108228         _throwUnsupportedException("Messaging.setCurrentEmailAccount");
108229     },
108230     deleteEmailAccount: function () {
108231         _throwUnsupportedException("Messaging.deleteEmailAccount");
108232     }
108233
108234 };
108235
108236 });
108237 define('ripple/platform/wac/1.0/Multimedia', function (require, exports, module) {
108238 /*
108239  *  Copyright 2011 Research In Motion Limited.
108240  *
108241  * Licensed under the Apache License, Version 2.0 (the "License");
108242  * you may not use this file except in compliance with the License.
108243  * You may obtain a copy of the License at
108244  *
108245  * http://www.apache.org/licenses/LICENSE-2.0
108246  *
108247  * Unless required by applicable law or agreed to in writing, software
108248  * distributed under the License is distributed on an "AS IS" BASIS,
108249  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
108250  * See the License for the specific language governing permissions and
108251  * limitations under the License.
108252  */
108253 var event = require('ripple/event'),
108254     VideoPlayer = require('ripple/platform/wac/1.0/VideoPlayer'),
108255     AudioPlayer = require('ripple/platform/wac/1.0/AudioPlayer'),
108256     constants = require('ripple/constants'),
108257     _volume = 5,
108258     _audioState,
108259     _videoState,
108260     _self;
108261
108262 event.on("MultimediaVolumeChanged", function updateVolume(volume) {
108263     _volume = volume;
108264 });
108265
108266 event.on("MultimediaAudioStateChanged", function updateAudioState(state) {
108267     _audioState = state;
108268 });
108269
108270 event.on("MultimediaVideoStateChanged", function updateVideoState(state) {
108271     _videoState = state;
108272 });
108273
108274 _self = {
108275
108276     isAudioPlaying: undefined,
108277     isVideoPlaying: undefined,
108278
108279     getVolume: function () {
108280         return _volume;
108281     },
108282
108283     stopAll: function () {
108284         VideoPlayer.stop();
108285         AudioPlayer.stop();
108286     }
108287 };
108288
108289 _self.__defineGetter__("isAudioPlaying", function () {
108290     return _audioState === constants.MULTIMEDIA.AUDIO_STATES.PLAYING;
108291 });
108292
108293 _self.__defineGetter__("isVideoPlaying", function () {
108294     return _videoState === "playing";
108295 });
108296
108297 module.exports = _self;
108298
108299 });
108300 define('ripple/platform/wac/1.0/PIM', function (require, exports, module) {
108301 /*
108302  *  Copyright 2011 Research In Motion Limited.
108303  *
108304  * Licensed under the Apache License, Version 2.0 (the "License");
108305  * you may not use this file except in compliance with the License.
108306  * You may obtain a copy of the License at
108307  *
108308  * http://www.apache.org/licenses/LICENSE-2.0
108309  *
108310  * Unless required by applicable law or agreed to in writing, software
108311  * distributed under the License is distributed on an "AS IS" BASIS,
108312  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
108313  * See the License for the specific language governing permissions and
108314  * limitations under the License.
108315  */
108316 var _self,
108317     exception = require('ripple/exception'),
108318     Exception = require('ripple/platform/wac/1.0/Exception'),
108319     ExceptionTypes = require('ripple/platform/wac/1.0/ExceptionTypes'),
108320     AddressBookItem = require('ripple/platform/wac/1.0/AddressBookItem'),
108321     CalendarItem = require('ripple/platform/wac/1.0/CalendarItem'),
108322     utils = require('ripple/utils'),
108323     db = require('ripple/db'),
108324     constants = require('ripple/constants');
108325
108326 function _throwUnsupportedException(method) {
108327     exception.raise(ExceptionTypes.UNSUPPORTED, "Method not supported." + (method || ""), new Exception());
108328 }
108329
108330 function _toAddressBookItem(contact) {
108331     if (!contact) {
108332         return null;
108333     }
108334
108335     var addressBookItem = new AddressBookItem();
108336
108337     utils.forEach(contact, function (prop, key) {
108338         addressBookItem[key] = contact[key];
108339     });
108340
108341     return addressBookItem;
108342 }
108343
108344 function _toCalendarItem(item) {
108345     if (!item) {
108346         return null;
108347     }
108348
108349     var calendarItem = new CalendarItem();
108350
108351     utils.forEach(item, function (prop, key) {
108352         calendarItem[key] = item[key];
108353     });
108354
108355     return calendarItem;
108356 }
108357
108358 function _getData(type) {
108359     var data = db.retrieveObject(type) || [];
108360     return data;
108361 }
108362
108363 function _saveData(type, items) {
108364     db.saveObject(type, items);
108365 }
108366
108367 function _getContacts() {
108368     var contacts = _getData(constants.PIM.ADDRESS_LIST_KEY),
108369         gord,
108370         dan,
108371         brent,
108372         pj,
108373         mark;
108374
108375     if (contacts.length === 0) {
108376
108377         gord = new AddressBookItem();
108378         gord.addressBookItemId = "0";
108379         gord.fullName = "Gord Tanner";
108380         gord.eMail = "gord@tinyHippos.com";
108381         gord.company = "tinyHippos Inc";
108382         gord.title = "Code Poet";
108383         gord.address = "121 Charles Street W, Kitchener, Ontario, Canada";
108384
108385         dan = new AddressBookItem();
108386         dan.addressBookItemId = "1";
108387         dan.fullName = "Dan Silivestru";
108388         dan.eMail = "dan@tinyHippos.com";
108389         dan.company = "tinyHippos Inc";
108390         dan.title = "Co-Founder And Chief Technology Officer";
108391         dan.address = "121 Charles Street W, Kitchener, Ontario, Canada";
108392
108393         pj = new AddressBookItem();
108394         pj.addressBookItemId = "2";
108395         pj.fullName = "PJ Lowe";
108396         pj.eMail = "pj@tinyHippos.com";
108397         pj.company = "tinyHippos Inc";
108398         pj.title = "Co-Founder And Chief Operations Officer";
108399         pj.address = "121 Charles Street W, Kitchener, Ontario, Canada";
108400
108401         brent = new AddressBookItem();
108402         brent.addressBookItemId = "2";
108403         brent.fullName = "Brent Lintner";
108404         brent.eMail = "brent@tinyHippos.com";
108405         brent.company = "tinyHippos Inc";
108406         brent.title = "Co-Founder And Chief Operations Officer";
108407         brent.address = "121 Charles Street W, Kitchener, Ontario, Canada";
108408
108409         mark = new AddressBookItem();
108410         mark.addressBookItemId = "3";
108411         mark.fullName = "Mark McArdle";
108412         mark.eMail = "mark@tinyHippos.com";
108413         mark.company = "tinyHippos Inc";
108414         mark.title = "Chief Executive Officer";
108415         mark.address = "121 Charles Street W, Kitchener, Ontario, Canada";
108416
108417         contacts.push(gord);
108418         contacts.push(dan);
108419         contacts.push(pj);
108420         contacts.push(brent);
108421         contacts.push(mark);
108422
108423         _saveData(constants.PIM.ADDRESS_LIST_KEY, contacts);
108424     }
108425     return contacts.map(_toAddressBookItem);
108426 }
108427
108428 function _getEvents() {
108429     var events = _getData(constants.PIM.CALENDAR_LIST_KEY);
108430     return events.map(_toCalendarItem);
108431 }
108432
108433 function _get(type, id, fetchIDFunc) {
108434     var items = _getData(type);
108435     return items.reduceRight(function (match, item) {
108436         return fetchIDFunc(item) === id ? item : match;
108437     }, null);
108438 }
108439
108440 function _getAddressBookID(item) {
108441     return item.addressBookItemId;
108442 }
108443
108444 function _getCalendarID(item) {
108445     return item.calendarItemId;
108446 }
108447
108448 function _getContact(id) {
108449     return _toAddressBookItem(_get(constants.PIM.ADDRESS_LIST_KEY, id, _getAddressBookID));
108450 }
108451
108452 function _getEvent(id) {
108453     return _toCalendarItem(_get(constants.PIM.CALENDAR_LIST_KEY, id, _getCalendarID));
108454 }
108455
108456 function _add(type, item, idProp) {
108457     var items = _getData(type);
108458
108459     if (!item[idProp]) {
108460         item[idProp] = Math.uuid(undefined, 16);
108461     }
108462
108463     items.push(item);
108464     _saveData(type, items);
108465 }
108466
108467 function _delete(type, id, fetchIDFunc) {
108468     var items = _getData(type);
108469
108470     _saveData(type, items.filter(function (item) {
108471         return fetchIDFunc(item) !== id;
108472     }));
108473 }
108474
108475 function _validateArgs(min, max, len) {
108476     utils.validateNumberOfArguments(min, max, len,
108477         ExceptionTypes.INVALID_PARAMETER, "invalid number of parameters", new Exception());
108478 }
108479
108480 function _validateType(arg, argType) {
108481     utils.validateArgumentType(arg, argType,
108482         ExceptionTypes.INVALID_PARAMETER,  "argument of wrong type provided",
108483         new Exception());
108484 }
108485
108486 function _validateAddressBookItem(item) {
108487     if ((item instanceof AddressBookItem) === false) {
108488         exception.raise(ExceptionTypes.INVALID_PARAMETER, "invalid contact, not instance of AddressBookItem.", new Exception());
108489     }
108490 }
108491
108492 _self = {
108493     addAddressBookItem: function (contact) {
108494         _validateArgs(1, 1, arguments.length);
108495         _validateAddressBookItem(contact);
108496
108497         _add(constants.PIM.ADDRESS_LIST_KEY, contact, "addressBookItemId");
108498     },
108499     createAddressBookGroup: function (groupName) {
108500         _throwUnsupportedException("Widget.PIM.createAddressBookGroup");
108501     },
108502     createAddressBookItem: function () {
108503         return new AddressBookItem();
108504     },
108505     deleteAddressBookItem: function (contactid) {
108506         _validateArgs(1, 1, arguments.length);
108507         _validateType(contactid, "string");
108508         _delete(constants.PIM.ADDRESS_LIST_KEY, contactid, _getAddressBookID);
108509     },
108510     deleteAddressBookGroup: function (groupName) {
108511         _throwUnsupportedException("Widget.PIM.deleteAddressBookGroup");
108512     },
108513     getAddressBookItem: function (contactid) {
108514         _validateArgs(1, 1, arguments.length);
108515         _validateType(contactid, "string");
108516         return _getContact(contactid);
108517     },
108518     getAddressBookItemsCount: function () {
108519         _validateArgs(0, 0, arguments.length);
108520         var items = _getContacts();
108521         return items.length;
108522     },
108523     getAvailableAddressGroupNames: function () {
108524         _throwUnsupportedException("Widget.PIM.getAvailableAddressGroupNames");
108525     },
108526     getAddressBookGroupMembers: function (groupName) {
108527         _throwUnsupportedException("Widget.PIM.getAddressBookGroupMembers");
108528     },
108529     findAddressBookItems: function (comparisonContact, startInx, endInx) {
108530         _validateArgs(3, 3, arguments.length);
108531         utils.validateMultipleArgumentTypes([comparisonContact, startInx, endInx], ["object", "number", "number"], ExceptionTypes.INVALID_PARAMETER,  "argument of wrong type provided",
108532             new Exception());
108533
108534         if (endInx < 0) {
108535             exception.raise(ExceptionTypes.INVALID_PARAMETER, "invalid number of parameters", new Exception());
108536         }
108537
108538         startInx = startInx < 0 ? 0 : startInx;
108539
108540         var contacts = _getContacts();
108541         utils.find(comparisonContact, contacts, startInx, endInx, _self.onAddressBookItemsFound);
108542     },
108543
108544     addCalendarItem: function (calendarItem) {
108545         _validateArgs(1, 1, arguments.length);
108546         _add(constants.PIM.CALENDAR_LIST_KEY, calendarItem, "calendarItemId");
108547     },
108548     deleteCalendarItem: function (calendarId) {
108549         _validateArgs(1, 1, arguments.length);
108550         _delete(constants.PIM.CALENDAR_LIST_KEY, calendarId, _getCalendarID);
108551     },
108552     getCalendarItem: function (calendarId) {
108553         _validateArgs(1, 1, arguments.length);
108554         return _getEvent(calendarId);
108555     },
108556     findCalendarItems: function (itemToMatch, startInx, endInx) {
108557         _validateArgs(1, 3, arguments.length);
108558         var events = _getEvents();
108559         utils.find(itemToMatch, events, startInx, endInx, _self.onCalendarItemsFound);
108560     },
108561     getCalendarItems: function (startTime, endTime) {
108562         var events = _getEvents();
108563
108564         return events.reduce(function (matches, event) {
108565             if (event.eventStartTime >= startTime && event.eventStartTime <= endTime) {
108566                 matches.push(event);
108567             }
108568             return matches;
108569         }, []);
108570     },
108571     exportAsVCard: function (addressBookItems) {
108572         _throwUnsupportedException("Widget.PIM.exportAsVCard");
108573     },
108574
108575     onAddressBookItemsFound: undefined, // function (addressBookItemsFound) { }
108576     onCalendarItemsFound: undefined, // function (calendarItemsFound) { }
108577     onCalendarItemAlert: undefined, // function (calendarItem) { }
108578     onVCardExportingFinish: undefined // function (vCardFilePath) { }
108579 };
108580
108581 module.exports = _self;
108582
108583 });
108584 define('ripple/platform/wac/1.0/PositionInfo', function (require, exports, module) {
108585 /*
108586  *  Copyright 2011 Research In Motion Limited.
108587  *
108588  * Licensed under the Apache License, Version 2.0 (the "License");
108589  * you may not use this file except in compliance with the License.
108590  * You may obtain a copy of the License at
108591  *
108592  * http://www.apache.org/licenses/LICENSE-2.0
108593  *
108594  * Unless required by applicable law or agreed to in writing, software
108595  * distributed under the License is distributed on an "AS IS" BASIS,
108596  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
108597  * See the License for the specific language governing permissions and
108598  * limitations under the License.
108599  */
108600 var geo = require('ripple/geo'),
108601     event = require('ripple/event'),
108602     exception = require('ripple/exception'),
108603     utils = require('ripple/utils'),
108604     _self = {
108605         latitude: undefined,
108606         longitude: undefined,
108607         altitude: undefined,
108608         cellID: undefined,
108609         accuracy: undefined,
108610         altitudeAccuracy: undefined,
108611         timeStamp: undefined
108612     };
108613
108614 utils.forEach(_self, function (value, property) {
108615     _self.__defineGetter__(property, function () {
108616         return geo.getPositionInfo()[property];
108617     });
108618 });
108619
108620 module.exports = _self;
108621
108622 });
108623 define('ripple/platform/wac/1.0/PowerInfo', function (require, exports, module) {
108624 /*
108625  *  Copyright 2011 Research In Motion Limited.
108626  *
108627  * Licensed under the Apache License, Version 2.0 (the "License");
108628  * you may not use this file except in compliance with the License.
108629  * You may obtain a copy of the License at
108630  *
108631  * http://www.apache.org/licenses/LICENSE-2.0
108632  *
108633  * Unless required by applicable law or agreed to in writing, software
108634  * distributed under the License is distributed on an "AS IS" BASIS,
108635  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
108636  * See the License for the specific language governing permissions and
108637  * limitations under the License.
108638  */
108639 var _self,
108640     event = require('ripple/event'),
108641     _console = require('ripple/console'),
108642     deviceSettings = require('ripple/deviceSettings'),
108643     _lastPercentRemaining;
108644
108645 _self = {
108646     isCharging: undefined,
108647     percentRemaining: undefined,
108648
108649     onChargeStateChange: undefined,
108650     onLowBattery: undefined,
108651     onChargeLevelChange: undefined
108652 };
108653
108654 function _getCurrentChargeState(percentRemaining, isCharging) {
108655     var batteryState;
108656     if (percentRemaining === 100 && isCharging) {
108657         batteryState = "full";
108658     }
108659     else if (!isCharging) {
108660         batteryState = "discharging";
108661     }
108662     else {
108663         batteryState = "charging";
108664     }
108665     return batteryState;
108666 }
108667
108668 event.on("DeviceBatteryStateChanged", function (isCharging) {
108669     var callback = _self.onChargeStateChange,
108670         msg = "",
108671         batteryLevel = _self.percentRemaining,
108672         batteryState;
108673
108674     batteryState = _getCurrentChargeState(batteryLevel, isCharging);
108675
108676     msg += "Fired onChargeStateChange with batteryState: " + batteryState;
108677
108678     if (callback && typeof callback === "function") {
108679         callback.apply(null, [batteryState]);
108680     }
108681     else {
108682         msg += " --> BUT there was no registered callback found.";
108683     }
108684
108685     _console.log(msg);
108686 });
108687
108688 event.on("DeviceBatteryLevelChanged", function (percentRemaining) {
108689
108690     var callback = _self.onChargeLevelChange,
108691         lowBatteryCallback = _self.onLowBattery,
108692         msg = "Fired onChargeLevelChange with percentRemaining: " + percentRemaining;
108693
108694     // blah, stupid Options returning strings
108695     percentRemaining = parseInt(percentRemaining, 10);
108696
108697     if (callback && typeof callback === "function") {
108698         callback.apply(null, [percentRemaining]);
108699     }
108700     else {
108701         msg += " --> BUT there was no registered callback found.";
108702     }
108703
108704     _console.log(msg);
108705
108706     if (percentRemaining <= 10) {
108707
108708         msg = "Fired onLowBattery with percentRemaining: " + percentRemaining;
108709
108710         if (lowBatteryCallback && typeof lowBatteryCallback === "function") {
108711             lowBatteryCallback.apply(null, [percentRemaining]);
108712         }
108713         else {
108714             msg += " --> BUT there was no registered callback found.";
108715         }
108716
108717         _console.log(msg);
108718     }
108719
108720     if (percentRemaining === 100 || (percentRemaining < 100 && _lastPercentRemaining === 100)) {
108721         event.trigger("DeviceBatteryStateChanged", [_self.isCharging]);
108722     }
108723
108724     _lastPercentRemaining = percentRemaining;
108725
108726 });
108727
108728 _self.__defineGetter__("isCharging", function () {
108729     return deviceSettings.retrieveAsBoolean("PowerInfo.isCharging");
108730 });
108731
108732 _self.__defineGetter__("percentRemaining", function () {
108733     return deviceSettings.retrieveAsInt("PowerInfo.percentRemaining");
108734 });
108735
108736 module.exports = _self;
108737
108738 });
108739 define('ripple/platform/wac/1.0/RadioInfo', function (require, exports, module) {
108740 /*
108741  *  Copyright 2011 Research In Motion Limited.
108742  *
108743  * Licensed under the Apache License, Version 2.0 (the "License");
108744  * you may not use this file except in compliance with the License.
108745  * You may obtain a copy of the License at
108746  *
108747  * http://www.apache.org/licenses/LICENSE-2.0
108748  *
108749  * Unless required by applicable law or agreed to in writing, software
108750  * distributed under the License is distributed on an "AS IS" BASIS,
108751  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
108752  * See the License for the specific language governing permissions and
108753  * limitations under the License.
108754  */
108755 var _self,
108756     event = require('ripple/event'),
108757     _console = require('ripple/console'),
108758     deviceSettings = require('ripple/deviceSettings');
108759
108760 _self = {
108761     isRoaming: undefined,
108762     radioSignalStrengthPercent: undefined,
108763     isRadioEnabled: undefined,
108764     radioSignalSource: undefined,
108765     onSignalSourceChange: undefined
108766 };
108767
108768 event.on("RadioSignalSourceChanged", function () {
108769     var callback = _self.onSignalSourceChange,
108770         isRoaming = _self.isRoaming,
108771         signalSource = _self.radioSignalSource,
108772         msg = "Fired onSignalSourceChange. signalSource: " + signalSource + ", isRoaming: " + isRoaming;
108773
108774     if (callback && typeof callback === "function") {
108775         callback.apply(null, [signalSource, isRoaming]);
108776     }
108777     else {
108778         msg += " --> BUT there was no registered callback found.";
108779     }
108780
108781     _console.log(msg);
108782 });
108783
108784 _self.__defineGetter__("radioSignalSource", function () {
108785     return deviceSettings.retrieve("RadioInfo.radioSignalSource");
108786 });
108787
108788 _self.__defineGetter__("isRoaming", function () {
108789     return deviceSettings.retrieveAsBoolean("RadioInfo.isRoaming");
108790 });
108791
108792 _self.__defineGetter__("isRadioEnabled", function () {
108793     return deviceSettings.retrieveAsBoolean("RadioInfo.isRadioEnabled");
108794 });
108795
108796 _self.__defineGetter__("radioSignalStrengthPercent", function () {
108797     return deviceSettings.retrieveAsInt("RadioInfo.radioSignalStrengthPercent");
108798 });
108799
108800 module.exports = _self;
108801
108802 });
108803 define('ripple/platform/wac/1.0/RadioSignalSourceTypes', function (require, exports, module) {
108804 /*
108805  *  Copyright 2011 Research In Motion Limited.
108806  *
108807  * Licensed under the Apache License, Version 2.0 (the "License");
108808  * you may not use this file except in compliance with the License.
108809  * You may obtain a copy of the License at
108810  *
108811  * http://www.apache.org/licenses/LICENSE-2.0
108812  *
108813  * Unless required by applicable law or agreed to in writing, software
108814  * distributed under the License is distributed on an "AS IS" BASIS,
108815  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
108816  * See the License for the specific language governing permissions and
108817  * limitations under the License.
108818  */
108819 var _self,
108820     utils = require('ripple/utils');
108821
108822 _self = {
108823     "CDMA": undefined,
108824     "GSM": undefined,
108825     "LTE": undefined,
108826     "TDSCDMA": undefined,
108827     "WCDMA": undefined
108828 };
108829
108830 utils.forEach(_self, function (value, property) {
108831     _self.__defineGetter__(property, function () {
108832         return property;
108833     });
108834 });
108835
108836 module.exports = _self;
108837
108838 });
108839 define('ripple/platform/wac/1.0/Telephony', function (require, exports, module) {
108840 /*
108841  *  Copyright 2011 Research In Motion Limited.
108842  *
108843  * Licensed under the Apache License, Version 2.0 (the "License");
108844  * you may not use this file except in compliance with the License.
108845  * You may obtain a copy of the License at
108846  *
108847  * http://www.apache.org/licenses/LICENSE-2.0
108848  *
108849  * Unless required by applicable law or agreed to in writing, software
108850  * distributed under the License is distributed on an "AS IS" BASIS,
108851  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
108852  * See the License for the specific language governing permissions and
108853  * limitations under the License.
108854  */
108855 var _self,
108856     exception = require('ripple/exception'),
108857     utils = require('ripple/utils'),
108858     db = require('ripple/db'),
108859     constants = require('ripple/constants'),
108860     Device = require('ripple/platform/wac/1.0/Device'),
108861     ExceptionTypes = require('ripple/platform/wac/1.0/ExceptionTypes'),
108862     Exception = require('ripple/platform/wac/1.0/Exception');
108863
108864
108865 function _throwUnsupportedException(method) {
108866     exception.raise(ExceptionTypes.UNSUPPORTED, "Method not supported." + (method || ""), new Exception());
108867 }
108868
108869 _self = {
108870
108871     // Public Callbacks
108872     onCallEvent: undefined,// function (callType, phoneNumber) { },
108873     onCallRecordsFound: undefined,// function (callRecords) { };
108874
108875     // Public Methods
108876     initiateVoiceCall: function (phoneNumber) {
108877         utils.validateNumberOfArguments(1, 1, arguments.length, ExceptionTypes.INVALID_PARAMETER, "initiateVoiceCall invalid number of parameters", new Exception());
108878         //HACK: should this be hardcoded?
108879         //I am still not even sure this is the correct behaviour
108880         Device.launchApplication("PHONECALL", phoneNumber);
108881
108882         if (_self.onCallEvent) {
108883             //HACK: shouldn't be hardcoded
108884             //also what should the context be? isn't spec'ed
108885             _self.onCallEvent.apply(_self, ["outgoing", phoneNumber]);
108886         }
108887     },
108888     getCallRecordCnt: function (callRecordType) {
108889         utils.validateNumberOfArguments(1, 1, arguments.length, ExceptionTypes.INVALID_PARAMETER, "getCallRecordCnt invalid number of parameters", new Exception());
108890         var calls = db.retrieveObject(constants.TELEPHONY.CALL_LIST_KEY);
108891
108892         return utils.sum(calls, function (call) {
108893             return call.callRecordType === callRecordType;
108894         });
108895     },
108896     getCallRecord: function (callRecordType, id) {
108897         utils.validateNumberOfArguments(2, 2, arguments.length, ExceptionTypes.INVALID_PARAMETER, "getCallRecord invalid number of parameters", new Exception());
108898         var calls = db.retrieveObject(constants.TELEPHONY.CALL_LIST_KEY);
108899
108900         return utils.map(calls, function (call) {
108901             return call.callRecordType === callRecordType ? call : null;
108902         }).reduce(function (match, call) {
108903             return match || call.callRecordId === id || null;
108904         }, null);
108905     },
108906     deleteCallRecord: function (callRecordType, id) {
108907         utils.validateNumberOfArguments(2, 2, arguments.length, ExceptionTypes.INVALID_PARAMETER, "deleteCallRecord invalid number of parameters", new Exception());
108908         var calls = db.retrieveObject(constants.TELEPHONY.CALL_LIST_KEY),
108909             indexToDelete = calls.reduce(function (result, call, index) {
108910                 return call.callRecordType === callRecordType &&
108911                        call.callRecordId === id ? index : result;
108912             }, -1);
108913
108914         if (indexToDelete >= 0) {
108915             calls.splice(indexToDelete, 1);
108916             db.saveObject(constants.TELEPHONY.CALL_LIST_KEY, calls);
108917         }
108918
108919     },
108920
108921     deleteAllCallRecords: function (callRecordType) {
108922         utils.validateNumberOfArguments(1, 1, arguments.length, ExceptionTypes.INVALID_PARAMETER, "deleteAllCallRecords invalid number of parameters", new Exception());
108923         var calls = db.retrieveObject(constants.TELEPHONY.CALL_LIST_KEY),
108924             indexesToDelete = calls.reduce(function (result, call, index) {
108925                 if (call.callRecordType === callRecordType) {
108926                     result.push(index);
108927                 }
108928                 return result;
108929             }, []);
108930
108931         utils.forEach(indexesToDelete, function (index) {
108932             calls.splice(index, 1);
108933         });
108934
108935         if (indexesToDelete.length > 0) {
108936             db.saveObject(constants.TELEPHONY.CALL_LIST_KEY, calls);
108937         }
108938
108939     },
108940
108941     findCallRecords: function (comparisonRecord, startInx, endInx) {
108942         utils.validateNumberOfArguments(1, 3, arguments.length, ExceptionTypes.INVALID_PARAMETER, "findCallRecords invalid number of parameters", new Exception());
108943         var calls = db.retrieveObject(constants.TELEPHONY.CALL_LIST_KEY);
108944         utils.find(comparisonRecord, calls, startInx, endInx, _self.onCallRecordsFound);
108945
108946     }
108947
108948 };
108949
108950 module.exports = _self;
108951
108952 });
108953 define('ripple/platform/wac/1.0/VideoPlayer', function (require, exports, module) {
108954 /*
108955  *  Copyright 2011 Research In Motion Limited.
108956  *
108957  * Licensed under the Apache License, Version 2.0 (the "License");
108958  * you may not use this file except in compliance with the License.
108959  * You may obtain a copy of the License at
108960  *
108961  * http://www.apache.org/licenses/LICENSE-2.0
108962  *
108963  * Unless required by applicable law or agreed to in writing, software
108964  * distributed under the License is distributed on an "AS IS" BASIS,
108965  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
108966  * See the License for the specific language governing permissions and
108967  * limitations under the License.
108968  */
108969 var _self,
108970     _console = require('ripple/console'),
108971     event = require('ripple/event'),
108972     utils = require('ripple/utils'),
108973     fileSystem = require('ripple/fileSystem'),
108974     ExceptionTypes = require('ripple/platform/wac/1.0/ExceptionTypes'),
108975     Exception = require('ripple/platform/wac/1.0/Exception'),
108976     exception = require('ripple/exception'),
108977     _currentlySet,
108978     _currentVideoFile,
108979     _state = null,
108980     _loopCount, _video,
108981     _STATES = {
108982         "OPENED": "opened",
108983         "STOPPED": "stopped",
108984         "PAUSED": "paused",
108985         "PLAYING": "playing",
108986         "COMPLETED": "completed"
108987     };
108988
108989 function _validateVideoType(fileUrl) {
108990     var matched = fileUrl.match(/\.(\w*)$/),
108991         maps = {
108992             "ogv": "ogg",
108993             "flv": "mp4"
108994         },
108995         type = matched ? matched[1] : "";
108996
108997     if (_video && _video.canPlayType("video/" + (maps[type] || type)) === "") {
108998         _console.warn("Attempting to load a video that might not work in the current browser [" + fileUrl + "]");
108999     }
109000 }
109001
109002 function _validateAndSet(state, validStates, callbackBeforeSuccess) {
109003     var i, valid = false;
109004
109005     for (i = 0; i < validStates.length; i++) {
109006         if (validStates[i] === _state) {
109007             valid = true;
109008         }
109009     }
109010
109011     if (!valid) {
109012         _console.warn("Attempted to initiate VideoPlayer." + state +
109013             " in invalid state. current state: " + _state);
109014     } else {
109015         if (typeof(callbackBeforeSuccess) === "function") {
109016             callbackBeforeSuccess.apply();
109017         }
109018         event.trigger("MultimediaVideoStateChanged", [state], true);
109019     }
109020
109021     return valid;
109022 }
109023
109024 event.on("MultimediaVideoStateChanged", function (state) {
109025     _state = state;
109026     if (typeof _self.onStateChange === "function") {
109027         _self.onStateChange.apply(_self, [state]);
109028     }
109029 });
109030
109031 _self = module.exports = {
109032     onStateChange: undefined,
109033
109034     open: function (fileUrl) {
109035         utils.validateNumberOfArguments(1, 1, arguments.length, ExceptionTypes.INVALID_PARAMETER,
109036            "VideoPlayer.open invalid number of arguments", new Exception());
109037         utils.validateArgumentType(fileUrl, "string", ExceptionTypes.INVALID_PARAMETER,
109038            "VideoPlayer.open expected valid fileUrl but got ->" + fileUrl, new Exception());
109039
109040         if (!_video) {
109041             return;
109042         }
109043
109044         _validateAndSet(_STATES.OPENED, [_STATES.OPENED, _STATES.STOPPED, _STATES.COMPLETED, null], function () {
109045             _validateVideoType(fileUrl);
109046             _currentVideoFile = fileSystem.getURI(fileUrl);
109047             _video.setAttribute("src", _currentVideoFile);
109048             _video.setAttribute("width", "100%");
109049             _video.addEventListener("ended", function () {
109050                 event.trigger("MultimediaVideoStateChanged", [_STATES.COMPLETED], true);
109051                 if (_loopCount > 1) {
109052                     _self.open(_currentVideoFile);
109053                     _self.play(_loopCount--);
109054                 }
109055             }, false);
109056         });
109057     },
109058
109059     setWindow: function (domObject) {
109060         utils.validateNumberOfArguments(0, 1, arguments.length, ExceptionTypes.INVALID_PARAMETER,
109061            "VideoPlayer.setWindow invalid number of arguments", new Exception());
109062
109063         if (_currentlySet) {
109064             _currentlySet.removeChild(_video);
109065             _currentlySet = null;
109066             _video = null;
109067         }
109068
109069         if (domObject !== null) {
109070             _video = utils.createElement("video", {
109071                 "id": "multimedia-video"
109072             });
109073             domObject.appendChild(_video);
109074             _currentlySet = domObject;
109075             event.trigger("MultimediaAppVideoPlayerCreated", [_video], true);
109076         }
109077     },
109078
109079     play: function (repeatTimes) {
109080         utils.validateNumberOfArguments(1, 1, arguments.length,
109081             ExceptionTypes.INVALID_PARAMETER, "invalid number of arguments (expected one)", new Exception());
109082
109083         if (typeof repeatTimes !== "number" || repeatTimes < 0) {
109084             exception.raise(ExceptionTypes.INVALID_PARAMETER, "VideoPlayer.play was passed an invalid number of play times: " + repeatTimes, new Exception());
109085         }
109086         if (repeatTimes !== 0) {
109087             if (!_video) {
109088                 return;
109089             }
109090             _loopCount = repeatTimes;
109091             _validateAndSet(_STATES.PLAYING, [_STATES.OPENED, _STATES.STOPPED, _STATES.COMPLETED], function () {
109092                 _video.play();
109093             });
109094         }
109095     },
109096
109097     pause: function () {
109098         if (!_video) {
109099             return;
109100         }
109101         _validateAndSet(_STATES.PAUSED, [_STATES.PLAYING], function () {
109102             _video.pause();
109103         });
109104     },
109105
109106     resume: function () {
109107         if (!_video) {
109108             return;
109109         }
109110         _validateAndSet(_STATES.PLAYING, [_STATES.PAUSED], function () {
109111             _video.play();
109112         });
109113     },
109114
109115     stop: function () {
109116         if (!_video) {
109117             return;
109118         }
109119         _validateAndSet(_STATES.STOPPED, [_STATES.PAUSED, _STATES.PLAYING], function () {
109120             _video.pause();
109121             _video.setAttribute("src", _currentVideoFile); // hack
109122         });
109123     }
109124
109125 };
109126
109127 });
109128 define('ripple/platform/wac/1.0/Widget', function (require, exports, module) {
109129 /*
109130  *  Copyright 2011 Research In Motion Limited.
109131  *
109132  * Licensed under the Apache License, Version 2.0 (the "License");
109133  * you may not use this file except in compliance with the License.
109134  * You may obtain a copy of the License at
109135  *
109136  * http://www.apache.org/licenses/LICENSE-2.0
109137  *
109138  * Unless required by applicable law or agreed to in writing, software
109139  * distributed under the License is distributed on an "AS IS" BASIS,
109140  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
109141  * See the License for the specific language governing permissions and
109142  * limitations under the License.
109143  */
109144 var event = require('ripple/event'),
109145     _console = require('ripple/console'),
109146     app = require('ripple/app'),
109147     platform = require('ripple/platform'),
109148     exception = require('ripple/exception'),
109149     ExceptionTypes = require('ripple/platform/wac/1.0/ExceptionTypes'),
109150     Exception = require('ripple/platform/wac/1.0/Exception'),
109151     utils = require('ripple/utils'),
109152     db = require('ripple/db'),
109153     _self;
109154
109155 event.on("ScreenChangeDimensions", function (height, width) {
109156     try {
109157         // TODO: are these per spec to call?
109158         if (typeof app.onMaximize === 'function') {
109159             app.onMaximize();
109160         }
109161         if (typeof app.onRestore === 'function') {
109162             app.onRestore();
109163         }
109164         _console.log("called Widget.onRestore and Widget.onMaximize callback function");
109165     }
109166     catch (e) {
109167         exception.handle(e, false);
109168     }
109169 });
109170
109171 event.on("WidgetWakeup", function () {
109172     if (_self.onWakeup) {
109173         _self.onWakeup();
109174     }
109175 });
109176
109177 event.on("WidgetMaximize", function () {
109178     if (_self.onMaximize) {
109179         _self.onMaximize();
109180     }
109181 });
109182
109183 event.on("WidgetFocus", function () {
109184     if (_self.onFocus) {
109185         _self.onFocus();
109186     }
109187 });
109188
109189 event.on("WidgetRestore", function () {
109190     if (_self.onRestore) {
109191         _self.onRestore();
109192     }
109193 });
109194
109195 _self = {
109196     onWakeup: undefined,
109197     onMaximize: undefined,
109198     onFocus: undefined,
109199     onRestore: undefined,
109200
109201     openURL: function (url) {
109202         window.open(url);
109203     },
109204
109205     setPreferenceForKey: function (value, key) {
109206
109207         utils.validateNumberOfArguments(1, 2, arguments.length, ExceptionTypes.INVALID_PARAMETER, "setPreferenceForKey invalid number of paramters", new Exception());
109208         utils.validateArgumentType(key, "string", ExceptionTypes.INVALID_PARAMETER, "setPreferenceForKey invalid parameter! Key:" +
109209             key + ", Value: " + value, new Exception());
109210
109211         var msg = "",
109212             prefix;
109213         if (app.isPreferenceReadOnly(key)) {
109214             msg += "Cannot modify a read only preference. Preference key: " + key;
109215         }
109216         else {
109217             prefix = platform.getPersistencePrefix();
109218             if (value === null) {
109219                 msg += "deleting preference " + key;
109220                 db.remove(key, prefix);
109221             }
109222             else {
109223                 msg += "setting preference " + key + " == " + value;
109224                 utils.validateArgumentType(value, "string", ExceptionTypes.INVALID_PARAMETER, msg, new Exception());
109225                 db.save(key, value, prefix);
109226             }
109227         }
109228
109229
109230         _console.log(msg);
109231
109232         // Trigger storageUpdatedEvent
109233         event.trigger("StorageUpdatedEvent");
109234
109235     },
109236
109237     // return value or undefined
109238     preferenceForKey: function (key) {
109239
109240         utils.validateNumberOfArguments(1, 1, arguments.length, ExceptionTypes.INVALID_PARAMETER, "preferenceForKey invalid number of parameters", new Exception());
109241         utils.validateArgumentType(key, "string", ExceptionTypes.INVALID_PARAMETER, "preferenceForKey invalid paramters", new Exception());
109242
109243         var prefix = platform.getPersistencePrefix(),
109244             value = db.retrieve(key, prefix);
109245
109246         if (!value && value !== "") {
109247             value = undefined;
109248         }
109249
109250         _console.log("retrieving preference " + key + " == " + value);
109251
109252         return value;
109253
109254     }
109255 };
109256
109257 module.exports = _self;
109258
109259 });
109260 define('ripple/platform/wac/1.0/WidgetManager', function (require, exports, module) {
109261 /*
109262  *  Copyright 2011 Research In Motion Limited.
109263  *
109264  * Licensed under the Apache License, Version 2.0 (the "License");
109265  * you may not use this file except in compliance with the License.
109266  * You may obtain a copy of the License at
109267  *
109268  * http://www.apache.org/licenses/LICENSE-2.0
109269  *
109270  * Unless required by applicable law or agreed to in writing, software
109271  * distributed under the License is distributed on an "AS IS" BASIS,
109272  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
109273  * See the License for the specific language governing permissions and
109274  * limitations under the License.
109275  */
109276 var exception = require('ripple/exception'),
109277     ExceptionTypes = require('ripple/platform/wac/1.0/ExceptionTypes'),
109278     Exception = require('ripple/platform/wac/1.0/Exception');
109279
109280 module.exports = {
109281     // This method is used to check the installation status of a specific widget.
109282     checkWidgetInstallationStatus: function () {
109283
109284         exception.raise(ExceptionTypes.UNSUPPORTED, "WidgetManager.checkWidgetInstallationStatus not supported", new Exception());
109285     }
109286 };
109287
109288 });
109289 define('ripple/platform/wac/1.0/spec/config', function (require, exports, module) {
109290 /*
109291  *  Copyright 2011 Research In Motion Limited.
109292  *
109293  * Licensed under the Apache License, Version 2.0 (the "License");
109294  * you may not use this file except in compliance with the License.
109295  * You may obtain a copy of the License at
109296  *
109297  * http://www.apache.org/licenses/LICENSE-2.0
109298  *
109299  * Unless required by applicable law or agreed to in writing, software
109300  * distributed under the License is distributed on an "AS IS" BASIS,
109301  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
109302  * See the License for the specific language governing permissions and
109303  * limitations under the License.
109304  */
109305 var platform = require('ripple/platform'),
109306     utils = require('ripple/utils'),
109307     db = require('ripple/db'),
109308     constants = require('ripple/constants');
109309
109310 module.exports = {
109311     fileName: "config.xml",
109312     validateVersion: function (configValidationObject) {
109313         var valid = true;
109314         valid = !((!configValidationObject.widget.validationResult[0].attributes.xmlns.valid) ||
109315             (!configValidationObject.widget.validationResult[0].attributes["xmlns:JIL"].valid));
109316
109317         return valid;
109318     },
109319     extractInfo: function (configValidationObject) {
109320         if (!configValidationObject) {
109321             return null;
109322         }
109323
109324         var widgetInfo = {},
109325             configFeatures,
109326             configPreferences,
109327             preferenceName,
109328             platform;
109329
109330         widgetInfo.id = configValidationObject.widget.validationResult[0].attributes.id.value || "";
109331         widgetInfo.name = configValidationObject.widget.children.name.validationResult[0].value;
109332         widgetInfo.icon = configValidationObject.widget.children.icon.validationResult[0].attributes.src.value;
109333         widgetInfo.version = configValidationObject.widget.validationResult[0].attributes.version.value;
109334
109335         widgetInfo.features = {};
109336
109337         configFeatures = configValidationObject.widget.children.feature.validationResult;
109338         utils.forEach(configFeatures, function (f) {
109339             if (f.valid === true) {
109340                 var feature = {id: f.attributes.name.value,
109341                          required: f.attributes.required.valid};
109342                 widgetInfo.features[feature.id] = feature;
109343             }
109344         });
109345
109346         widgetInfo.preferences = {};
109347
109348         configPreferences = configValidationObject.widget.children.preference.validationResult;
109349
109350         platform = require('ripple/platform');
109351         utils.forEach(configPreferences, function (preference) {
109352             preferenceName = preference.attributes.name.value;
109353             if (preferenceName) {
109354                 widgetInfo.preferences[preferenceName] = {
109355                     "key": preferenceName,
109356                     "value": preference.attributes.value.value || "",
109357                     "readonly": preference.attributes.readonly.value === "true"
109358                 };
109359
109360                 db.save(preferenceName,
109361                         widgetInfo.preferences[preferenceName].value,
109362                         platform.getPersistencePrefix(widgetInfo.id));
109363             }
109364         });
109365
109366         return widgetInfo;
109367     },
109368     schema: {
109369         rootElement: "widget",
109370         widget: {
109371             nodeName: "widget",
109372             required: true,
109373             occurrence: 1,
109374             helpText: "\"widget\" element describes widget information in configuration documents and serves as a container for other elements. It must be used in configuration document and may have following child elments: name,description,icon,author,license,content,maximum_display_mode,update,feature,access,billing. \"widget\" element MAY have following attributes: id,version,height,width,xml:lang",
109375             attributes: {
109376                 xmlns: {
109377                     attributeName: "xmlns",
109378                     required: true,
109379                     type: "list",
109380                     listValues: ["http://www.w3.org/ns/widgets"]
109381                 },
109382                 "xmlns:JIL": {
109383                     attributeName: "xmlns:JIL",
109384                     required: true,
109385                     type: "list",
109386                     listValues: ["http://www.jil.org/ns/widgets1.2"]
109387                 },
109388                 "xmlns:its": {
109389                     attributeName: "xmlns:its",
109390                     helpText: "Indicates Text Directionality can be used. According to W3C spec, this feature is at risk, therefore we don't currently validate this.",
109391                     required: false,
109392                     type: "string"
109393                 },
109394                 id: {
109395                     attributeName: "id",
109396                     required: true,
109397                     type: "string"
109398                 },
109399                 version: {
109400                     attributeName: "version",
109401                     helpText: "Version must be in the following format: jil-rec-version-tag = major-version \".\" minor-version [\".\" version-desc]",
109402                     required: true,
109403                     type: "regex",
109404                     regex: /^\d{1,2}\.\d{1,2}(\.[A-Za-z0-9]{1,10})?$/
109405                 },
109406                 height: {
109407                     attributeName: "height",
109408                     required: true,
109409                     type: "integer"
109410                 },
109411                 width: {
109412                     attributeName: "width",
109413                     required: true,
109414                     type: "integer"
109415                 },
109416                 viewmodes: {
109417                     attributeName: "viewmodes",
109418                     required: false,
109419                     type: "list",
109420                     listValues: ["floating", "fullscreen"]
109421                 },
109422                 "xml:lang": {
109423                     attributeName: "xml:lang",
109424                     required: false,
109425                     type: "iso-language"
109426                 }
109427             },
109428             children: {
109429                 preference: {
109430                     nodeName: "preference",
109431                     required: false,
109432                     occurrence: 0,
109433                     attributes: {
109434                         name: {
109435                             attributeName: "name",
109436                             type: "string",
109437                             required: true
109438                         },
109439                         value: {
109440                             type: "string",
109441                             attributeName: "value",
109442                             required: false
109443                         },
109444                         readonly: {
109445                             attributeName: "readonly",
109446                             type: "boolean",
109447                             required: false
109448                         }
109449                     }
109450                 },
109451                 name: {
109452                     nodeName: "name",
109453                     required: false,
109454                     occurrence: 0,
109455                     type: "string",
109456                     attributes: {
109457                         "short": {
109458                             attributeName: "short",
109459                             type: "string",
109460                             required: false
109461                         },
109462                         "xml:lang": {
109463                             attributeName: "xml:lang",
109464                             type: "string",
109465                             required: false,
109466                             unique: true
109467                         }
109468                     }
109469                 },
109470                 description: {
109471                     nodeName: "description",
109472                     required: false,
109473                     occurrence: 0,
109474                     type: "string",
109475                     attributes: {
109476                         "xml:lang": {
109477                             attributeName: "xml:lang",
109478                             type: "string",
109479                             required: false,
109480                             unique: true
109481                         }
109482                     }
109483                 },
109484                 icon: {
109485                     nodeName: "icon",
109486                     required: false,
109487                     occurrence: 0,
109488                     attributes: {
109489                         src: {
109490                             attributeName: "src",
109491                             type: "string",
109492                             required: true
109493                         },
109494                         height: {
109495                             attributeName: "height",
109496                             required: false,
109497                             type: "integer"
109498                         },
109499                         width: {
109500                             attributeName: "width",
109501                             required: false,
109502                             type: "integer"
109503                         },
109504                         "xml:lang": {
109505                             attributeName: "xml:lang",
109506                             type: "string",
109507                             required: false,
109508                             unique: true
109509                         }
109510                     }
109511                 },
109512                 author: {
109513                     nodeName: "author",
109514                     required: false,
109515                     occurrence: 1,
109516                     type: "string",
109517                     attributes: {
109518                         email: {
109519                             attributeName: "email",
109520                             type: "regex",
109521                             required: false,
109522                             regex: constants.REGEX.EMAIL
109523                         },
109524                         href: {
109525                             attributeName: "href",
109526                             type: "regex",
109527                             required: false,
109528                             regex: constants.REGEX.URL
109529                         },
109530                         "xml:lang": {
109531                             attributeName: "xml:lang",
109532                             type: "string",
109533                             required: false,
109534                             unique: true
109535                         }
109536                     }
109537                 },
109538                 license: {
109539                     nodeName: "license",
109540                     required: false,
109541                     occurrence: 1,
109542                     type: "string",
109543                     attributes: {
109544                         href: {
109545                             attributeName: "href",
109546                             type: "regex",
109547                             required: false,
109548                             regex: constants.REGEX.URL
109549                         },
109550                         "xml:lang": {
109551                             attributeName: "xml:lang",
109552                             type: "string",
109553                             required: false,
109554                             unique: true
109555                         }
109556                     }
109557                 },
109558                 content: {
109559                     nodeName: "content",
109560                     required: false,
109561                     occurrence: 1,
109562                     attributes: {
109563                         src: {
109564                             attributeName: "src",
109565                             type: "string",
109566                             required: true
109567                         },
109568                         encoding: {
109569                             attributeName: "encoding",
109570                             type: "string",
109571                             required: false
109572                         },
109573                         type: {
109574                             attributeName: "type",
109575                             type: "string",
109576                             required: false
109577                         }
109578                     }
109579                 },
109580                 feature: {
109581                     nodeName: "feature",
109582                     required: false,
109583                     occurrence: 0,
109584                     attributes: {
109585                         name: {
109586                             attributeName: "name",
109587                             type: "list",
109588                             required: true,
109589                             listValues: ["http://jil.org/jil/api/1.1/widget", "http://jil.org/jil/api/1.1.5/exception",
109590                                             "http://jil.org/jil/api/1.1.5/exceptiontypes", "http://jil.org/jil/api/1.1/device",
109591                                             "http://jil.org/jil/api/1.1/accountinfo", "http://jil.org/jil/api/1.1/deviceinfo",
109592                                             "http://jil.org/jil/api/1.1.1/datanetworkinfo", "http://jil.org/jil/api/1.1/devicestateinfo",
109593                                             "http://jil.org/jil/api/1.1/accelerometerinfo", "http://jil.org/jil/api/1.1/config",
109594                                             "http://jil.org/jil/api/1.1.1/file", "http://jil.org/jil/api/1.1/positioninfo",
109595                                             "http://jil.org/jil/api/1.1/powerinfo", "http://jil.org/jil/api/1.1.1/radioinfo",
109596                                             "http://jil.org/jil/api/1.1.5/radiosignalsourcetypes", "http://jil.org/jil/api/1.1.5/applicationtypes",
109597                                             "http://jil.org/jil/api/1.1/messaging", "http://jil.org/jil/api/1.1/account",
109598                                             "http://jil.org/jil/api/1.1/attachment", "http://jil.org/jil/api/1.1/message",
109599                                             "http://jil.org/jil/api/1.1.4/messagefoldertypes", "http://jil.org/jil/api/1.1/messagequantities",
109600                                             "http://jil.org/jil/api/1.1/messagetypes", "http://jil.org/jil/api/1.1/multimedia",
109601                                             "http://jil.org/jil/api/1.1/audioplayer", "http://jil.org/jil/api/1.1.2/camera",
109602                                             "http://jil.org/jil/api/1.1.2/videoplayer", "http://jil.org/jil/api/1.1.1/pim",
109603                                             "http://jil.org/jil/api/1.1/addressbookitem", "http://jil.org/jil/api/1.1/calendaritem",
109604                                             "http://jil.org/jil/api/1.1/eventrecurrencetypes", "http://jil.org/jil/api/1.1.1/telephony",
109605                                             "http://jil.org/jil/api/1.1/callrecord", "http://jil.org/jil/api/1.1.1/callrecordtypes",
109606                                             "http://jil.org/jil/api/1.1.1/widgetmanager"]
109607                         },
109608                         required: {
109609                             attributeName: "required",
109610                             type: "boolean",
109611                             required: false
109612                         }
109613                     }
109614                 },
109615                 "JIL:maximum_display_mode": {
109616                     nodeName: "JIL:maximum_display_mode",
109617                     required: false,
109618                     occurrence: 1,
109619                     attributes: {
109620                         height: {
109621                             attributeName: "height",
109622                             type: "integer",
109623                             required: false
109624                         },
109625                         width: {
109626                             attributeName: "width",
109627                             type: "integer",
109628                             required: false
109629                         }
109630                     }
109631                 },
109632                 "JIL:update": {
109633                     nodeName: "JIL:update",
109634                     required: false,
109635                     occurrence: 1,
109636                     attributes: {
109637                         href: {
109638                             attributeName: "href",
109639                             type: "regex",
109640                             required: true,
109641                             regex: constants.REGEX.URL
109642                         },
109643                         period: {
109644                             attributeName: "period",
109645                             helpText: "Possible values for the period attribute are: 0, 1, 2, 3 meaning: every time the widget is opened in maximum display mode, every day, every week, every month; respectivly",
109646                             type: "list",
109647                             required: true,
109648                             listValues: ["0", "1", "2", "3"]
109649                         }
109650                     }
109651                 },
109652                 "JIL:access": {
109653                     nodeName: "JIL:access",
109654                     required: false,
109655                     occurrence: 1,
109656                     attributes: {
109657                         network: {
109658                             attributeName: "network",
109659                             type: "boolean",
109660                             required: false
109661                         },
109662                         localfs: {
109663                             attributeName: "localfs",
109664                             type: "boolean",
109665                             required: false
109666                         },
109667                         remote_scripts: {
109668                             attributeName: "remote_scripts",
109669                             type: "boolean",
109670                             required: false
109671                         }
109672                     }
109673                 },
109674                 "JIL:billing": {
109675                     nodeName: "JIL:billing",
109676                     required: false,
109677                     occurrence: 1,
109678                     attributes: {
109679                         required: {
109680                             attributeName: "required",
109681                             type: "boolean",
109682                             required: true
109683                         }
109684                     }
109685                 }
109686             }
109687         }
109688     }
109689 };
109690
109691 });
109692 define('ripple/platform/wac/1.0/spec/device', function (require, exports, module) {
109693 /*
109694  *  Copyright 2011 Research In Motion Limited.
109695  *
109696  * Licensed under the Apache License, Version 2.0 (the "License");
109697  * you may not use this file except in compliance with the License.
109698  * You may obtain a copy of the License at
109699  *
109700  * http://www.apache.org/licenses/LICENSE-2.0
109701  *
109702  * Unless required by applicable law or agreed to in writing, software
109703  * distributed under the License is distributed on an "AS IS" BASIS,
109704  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
109705  * See the License for the specific language governing permissions and
109706  * limitations under the License.
109707  */
109708 var constants = require('ripple/constants'),
109709     event = require('ripple/event');
109710
109711 module.exports = {
109712     "AccountInfo": {
109713         "phoneUserUniqueId": {
109714             "name": "User Unique Id",
109715             "control": {
109716                 "type": "text",
109717                 "value": new Date().getTime().toString()
109718             }
109719         },
109720         "phoneMSISDN":  {
109721             "name": "MSISDN",
109722             "control": {
109723                 "type": "text",
109724                 "value": "15199999999"
109725             }
109726         },
109727         "phoneOperatorName":  {
109728             "name": "Operator Name",
109729             "control": {
109730                 "type": "text",
109731                 "value": ""
109732             }
109733         },
109734         "userAccountBalance":  {
109735             "name": "Account Balance",
109736             "control": {
109737                 "type": "number",
109738                 "value": 0
109739             }
109740         },
109741         "userSubscriptionType":  {
109742             "name": "Subscription Type",
109743             "control": {
109744                 "type": "select",
109745                 "value": "other"
109746             },
109747             "options": {
109748                 "other": "other",
109749                 "prepaid": "prepaid",
109750                 "postpaid": "postpaid"
109751             }
109752         }
109753     },
109754     "RadioInfo": {
109755         "isRoaming": {
109756             "name": "Is Roaming",
109757             "control": {
109758                 "type": "checkbox",
109759                 "value": false
109760             },
109761             "callback": function () {
109762                 event.trigger("RadioSignalSourceChanged");
109763             }
109764         },
109765         "isRadioEnabled":  {
109766             "name": "Is Radio Enabled",
109767             "control": {
109768                 "type": "checkbox",
109769                 "value": true
109770             }
109771         },
109772         "radioSignalSource": {
109773             "name": "Radio Signal Source",
109774             "control": {
109775                 "type": "select",
109776                 "value": "GSM"
109777             },
109778             // TODO: try not to duplicate from RadioSignalSourceTypes
109779             "options": {
109780                 "CDMA": "cdma",
109781                 "GSM": "gsm",
109782                 "LTE": "lte",
109783                 "TDSCDMA": "tdscdma",
109784                 "WCDMA": "wcdma"
109785             },
109786             "callback": function () {
109787                 event.trigger("RadioSignalSourceChanged");
109788             }
109789         },
109790         "radioSignalStrengthPercent": {
109791             "name": "Signal Strength %",
109792             "control": {
109793                 "type": "select",
109794                 "value": 80
109795             },
109796             "options": (function () {
109797                 var i,
109798                     optionList = {};
109799
109800                 for (i = 0; i <= 100; i++) {
109801                     optionList[i] = i;
109802                 }
109803
109804                 return optionList;
109805             }())
109806         }
109807     },
109808     "Config": {
109809         "ringtoneVolume": {
109810             "name": "Ringtone Volume",
109811             "control": {
109812                 "type": "select",
109813                 "value": 10
109814             },
109815             "options": (function () {
109816                 var i,
109817                     optionList = {};
109818
109819                 for (i = 0; i <= 10; i++) {
109820                     optionList[i] = i;
109821                 }
109822
109823                 return optionList;
109824             }())
109825         },
109826         "msgRingtoneVolume":  {
109827             "name": "Msg Ringtone Volume",
109828             "control": {
109829                 "type": "select",
109830                 "value": 10
109831             },
109832             "options": (function () {
109833                 var i,
109834                     optionList = {};
109835
109836                 for (i = 0; i <= 10; i++) {
109837                     optionList[i] = i;
109838                 }
109839
109840                 return optionList;
109841             }())
109842         },
109843         "vibrationSetting":  {
109844             "name": "Vibration",
109845             "control": {
109846                 "type": "select",
109847                 "value": "off"
109848             },
109849             "options": {
109850                 "on": "ON",
109851                 "off": "OFF"
109852             }
109853         }
109854     },
109855     "Account": {
109856         "accountName":  {
109857             "name": "Name",
109858             "control": {
109859                 "type": "text",
109860                 "value": ""
109861             }
109862         },
109863         "accountId":  {
109864             "name": "Id",
109865             "control": {
109866                 "type": "text",
109867                 "value": ""
109868             }
109869         }
109870     },
109871     "DeviceInfo": {
109872         "totalMemory": {
109873             "name": "Total Memory",
109874             "control": {
109875                 "type": "range",
109876                 "value": 262144,
109877                 "min": 0,
109878                 "max": 4096000
109879             }
109880         },
109881         "phoneColorDepthDefault": {
109882             "name": "Color Depth",
109883             "control": {
109884                 "type": "number",
109885                 "value": 24
109886             }
109887         }
109888     },
109889     "DeviceStateInfo": {
109890         "availableMemory": {
109891             "name": "Available Memory",
109892             "control": {
109893                 "type": "range",
109894                 "value": 262144,
109895                 "min": 0,
109896                 "max": 4096000
109897             }
109898         },
109899         "keypadLightOn":   {
109900             "name": "Keypad Light On",
109901             "control": {
109902                 "type": "checkbox",
109903                 "value": false
109904             }
109905         },
109906         "backLightOn": {
109907             "name": "Back Light On",
109908             "control": {
109909                 "type": "checkbox",
109910                 "value": false
109911             }
109912         },
109913         "audioPath":  {
109914             "name": "Audio Path",
109915             "control": {
109916                 "type": "select",
109917                 "value": "receiver"
109918             },
109919             "options": {
109920                 "speaker": "speaker",
109921                 "receiver": "receiver",
109922                 "earphone": "earphone"
109923             }
109924         },
109925         "processorUtilizationPercent":  {
109926             "name": "CPU Utilization %",
109927             "control": {
109928                 "type": "select",
109929                 "value": "5"
109930             },
109931             "options": (function () {
109932                 var i,
109933                     optionList = {};
109934
109935                 for (i = 0; i <= 100; i++) {
109936                     optionList[i] = i;
109937                 }
109938
109939                 return optionList;
109940             }())
109941         },
109942         "language":  {
109943             "name": "Language",
109944             "control": {
109945                 "type": "select",
109946                 "value": "eng"
109947             },
109948             "options": (function () {
109949                 var i,
109950                     optionList = {},
109951                     iterator = constants.LANG.ISO6392_LIST;
109952
109953                 for (i = 0; i <= iterator.length; i++) {
109954                     optionList[iterator[i]] = iterator[i];
109955                 }
109956
109957                 return optionList;
109958             }())
109959         }
109960     },
109961     "DataNetworkInfo": {
109962         "isDataNetworkConnected": {
109963             "name": "Data Network Is Connected",
109964             "control": {
109965                 "type": "checkbox",
109966                 "value": true
109967             }
109968         },
109969         "networkConnectionType": {
109970             "name": "Network Connection Type",
109971             "control": {
109972                 "type": "select",
109973                 "value": ["GPRS"]
109974             },
109975             // TODO: try not to duplicate from DataNetworkConnectionTypes
109976             "options": {
109977                 "BLUETOOTH": "bluetooth",
109978                 "EDGE": "edge",
109979                 "EVDO": "evdo",
109980                 "GPRS": "gprs",
109981                 "IRDA": "irda",
109982                 "LTE": "lte",
109983                 "ONEXRTT": "1xrtt",
109984                 "WIFI": "wifi"
109985             },
109986             "callback": function (setting) {
109987                 event.trigger("DataNetworkConnectionChanged", [setting]);
109988             }
109989         }
109990     },
109991     "PowerInfo": {
109992         "isCharging": {
109993             "name": "Battery Is Charging",
109994             "control": {
109995                 "type": "checkbox",
109996                 "value": true
109997             },
109998             "callback": function (setting) {
109999                 event.trigger("DeviceBatteryStateChanged", [setting]);
110000             }
110001         },
110002         "percentRemaining":  {
110003             "name": "Battery Remaining %",
110004             "control": {
110005                 "type": "select",
110006                 "value": 100
110007             },
110008             "options": (function () {
110009                 var i,
110010                     optionList = {};
110011
110012                 for (i = 0; i <= 100; i++) {
110013                     optionList[i] = i;
110014                 }
110015
110016                 return optionList;
110017             }()),
110018             "callback": function (setting) {
110019                 event.trigger("DeviceBatteryLevelChanged", [setting]);
110020             }
110021         }
110022     }
110023 };
110024
110025 });
110026 define('ripple/platform/wac/1.0/spec/events', function (require, exports, module) {
110027 /*
110028  *  Copyright 2011 Research In Motion Limited.
110029  *
110030  * Licensed under the Apache License, Version 2.0 (the "License");
110031  * you may not use this file except in compliance with the License.
110032  * You may obtain a copy of the License at
110033  *
110034  * http://www.apache.org/licenses/LICENSE-2.0
110035  *
110036  * Unless required by applicable law or agreed to in writing, software
110037  * distributed under the License is distributed on an "AS IS" BASIS,
110038  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
110039  * implied.
110040  * See the License for the specific language governing permissions and
110041  * limitations under the License.
110042  */
110043
110044 var event = require('ripple/event');
110045
110046 module.exports = {
110047     "WidgetWakeup": {
110048         callback: function () {
110049             event.trigger("WidgetWakeup");
110050         }
110051     },
110052     "WidgetMaximize": {
110053         callback: function () {
110054             event.trigger("WidgetMaximize");
110055         }
110056     },
110057     "WidgetFocus": {
110058         callback: function () {
110059             event.trigger("WidgetFocus");
110060         }
110061     },
110062     "WidgetRestore": {
110063         callback: function () {
110064             event.trigger("WidgetRestore");
110065         }
110066     }
110067 };
110068
110069 });
110070 define('ripple/platform/wac/1.0/spec/ui', function (require, exports, module) {
110071 /*
110072  *  Copyright 2011 Research In Motion Limited.
110073  *
110074  * Licensed under the Apache License, Version 2.0 (the "License");
110075  * you may not use this file except in compliance with the License.
110076  * You may obtain a copy of the License at
110077  *
110078  * http://www.apache.org/licenses/LICENSE-2.0
110079  *
110080  * Unless required by applicable law or agreed to in writing, software
110081  * distributed under the License is distributed on an "AS IS" BASIS,
110082  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
110083  * See the License for the specific language governing permissions and
110084  * limitations under the License.
110085  */
110086 module.exports = {
110087     plugins: [
110088         "accelerometer",
110089         //"deviceSettings",
110090         "fileSystem",
110091         "geoView",
110092 /*
110093         "multimedia",
110094         "audioPlayer",
110095         "telephony",
110096 */
110097         "platformEvents",
110098         "storage",
110099         "widgetConfig"
110100     ]
110101 };
110102
110103 });
110104 define('ripple/platform/wac/1.0/spec', function (require, exports, module) {
110105 module.exports = {
110106
110107     id: "wac",
110108     version: "1.0",
110109     name: "WAC",
110110     type: "plaform",
110111
110112     persistencePrefix: "wac-",
110113
110114     config: require('ripple/platform/wac/1.0/spec/config'),
110115     device: require('ripple/platform/wac/1.0/spec/device'),
110116     ui: require('ripple/platform/wac/1.0/spec/ui'),
110117     events: require('ripple/platform/wac/1.0/spec/events'),
110118
110119     objects: {
110120         navigator: {
110121             path: "w3c/1.0/navigator"
110122         },
110123         WidgetManager: {
110124             path: "wac/1.0/WidgetManager",
110125             feature: "http://jil.org/jil/api/1.1.1/widgetmanager"
110126         },
110127         Widget: {
110128             path: "wac/1.0/Widget",
110129             feature: "http://jil.org/jil/api/1.1/widget",
110130             children: {
110131                 Device: {
110132                     path: "wac/1.0/Device",
110133                     feature: "http://jil.org/jil/api/1.1/device",
110134                     children: {
110135                         AccountInfo: {
110136                             path: "wac/1.0/AccountInfo",
110137                             feature: "http://jil.org/jil/api/1.1/accountinfo"
110138                         },
110139                         ApplicationTypes: {
110140                             path: "wac/1.0/ApplicationTypes",
110141                             feature: "http://jil.org/jil/api/1.1.5/applicationtypes"
110142                         },
110143                         DataNetworkInfo: {
110144                             path: "wac/1.0/DataNetworkInfo",
110145                             feature: "http://jil.org/jil/api/1.1.1/datanetworkinfo",
110146                             children: {
110147                                 DataNetworkConnectionTypes: {
110148                                     path: "wac/1.0/DataNetworkConnectionTypes"
110149                                 }
110150                             }
110151                         },
110152                         DeviceInfo: {
110153                             path: "wac/1.0/DeviceInfo",
110154                             feature: "http://jil.org/jil/api/1.1/deviceinfo"
110155                         },
110156                         DeviceStateInfo: {
110157                             path: "wac/1.0/DeviceStateInfo",
110158                             feature: "http://jil.org/jil/api/1.1/devicestateinfo",
110159                             children: {
110160                                 Config: {
110161                                     path: "wac/1.0/Config",
110162                                     feature: "http://jil.org/jil/api/1.1/config"
110163                                 },
110164                                 AccelerometerInfo: {
110165                                     path: "wac/1.0/AccelerometerInfo",
110166                                     feature: "http://jil.org/jil/api/1.1/accelerometerinfo"
110167                                 }
110168                             }
110169                         },
110170                         File: {
110171                             path: "wac/1.0/File",
110172                             feature: "http://jil.org/jil/api/1.1.1/file"
110173                         },
110174                         PositionInfo: {
110175                             path: "wac/1.0/PositionInfo",
110176                             feature: "http://jil.org/jil/api/1.1/positioninfo"
110177                         },
110178                         RadioInfo: {
110179                             path: "wac/1.0/RadioInfo",
110180                             feature: "http://jil.org/jil/api/1.1.1/radioinfo",
110181                             children: {
110182                                 RadioSignalSourceTypes: {
110183                                     path: "wac/1.0/RadioSignalSourceTypes",
110184                                     feature: "http://jil.org/jil/api/1.1.5/radiosignalsourcetypes"
110185                                 }
110186                             }
110187                         },
110188                         PowerInfo: {
110189                             path: "wac/1.0/PowerInfo",
110190                             feature: "http://jil.org/jil/api/1.1/powerinfo"
110191                         }
110192                     }
110193                 },
110194                 ExceptionTypes: {
110195                     path: "wac/1.0/ExceptionTypes",
110196                     feature: "http://jil.org/jil/api/1.1.5/exceptiontypes"
110197                 },
110198                 Exception: {
110199                     path: "wac/1.0/Exception",
110200                     feature: "http://jil.org/jil/api/1.1.5/exception"
110201                 },
110202                 Multimedia: {
110203                     path: "wac/1.0/Multimedia",
110204                     feature: "http://jil.org/jil/api/1.1/multimedia",
110205                     children: {
110206                         Camera: {
110207                             path: "wac/1.0/Camera",
110208                             feature: "http://jil.org/jil/api/1.1.2/camera"
110209                         },
110210                         AudioPlayer: {
110211                             path: "wac/1.0/AudioPlayer",
110212                             feature: "http://jil.org/jil/api/1.1/audioplayer"
110213                         },
110214                         VideoPlayer: {
110215                             path: "wac/1.0/VideoPlayer",
110216                             feature: "http://jil.org/jil/api/1.1.2/videoplayer"
110217                         }
110218                     }
110219                 },
110220                 Telephony: {
110221                     path: "wac/1.0/Telephony",
110222                     feature: "http://jil.org/jil/api/1.1.1/telephony",
110223                     children: {
110224                         CallRecord: {
110225                             path: "wac/1.0/CallRecord",
110226                             feature: "http://jil.org/jil/api/1.1/callrecord"
110227                         },
110228                         CallRecordTypes: {
110229                             path: "wac/1.0/CallRecordTypes",
110230                             feature: "http://jil.org/jil/api/1.1.1/callrecordtypes"
110231                         }
110232                     }
110233                 },
110234                 PIM: {
110235                     path: "wac/1.0/PIM",
110236                     feature: "http://jil.org/jil/api/1.1.1/pim",
110237                     children: {
110238                         AddressBookItem: {
110239                             path: "wac/1.0/AddressBookItem",
110240                             feature: "http://jil.org/jil/api/1.1/addressbookitem"
110241                         },
110242                         CalendarItem: {
110243                             path: "wac/1.0/CalendarItem",
110244                             feature: "http://jil.org/jil/api/1.1/calendaritem"
110245                         },
110246                         EventRecurrenceTypes: {
110247                             path: "wac/1.0/EventRecurrenceTypes",
110248                             feature: "http://jil.org/jil/api/1.1/eventrecurrencetypes"
110249                         }
110250                     }
110251                 },
110252                 Messaging: {
110253                     path: "wac/1.0/Messaging",
110254                     feature: "http://jil.org/jil/api/1.1/messaging",
110255                     children: {
110256                         Account: {
110257                             path: "wac/1.0/Account",
110258                             feature: "http://jil.org/jil/api/1.1/account"
110259                         },
110260                         Attachment: {
110261                             path: "wac/1.0/Attachment",
110262                             feature: "http://jil.org/jil/api/1.1/attachment"
110263                         },
110264                         Message: {
110265                             path: "wac/1.0/Message",
110266                             feature: "http://jil.org/jil/api/1.1/message"
110267                         },
110268                         MessageFolderTypes: {
110269                             path: "wac/1.0/MessageFolderTypes",
110270                             feature: "http://jil.org/jil/api/1.1.4/messagefoldertypes"
110271                         },
110272                         MessageQuantities: {
110273                             path: "wac/1.0/MessageQuantities",
110274                             feature: "http://jil.org/jil/api/1.1/messagequantities"
110275                         },
110276                         MessageTypes: {
110277                             path: "wac/1.0/MessageTypes",
110278                             feature: "http://jil.org/jil/api/1.1/messagetypes"
110279                         }
110280                     }
110281                 }
110282             }
110283         }
110284     }
110285
110286 };
110287
110288 });
110289 define('ripple/platform/wac/2.0/accelerometer', function (require, exports, module) {
110290 /*
110291  *  Copyright 2011 Intel Corporation.
110292  *
110293  * Licensed under the Apache License, Version 2.0 (the "License");
110294  * you may not use this file except in compliance with the License.
110295  * You may obtain a copy of the License at
110296  *
110297  * http://www.apache.org/licenses/LICENSE-2.0
110298  *
110299  * Unless required by applicable law or agreed to in writing, software
110300  * distributed under the License is distributed on an "AS IS" BASIS,
110301  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
110302  * See the License for the specific language governing permissions and
110303  * limitations under the License.
110304  */
110305
110306 var utils = require('ripple/utils'),
110307     event = require('ripple/event'),
110308     Acceleration = function (x, y, z) {
110309         return {
110310             xAxis: x || 0,
110311             yAxis: y || 0,
110312             zAxis: z || 0
110313         };
110314     },
110315     wac2_utils = require('ripple/platform/wac/2.0/wac2_utils'),
110316     _accelerometerInfo = new Acceleration(),
110317     _defaultInterval = 100,
110318     _watches = {},
110319     _self;
110320
110321 module.exports = _self = {
110322     getCurrentAcceleration: function (onSuccess, onError) {
110323         function _getCurrentAcceleration() {
110324             setTimeout(function () {
110325                 onSuccess(utils.copy(_accelerometerInfo));
110326             }, 1);
110327             return null;
110328         }
110329
110330         return wac2_utils.validateTypeMismatch(onSuccess, onError, "getCurrentAcceleration", _getCurrentAcceleration); 
110331     },
110332
110333     watchAcceleration: function (accelerometerSuccess, accelerometerError, options) {
110334         function _watchAcceleration() {
110335             var watchId = (new Date()).getTime() | 0,
110336                 watchObj = {},
110337                 opt = Object(options),
110338                 minNotificationInterval = opt.minNotificationInterval | 0,
110339                 accelerometerInterval = _defaultInterval;
110340
110341             if (minNotificationInterval > 0) {
110342                 accelerometerInterval = minNotificationInterval;
110343             }
110344
110345             watchObj = {
110346                 onSuccess: accelerometerSuccess,
110347                 onError: accelerometerError,
110348                 interval: accelerometerInterval
110349             };
110350
110351             _watches[watchId] = watchObj;
110352
110353             _watches[watchId].intervalId = setInterval(function () {
110354                 _self.getCurrentAcceleration(_watches[watchId].onSuccess, _watches[watchId].onError);
110355             }, _watches[watchId].interval);
110356
110357             return watchId;
110358         }
110359
110360         return wac2_utils.validateTypeMismatch(accelerometerSuccess, accelerometerError, "watchAcceleration", _watchAcceleration); 
110361     },
110362
110363     clearWatch: function (watchId) {
110364
110365         var id = watchId | 0;
110366
110367         if (_watches[id]) {
110368             clearInterval(_watches[id].intervalId);
110369             delete(_watches[id]);
110370             return null;
110371         }
110372
110373         return undefined;
110374     }
110375 };
110376
110377 event.on("AccelerometerInfoChangedEvent", function (accelerometerInfo) {
110378     _accelerometerInfo.xAxis = accelerometerInfo.accelerationIncludingGravity.x;
110379     _accelerometerInfo.yAxis = accelerometerInfo.accelerationIncludingGravity.y;
110380     _accelerometerInfo.zAxis = accelerometerInfo.accelerationIncludingGravity.z;
110381 });
110382
110383
110384 });
110385 define('ripple/platform/wac/2.0/calendar', function (require, exports, module) {
110386 /*
110387  *  Copyright 2011 Intel Corporation.
110388  *
110389  * Licensed under the Apache License, Version 2.0 (the "License");
110390  * you may not use this file except in compliance with the License.
110391  * You may obtain a copy of the License at
110392  *
110393  * http://www.apache.org/licenses/LICENSE-2.0
110394  *
110395  * Unless required by applicable law or agreed to in writing, software
110396  * distributed under the License is distributed on an "AS IS" BASIS,
110397  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
110398  * See the License for the specific language governing permissions and
110399  * limitations under the License.
110400  */
110401
110402 var db = require('ripple/db'),
110403     utils = require('ripple/utils'),
110404     exception = require('ripple/exception'),
110405     constants = require('ripple/constants'),
110406     errorcode = require('ripple/platform/wac/2.0/errorcode'),
110407     PendingOperation = require('ripple/platform/wac/2.0/pendingoperation'),
110408     PendingObject = require('ripple/platform/wac/2.0/pendingObject'),
110409     wac2_utils = require('ripple/platform/wac/2.0/wac2_utils'),
110410     _console = require('ripple/console'),
110411     DeviceApiError = require('ripple/platform/wac/2.0/deviceapierror'),
110412     _SIM_CALENDAR = 0, _DEVICE_CALENDAR = 1,
110413     _NO_RECURRENCE = 0, _DAILY_RECURRENCE = 1, _WEEKLY_RECURRENCE = 2,
110414     _MONTHLY_RECURRENCE = 3, _YEARLY_RECURRENCE = 4,
110415     _TENTATIVE_STATUS = 0, _CONFIRMED_STATUS = 1, _CANCELLED_STATUS = 2,
110416     _NO_ALARM = 0, _SILENT_ALARM = 1, _SOUND_ALARM = 2,
110417     _calendars = [], _DB_CALENDARS_KEY = "wac2-db-calendars",
110418     _FAKEWAITTIME = 5, _FAKE_LONG_WAITTIME = 10,
110419     _save_calendars, _eventPropCheck, _eventFilterCheck,
110420     _addEventAllowed = true, _deleteEventAllowed = true,
110421     _updateEventAllowed = true, _findEventsAllowed = true,
110422     CalendarEventProperties, Calendar, CalendarEvent;
110423
110424 _save_calendars = function (_name, _type, _events) {
110425     var i;
110426     for (i = 0; i < _calendars.length; i++) {
110427         if (_calendars[i].name === _name && _calendars[i].type === _type) {
110428             _calendars[i].events = _events;
110429             break;
110430         }
110431     }
110432     db.saveObject(_DB_CALENDARS_KEY, _calendars);
110433 };
110434
110435 _eventPropCheck = function (prop, dst) {
110436     var i;
110437     if (prop.description !== null && prop.description !== undefined) {
110438         dst.description = String(prop.description);
110439     }
110440     if (prop.summary !== null && prop.summary !== undefined) {
110441         dst.summary = String(prop.summary);
110442     } 
110443     if (prop.startTime !== null && prop.startTime !== undefined) {
110444         if (!wac2_utils.isValidDate(prop.startTime)) {
110445             return false;
110446         }
110447         dst.startTime = new Date(prop.startTime);
110448     }
110449     dst.duration = prop.duration | 0;
110450     if (prop.location !== null && prop.location !== undefined) {
110451         dst.location = String(prop.location);
110452     }
110453     if (prop.categories !== null && prop.categories !== undefined) {
110454         if (!wac2_utils.isValidArray(prop.categories))  {
110455             return false;
110456         }
110457         dst.categories = [];
110458         for (i = 0; i < prop.categories.length; i++) {
110459             dst.categories.push(String(prop.categories[i]));
110460         }
110461     }
110462     if (prop.recurrence !== null && prop.recurrence !== undefined) {
110463         if (prop.recurrence === _NO_RECURRENCE ||
110464             prop.recurrence === _DAILY_RECURRENCE ||
110465             prop.recurrence === _WEEKLY_RECURRENCE ||
110466             prop.recurrence === _MONTHLY_RECURRENCE ||
110467             prop.recurrence === _YEARLY_RECURRENCE) {
110468             dst.recurrence = prop.recurrence | 0;
110469         } else {
110470             return false;
110471         }
110472     }
110473     if (dst.recurrence === _NO_RECURRENCE) {
110474         dst.expires = null;
110475         dst.interval = null;
110476     } else {
110477         // expires and interval matters when recurrence is not NO_RECURRENCE
110478         if (prop.expires !== null && prop.expires !== undefined) {
110479             if (!wac2_utils.isValidDate(prop.expires)) {
110480                 return false;
110481             }
110482             dst.expires = new Date(prop.expires);
110483         }
110484         // expires === undefined -> to recur indefinitely
110485         // expires === null -> keep dst.expires unchanged, even it's null
110486         if (prop.expires === undefined) {
110487             dst.expires = null;
110488         }
110489         if (prop.interval !== null && prop.interval !== undefined) {
110490             dst.interval = prop.interval | 0;
110491         }
110492     }
110493
110494     if (prop.status !== null && prop.status !== undefined) {
110495         if (prop.status === _TENTATIVE_STATUS ||
110496             prop.status === _CONFIRMED_STATUS ||
110497             prop.status === _CANCELLED_STATUS) {
110498             dst.status = prop.status | 0;
110499         } else {
110500             return false;
110501         }
110502     }
110503
110504     if (prop.alarmType !== null && prop.alarmType !== undefined) {
110505         if (prop.alarmType === _NO_ALARM ||
110506             prop.alarmType === _SILENT_ALARM ||
110507             prop.alarmType === _SOUND_ALARM) {
110508             dst.alarmType = prop.alarmType;
110509         } else {
110510             return false;
110511         }
110512     } 
110513     if (dst.alarmType !== _NO_ALARM && prop.alarmTrigger !== undefined && prop.alarmTrigger !== undefined) {
110514         dst.alarmTrigger = prop.alarmTrigger | 0;
110515     }
110516 };
110517
110518 _eventFilterCheck = function (filter) {
110519     if (filter.id !== undefined && filter.id !== null) {
110520         filter.id = String(filter.id);
110521     } else {
110522         filter.id = undefined;
110523     }
110524     if (filter.summary !== undefined && filter.summary !== null) {
110525         filter.summary = String(filter.summary);
110526     } else {
110527         filter.summary = undefined;
110528     }
110529     if (filter.description !== undefined && filter.description !== null) {
110530         filter.description = String(filter.description);
110531     } else {
110532         filter.description = undefined;
110533     }
110534     if (filter.location !== undefined && filter.location !== null) {
110535         filter.location = String(filter.location);
110536     } else {
110537         filter.location = undefined;
110538     }
110539     if (filter.catetory !== undefined && filter.catetory !== null) {
110540         filter.catetory = String(filter.catetory);
110541     } else {
110542         filter.catetory = undefined;
110543     }
110544     if (filter.status !== undefined && filter.status !== null) {
110545         var i;
110546         if (!wac2_utils.isValidArray(filter.status))  {
110547             return false;
110548         }
110549         for (i = 0; i < filter.status.length; i++) {
110550             filter.status[i] = filter.status[i] | 0;
110551             if (filter.status[i] > _CANCELLED_STATUS || filter.status[i] < _TENTATIVE_STATUS)
110552                 return false;
110553         }
110554     } else {
110555         filter.status = undefined;
110556     }
110557     if (filter.initialStartDate !== undefined && filter.initialStartDate !== null) {
110558         if (!wac2_utils.isValidDate(filter.initialStartDate)) {
110559             return false;
110560         }
110561         filter.initialStartDate = new Date(filter.initialStartDate);
110562     } else {
110563         filter.initialStartDate = undefined;
110564     }
110565     if (filter.endStartDate !== undefined && filter.endStartDate !== null) {
110566         if (!wac2_utils.isValidDate(filter.endStartDate)) {
110567             return false;
110568         }
110569         filter.endStartDate = new Date(filter.endStartDate);
110570     } else {
110571         filter.endStartDate = undefined;
110572     }
110573     return true;
110574 };
110575
110576 CalendarEventProperties = function (prop) {
110577     var _self;
110578     _self = {
110579         description : "",
110580         summary : "",
110581         startTime : new Date(),
110582         duration : 0,
110583         location : "",
110584         categories : undefined,
110585         recurrence : _NO_RECURRENCE,
110586         expires : null,  // ignored if recurrence == NO_RECURRENCE
110587         interval : null, // ignored if recurrence == NO_RECURRENCE
110588         status : _CONFIRMED_STATUS,
110589         alarmTrigger : 0,
110590         alarmType : _NO_ALARM
110591     };
110592     if (prop) {
110593         if (_eventPropCheck(prop, _self) === false) {
110594             return undefined;
110595         }
110596     }
110597     return _self;
110598 };
110599
110600 CalendarEvent = function (prop, genNewID) {
110601     var id, _self = new CalendarEventProperties(prop);
110602
110603     /* if error occurs during checking, _self is an empty object.
110604        so i randomly pick description to check if property check fails */
110605     if (_self.description === undefined) {
110606         return undefined;
110607     }
110608
110609     if (genNewID === true) {
110610         id = Math.uuid(undefined, 16);
110611     } else {
110612         id = prop.id;
110613     }
110614     _self.__defineGetter__("id", function () {
110615         return id;
110616     });
110617     return _self;
110618 };
110619
110620 Calendar = function (type, name, events) {
110621     var _type = type,
110622         _name = name,
110623         _events = events, _self;
110624
110625     _self = {
110626         createEvent: function (evtProp) {
110627             var rst = {};
110628             rst = new CalendarEventProperties(evtProp);
110629             /* if error occurs during checking, rst is an empty object.
110630                so i randomly pick description to check if property check fails */
110631             if (rst.description === undefined) {
110632                 exception.raise(exception.types.Argument, "EventProperties: input parameter contains invalid values", new DeviceApiError(errorcode.INVALID_VALUES_ERR));
110633                 return undefined;
110634             } else {
110635                 return rst;
110636             }
110637         },
110638
110639         addEvent: function (onSuccess, onError, calEvent) {
110640             var pendingOperation, pendingObj = {},
110641                 newEvent = {}, _doAddEvent, _calEvent = Object(calEvent);
110642
110643             _doAddEvent = function () {
110644                 if (!_addEventAllowed) {
110645                     if (onError) {
110646                         setTimeout(function () {
110647                             onError(new DeviceApiError(errorcode.SECURITY_ERR));
110648                         }, 1);
110649                     }
110650                     return undefined;
110651                 }
110652                 newEvent = new CalendarEvent(_calEvent, true);
110653                 /* if newEvent.id === undefined,
110654                    means somthing wrong in calEvent  */
110655                 if (newEvent.id === undefined) {
110656                     if (onError) {
110657                         setTimeout(function () {
110658                             onError(new DeviceApiError(errorcode.INVALID_VALUES_ERR));
110659                         }, 1);
110660                     }
110661                     return undefined;
110662                 }
110663
110664                 pendingObj = new PendingObject();
110665                 pendingObj.pendingID = setTimeout(function () {
110666                     pendingObj.setCancelFlag(false);
110667                     _events[newEvent.id] = newEvent;
110668                     _save_calendars(_name, _type, _events);
110669                     onSuccess(new CalendarEvent(newEvent), false);
110670                 }, _FAKEWAITTIME);
110671                 pendingOperation = new PendingOperation(pendingObj);
110672                 return pendingOperation;
110673             };
110674
110675             return wac2_utils.validateTypeMismatch(onSuccess, onError, "Calendar:addEvent", _doAddEvent);
110676         },
110677
110678         updateEvent: function (onSuccess, onError, calEvent) {
110679             var pendingOperation, pendingObj = {},
110680                 chkEvent, _doUpdateEvent, _calEvent = Object(calEvent);
110681
110682             _doUpdateEvent = function () {
110683                 if (!_updateEventAllowed) {
110684                     if (onError) {
110685                         setTimeout(function () {
110686                             onError(new DeviceApiError(errorcode.SECURITY_ERR));
110687                         }, 1);
110688                     }
110689                     return undefined;
110690                 }
110691                 if (!_events[_calEvent.id]) {
110692                     if (onError) {
110693                         setTimeout(function () {
110694                             onError(new DeviceApiError(errorcode.NOT_FOUND_ERR));
110695                         }, 1);
110696                     }
110697                     return undefined;
110698                 }
110699
110700                 chkEvent = new CalendarEvent(_events[_calEvent.id], false);
110701                 /* _eventPropCheck will also update chkEvent btw */
110702                 if (_eventPropCheck(_calEvent, chkEvent) === false) {
110703                     if (onError) {
110704                         setTimeout(function () {
110705                             onError(new DeviceApiError(errorcode.INVALID_VALUES_ERR));
110706                         }, 1);
110707                     }
110708                     return undefined;
110709                 }
110710                 pendingObj = new PendingObject();
110711                 pendingObj.pendingID = setTimeout(function () {
110712                     pendingObj.setCancelFlag(false);
110713
110714                     _events[chkEvent.id] = chkEvent;
110715                     _save_calendars(_name, _type, _events);
110716                     onSuccess();
110717                 }, _FAKEWAITTIME);
110718                 pendingOperation = new PendingOperation(pendingObj);
110719                 return pendingOperation;
110720             };
110721
110722             return wac2_utils.validateTypeMismatch(onSuccess, onError, "Calendar:updateEvent", _doUpdateEvent);
110723         },
110724
110725         deleteEvent: function (onSuccess, onError, id) {
110726             var pendingOperation, pendingObj = {},
110727                 _doDeleteEvent;
110728
110729             _doDeleteEvent = function () {
110730                 /* according to spec  "If any of the input parameters are not 
110731                    compatible with the expected type for that parameter, 
110732                    a DeviceAPIError with code TYPE_MISMATCH_ERR MUST be 
110733                    synchronously thrown." 
110734                    so an error is raised synchronously */
110735                 utils.validateArgumentType(id, "string", null,
110736                                        "Calendar:deleteEvent: " + " invalid id parameter",
110737                                        new DeviceApiError(errorcode.TYPE_MISMATCH_ERR));
110738
110739                 if (!_deleteEventAllowed) {
110740                     if (onError) {
110741                         setTimeout(function () {
110742                             onError(new DeviceApiError(errorcode.SECURITY_ERR));
110743                         }, 1);
110744                     }
110745                     return undefined;
110746                 }
110747                 if (!_events[id]) {
110748                     if (onError) {
110749                         setTimeout(function () {
110750                             onError(new DeviceApiError(errorcode.NOT_FOUND_ERR));
110751                         }, 1);
110752                     }
110753                     return undefined;
110754                 }
110755
110756                 pendingObj = new PendingObject();
110757                 pendingObj.pendingID = setTimeout(function () {
110758                     pendingObj.setCancelFlag(false);
110759
110760                     delete _events[id];
110761                     _save_calendars(_name, _type, _events);
110762                     onSuccess();
110763                 }, _FAKEWAITTIME);
110764                 pendingOperation = new PendingOperation(pendingObj);
110765                 return pendingOperation;
110766             };
110767
110768             return wac2_utils.validateTypeMismatch(onSuccess, onError, "Calendar:deleteEvent", _doDeleteEvent);
110769         },
110770
110771         findEvents: function (onSuccess, onError, eventFilter) {
110772             var pendingOperation, pendingObj = {}, i,
110773                 tmp = [], valid_tmp = false, rst = [], _doFindEvents,
110774                 _eventFilter = Object(eventFilter);
110775
110776             _doFindEvents = function () {
110777                 if (!_eventFilterCheck(_eventFilter)) {
110778                     if (onError) {
110779                         setTimeout(function () {
110780                             onError(new DeviceApiError(errorcode.INVALID_VALUES_ERR));
110781                         }, 1);
110782                     }
110783                     return undefined;
110784                 }
110785                 if (!_findEventsAllowed) {
110786                     if (onError) {
110787                         setTimeout(function () {
110788                             onError(new DeviceApiError(errorcode.SECURITY_ERR));
110789                         }, 1);
110790                     }
110791                     return undefined;
110792                 }
110793
110794                 pendingObj = new PendingObject();
110795                 pendingObj.pendingID = setTimeout(function () {
110796                     pendingObj.setCancelFlag(false);
110797                     if (_eventFilter.id !== undefined) {
110798                         tmp = wac2_utils.matchOptionString(_events, "id", _eventFilter.id);
110799                         valid_tmp = true;
110800                     }
110801                     if (_eventFilter.summary !== undefined) {
110802                         if (valid_tmp) {
110803                             tmp = wac2_utils.matchOptionString(tmp, "summary", _eventFilter.summary);
110804                         } else {
110805                             tmp = wac2_utils.matchOptionString(_events, "summary", _eventFilter.summary);
110806                             valid_tmp = true;
110807                         }
110808                     }
110809                     if (_eventFilter.description !== undefined) {
110810                         if (valid_tmp) {
110811                             tmp = wac2_utils.matchOptionString(tmp, "description", _eventFilter.description);
110812                         } else {
110813                             tmp = wac2_utils.matchOptionString(_events, "description", _eventFilter.description);
110814                             valid_tmp = true;
110815                         }
110816                     }
110817                     if (_eventFilter.location !== undefined) {
110818                         if (valid_tmp) {
110819                             tmp = wac2_utils.matchOptionString(tmp, "location", _eventFilter.location);
110820                         } else {
110821                             tmp = wac2_utils.matchOptionString(_events, "location", _eventFilter.location);
110822                             valid_tmp = true;
110823                         }
110824                     }
110825                     if (_eventFilter.category !== undefined) {
110826                         if (valid_tmp) {
110827                             tmp = wac2_utils.matchOptionArrayString(tmp, "categories", _eventFilter.category);
110828                         } else {
110829                             tmp = wac2_utils.matchOptionArrayString(_events, "categories", _eventFilter.category);
110830                             valid_tmp = true;
110831                         }
110832                     }
110833                     if (_eventFilter.status !== undefined) {
110834                         if (valid_tmp) {
110835                             tmp = wac2_utils.matchOptionShortArray(tmp, "status", _eventFilter.status);
110836                         } else {
110837                             tmp = wac2_utils.matchOptionShortArray(_events, "status", _eventFilter.status);
110838                             valid_tmp = true;
110839                         }
110840                     }
110841                     if (_eventFilter.initialStartDate !== undefined ||
110842                         _eventFilter.endStartDate !== undefined) {
110843                         if (valid_tmp) {
110844                             tmp = wac2_utils.matchOptionDate(tmp, "startTime", _eventFilter.initialStartDate, _eventFilter.endStartDate);
110845                         } else {
110846                             tmp = wac2_utils.matchOptionDate(_events, "startTime", _eventFilter.initialStartDate, _eventFilter.endStartDate);
110847                             valid_tmp = true;
110848                         }
110849                     }
110850
110851                     // to make id readonly
110852                     if (valid_tmp) {
110853                         for (i = 0; i < tmp.length; i++) {
110854                             rst.push(new CalendarEvent(tmp[i], false));
110855                         }
110856                     } else {
110857                         for (var e in _events) {
110858                             rst.push(new CalendarEvent(_events[e], false));
110859                         }
110860                     }
110861                     onSuccess(rst);
110862                 }, _FAKE_LONG_WAITTIME);
110863                 pendingOperation = new PendingOperation(pendingObj);
110864                 return pendingOperation;
110865             };
110866
110867             return wac2_utils.validateTypeMismatch(onSuccess, onError, "Calendar:findEvent", _doFindEvents);
110868         },
110869     };
110870     _self.__defineGetter__("type", function () {
110871         return _type;
110872     });
110873     _self.__defineGetter__("name", function () {
110874         return name;
110875     });
110876     return _self;
110877 };
110878
110879 module.exports = function () {
110880     this.__defineGetter__("SIM_CALENDAR", function () {
110881         return 0;
110882     });
110883     this.__defineGetter__("DEVICE_CALENDAR", function () {
110884         return 1;
110885     });
110886     this.__defineGetter__("NO_RECURRENCE", function () { 
110887         return 0;
110888     });
110889     this.__defineGetter__("DAILY_RECURRENCE", function () {
110890         return 1;
110891     });
110892     this.__defineGetter__("WEEKLY_RECURRENCE", function () {
110893         return 2;
110894     });
110895     this.__defineGetter__("MONTHLY_RECURRENCE", function () {
110896         return 3;
110897     });
110898     this.__defineGetter__("YEARLY_RECURRENCE", function () {
110899         return 4;
110900     });
110901     this.__defineGetter__("TENTATIVE_STATUS", function () {
110902         return 0;
110903     });
110904     this.__defineGetter__("CONFIRMED_STATUS", function () {
110905         return 1;
110906     });
110907     this.__defineGetter__("CANCELLED_STATUS", function () {
110908         return 2;
110909     });
110910     this.__defineGetter__("NO_ALARM", function () {
110911         return 0;
110912     });
110913     this.__defineGetter__("SILENT_ALARM", function () {
110914         return 1;
110915     });
110916     this.__defineGetter__("SOUND_ALARM", function () {
110917         return 2;
110918     });
110919
110920     this.getCalendars = function (onSuccess, onError) {
110921         var i, pendingOperation, pendingObj = {}, cal, _doGetCalendars;
110922
110923         _doGetCalendars = function () {
110924             pendingObj = new PendingObject();
110925
110926             pendingObj.pendingID = setTimeout(function () {
110927                 pendingObj.setCancelFlag(false);
110928                 cal = db.retrieveObject(_DB_CALENDARS_KEY) || [];
110929                 _calendars = [];
110930                 if (cal.length === 0) {
110931                     _calendars.push(new Calendar(_SIM_CALENDAR, "sim cal", {}));
110932                     _calendars.push(new Calendar(_DEVICE_CALENDAR, "dev cal", {}));
110933                 } else {
110934                     for (i = 0; i < cal.length; i++) {
110935                         /* after getting Date out of DB, Date will become 
110936                            a string, so need to recast it back to Date */
110937                         /* NOTE: id becomes writable, so need to recast it
110938                            before passing to application */
110939                         for (var e in cal[i].events) {
110940                             if ((cal[i].events[e].startTime !== undefined) &&
110941                                 cal[i].events[e].startTime !== null) {
110942                                 cal[i].events[e].startTime = new Date(cal[i].events[e].startTime);
110943                             }
110944                             if ((cal[i].events[e].expires !== undefined) &&
110945                                 cal[i].events[e].expires !== null) {
110946                                 cal[i].events[e].expires = new Date(cal[i].events[e].expires);
110947                             }
110948                         }
110949                         _calendars.push(new Calendar(cal[i].type, cal[i].name, cal[i].events));
110950                     }
110951                 }
110952                 if (_calendars.length !== 0) {
110953                     onSuccess(utils.copy(_calendars));
110954                 } else {
110955                     if (onError) {
110956                         onError(new DeviceApiError(errorcode.UNKNOWN_ERR));
110957                     }
110958                 }
110959             }, _FAKEWAITTIME);
110960             pendingOperation = new PendingOperation(pendingObj);
110961             return pendingOperation;
110962         };
110963     
110964         return wac2_utils.validateTypeMismatch(onSuccess, onError, "getCalendars", _doGetCalendars);
110965     };
110966
110967     this.handleSubFeatures = function (subFeatures) {
110968         if (wac2_utils.isEmptyObject(subFeatures) ||
110969             subFeatures["http://wacapps.net/api/pim.calendar"] ||
110970             (subFeatures["http://wacapps.net/api/pim.calendar.read"] &&
110971             subFeatures["http://wacapps.net/api/pim.calendar.write"])) {
110972             return;
110973         } 
110974         if (subFeatures["http://wacapps.net/api/pim.calendar.read"]) {
110975             _addEventAllowed = false;
110976             _deleteEventAllowed = false;
110977             _updateEventAllowed = false;
110978             return;
110979         } 
110980         if (subFeatures["http://wacapps.net/api/pim.calendar.write"]) {
110981             _findEventsAllowed = false;
110982             return;
110983         } 
110984         _console.warn("WAC-2.0-Calendar-handleSubFeatures: something wrong");
110985     };
110986 };
110987
110988 });
110989 define('ripple/platform/wac/2.0/camera', function (require, exports, module) {
110990 /*
110991  *  Copyright 2011 Intel Corporation.
110992  *
110993  * Licensed under the Apache License, Version 2.0 (the "License");
110994  * you may not use this file except in compliance with the License.
110995  * You may obtain a copy of the License at
110996  *
110997  * http://www.apache.org/licenses/LICENSE-2.0
110998  *
110999  * Unless required by applicable law or agreed to in writing, software
111000  * distributed under the License is distributed on an "AS IS" BASIS,
111001  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
111002  * See the License for the specific language governing permissions and
111003  * limitations under the License.
111004  */
111005
111006 var utils = require('ripple/utils'),
111007     constants = require('ripple/constants'),
111008     _console = require('ripple/console'),
111009     errorcode = require('ripple/platform/wac/2.0/errorcode'),
111010     PendingOperation = require('ripple/platform/wac/2.0/pendingoperation'),
111011     PendingObject = require('ripple/platform/wac/2.0/pendingObject'),
111012     DeviceApiError = require('ripple/platform/wac/2.0/deviceapierror'),
111013     wac2_utils = require('ripple/platform/wac/2.0/wac2_utils');
111014
111015 module.exports = function () {
111016     var _cameraArray, Camera, _videoStatus = {},
111017         _captureImage, _startVideoCapture,
111018         _doCaptureImage, _doStartVideoCapture,
111019         _doGetPreview, _doGetCameras,
111020         _stopVideoCapture, _createPreviewNode,
111021         _FAKEWAITTIME = 5,
111022         _defaultHighRes = true,
111023         _defaultImageFilename = "_capture.jpg",
111024         _defaultVideoFilename = "_capture.avi",
111025         _captureImageAllowed = true,
111026         _startVideoCaptureAllowed = true,
111027         _stopVideoCaptureAllowed = true,
111028         _createPreviewNodeAllowed = true;
111029
111030     _doCaptureImage = function (onSuccess, onError, capFilename, capHighRes, pendingObj) {
111031         pendingObj.pendingID = setTimeout(function () {
111032             var dname = "", fname = "";
111033             //pretend to do sth.
111034             pendingObj.setCancelFlag(false);  // too late to cancel
111035             if (capFilename.indexOf("/") !== -1) {
111036                 dname = capFilename.replace(/(.*\/)[^\/]+$/i, "$1");
111037                 fname = capFilename.replace(/.*\/([^\/]*)$/i, "$1");
111038                 //replace extension with jpg
111039                 fname = fname.replace(/\.[^\/\.]+$/i, ".jpg");
111040             } else {
111041                 dname = "";
111042                 fname = capFilename.replace(/\.[^\/\.]+$/i, ".jpg");
111043             }
111044             if (fname === "") {
111045                 fname = _defaultImageFilename;
111046             }
111047             if (fname.search(/\.jpg$/) === -1) {
111048                 fname = fname + ".jpg";
111049             }
111050             if (capHighRes) {
111051                 onSuccess(dname + "high-" + fname);
111052             } else {
111053                 onSuccess(dname + "low-" + fname);
111054             }
111055         }, _FAKEWAITTIME);
111056     };
111057
111058     _captureImage = function (onSuccess, onError, options) {
111059         var pendingOperation = {}, pendingObj,
111060             filename = this.id + _defaultImageFilename,
111061             highRes = _defaultHighRes, opt;
111062
111063         if (onSuccess) {
111064             utils.validateArgumentType(onSuccess, "function", null, "captureImage: invalid successCallback parameter", new DeviceApiError(errorcode.TYPE_MISMATCH_ERR));
111065         }
111066         if (onError) {
111067             utils.validateArgumentType(onError, "function", null, "captureImage: invalid errorCallback parameter", new DeviceApiError(errorcode.TYPE_MISMATCH_ERR));
111068         }
111069         if (options) {
111070             opt = new Object(options);
111071             /* NOTE: if desktinationFilename or highRes is not provided by
111072                user, i.e. undefined or null, a default value is used.
111073              */
111074             if (opt.destinationFilename !== null && opt.destinationFilename !== undefined) {
111075             // TODO: validate filename via Filesystem.resolve()
111076                 filename = String(opt.destinationFilename);
111077             }
111078             if (opt.highRes !== null && opt.highRes !== undefined) {
111079                 highRes = Boolean(opt.highRes);
111080             }
111081         }
111082         if (!_captureImageAllowed) {
111083             if (onError) {
111084                 setTimeout(function () {
111085                     onError(new DeviceApiError(errorcode.SECURITY_ERR));
111086                 }, 1);
111087             }
111088             return undefined;
111089         }
111090
111091         if (onSuccess) {
111092             pendingObj = new PendingObject();
111093             _doCaptureImage(onSuccess, onError, filename, highRes, pendingObj);
111094             pendingOperation = new PendingOperation(pendingObj);
111095             return pendingOperation;
111096         } else {
111097             if (onError) {
111098                 setTimeout(function () {
111099                     onError(new DeviceApiError(errorcode.INVALID_VALUES_ERR));
111100                 }, 1);
111101             }
111102         }
111103         return undefined;
111104     };
111105
111106     _stopVideoCapture = function () {
111107         var dname = "", fname = "", capFilename = _videoStatus[this.id].capFilename;
111108         if (_videoStatus[this.id]) {
111109             if (capFilename.indexOf("/") !== -1) {
111110                 dname = capFilename.replace(/(.*\/)[^\/]+$/i, "$1");
111111                 fname = capFilename.replace(/.*\/([^\/]*)$/i, "$1");
111112                 //replace extension with avi
111113                 fname = fname.replace(/\.[^\/\.]+$/i, ".avi");
111114             } else {
111115                 dname = "";
111116                 fname = capFilename.replace(/\.[^\/\.]+$/i, ".avi");
111117             }
111118             if (fname === "") {
111119                 fname = _defaultVideoFilename;
111120             }
111121             if (fname.search(/\.avi$/) === -1) {
111122                 fname = fname + ".avi";
111123             }
111124             if (_videoStatus[this.id].capHighRes) {
111125                 _videoStatus[this.id].capSuccess(dname + "high-" + fname);
111126             } else {
111127                 _videoStatus[this.id].capSuccess(dname + "low-" + fname);
111128             }
111129             delete _videoStatus[this.id];
111130         }
111131     };
111132
111133     _doStartVideoCapture = function (camID, onSuccess, onError, filename, highRes, pendingObj) {
111134         var videoStatus = {};
111135         _videoStatus[camID] = videoStatus;
111136         pendingObj.userCancel = function () {
111137             delete _videoStatus[camID];
111138         };
111139         pendingObj.getCancelFlag = function () {
111140             return !!_videoStatus[camID];
111141         };
111142         pendingObj.pendingID = setTimeout(function () {
111143             // waiting to be cancelled
111144             videoStatus = {
111145                 capSuccess: onSuccess,
111146                 capError: onError,
111147                 capFilename: filename,
111148                 capHighRes: highRes
111149             };
111150             _videoStatus[camID] = videoStatus;
111151         }, _FAKEWAITTIME);
111152     };
111153
111154     _startVideoCapture = function (onSuccess, onError, options) {
111155         var pendingOperation = {}, pendingObj,
111156             filename = this.id + _defaultVideoFilename,
111157             highRes = _defaultHighRes, opt;
111158
111159         if (onSuccess) {
111160             utils.validateArgumentType(onSuccess, "function", null, "startVideoCapture: invalid successCallback parameter", new DeviceApiError(errorcode.TYPE_MISMATCH_ERR));
111161         }
111162         if (onError) {
111163             utils.validateArgumentType(onError, "function", null, "startVideoCapture: invalid errorCallback parameter", new DeviceApiError(errorcode.TYPE_MISMATCH_ERR));
111164         }
111165         if (options) {
111166             opt = new Object(options);
111167             /* NOTE: if desktinationFilename or highRes is not provided by
111168                user, i.e. undefined or null, a default value is used.
111169              */
111170             if (opt.destinationFilename !== null && opt.destinationFilename !== undefined) {
111171             // TODO: validate filename via Filesystem.resolve()
111172                 filename = String(opt.destinationFilename);
111173             }
111174             if (opt.highRes !== null && opt.highRes !== undefined) {
111175                 highRes = Boolean(opt.highRes);
111176             }
111177         }
111178         if (!_captureImageAllowed) {
111179             if (onError) {
111180                 setTimeout(function () {
111181                     onError(new DeviceApiError(errorcode.SECURITY_ERR));
111182                 }, 1);
111183             }
111184             return undefined;
111185         }
111186         if (_videoStatus[this.id]) { 
111187             // capture already started
111188             _console.warn("WAC-2.0-startVideoCapture: capture already started");
111189             if (onError) {
111190                 setTimeout(function () {
111191                     onError(new DeviceApiError(errorcode.UNKNOWN_ERR));
111192                 }, 1);
111193             }
111194             return undefined;
111195         }
111196
111197         if (onSuccess) {
111198             pendingObj = new PendingObject();
111199             _doStartVideoCapture(this.id, onSuccess, onError, filename, highRes, pendingObj);
111200             
111201             pendingOperation = new PendingOperation(pendingObj);
111202             return pendingOperation;
111203         } else {
111204             if (onError) {
111205                 setTimeout(function () {
111206                     onError(new DeviceApiError(errorcode.INVALID_VALUES_ERR));
111207                 }, 1);
111208             }
111209         }
111210         return undefined;
111211     };
111212
111213     _doGetPreview = function (camID, onSuccess, onError, pendingObj) {
111214         var container, demoImg, loc, imageSrc;
111215         container = document.createElement("div");
111216         container.setAttribute("id", camID + "-wac-2-0-camera-preview-container");
111217         demoImg = document.createElement("img");
111218         demoImg.setAttribute("id", camID + "-wac-2-0-camera-demo-image");
111219         loc = document.location;
111220         imageSrc = loc.protocol + "//" + loc.hostname + loc.pathname.replace(/index\.html$/, "") + constants.CAMERA.WINDOW_ANIMATION;
111221         demoImg.setAttribute("src", imageSrc);
111222         demoImg.setAttribute("width", "100%");
111223         container.appendChild(demoImg);
111224         
111225         pendingObj.pendingID = setTimeout(function () {
111226             pendingObj.setCancelFlag(false);  // too late to cancel
111227             onSuccess(container);
111228         }, _FAKEWAITTIME);
111229     };
111230
111231     _createPreviewNode = function (onSuccess, onError) {
111232         var pendingOperation, pendingObj = {};
111233         if (onSuccess) {
111234             utils.validateArgumentType(onSuccess, "function", null, "createPreviewNode: invalid successCallback parameter", new DeviceApiError(errorcode.TYPE_MISMATCH_ERR));
111235         }
111236         if (onError) {
111237             utils.validateArgumentType(onError, "function", null, "createPreviewNode: invalid errorCallback parameter", new DeviceApiError(errorcode.TYPE_MISMATCH_ERR));
111238         }
111239         if (!_createPreviewNodeAllowed) {
111240             if (onError) {
111241                 setTimeout(function () {
111242                     onError(new DeviceApiError(errorcode.SECURITY_ERR));
111243                 }, 1);
111244             }
111245             return undefined;
111246         }
111247         if (onSuccess) {
111248             pendingObj = new PendingObject();
111249             _doGetPreview(this.id, onSuccess, onError, pendingObj);
111250             pendingOperation = new PendingOperation(pendingObj);
111251             return pendingOperation;
111252         } else {
111253             if (onError) {
111254                 setTimeout(function () {
111255                     onError(new DeviceApiError(errorcode.INVALID_VALUES_ERR));
111256                 }, 1);
111257             }
111258         }
111259         return undefined;
111260     };
111261
111262     Camera = function (cameraID) {
111263         return {
111264             id: cameraID,
111265             captureImage: _captureImage,
111266             startVideoCapture: _startVideoCapture,
111267             stopVideoCapture: _stopVideoCapture,
111268             createPreviewNode: _createPreviewNode
111269         };
111270     };
111271
111272     _cameraArray = [new Camera("rear"), new Camera("front")];
111273
111274     _doGetCameras = function (onSuccess, onError, pendingObj) {
111275         pendingObj.pendingID = setTimeout(function () {
111276             pendingObj.setCancelFlag(false);  // too late to cancel
111277             if (_cameraArray.length !== 0) {
111278                 onSuccess(utils.copy(_cameraArray));
111279             } else {
111280                 // no camera
111281                 if (onError) {
111282                     setTimeout(function () {
111283                         onError(new DeviceApiError(errorcode.UNKNOWN_ERR));
111284                     }, 1);
111285                 }
111286             }
111287         }, _FAKEWAITTIME);
111288     };
111289
111290     this.getCameras = function (onSuccess, onError) {
111291         var pendingOperation, pendingObj = {};
111292         if (onSuccess) {
111293             utils.validateArgumentType(onSuccess, "function", null, "getCameras: invalid successCallback parameter", new DeviceApiError(errorcode.TYPE_MISMATCH_ERR));
111294         }
111295         if (onError) {
111296             utils.validateArgumentType(onError, "function", null, "getCameras: invalid errorCallback parameter", new DeviceApiError(errorcode.TYPE_MISMATCH_ERR));
111297         }
111298         if (onSuccess) {
111299             pendingObj = new PendingObject();
111300             _doGetCameras(onSuccess, onError, pendingObj);
111301             pendingOperation = new PendingOperation(pendingObj);
111302             return pendingOperation;
111303         } else {
111304             if (onError) {
111305                 setTimeout(function () {
111306                     onError(new DeviceApiError(errorcode.INVALID_VALUES_ERR));
111307                 }, 1);
111308             }
111309         }
111310         return undefined;
111311     };
111312
111313     this.handleSubFeatures = function (subFeatures) {
111314         if (wac2_utils.isEmptyObject(subFeatures) ||
111315             subFeatures["http://wacapps.net/api/camera"] ||
111316             (subFeatures["http://wacapps.net/api/camera.capture"] &&
111317             subFeatures["http://wacapps.net/api/camera.show"])) {
111318             return;
111319         }
111320         if (subFeatures["http://wacapps.net/api/camera.show"] &&
111321            !subFeatures["http://wacapps.net/api/camera.capture"]) {
111322             _captureImageAllowed = false;
111323             _startVideoCaptureAllowed = false;
111324             _stopVideoCaptureAllowed = false;
111325             return;
111326         }
111327         if (subFeatures["http://wacapps.net/api/camera.capture"] &&
111328            !subFeatures["http://wacapps.net/api/camera.show"]) {
111329             _createPreviewNodeAllowed = false;
111330             return;
111331         }
111332         _console.warn("WAC-2.0-Camera-handleSubFeatures: something wrong");
111333     };
111334 };
111335
111336 });
111337 define('ripple/platform/wac/2.0/contact', function (require, exports, module) {
111338 /*
111339  *  Copyright 2011 Intel Corporation.
111340  *
111341  * Licensed under the Apache License, Version 2.0 (the "License");
111342  * you may not use this file except in compliance with the License.
111343  * You may obtain a copy of the License at
111344  *
111345  * http://www.apache.org/licenses/LICENSE-2.0
111346  *
111347  * Unless required by applicable law or agreed to in writing, software
111348  * distributed under the License is distributed on an "AS IS" BASIS,
111349  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
111350  * See the License for the specific language governing permissions and
111351  * limitations under the License.
111352  */
111353
111354 var utils = require('ripple/utils'),
111355     db = require('ripple/db'),
111356     constants = require('ripple/constants'),
111357     exception = require('ripple/exception'),
111358     errorcode = require('ripple/platform/wac/2.0/errorcode'),
111359     wac2_utils = require('ripple/platform/wac/2.0/wac2_utils'),
111360     DeviceApiError = require('ripple/platform/wac/2.0/deviceapierror'),
111361     PendingOperation = require('ripple/platform/wac/2.0/pendingoperation'),
111362     PendingObject = require('ripple/platform/wac/2.0/pendingObject'),
111363     TypeCoerce = require('ripple/platform/wac/2.0/typecoerce'),
111364     Filter = require('ripple/platform/wac/2.0/contactfilter'),
111365     AddressBook,
111366     ContactProperties,
111367     Contact,
111368     Address,
111369     ContactAddress,
111370     PhoneNumber,
111371     EmailAddress,
111372     ContactFilter,
111373     _KEY = "wac2-pim-contact",
111374     _PENDING_TIME = 600,
111375     _addressBooks = [],
111376     _contacts = {},
111377     _security = {
111378         "http://wacapps.net/api/pim.contact": [],
111379         "http://wacapps.net/api/pim.contact.read": ["findContacts"],
111380         "http://wacapps.net/api/pim.contact.write": ["addContact", "updateContact", "deleteContact"],
111381         all: true
111382     },
111383     _self;
111384
111385 function _errorOccurred(onError, code) {
111386     if (!onError)
111387         return;
111388
111389     setTimeout(function () {
111390         onError(new DeviceApiError(code));
111391     }, 1);
111392 }
111393
111394 function _pendingOperate(operate, scope) {
111395     var i, argumentVector = [];
111396
111397     for (i = 0; i < arguments.length - 2; i++)
111398         argumentVector[i] = arguments[i + 2];
111399
111400     return function () {
111401         var pendingObj, pendingOperation;
111402
111403         pendingObj = new PendingObject();
111404         pendingObj.pendingID = window.setTimeout(function () {
111405             pendingObj.setCancelFlag(false);
111406             operate.apply(scope, argumentVector);
111407         }, _PENDING_TIME);
111408
111409         pendingOperation = new PendingOperation(pendingObj);
111410
111411         return pendingOperation;
111412     };
111413 }
111414
111415 function _defaultContacts() {
111416     var id1 = Math.uuid(null, 16),
111417         id2 = Math.uuid(null, 16),
111418         id3 = Math.uuid(null, 16),
111419         id4 = Math.uuid(null, 16),
111420         contacts = {};
111421
111422     contacts.PHONE_ADDRESS_BOOK = {
111423         type: _self().PHONE_ADDRESS_BOOK,
111424         items: [{
111425             id: id1,
111426             firstName: "Leonardo",
111427             lastName: "Gates",
111428             nicknames: ["Leo"],
111429             phoneticName: "",
111430             addresses: [{streetAddress: "Gran Via, 32", postalCode: "50013", city: "Zaragoza", country: "ES"}],
111431             photoURI: "",
111432             phoneNumbers: [],
111433             emails: ["leo@underground.com"]
111434         }, {
111435             id: id2,
111436             firstName: "Jordan",
111437             lastName: "",
111438             nicknames: [""],
111439             phoneticName: "",
111440             addresses: [],
111441             photoURI: "",
111442             phoneNumbers: [],
111443             emails: ["jordan@underground.com"]
111444         }]
111445     };
111446
111447     contacts.SIM_ADDRESS_BOOK = {
111448         type: _self().SIM_ADDRESS_BOOK,
111449         items: [{
111450             id: id3,
111451             firstName: "Raphael",
111452             lastName: "",
111453             nicknames: [""],
111454             phoneticName: "",
111455             addresses: [],
111456             photoURI: "",
111457             phoneNumbers: [],
111458             emails: ["raph@underground.com"]
111459         }]
111460     };
111461
111462     contacts.DEVICE_ADDRESS_BOOK = {
111463         type: _self().DEVICE_ADDRESS_BOOK,
111464         items: [{
111465             id: id4,
111466             firstName: "Michelangelo",
111467             lastName: "",
111468             nicknames: [""],
111469             phoneticName: "",
111470             addresses: [],
111471             photoURI: "",
111472             phoneNumbers: [],
111473             emails: ["mike@underground.com"]
111474         }]
111475     };
111476
111477     return contacts;
111478 }
111479
111480 function _get() {
111481     _contacts = db.retrieveObject(_KEY) || _defaultContacts();
111482 }
111483
111484 function _save() {
111485     db.saveObject(_KEY, _contacts);
111486 }
111487
111488 function _initAddressBooks() {
111489     _get();
111490     utils.forEach(_contacts, function (contactObj, name) {
111491         _addressBooks.push(new AddressBook(contactObj.type, name));
111492     });
111493 }
111494
111495 _self = function () {
111496     var contact = {
111497         getAddressBooks: function (successCallback, errorCallback) {
111498             function _getAddressBooks() {
111499                 if (_addressBooks.length === 0) {
111500                     _initAddressBooks();
111501                 }
111502                 successCallback(_addressBooks);
111503             }
111504             return wac2_utils.validateTypeMismatch(successCallback, errorCallback, "getAddressBooks", _getAddressBooks);
111505         },
111506
111507         handleSubFeatures: function (subFeatures) {
111508             for (var subFeature in subFeatures) {
111509                 if (_security[subFeature].length === 0) {
111510                     _security.all = true;
111511                     return;
111512                 }
111513                 _security.all = false;
111514                 utils.forEach(_security[subFeature], function (method) {
111515                     _security[method] = true;
111516                 });
111517             }
111518         }
111519     };
111520
111521     contact.__defineGetter__("SIM_ADDRESS_BOOK", function () {
111522         return 0x0000;
111523     });
111524
111525     contact.__defineGetter__("DEVICE_ADDRESS_BOOK", function () {
111526         return 0x000F;
111527     });
111528
111529     contact.__defineGetter__("PHONE_ADDRESS_BOOK", function () {
111530         return 0x00FF;
111531     });
111532
111533     return contact;
111534 };
111535
111536 AddressBook = function (type, name) {
111537     var addressBook,
111538         contactItems = _contacts[name].items;
111539
111540     addressBook = {
111541         createContact: function (contactProperties) {
111542             var cp, contact = new Contact();
111543
111544             if ((contactProperties !== undefined) &&
111545                 (contactProperties !== null)) {
111546                 cp = TypeCoerce(ContactProperties).cast(contactProperties);
111547                 !cp.firstName    || (contact.firstName    = utils.copy(cp.firstName));
111548                 !cp.lastName     || (contact.lastName     = utils.copy(cp.lastName));
111549                 !cp.nicknames    || (contact.nicknames    = utils.copy(cp.nicknames));
111550                 !cp.phoneticName || (contact.phoneticName = utils.copy(cp.phoneticName));
111551                 !cp.addresses    || (contact.addresses    = utils.copy(cp.addresses));
111552                 !cp.photoURI     || (contact.photoURI     = utils.copy(cp.photoURI));
111553                 !cp.phoneNumbers || (contact.phoneNumbers = utils.copy(cp.phoneNumbers));
111554                 !cp.emails       || (contact.emails       = utils.copy(cp.emails));
111555             }
111556
111557             return contact;
111558         },
111559
111560         addContact: function (successCallback, errorCallback, contact) {
111561             function _addContact() {
111562                 var c;
111563
111564                 if (!contact)
111565                     exception.raise(exception.types.Argument, "addContact invalid message parameter", new DeviceApiError(errorcode.INVALID_VALUES_ERR));
111566
111567                 if (!_security.all && !_security.addContact)
111568                     return _errorOccurred(errorCallback, errorcode.SECURITY_ERR);
111569
111570                 c = TypeCoerce(new Contact()).cast(contact);
111571                 contactItems.push(c);
111572                 _save();
111573                 successCallback(c);
111574             }
111575             return wac2_utils.validateTypeMismatch(successCallback, errorCallback, "addContact", _pendingOperate(_addContact));
111576         },
111577
111578         updateContact: function (successCallback, errorCallback, contact) {
111579             function _updateContact() {
111580                 var c, isFound = false;
111581
111582                 if (!contact)
111583                     exception.raise(exception.types.Argument, "updateContact invalid message parameter", new DeviceApiError(errorcode.INVALID_VALUES_ERR));
111584
111585                 if (!_security.all && !_security.updateContact)
111586                     return _errorOccurred(errorCallback, errorcode.SECURITY_ERR);
111587
111588                 c = TypeCoerce(new Contact()).cast(contact);
111589                 utils.forEach(contactItems, function (contactItem) {
111590                     if (contactItem.id === c.id) {
111591                         !c.firstName    || (contactItem.firstName    = utils.copy(c.firstName));
111592                         !c.lastName     || (contactItem.lastName     = utils.copy(c.lastName));
111593                         !c.nicknames    || (contactItem.nicknames    = utils.copy(c.nicknames));
111594                         !c.phoneticName || (contactItem.phoneticName = utils.copy(c.phoneticName));
111595                         !c.addresses    || (contactItem.addresses    = utils.copy(c.addresses));
111596                         !c.photoURI     || (contactItem.photoURI     = utils.copy(c.photoURI));
111597                         !c.phoneNumbers || (contactItem.phoneNumbers = utils.copy(c.phoneNumbers));
111598                         !c.emails       || (contactItem.emails       = utils.copy(c.emails));
111599
111600                         _save();
111601                         isFound = true;
111602                         successCallback();
111603                     }
111604                 });
111605
111606                 if (!isFound)
111607                     _errorOccurred(errorCallback, errorcode.NOT_FOUND_ERR);
111608             }
111609             return wac2_utils.validateTypeMismatch(successCallback, errorCallback, "updateContact", _pendingOperate(_updateContact));
111610         },
111611
111612         deleteContact: function (successCallback, errorCallback, id) {
111613             function _deleteContact() {
111614                 var isFound = false;
111615
111616                 if (!_security.all && !_security.deleteContact)
111617                     return _errorOccurred(errorCallback, errorcode.SECURITY_ERR);
111618
111619                 utils.forEach(contactItems, function (contactItem, index) {
111620                     if (contactItem.id === id) {
111621                         contactItems.splice(index, 1);
111622                         _save();
111623                         isFound = true;
111624                         successCallback();
111625                     }
111626                 });
111627
111628                 if (!isFound)
111629                     _errorOccurred(errorCallback, errorcode.NOT_FOUND_ERR);
111630             }
111631             return wac2_utils.validateTypeMismatch(successCallback, errorCallback, "deleteContact", _pendingOperate(_deleteContact));
111632         },
111633
111634         findContacts: function (successCallback, errorCallback, filter) {
111635             function _findContacts() {
111636                 var contact, result = [];
111637
111638                 if (!_security.all && !_security.findContacts)
111639                     return _errorOccurred(errorCallback, errorcode.SECURITY_ERR);
111640
111641                 utils.forEach(contactItems, function (contactItem) {
111642                     if ((filter              === undefined || filter === null) ||
111643                         (filter.id           === undefined || Filter(filter.id).match(contactItem.id)) &&
111644                         (filter.firstName    === undefined || Filter(filter.firstName).match(contactItem.firstName)) &&
111645                         (filter.lastName     === undefined || Filter(filter.lastName).match(contactItem.lastName)) &&
111646                         (filter.phoneticName === undefined || Filter(filter.phoneticName).match(contactItem.phoneticName)) &&
111647                         (filter.nickname     === undefined || Filter(filter.nickname).match(contactItem.nicknames)) &&
111648                         (filter.phoneNumber  === undefined || Filter(filter.phoneNumber).match(contactItem.phoneNumbers)) &&
111649                         (filter.email        === undefined || Filter(filter.email).match(contactItem.emails)) &&
111650                         (filter.address      === undefined || Filter(filter.address).match(contactItem.addresses))) {
111651                         contact = new Contact(contactItem.id);
111652
111653                         contact.firstName    = utils.copy(contactItem.firstName);
111654                         contact.lastName     = utils.copy(contactItem.lastName);
111655                         contact.nicknames    = utils.copy(contactItem.nicknames);
111656                         contact.phoneticName = utils.copy(contactItem.phoneticName);
111657                         contact.addresses    = utils.copy(contactItem.addresses);
111658                         contact.photoURI     = utils.copy(contactItem.photoURI);
111659                         contact.phoneNumbers = utils.copy(contactItem.phoneNumbers);
111660                         contact.emails       = utils.copy(contactItem.emails);
111661
111662                         result.push(contact);
111663                     }
111664                 });
111665                 successCallback(result);
111666             }
111667             return wac2_utils.validateTypeMismatch(successCallback, errorCallback, "findContacts", _pendingOperate(_findContacts));
111668         }
111669     };
111670
111671     addressBook.__defineGetter__("type", function () {
111672         return type;
111673     });
111674
111675     addressBook.__defineGetter__("name", function () {
111676         return name;
111677     });
111678
111679     return addressBook;
111680 };
111681
111682 Address = {
111683     country: "",
111684     region: "",
111685     county: "",
111686     city: "",
111687     streetAddress: "",
111688     additionalInformation: "",
111689     postalCode: ""
111690 };
111691
111692 ContactAddress = function () {
111693     this.types = [""]; // "WORK", "PREF", "HOME"
111694 };
111695
111696 ContactAddress.prototype = Address;
111697
111698 PhoneNumber = {
111699     number: "",
111700     types: [""] // "WORK", "PREF", "HOME", "VOICE", "FAX", "MSG", "CELL",
111701                 // "PAGER", "BBS", "MODEM", "CAR", "ISDN", "VIDEO", "PCS"
111702 };
111703
111704 EmailAddress = {
111705     email: "",
111706     types: [""] // "WORK", "PREF", "HOME"
111707 };
111708
111709 ContactProperties = {
111710     firstName: "",
111711     lastName: "",
111712     nicknames: [""],
111713     phoneticName: "",
111714     addresses: [new ContactAddress()],
111715     photoURI: "",
111716     phoneNumbers: [PhoneNumber],
111717     emails: [EmailAddress]
111718 };
111719
111720 Contact = function (id) {
111721     id = id || Math.uuid(null, 16);
111722
111723     this.__defineGetter__("id", function () {
111724         return id;
111725     });
111726 };
111727
111728 Contact.prototype = ContactProperties;
111729
111730 ContactFilter = {
111731     id: "",
111732     firstName: "",
111733     lastName: "",
111734     phoneticName: "",
111735     nickname: "",
111736     phoneNumber: "",
111737     email: "",
111738     address: ""
111739 };
111740
111741 module.exports = _self;
111742
111743 });
111744 define('ripple/platform/wac/2.0/contactfilter', function (require, exports, module) {
111745 /*\r
111746  *  Copyright 2011 Intel Corporation.\r
111747  *\r
111748  * Licensed under the Apache License, Version 2.0 (the "License");\r
111749  * you may not use this file except in compliance with the License.\r
111750  * You may obtain a copy of the License at\r
111751  *\r
111752  * http://www.apache.org/licenses/LICENSE-2.0\r
111753  *\r
111754  * Unless required by applicable law or agreed to in writing, software\r
111755  * distributed under the License is distributed on an "AS IS" BASIS,\r
111756  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
111757  * See the License for the specific language governing permissions and\r
111758  * limitations under the License.\r
111759  */\r
111760 \r
111761 var utils = require('ripple/utils'),\r
111762     _self;\r
111763 \r
111764 _self = function (criteria) {\r
111765     var pattern,\r
111766         contactFilter;\r
111767 \r
111768     contactFilter = {\r
111769         match: function (target) {\r
111770             var result = false, key, value, index;\r
111771 \r
111772             switch (Object.prototype.toString.call(target)) {\r
111773             case "[object String]":\r
111774                 result = pattern.test(target);\r
111775                 break;\r
111776 \r
111777             case "[object Object]":\r
111778                 for (key in criteria) {\r
111779                     result = true;\r
111780                     value = criteria[key];\r
111781                     if ((value !== undefined) && (!_self(value).match(target[key])))\r
111782                         return false;\r
111783                 }\r
111784                 break;\r
111785 \r
111786             case "[object Array]":\r
111787                 for (index in target) {\r
111788                     if (contactFilter.match(target[index]))\r
111789                         return true;\r
111790                 }\r
111791                 break;\r
111792             }\r
111793 \r
111794             return result;\r
111795         }\r
111796     };\r
111797 \r
111798     if (typeof criteria === "string")\r
111799         pattern = new RegExp(criteria.replace(/(^|[^\\])%+/g, "$1.*").replace(/\\%/g, "%").replace(/.*/, "^$&$"), "i");\r
111800 \r
111801     return contactFilter;\r
111802 };\r
111803 \r
111804 module.exports = _self;\r
111805
111806 });
111807 define('ripple/platform/wac/2.0/dbfs', function (require, exports, module) {
111808 /*
111809  *  Copyright 2011 Research In Motion Limited.
111810  *  Copyright 2011 Intel Corporation.
111811  *
111812  * Licensed under the Apache License, Version 2.0 (the "License");
111813  * you may not use this file except in compliance with the License.
111814  * You may obtain a copy of the License at
111815  *
111816  * http://www.apache.org/licenses/LICENSE-2.0
111817  *
111818  * Unless required by applicable law or agreed to in writing, software
111819  * distributed under the License is distributed on an "AS IS" BASIS,
111820  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
111821  * See the License for the specific language governing permissions and
111822  * limitations under the License.
111823  */
111824
111825 /* We know the dbfs is not an accurate simulation of WAC 2.0 filesystem.
111826  *
111827  * 1) We have tried W3C File API, as some of WAC filesystem APIs are synchronous, 
111828  * it is impossible to simulate them by using the asynchronous API in the main
111829  * UI thread and although we could use synchronous W3C API in a worker, it is
111830  * not reasonable to limit WAC filesystem API usage in a worker.
111831  *
111832  * 2) The problem is partially solved by using database to simulate the filesystem,
111833  * For the asynchronous aspect, actually all the files are read into memory (cache 
111834  * object in this file) and the cache operation is synchronous. It is not perfect.
111835  * And the database has 5MB limitation when running in Chrome.
111836  *
111837  * In the future, we might use ajax or NPAPI to get a better simulation.
111838  */
111839
111840 /* Note: The entry object is shared between this module and filesystem */
111841
111842 var db = require('ripple/db'),
111843     utils = require('ripple/utils'),
111844     _console = require('ripple/console'),
111845     _cache = {},
111846     _self;
111847
111848 function _get(path) {
111849     return path.replace(/^\//, '').split("/").reduce(function (obj, token) {
111850         return token === "" ? obj : (obj.children ? obj.children[token] || null : null);
111851     }, _cache);
111852 }
111853
111854 function _getInfo(path) {
111855     var parent = ("/" + path.replace(/^\//, '').replace(/\/$/, '')).split("/"),
111856         name = parent.splice(parent.length - 1, 1).join("");
111857
111858     return {
111859         name: name,
111860         parent: parent.join("/") || "/"
111861     };
111862 }
111863
111864 function _set(path, obj) {
111865     var parent = _cache,
111866         tokens = path.replace(/^\//, '').split("/"),
111867         child = tokens.splice(tokens.length - 1, 1).join("");
111868
111869     tokens.forEach(function (token) {
111870         parent = parent.children[token];
111871     });
111872
111873     parent.children = parent.children || {};
111874     parent.children[child] = obj;
111875 }
111876
111877 function _delete(path) {
111878     var parent = _cache,
111879         tokens = path.replace(/^\//, '').split("/"),
111880         child = tokens.splice(tokens.length - 1, 1).join("");
111881
111882     tokens.forEach(function (token) {
111883         parent = parent.children[token];
111884     });
111885
111886     delete parent.children[child];
111887 }
111888
111889 function _save() {
111890     db.saveObject("wac2-db-filesystem", _cache);
111891 }
111892
111893 function _walk(path, parent) { 
111894     _self.ls(path, function (entries) { 
111895         parent.children = parent.children || {}; 
111896
111897         entries.forEach(function (entry) { 
111898             parent.children[entry.name] = entry; 
111899
111900             if (entry.isDirectory) { 
111901                 _walk(entry.fullPath, entry); 
111902             } else { 
111903                 /* after getting Date out of DB, Date will become 
111904                    a string, so need to recast it back to Date */
111905                 if (entry.lastModifiedDate !== null && entry.lastModifiedDate !== undefined)
111906                     entry.lastModifiedDate = new Date(entry.lastModifiedDate);
111907
111908                 _self.read(entry.fullPath, function (data) { 
111909                     parent.children[entry.name].data = data; 
111910                 }, function (e) { 
111911                     _console.error(e); 
111912                 }); 
111913             } 
111914         }); 
111915     }, function (e) { 
111916         _console.error(e); 
111917     }); 
111918
111919  
111920 function _createPath(path) { 
111921     var parts = path.replace(/^\//, '').split("/"), 
111922         workflow = jWorkflow.order(); 
111923  
111924     parts.forEach(function (part, index) { 
111925         var dir = "/" + utils.copy(parts).splice(0, index + 1).join("/"); 
111926  
111927         workflow.andThen(function (prev, baton) { 
111928             baton.take(); 
111929             _self.mkdir(dir, baton.pass, baton.pass); 
111930         }); 
111931     }); 
111932  
111933     workflow.start(); 
111934 }
111935
111936 _self = {
111937     // The order is consistent with _virtualRoots in filesystem.js
111938     roots: ["/opt/documents", "/opt/images", "/opt/music", "/opt/videos", "/opt/downloads", "/home/user/appdata/simulatedapp/wgt-package", "/home/user/appdata/simulatedapp/wgt-private", "/home/user/appdata/simulatedapp/wgt-private-tmp", "/SDCard", "/opt/attachments"],
111939     initialize: function () {
111940         // TODO: Initialize at bootstrap and emulatorBridge.link 
111941         _cache = db.retrieveObject("wac2-db-filesystem") || {};
111942         // create real root paths if empty
111943         _self.roots.every(function (root) {
111944             _createPath(root);
111945             return true;
111946         }); 
111947        // build the file system cache so that we could access information synchronously
111948         _walk("/", _cache);
111949     },
111950     ls: function (path, success, error) {
111951         try {
111952             var dir = _get(path),
111953                 items = [];
111954
111955             if (dir) {
111956                 utils.forEach(dir.children, function (item) {
111957                     items.push(item);
111958                 });
111959             }
111960             else {
111961                 items = {};
111962             }
111963
111964             success(items);
111965         }
111966         catch (e) {
111967             e.code = 1;
111968             error(e);
111969         }
111970     },
111971     rm: function (path, success, error, options) {
111972         _delete(path);
111973         _save();
111974         success();
111975     },
111976     rmdir: function (path, success, error, options) {
111977         _delete(path);
111978         _save();
111979         success();
111980     },
111981     mkdir: function (path, success, error) {
111982         var entry = _get(path),
111983             info = _getInfo(path);
111984
111985         if (!entry) {
111986             _set(path, {
111987                 name: info.name,
111988                 isDirectory: true,
111989                 fullPath: path
111990             });
111991             entry = _get(path);
111992             _save();
111993         }
111994         
111995         if (entry) {
111996             success(entry);
111997         }
111998         else {
111999             error({code: 1});
112000         }
112001     },
112002     mv: function (from, to, success, error) {
112003         try {
112004             var fromEntry = _get(from),
112005                 toInfo = _getInfo(to);
112006
112007             fromEntry.fullPath = to;
112008             fromEntry.name = toInfo.name;
112009
112010             _set(to, fromEntry);
112011             _delete(from);
112012             _save();
112013             success();
112014         }
112015         catch (e) {
112016             e.code = 1;
112017             error(e);
112018         }
112019     },
112020     touch: function (path, success, error) {
112021         var entry = _get(path),
112022             info  = _getInfo(path);
112023
112024         if (!entry) {
112025             _set(path, {
112026                 lastModifiedDate: new Date(),
112027                 name: info.name,
112028                 isDirectory: false,
112029                 fullPath: path,
112030                 data: ""
112031             });
112032             entry = _get(path);
112033         }
112034         _save();
112035         success(entry);
112036     },
112037     cp: function (from, to, success, error) {
112038         try {
112039             var fromEntry = _get(from),
112040                 copied = utils.copy(fromEntry);
112041
112042             copied.name  = _getInfo(to).name;
112043             copied.fullPath = to;
112044             _set(to, copied);
112045             _save();
112046             success();
112047         }
112048         catch (e) {
112049             e.code = 1;
112050             error(e);
112051         }
112052     },
112053     stat: function (path, success, error) {
112054         var entry = _get(path);
112055         
112056         if (entry) {
112057             success(entry);
112058         } else {
112059             error({code: 1});
112060         }
112061     },
112062     write: function (path, contents, success, error, options) {
112063         var entry = _get(path);
112064
112065         if (entry) {
112066             entry.lastModifiedDate = new Date();
112067             entry.data = contents;
112068             _save();
112069             success();
112070         } else {
112071             error({code: 1});
112072         }
112073
112074     },
112075     read: function (path, success, error) {
112076         var entry = _get(path);
112077
112078         if (entry) {
112079             success(utils.copy(entry.data));
112080         }
112081         else {
112082             error({code: 1});
112083         }
112084     }
112085 };
112086
112087 module.exports = _self;
112088
112089
112090 });
112091 define('ripple/platform/wac/2.0/deviceapierror', function (require, exports, module) {
112092 /*
112093  *  Copyright 2011 Intel Corporation.
112094  *
112095  * Licensed under the Apache License, Version 2.0 (the "License");
112096  * you may not use this file except in compliance with the License.
112097  * You may obtain a copy of the License at
112098  *
112099  * http://www.apache.org/licenses/LICENSE-2.0
112100  *
112101  * Unless required by applicable law or agreed to in writing, software
112102  * distributed under the License is distributed on an "AS IS" BASIS,
112103  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
112104  * See the License for the specific language governing permissions and
112105  * limitations under the License.
112106  */
112107
112108 var errorcode = require('ripple/platform/wac/2.0/errorcode');
112109
112110 module.exports = function (code) {
112111     for (var c in errorcode) {
112112         var g = errorcode.__lookupGetter__(c);
112113         if (g) {
112114             this.__defineGetter__(c, g);
112115         }
112116     }
112117
112118     this.code = code;
112119     this.message = errorcode.message[code];
112120     this.type =  "";
112121
112122     this.toString = function () {
112123         var result = this.type + ': "' + this.message + '"';
112124
112125         if (this.stack) {
112126             result += "\n" + this.stack;
112127         }
112128         return result;
112129     };
112130 };
112131
112132
112133 });
112134 define('ripple/platform/wac/2.0/deviceapis', function (require, exports, module) {
112135 /*
112136  *  Copyright 2011 Intel Corporation.
112137  *
112138  * Licensed under the Apache License, Version 2.0 (the "License");
112139  * you may not use this file except in compliance with the License.
112140  * You may obtain a copy of the License at
112141  *
112142  * http://www.apache.org/licenses/LICENSE-2.0
112143  *
112144  * Unless required by applicable law or agreed to in writing, software
112145  * distributed under the License is distributed on an "AS IS" BASIS,
112146  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
112147  * See the License for the specific language governing permissions and
112148  * limitations under the License.
112149  */
112150
112151 var platform = require('ripple/platform'),
112152     app = require('ripple/app'),
112153     utils = require('ripple/utils'),
112154     init_done = false,
112155     _activatedSet = {},
112156     _activatedFeatures = [],
112157     _availableSet = {},
112158     _availableFeatures = [],
112159     _features = {},
112160     initFeaturesSet,
112161     populateFeatures;
112162
112163 populateFeatures = function (objects) {
112164     utils.forEach(objects, function (obj, key) {
112165         var objFeatures = {}, rpt, i, j;
112166         if (obj.feature) {
112167             objFeatures = obj.feature.split('|');
112168             utils.forEach(objFeatures, function (feature) {
112169                 var avail = {uri: feature,
112170                              required: false,
112171                              param: null};
112172                 _availableSet[feature] = avail;
112173             });
112174             if (_features) {
112175                 rpt = objFeatures.length;
112176                 j = 0;
112177                 for (i = 0; i < rpt; i++) {
112178                     if (!_features[objFeatures[j]]) {
112179                         objFeatures.splice(j, 1);
112180                     } else {
112181                         j++;
112182                     }
112183                 }
112184             }
112185             utils.forEach(objFeatures, function (feature) {
112186                 var avail = {uri: feature,
112187                              required: true,
112188                              param: null};
112189                 _activatedSet[feature] = avail;
112190             });
112191         }
112192         if (obj.children) {
112193             populateFeatures(obj.children);
112194         }
112195     });
112196 };
112197
112198 initFeaturesSet = function () {
112199     _features = utils.copy(app.getInfo().features);
112200     populateFeatures(platform.current().objects);
112201     utils.forEach(_activatedSet, function (obj, key) {
112202             _activatedFeatures.push(obj);
112203         });
112204     utils.forEach(_availableSet, function (obj, key) {
112205             _availableFeatures.push(obj);
112206         });
112207     init_done = true;
112208 };
112209
112210 module.exports = {
112211     listAvailableFeatures: function () {
112212         if (!init_done)
112213             initFeaturesSet();
112214         return _availableFeatures;
112215     },
112216
112217     listActivatedFeatures: function () {
112218         if (!init_done)
112219             initFeaturesSet();
112220         return _activatedFeatures;
112221     }
112222 };
112223
112224
112225 });
112226 define('ripple/platform/wac/2.0/deviceinteraction', function (require, exports, module) {
112227 /*
112228  *  Copyright 2011 Intel Corporation.
112229  *
112230  * Licensed under the Apache License, Version 2.0 (the "License");
112231  * you may not use this file except in compliance with the License.
112232  * You may obtain a copy of the License at
112233  *
112234  * http://www.apache.org/licenses/LICENSE-2.0
112235  *
112236  * Unless required by applicable law or agreed to in writing, software
112237  * distributed under the License is distributed on an "AS IS" BASIS,
112238  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
112239  * See the License for the specific language governing permissions and
112240  * limitations under the License.
112241  */
112242
112243 var notifications = require('ripple/notifications'),
112244     constants = require('ripple/constants'),
112245     PendingOperation = require('ripple/platform/wac/2.0/pendingoperation'),
112246     PendingObject = require('ripple/platform/wac/2.0/pendingObject'),
112247     DeviceApiError = require('ripple/platform/wac/2.0/deviceapierror'),
112248     errorcode = require('ripple/platform/wac/2.0/errorcode'),
112249     utils = require('ripple/utils'),
112250     event = require('ripple/event'),
112251     deviceSettings = require('ripple/deviceSettings'),
112252     wac2_utils = require('ripple/platform/wac/2.0/wac2_utils'),
112253     _self,
112254     NOTIFY_DURATION_LIMIT = 5000;
112255
112256 function pendingOperation(f) {
112257     var _FAKEWAITTIME = 0,
112258         pendingObj;
112259     
112260     if (_FAKEWAITTIME === 0) {
112261         f();
112262         return undefined;
112263     }
112264     else {
112265         pendingObj = new PendingObject();
112266         pendingObj.pendingID = setTimeout(function () {
112267             pendingObj.setCancelFlag(false);
112268             f();
112269         }, _FAKEWAITTIME);
112270         return new PendingOperation(pendingObj);
112271     }
112272 }
112273
112274 function checkDuration(duration) {
112275     if (duration) {
112276         duration = duration | 0;  
112277         if (duration <= 0 || duration > NOTIFY_DURATION_LIMIT) {
112278             return NOTIFY_DURATION_LIMIT;
112279         } else {
112280             return duration;
112281         }
112282     } else {
112283         return NOTIFY_DURATION_LIMIT;
112284     }
112285 }
112286
112287 function isMute() {
112288     return deviceSettings.retrieve("Config.soundVolume") <= 0;
112289 }
112290
112291 function isInVibrateMode() {
112292     return deviceSettings.retrieve("Config.vibratingMode");
112293 }
112294
112295 function isBacklightOn() {
112296     return deviceSettings.retrieve("Config.backlight");
112297 }
112298
112299 var vibrator = (function () {
112300     var isVibrating = false,
112301         terminateAfterPattern = false,
112302         pattern = null,
112303         pulseIndex = 0,
112304         vibrateTimeout = null,
112305         terminateTimeout = null,
112306         MILLILSECONDS_OF_ONE_VIBRATION = 100,
112307         node = jQuery("#" + constants.COMMON.DEVICE_CONTAINER),
112308         movementIndex = 0,
112309         movement = [{ left: -10 }, { left: 0 }, { left: 10 }, { left: 0 },
112310              {top: -10 }, { top: 0 }, {top: 10 }, { top: 0 }];
112311
112312     function _clearTimeout() {
112313         if (vibrateTimeout) {
112314             clearInterval(vibrateTimeout);
112315             vibrateTimeout = null;        
112316         }
112317         if (terminateTimeout) {
112318             clearTimeout(terminateTimeout);
112319             terminateTimeout = null;        
112320         }
112321     }  
112322     
112323     function stopVibrate() {
112324         isVibrating = false;
112325         _clearTimeout();
112326         node.css({left: 0, top: 0}, MILLILSECONDS_OF_ONE_VIBRATION);
112327     }
112328     
112329     function vibrate() {
112330         //node.animate(movement[movementIndex], MILLILSECONDS_OF_ONE_VIBRATION);
112331         node.css(movement[movementIndex]);
112332         movementIndex = (movementIndex + 1) % 8;
112333     }
112334     
112335     function changePulse() {
112336         //pattern != null
112337         var pulse = pattern[pulseIndex];
112338         if (pulse === '.') vibrate();
112339         ++pulseIndex;
112340         if (pulseIndex >= pattern.length) {
112341             if (terminateAfterPattern) {
112342                 setTimeout(stopVibrate, 1);
112343                 return;
112344             }
112345             pulseIndex = 0;
112346         }
112347     }
112348     
112349     function terminateVibrate() {
112350         terminateAfterPattern = true;
112351         terminateTimeout = null;
112352         if (pattern === null) {
112353             stopVibrate();        
112354         }
112355     }  
112356   
112357     function startVibrate(duration, _pattern) {
112358         if (!isInVibrateMode()) return;
112359         _clearTimeout();
112360         terminateAfterPattern = false;
112361         movementIndex = 0;
112362         
112363         if (_pattern) {
112364             pattern = _pattern;
112365             pulseIndex = 0;
112366             vibrateTimeout = setInterval(changePulse, MILLILSECONDS_OF_ONE_VIBRATION);
112367             if (duration) 
112368                 terminateAfterPattern = false;
112369             else 
112370                 terminateAfterPattern = true;
112371         } else {
112372             pattern = null;
112373             vibrateTimeout = setInterval(vibrate, MILLILSECONDS_OF_ONE_VIBRATION);
112374         }
112375         terminateTimeout = setTimeout(terminateVibrate, checkDuration(duration));        
112376         isVibrating = true;
112377     }
112378
112379     event.on("VibratingModeChanged", function (value) {
112380         if (value === false) {
112381             stopVibrate();
112382         }
112383     });
112384
112385     return {
112386         startVibrate: startVibrate,
112387         stopVibrate: stopVibrate
112388     };
112389 }()); //jslint style
112390
112391 var backlight = (function () {
112392     var timeout = null,
112393         isNotifying = false,
112394         node = jQuery("#" + constants.COMMON.VIEWPORT_CONTAINER);
112395         
112396     function _clearTimeout() {
112397         if (timeout) {
112398             clearTimeout(timeout); 
112399             timeout = null;
112400         }
112401     }
112402     
112403     function _switch(on) {
112404         node.css('opacity', on ? '':'0.4');
112405     }
112406     
112407     function switchOff() {
112408         if (!isNotifying) return;
112409         _clearTimeout();
112410         _switch(false);
112411         isNotifying = false;
112412     }
112413     
112414     function switchOn(duration) {
112415         if (isBacklightOn()) return;
112416         _clearTimeout();
112417         _switch(true);
112418         timeout = setTimeout(switchOff, checkDuration(duration));
112419         isNotifying = true;
112420     }
112421
112422     _switch(isBacklightOn());
112423     event.on("BacklightChanged", function (value) {
112424         _clearTimeout();
112425         isNotifying = false;
112426         _switch(value);
112427     });
112428
112429     return {
112430         switchOn  : switchOn,
112431         switchOff : switchOff
112432     };
112433 }()); //jslint style
112434
112435 var beeper = (function () {
112436     var isBeeping = false,
112437         timeout = null,
112438         beepFile = "beep.wav", //TODO: license issues
112439         errorHandler = null,
112440         _beeper = utils.createElement("audio", {"id": "notify-beeper"});
112441         
112442     document.getElementById("ui").appendChild(_beeper);
112443     _beeper.setAttribute("src", beepFile);
112444     _beeper.setAttribute("loop", "true");
112445     _beeper.load();
112446     
112447     function _clearTimeout() {
112448         if (timeout) {
112449             clearTimeout(timeout);
112450             timeout = false;
112451         }
112452     }
112453     
112454     function raiseError() {
112455         if (errorHandler) {
112456             setTimeout(function () {
112457                 errorHandler(new DeviceApiError(errorcode.UNKNOWN_ERR));
112458             }, 1);
112459         }
112460     }
112461     
112462     function stopBeep() {
112463         _clearTimeout();
112464         if (isBeeping) {
112465             try {
112466                 _beeper.pause();
112467             } catch (e) {}
112468             isBeeping = false;
112469         }
112470     }
112471     
112472     _beeper.addEventListener('error', function () {
112473         stopBeep();
112474         raiseError();
112475     });
112476    
112477     function startBeep(onSuccess, onError, duration) {
112478         errorHandler = onError;
112479         try {
112480             stopBeep();
112481             _beeper.currentTime = 0;
112482             _beeper.play();
112483             isBeeping = true;
112484             timeout = setTimeout(stopBeep, checkDuration(duration));
112485             setTimeout(function () {
112486                 onSuccess();
112487             }, 1);
112488         }catch (e) {
112489             raiseError();
112490         }
112491     }
112492     
112493     event.on("VolumeChanged", function (value) {
112494         value = value | 0;
112495         if (value < 0) value = 0;
112496         else if (value > 100) value = 100;       
112497         _beeper.volume = value / 100.0;
112498     });
112499     
112500     return {
112501         startBeep : startBeep,
112502         stopBeep  : stopBeep
112503     };
112504 }()); //jslint style
112505
112506 module.exports = _self = {
112507
112508     startNotify : function (onSuccess, onError, duration) {
112509         return wac2_utils.validateTypeMismatch(onSuccess, onError, "startNotify", function () {
112510             if (!isMute()) {
112511                 return pendingOperation(function () {
112512                     beeper.startBeep(onSuccess, onError, duration);
112513                 });
112514             } else if (isInVibrateMode()) {
112515                 return _self.startVibrate(onSuccess, onError, duration);
112516             } else {
112517                 return _self.lightOn(onSuccess, onError, duration);
112518             }
112519         });
112520     },
112521
112522     stopNotify : function () {
112523         beeper.stopBeep();
112524         vibrator.stopVibrate();
112525         backlight.switchOff();
112526     },
112527
112528     startVibrate : function (onSuccess, onError, duration, pattern) {       
112529         return wac2_utils.validateTypeMismatch(onSuccess, onError, "startVibrate", function () {
112530             if (pattern) {
112531                 pattern = String(pattern);
112532                 if (!pattern.match(/[\._]{1,10}/)) {
112533                     if (onError) {
112534                         setTimeout(function () {
112535                             onError(new DeviceApiError(errorcode.INVALID_VALUES_ERR));
112536                         }, 1);
112537                     }
112538                     return undefined;
112539                 }   
112540             }
112541             
112542             if (!isInVibrateMode()) {
112543                 if (onError) {
112544                     setTimeout(function () {
112545                         onError(new DeviceApiError(errorcode.UNKNOWN_ERR));
112546                     }, 1);
112547                 }
112548                 return undefined;          
112549             }
112550   
112551             setTimeout(function () {
112552                 onSuccess();
112553             }, 1);
112554             return pendingOperation(function () {
112555                 vibrator.startVibrate(duration, pattern);
112556             });
112557
112558         });
112559     },
112560     
112561     stopVibrate : function () {
112562         vibrator.stopVibrate();
112563     },
112564
112565     lightOn : function (onSuccess, onError, duration) {
112566         return wac2_utils.validateTypeMismatch(onSuccess, onError, "lightOn", function () {
112567             if (isBacklightOn()) {
112568                 if (onError) {
112569                     setTimeout(function () {
112570                         onError(new DeviceApiError(errorcode.UNKNOWN_ERR));
112571                     }, 1);
112572                 }
112573                 return undefined;               
112574             }
112575         
112576             setTimeout(function () {
112577                 onSuccess();
112578             }, 1);
112579             return pendingOperation(function () {
112580                 backlight.switchOn(duration);
112581             });
112582         });
112583     },
112584
112585     lightOff : function () {
112586         backlight.switchOff();
112587     },
112588
112589     setWallpaper : function (onSuccess, onError, fileName) {
112590         //TODO: file name, existance, extension checking.
112591         return wac2_utils.validateTypeMismatch(onSuccess, onError, "setWallpaper", function () {
112592             return pendingOperation(function () {
112593                 notifications.openNotification("normal", "setWallpaper:" + fileName);
112594                 setTimeout(function () {
112595                     onSuccess();
112596                 }, 1);
112597             });
112598         });
112599     }
112600 };
112601
112602
112603 });
112604 define('ripple/platform/wac/2.0/devicestatus', function (require, exports, module) {
112605 /*
112606  *  Copyright 2011 Intel Corporation.
112607  *
112608  * Licensed under the Apache License, Version 2.0 (the "License");
112609  * you may not use this file except in compliance with the License.
112610  * You may obtain a copy of the License at
112611  *
112612  * http://www.apache.org/licenses/LICENSE-2.0
112613  *
112614  * Unless required by applicable law or agreed to in writing, software
112615  * distributed under the License is distributed on an "AS IS" BASIS,
112616  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
112617  * See the License for the specific language governing permissions and
112618  * limitations under the License.
112619  */
112620
112621 var utils = require('ripple/utils'),
112622     wac2_utils = require('ripple/platform/wac/2.0/wac2_utils'),
112623     errorcode = require('ripple/platform/wac/2.0/errorcode'),
112624     _console = require('ripple/console'),
112625     DeviceApiError = require('ripple/platform/wac/2.0/deviceapierror'),
112626     deviceSettings = require('ripple/deviceSettings'),    
112627     event = require('ripple/event'),    
112628     PendingOperation = require('ripple/platform/wac/2.0/pendingoperation'),
112629     PendingObject = require('ripple/platform/wac/2.0/pendingObject'),
112630     _getDeviceInfoAspect = true,
112631     _getNetworkInfoAspect = true,    
112632     _deviceInfoAspect = ["Battery", "Device", "Display", "MemoryUnit", "OperatingSystem", "WebRuntime"],    
112633     _networkInfoAspect = ["CellularHardware", "CellularNetwork", "WiFiHardware", "WiFiNetwork"],
112634     _aspectArray = [], 
112635     _propertyMap = {},
112636     _watches = {},
112637     _self;
112638
112639 function _asynchErrorCallback(errorCallback, errorCode) {
112640     if (errorCallback) {        
112641         setTimeout(function () {
112642             errorCallback(errorCode);
112643         }, 1);  
112644     }
112645 }
112646
112647 function _initialize() {
112648     var aspectName, index, i;
112649
112650     _aspectArray = _deviceInfoAspect.concat(_networkInfoAspect);
112651     for (index = 0; index < _aspectArray.length; index++) {
112652         aspectName = _aspectArray[index];
112653         _propertyMap[aspectName] = [];
112654         for (i in deviceSettings.retrieve(aspectName)) {
112655             _propertyMap[aspectName].push(i);
112656         }
112657     }     
112658 }
112659
112660 function _isPropertyFound(aspect, property) {
112661     if (_aspectArray.length === 0) {
112662         _initialize();
112663     }
112664
112665     if (_propertyMap[aspect]) {
112666         if (property) {
112667             return _propertyMap[aspect].some(function (prop) {
112668                 return prop === property;
112669             });
112670         }
112671         return true;
112672     }
112673     return false;
112674 }
112675
112676 function _isPropertyAllowed(aspect) {
112677     function hasAspect(asp) {
112678         return asp === aspect;
112679     }
112680
112681     if ((_deviceInfoAspect.some(hasAspect) && _getDeviceInfoAspect === false) ||
112682         (_networkInfoAspect.some(hasAspect) && _getNetworkInfoAspect === false)) {
112683         return false;
112684     }
112685
112686     return true;
112687 }
112688
112689 function _isPropertyValid(prop, errorCallback) {
112690     var _prop = Object(prop);
112691
112692     if (_prop && _prop.aspect && _prop.property) {
112693         if (_isPropertyFound(_prop.aspect, _prop.property) === false) {
112694             _asynchErrorCallback(errorCallback, new DeviceApiError(errorcode.NOT_FOUND_ERR));
112695             return false;
112696         }
112697         else if (_isPropertyAllowed(_prop.aspect) === false) {
112698             _asynchErrorCallback(errorCallback, new DeviceApiError(errorcode.SECURITY_ERR));
112699             return false;
112700         }
112701     } 
112702     else {
112703         _asynchErrorCallback(errorCallback, new DeviceApiError(errorcode.INVALID_VALUES_ERR));
112704         return false;
112705     }
112706     return true;
112707 }
112708
112709 module.exports = function () {
112710     return {  
112711         getComponents: function (aspect) {
112712             if (_isPropertyFound(aspect))
112713                 return ["_default"];
112714             return null;              
112715         },
112716
112717         isSupported: function (aspect, property) {
112718             return _isPropertyFound(aspect, property);
112719         },
112720
112721         getPropertyValue: function (successCallback, errorCallback, prop) {
112722             return wac2_utils.validateTypeMismatch(successCallback, errorCallback, "getPropertyValue", function () {                                  
112723                 if (_isPropertyValid(prop, errorCallback) !== true)
112724                     return undefined;
112725                 
112726                 var value = deviceSettings.retrieve(prop.aspect + "." + prop.property);
112727                 if (value !== undefined) {
112728                     successCallback(value, prop);
112729                 }
112730                 else {
112731                     _asynchErrorCallback(errorCallback, new DeviceApiError(errorcode.NOT_AVAILABLE_ERR)); 
112732                 }
112733                 
112734                 return null;    
112735             });        
112736         },
112737        
112738         watchPropertyChange: function (successCallback, errorCallback, prop, options) {  
112739             return wac2_utils.validateTypeMismatch(successCallback, errorCallback, "watchPropertyChange", function () {
112740                 if (_isPropertyValid(prop, errorCallback) !== true)
112741                     return undefined;
112742
112743                 var _options = Object(options),
112744                     eventType = deviceSettings.retrieve(prop.aspect)[prop.property].event,
112745                     watchObj = {
112746                         eventType: eventType,
112747                         onEvent: function (newValue) {
112748                             if (watchObj.timeStamp && 
112749                                 ((new Date()).getTime() - watchObj.timeStamp < options.minNotificationInterval)) {
112750                                 return undefined;
112751                             }                       
112752                             else if (watchObj.value &&
112753                                      (newValue > watchObj.value * (1 - _options.minChangePercent) && 
112754                                       newValue < watchObj.value * (1 + _options.minChangePercent))) {
112755                                 return undefined;
112756                             }
112757
112758                             if (watchObj.intervalId) {
112759                                 clearInterval(watchObj.intervalId);
112760                                 watchObj.intervalId = setInterval(function () {
112761                                     successCallback(deviceSettings.retrieve(prop.aspect + "." + prop.property), prop);
112762                                 }, _options.maxNotificationInterval);
112763                             }
112764                             successCallback(newValue, prop);
112765                             if (watchObj.timeStamp) {
112766                                 watchObj.timeStamp = (new Date()).getTime();
112767                             }
112768                             if (watchObj.value) {
112769                                 watchObj.value = newValue;
112770                             }
112771                         }                              
112772                     },
112773                     watchId = (new Date()).getTime() | 0;
112774
112775                 if (options && _options.minNotificationInterval && _options.maxNotificationInterval && 
112776                     (_options.minNotificationInterval < 0 || _options.maxNotificationInterval < 0 || 
112777                      _options.minNotificationInterval >= _options.maxNotificationInterval)) {
112778                     _asynchErrorCallback(errorCallback, new DeviceApiError(errorcode.INVALID_VALUES_ERR));
112779                     return undefined;
112780                 }
112781
112782                 if (options && _options.maxNotificationInterval) {
112783                     watchObj.intervalId = setInterval(function () {
112784                         successCallback(deviceSettings.retrieve(prop.aspect + "." + prop.property), prop);
112785                     }, _options.maxNotificationInterval);
112786                 }    
112787
112788                 if (options && _options.minNotificationInterval) {
112789                     watchObj.timeStamp = (new Date()).getTime();
112790                 }                    
112791
112792                 if (options && _options.minChangePercent) {
112793                     if (_options.minNotificationInterval || _options.maxNotificationInterval) {}
112794                     else {                
112795                         watchObj.value = deviceSettings.retrieve(prop.aspect + "." + prop.property);
112796                     }
112797                 }
112798                
112799                 _watches[watchId] = watchObj;
112800                 if (watchObj.eventType) {
112801                     event.on(watchObj.eventType, watchObj.onEvent);
112802                 }
112803
112804                 return watchId;
112805             });             
112806         },
112807
112808         clearPropertyChange: function (watchHandler) {
112809             var _handler = watchHandler | 0;
112810             
112811             if (_watches[_handler]) {
112812                 event.deleteEventHandler(_watches[_handler].eventType, _watches[_handler].onEvent);            
112813                 if (_watches[_handler].intervalId) {
112814                     clearInterval(_watches[_handler].intervalId);
112815                 }
112816                 delete(_watches[_handler]); 
112817             }
112818             return null;
112819         },
112820
112821         handleSubFeatures: function (subFeatures) {
112822             if (wac2_utils.isEmptyObject(subFeatures) ||
112823                 subFeatures["http://wacapps.net/api/devicestatus"] || 
112824                 (subFeatures["http://wacapps.net/api/devicestatus.deviceinfo"] &&
112825                  subFeatures["http://wacapps.net/api/devicestatus.networkinfo"])) {
112826                 return;
112827             }
112828             if (subFeatures["http://wacapps.net/api/devicestatus.deviceinfo"]) {
112829                 _getNetworkInfoAspect = false;
112830                 return;
112831             }
112832             if (subFeatures["http://wacapps.net/api/devicestatus.networkinfo"]) {
112833                 _getDeviceInfoAspect = false;
112834                 return;
112835             }
112836             _console.warn("WAC-2.0-Devicestatus-handleSubFeatures: something wrong");
112837         }
112838     };
112839 };
112840
112841
112842 });
112843 define('ripple/platform/wac/2.0/errorcode', function (require, exports, module) {
112844 /*
112845  *  Copyright 2011 Intel Corporation.
112846  *
112847  * Licensed under the Apache License, Version 2.0 (the "License"),
112848  * you may not use this file except in compliance with the License.
112849  * You may obtain a copy of the License at
112850  *
112851  * http://www.apache.org/licenses/LICENSE-2.0
112852  *
112853  * Unless required by applicable law or agreed to in writing, software
112854  * distributed under the License is distributed on an "AS IS" BASIS,
112855  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
112856  * See the License for the specific language governing permissions and
112857  * limitations under the License.
112858  */
112859
112860 var _self = {
112861     message : []
112862 };
112863
112864 _self.__defineGetter__("UNKNOWN_ERR", function () {
112865     return 0;
112866 });
112867
112868 _self.__defineGetter__("INDEX_SIZE_ERR", function () {
112869     return 1;
112870 });
112871
112872 _self.__defineGetter__("DOMSTRING_SIZE_ERR", function () {
112873     return 2;
112874 });
112875
112876 _self.__defineGetter__("HIERARCHY_REQUEST_ERR", function () {
112877     return 3;
112878 });
112879
112880 _self.__defineGetter__("WRONG_DOCUMENT_ERR", function () {
112881     return 4;
112882 });
112883
112884 _self.__defineGetter__("INVALID_CHARACTER_ERR", function () {
112885     return 5;
112886 });
112887
112888 _self.__defineGetter__("NO_DATA_ALLOWED_ERR", function () {
112889     return 6;
112890 });
112891
112892 _self.__defineGetter__("NO_MODIFICATION_ALLOWED_ERR", function () {
112893     return 7;
112894 });
112895
112896 _self.__defineGetter__("NOT_FOUND_ERR", function () {
112897     return 8;
112898 });
112899
112900 _self.__defineGetter__("NOT_SUPPORTED_ERR", function () {
112901     return 9;
112902 });
112903
112904 _self.__defineGetter__("INUSE_ATTRIBUTE_ERR", function () {
112905     return 10;
112906 });
112907
112908 _self.__defineGetter__("INVALID_STATE_ERR", function () {
112909     return 11;
112910 });
112911
112912 _self.__defineGetter__("SYNTAX_ERR", function () {
112913     return 12;
112914 });
112915
112916 _self.__defineGetter__("INVALID_MODIFICATION_ERR", function () {
112917     return 13;
112918 });
112919
112920 _self.__defineGetter__("NAMESPACE_ERR", function () {
112921     return 14;
112922 });
112923
112924 _self.__defineGetter__("INVALID_ACCESS_ERR", function () {
112925     return 15;
112926 });
112927
112928 _self.__defineGetter__("VALIDATION_ERR", function () {
112929     return 16;
112930 });
112931
112932 _self.__defineGetter__("TYPE_MISMATCH_ERR", function () {
112933     return 17;
112934 });
112935
112936 _self.__defineGetter__("SECURITY_ERR", function () {
112937     return 18;
112938 });
112939
112940 _self.__defineGetter__("NETWORK_ERR", function () {
112941     return 19;
112942 });
112943
112944 _self.__defineGetter__("ABORT_ERR", function () {
112945     return 20;
112946 });
112947
112948 _self.__defineGetter__("TIMEOUT_ERR", function () {
112949     return 21;
112950 });
112951
112952 _self.__defineGetter__("INVALID_VALUES_ERR", function () {
112953     return 22;
112954 });
112955
112956 _self.__defineGetter__("IO_ERR", function () {
112957     return 100;
112958 });
112959
112960 _self.__defineGetter__("NOT_AVAILABLE_ERR", function () {
112961     return 101;
112962 });
112963
112964 function _setMessage(_self) {
112965     var c, g;
112966     for (c in _self) {
112967         g = _self.__lookupGetter__(c);
112968         if (g) {
112969             _self.message[g()] = c;
112970         }
112971     }
112972 }
112973
112974 _setMessage(_self);
112975
112976 module.exports = _self;
112977
112978
112979 });
112980 define('ripple/platform/wac/2.0/filesystem', function (require, exports, module) {
112981 /*
112982  *  Copyright 2011 Intel Corporation.
112983  *
112984  * Licensed under the Apache License, Version 2.0 (the "License");
112985  * you may not use this file except in compliance with the License.
112986  * You may obtain a copy of the License at
112987  *
112988  * http://www.apache.org/licenses/LICENSE-2.0
112989  *
112990  * Unless required by applicable law or agreed to in writing, software
112991  * distributed under the License is distributed on an "AS IS" BASIS,
112992  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
112993  * See the License for the specific language governing permissions and
112994  * limitations under the License.
112995  */
112996
112997 var errorcode = require('ripple/platform/wac/2.0/errorcode'),
112998     DeviceApiError = require('ripple/platform/wac/2.0/deviceapierror'),
112999     utils = require('ripple/utils'),
113000     dbfs  = require('ripple/platform/wac/2.0/dbfs'),
113001     wac2_utils = require('ripple/platform/wac/2.0/wac2_utils'),
113002     _console = require('ripple/console'),
113003     _maxPathLength = 256,
113004     _virtualRoots = ["documents", "images", "music", "videos", "downloads", "wgt-package", "wgt-private", "wgt-private-tmp", "removable", "attachments"],
113005     _realRoots = dbfs.roots,
113006     _r2vmap = {},
113007     _v2rmap = {},
113008     _initialized = false,
113009     _readOnly  = false,
113010     _writeOnly = false,
113011     _defaultMode = "rw",
113012     File, 
113013     FileStream;
113014
113015 function _isValidChar(c) {
113016     return  (c >= '0' && c <= '9') || 
113017         (c >= 'a' && c <= 'z') || 
113018         (c >= 'A' && c <= 'Z') || 
113019         (c === ' ') || 
113020         (c === '_') ||
113021         (c === '-') ||
113022         (c === '.');
113023 }
113024
113025 function _isValidFileName(name) {
113026     var _valid = true,
113027         _c;
113028
113029     if (name === '' || name === '.' || name === '..' || (name.length > _maxPathLength)) {
113030         _valid = false;
113031     } else {
113032         for (_c = 0; _c < name.length; _c++) {
113033             if (!_isValidChar(name[_c])) {
113034                 _valid = false;
113035                 break;
113036             }
113037         }
113038     }
113039     
113040     return _valid;
113041 }
113042
113043 function _initialize() {
113044     var _i;
113045
113046     dbfs.initialize();
113047     
113048     // set up the map between real path and virtual path
113049     for (_i = 0; _i < _virtualRoots.length; _i++) {
113050         _r2vmap[_realRoots[_i]] = _virtualRoots[_i];
113051     }
113052
113053     utils.forEach(_r2vmap, function (value, key) {
113054         _v2rmap[value] = key;
113055     });
113056 }
113057
113058 function _resolveSync(srcLocation, onSuccess, onError, accessMode) {
113059     var _parts = srcLocation.replace(/\/$/, '').split("/"),
113060         _header, _fullPath,
113061         _i;
113062
113063     // TODO: Initialize at bootstrap and emulatorBridge.link 
113064     if (!_initialized) {
113065         _initialize();
113066         _initialized = true;
113067     }
113068
113069     for (_i = 0; _i < _parts.length; _i++) {
113070         if (!_isValidFileName(_parts[_i])) {
113071             if (onError) {
113072                 onError(new DeviceApiError(errorcode.INVALID_VALUES_ERR));
113073             }
113074             return;
113075         }
113076     }
113077
113078     _header = _v2rmap[_parts[0]];
113079     if (_header === undefined) {
113080         if (onError) {
113081             onError(new DeviceApiError(errorcode.NOT_FOUND_ERR));
113082         }
113083         return;
113084     }
113085
113086     if (_parts.length === 1) {
113087         _fullPath = _header;
113088     } else {
113089         _fullPath = _header + "/" + _parts.splice(1, _parts.length - 1).join("/");
113090     }
113091
113092     dbfs.stat(_fullPath, 
113093             function (entry) {
113094                 onSuccess(new File(entry, accessMode));
113095             }, 
113096             function () {
113097                 if (onError) {
113098                     onError(new DeviceApiError(errorcode.NOT_FOUND_ERR));
113099                 }    
113100             });
113101 }
113102
113103 function _resolveAsync(onSuccess, onError, srcLocation, accessMode) {
113104     _resolveSync(srcLocation,
113105                 function (file) {
113106                     setTimeout(function () {
113107                         onSuccess(file);
113108                     }, 1);
113109                 },
113110                 function (e) {
113111                     setTimeout(function () {
113112                         onError(e);
113113                     }, 1);
113114                 },
113115                 accessMode);
113116 }
113117
113118 File = function (entry, mode) {
113119     var _entry = entry,
113120         _mode = mode,
113121         _parent,
113122         _self;
113123
113124     function _r2v(rpath) {
113125         var i, v, r, regExp;
113126
113127         for (i = 0; i < _virtualRoots.length; i++) {
113128             v = _virtualRoots[i];
113129             r = _v2rmap[v];
113130             if (rpath.match("^" + r)) {
113131                 regExp = new RegExp("^" + r);
113132                 return rpath.replace(regExp, v);
113133             }
113134         }
113135
113136         return ""; 
113137     }
113138
113139     function _v2r(vpath) {
113140         var i, v, r, regExp;
113141
113142         for (i = 0; i < _virtualRoots.length; i++) {
113143             v = _virtualRoots[i];
113144             r = _v2rmap[v];
113145             if (vpath.match("^" + v)) {
113146                 regExp = new RegExp("^" + v);
113147                 return vpath.replace(regExp, r);
113148             }
113149         }
113150
113151         return ""; 
113152     }
113153
113154     function _copyMoveInternal(onSuccess, onError, src, dst, overwrite, func) {
113155         var _srcName = String(src),
113156             _dstName = String(dst),
113157             _src = null,
113158             _dst = null,
113159             _error = false,
113160             _dstParent = null,
113161             _dstParts  = _dstName.split("/"),
113162             _dstParentName = _dstParts.splice(0, _dstParts.length - 1).join("/");
113163
113164         if (!_entry.isDirectory) {
113165             if (onError) {
113166                 setTimeout(function () {
113167                     onError(new DeviceApiError(errorcode.IO_ERR));
113168                 }, 1);
113169             }
113170             return undefined;
113171         }
113172
113173         _resolveSync(_srcName, 
113174                 function (file) {
113175                     _src = file;
113176                 },
113177                 function (e) {
113178                     setTimeout(function () {
113179                         onError(e);
113180                     }, 1);
113181                 },
113182                 _mode);
113183
113184         if (_src) {
113185             if (_src.parent.fullPath === _self.fullPath) {
113186                 if (!_readOnly && _mode !== "r") {
113187                     _resolveSync(_dstParentName, 
113188                             function (file) {
113189                                 _dstParent = file;
113190                             },
113191                             function (e) {
113192                                 setTimeout(function () {
113193                                     onError(e);
113194                                 }, 1);
113195                             },
113196                             _mode);
113197
113198                     if (_dstParent === null) {
113199                         return undefined;
113200                     }
113201
113202                     _resolveSync(_dstName, 
113203                             function (file) {
113204                                 _dst = file;
113205                             },
113206                             function (e) {
113207                                 if (e.code !== errorcode.NOT_FOUND_ERR) {
113208                                     setTimeout(function () {
113209                                         onError(e);
113210                                     }, 1);
113211                                     _error = true;
113212                                 } 
113213                             },
113214                             _mode);
113215
113216                     if (_error) {
113217                         return undefined;
113218                     }
113219
113220                     if (_src.isFile) {
113221                         if (_dst === null) {
113222                             func(_v2r(_srcName), _v2r(_dstName),
113223                                     function () {
113224                                         setTimeout(function () {
113225                                             onSuccess();
113226                                         }, 1);
113227                                     },
113228                                     function () {});
113229                             return null;
113230                         } else {
113231                             if (_dst.isFile && Boolean(overwrite) && (_srcName !== _dstName)) {
113232                                 func(_v2r(_srcName), _v2r(_dstName),
113233                                         function () {
113234                                             setTimeout(function () {
113235                                                 onSuccess();
113236                                             }, 1);
113237                                         },
113238                                         function () {});
113239                                 return null;
113240                             } else {
113241                                 setTimeout(function () {
113242                                     onError(new DeviceApiError(errorcode.IO_ERR));
113243                                 }, 1);
113244                             }
113245                         }
113246                     } else {
113247                         if (_dst === null) {
113248                             func(_v2r(_srcName), _v2r(_dstName),
113249                                 function () {
113250                                     setTimeout(function () {
113251                                         onSuccess();
113252                                     }, 1);
113253                                 },
113254                                 function () {});
113255                             return null;
113256                         } else {
113257                             setTimeout(function () {
113258                                 onError(new DeviceApiError(errorcode.IO_ERR));
113259                             }, 1);
113260                         } 
113261                     }
113262                 } else {
113263                     if (onError) {
113264                         setTimeout(function () {
113265                             onError(new DeviceApiError(errorcode.SECURITY_ERR));
113266                         }, 1);
113267                     }
113268                 }
113269             } else {
113270                 if (onError) {
113271                     setTimeout(function () {
113272                         onError(new DeviceApiError(errorcode.IO_ERR));
113273                     }, 1);
113274                 }
113275             }
113276         }
113277
113278         return undefined;
113279     }
113280
113281     _self = {
113282         toURI: function () {
113283             return "file://" + _entry.fullPath;
113284         },
113285         listFiles: function (onSuccess, onError, filter) {
113286             var _filter = Object(filter),
113287                 _filterName = _filter.name,
113288                 _startModified = _filter.startModified,
113289                 _endModified   = _filter.endModified;
113290
113291             function _matchName(fileName) {
113292                 var _matched = true, 
113293                     _name1 = String(_filterName).toLowerCase(),
113294                     _name2 = fileName.toLowerCase(),
113295                     _pattern;
113296
113297                 if (_filterName !== undefined && _filterName !== null) {
113298                     if (!_name1.match("\\\\%")) {
113299                         if (_name1.match("%")) {
113300                             _pattern = new RegExp("^" + _name1.replace(/%/g, ".*") + "$");
113301                             _matched = _name2.match(_pattern) ? true : false;
113302                         } else {
113303                             _matched = (_name1 === _name2);
113304                         }
113305                     } else {
113306                         // % is not allowed as a part of file name
113307                         _matched = false;
113308                     }
113309                 }
113310                 
113311                 return _matched;
113312             }
113313
113314             function _matchDate(date) {
113315                 var _matched = true;
113316
113317                 if (_startModified !== undefined && _startModified !== null) {
113318                     _matched = (date.getTime() >= _startModified.getTime());
113319                 }
113320
113321                 if (_matched && (_endModified !== undefined && _endModified !== null)) {
113322                     _matched = (date.getTime() <= _endModified.getTime());
113323                 }
113324
113325                 return _matched;
113326             }
113327
113328             function _matchFilter(entry) {
113329                 return _matchName(entry.name) && _matchDate(entry.lastModifiedDate);
113330             } 
113331
113332             function _listFiles() {
113333                 var _files = [];
113334
113335                 if ((_startModified !== undefined && !wac2_utils.isValidDate(_startModified)) ||
113336                     (_endModified !== undefined && !wac2_utils.isValidDate(_endModified))) {
113337                     if (onError) {
113338                         setTimeout(function () {
113339                             onError(new DeviceApiError(errorcode.INVALID_VALUES_ERR));
113340                         }, 1);
113341                     }
113342                     return undefined;
113343                 }
113344
113345                 if (!_entry.isDirectory) {
113346                     if (onError) {
113347                         setTimeout(function () {
113348                             onError(new DeviceApiError(errorcode.IO_ERR));
113349                         }, 1);
113350                     }
113351                     return undefined;
113352                 }
113353
113354                 utils.forEach(_entry.children, function (child) {
113355                     if (_matchFilter(child)) {
113356                         _files.push(new File(child, _mode));
113357                     }
113358                 });
113359
113360                 setTimeout(function () {
113361                     onSuccess(_files);
113362                 }, 1);
113363
113364                 return null;
113365             }
113366
113367             return wac2_utils.validateTypeMismatch(onSuccess, onError, "listFiles", _listFiles);
113368         },
113369         openStream: function (onSuccess, onError, mode, encoding) {
113370             function _openStream() {
113371                 var  _openMode = String(mode),
113372                     _encoding = encoding ? String(encoding) : "UTF-8";
113373
113374                 if (_openMode !== "r" && _openMode !== "w" && _openMode !== "a") {
113375                     if (onError) {
113376                         setTimeout(function () {
113377                             onError(new DeviceApiError(errorcode.INVALID_VALUES_ERR));
113378                         }, 1);
113379                     }
113380                     return undefined;
113381                 }
113382                 if (_encoding !== "UTF-8" && _encoding !== "ISO-8859-1") {
113383                     if (onError) {
113384                         setTimeout(function () {
113385                             onError(new DeviceApiError(errorcode.INVALID_VALUES_ERR));
113386                         }, 1);
113387                     }
113388                     return undefined;
113389                 }
113390                 
113391                 if (((_readOnly || _mode === "r") && (_openMode === "w" || _openMode === "a")) ||
113392                     (_writeOnly && _openMode === "r")) {
113393                     if (onError) {
113394                         setTimeout(function () {
113395                             onError(new DeviceApiError(errorcode.SECURITY_ERR));
113396                         }, 1);
113397                     }
113398                     return undefined;
113399                 }
113400                  
113401                 setTimeout(function () {
113402                     onSuccess(new FileStream(_entry, _openMode, _encoding));
113403                 }, 1);
113404
113405                 return null;
113406             }
113407
113408             return wac2_utils.validateTypeMismatch(onSuccess, onError, "openStream", _openStream);
113409         },
113410         readAsText: function (onSuccess, onError, encoding) {
113411             function _readAsText() {
113412                 var _encoding = encoding ? String(encoding) : "UTF-8";
113413                 if (_encoding !== "UTF-8" && _encoding !== "ISO-8859-1") {
113414                     if (onError) {
113415                         setTimeout(function () {
113416                             onError(new DeviceApiError(errorcode.INVALID_VALUES_ERR));
113417                         }, 1);
113418                     }
113419                     return undefined;
113420                 }
113421
113422                 if (_writeOnly) {
113423                     if (onError) {
113424                         setTimeout(function () {
113425                             onError(new DeviceApiError(errorcode.SECURITY_ERR));
113426                         }, 1);
113427                     }
113428                     return undefined;
113429                 }
113430
113431                 if (_self.isFile) {
113432                     dbfs.read(_entry.fullPath, 
113433                             function (data) {
113434                                 setTimeout(function () {
113435                                     onSuccess(data);
113436                                 }, 1);
113437                             },
113438                             function () {});
113439                     return null;
113440                 } else {
113441                     if (onError) {
113442                         setTimeout(function () {
113443                             onError(new DeviceApiError(errorcode.IO_ERR));
113444                         }, 1);
113445                     }
113446                 }
113447
113448                 return undefined;
113449             }
113450
113451             return wac2_utils.validateTypeMismatch(onSuccess, onError, "readAsText", _readAsText);
113452         },
113453         copyTo: function (onSuccess, onError, src, dst, overwrite) {
113454             function _copyTo() {
113455                 return _copyMoveInternal(onSuccess, onError, src, dst, overwrite, dbfs.cp);
113456             }
113457             
113458             return wac2_utils.validateTypeMismatch(onSuccess, onError, "copyTo", _copyTo);
113459         },
113460         moveTo: function (onSuccess, onError, src, dst, overwrite) {
113461             function _moveTo() {
113462                 return _copyMoveInternal(onSuccess, onError, src, dst, overwrite, dbfs.mv);
113463             }
113464
113465             return wac2_utils.validateTypeMismatch(onSuccess, onError, "moveTo", _moveTo);
113466         },
113467         createDirectory: function (dirPath) {
113468             var _path  = String(dirPath),
113469                 _parts = _path.replace(/\/$/, "").split("/"),
113470                 _dir   = null,
113471                 _exist = null,
113472                 _current = _entry.fullPath,
113473                 _i;
113474
113475             function onSuccess(entry) {
113476                 _dir = entry;
113477             }
113478
113479             for (_i = 0; _i < _parts.length; _i++) {
113480                 if (!_isValidFileName(_parts[_i])) {
113481                     throw new DeviceApiError(errorcode.INVALID_VALUES_ERR);
113482                 }
113483             }
113484       
113485             if (!entry.isDirectory) {
113486                 throw new DeviceApiError(errorcode.IO_ERR);
113487             }
113488
113489             _exist = _parts.reduce(function (obj, token) {
113490                 return token === "" ? obj : (obj.children ? obj.children[token] || null : null);
113491             }, _entry);
113492
113493             if (_exist) {
113494                 throw new DeviceApiError(errorcode.IO_ERR);
113495             }
113496
113497             if (_readOnly || _mode === "r") {
113498                 throw new DeviceApiError(errorcode.SECURITY_ERR);
113499             }
113500
113501             for (_i = 0; _i < _parts.length; _i++) {
113502                 _current = _current + "/" + _parts[_i];
113503                 dbfs.mkdir(_current, onSuccess);
113504             }
113505             
113506             return new File(_dir, _mode);
113507         },
113508         createFile: function (filePath) {
113509             var _name = String(filePath),
113510                 _file = null;
113511
113512             if (!_isValidFileName(_name)) {
113513                 throw new DeviceApiError(errorcode.INVALID_VALUES_ERR);
113514             }
113515
113516             if (!entry.isDirectory || (_entry.children && _entry.children[_name])) {
113517                 throw new DeviceApiError(errorcode.IO_ERR);
113518             }
113519
113520             if (_readOnly || _mode === "r") {
113521                 throw new DeviceApiError(errorcode.SECURITY_ERR);
113522             }
113523
113524             dbfs.touch(_entry.fullPath + "/" + _name,
113525                         function (entry) {
113526                             _file = new File(entry, _mode);
113527                         },
113528                         function () {});
113529             
113530             return _file;
113531         },
113532         resolve: function (filePath) {
113533             var _fullPath = _self.fullPath + "/" + String(filePath),
113534                 _file = null;
113535  
113536             if (!_entry.isDirectory) {
113537                 throw new DeviceApiError(errorcode.IO_ERR); 
113538             }
113539
113540             _resolveSync(_fullPath,
113541                     function (file) {
113542                         _file = file;
113543                     },
113544                     function (e) {
113545                         throw (e);
113546                     },
113547                     _mode);
113548
113549             return _file;
113550         }, 
113551         deleteDirectory: function (onSuccess, onError, directory, recursive) {
113552             function _deleteDirectory() {
113553                 var _dir = null,
113554                     _dirName = String(directory);
113555                 _resolveSync(_dirName, 
113556                         function (file) {
113557                             _dir = file;
113558                         },
113559                         function (e) {
113560                             setTimeout(function () {
113561                                 onError(e);
113562                             }, 1);
113563                         },
113564                         _mode);
113565
113566                 if (_dir) {
113567                     if (_dir.isDirectory && 
113568                         _dir.parent.fullPath === _self.fullPath &&
113569                         (!recursive && _dir.length === 0)) {
113570                         if (!_readOnly && _mode !== "r") {
113571                             dbfs.rmdir(_v2r(_dirName),
113572                                     function () {
113573                                         setTimeout(function () {
113574                                             onSuccess();
113575                                         }, 1);
113576                                     },
113577                                     function () {});
113578                             return null;
113579                         } else {
113580                             if (onError) {
113581                                 setTimeout(function () {
113582                                     onError(new DeviceApiError(errorcode.SECURITY_ERR));
113583                                 }, 1);
113584                             }
113585                         }
113586                     } else {
113587                         if (onError) {
113588                             setTimeout(function () {
113589                                 onError(new DeviceApiError(errorcode.IO_ERR));
113590                             }, 1);
113591                         }
113592                     }
113593                 }
113594
113595                 return undefined; 
113596             }
113597
113598             return wac2_utils.validateTypeMismatch(onSuccess, onError, "deleteDirectory", _deleteDirectory);
113599         },
113600         deleteFile: function (onSuccess, onError, fileName) {
113601             function _deleteFile() {
113602                 var _file = null;
113603                 _resolveSync(String(fileName),
113604                         function (file) {
113605                             _file = file;
113606                         },
113607                         function (e) {
113608                             if (onError) {
113609                                 setTimeout(function () {
113610                                     onError(e);
113611                                 }, 1);
113612                             }
113613                         },
113614                         _mode);
113615
113616                 if (_file) {
113617                     if (_file.isFile && _file.parent.fullPath === _self.fullPath) {
113618                         if (!_readOnly && _mode !== "r") {
113619                             dbfs.rm(_v2r(fileName),
113620                                     function () {
113621                                         setTimeout(function () {
113622                                             onSuccess();
113623                                         }, 1);
113624                                     },
113625                                     function () {});
113626                             return null;
113627                         } else {
113628                             if (onError) {
113629                                 setTimeout(function () {
113630                                     onError(new DeviceApiError(errorcode.SECURITY_ERR));
113631                                 }, 1);
113632                             }
113633                         }
113634                     } else {
113635                         if (onError) {
113636                             setTimeout(function () {
113637                                 onError(new DeviceApiError(errorcode.IO_ERR));
113638                             }, 1);
113639                         }
113640                     }
113641                 }
113642
113643                 return undefined; 
113644             }
113645
113646             return wac2_utils.validateTypeMismatch(onSuccess, onError, "deleteFile", _deleteFile);
113647         }
113648     };
113649
113650     _self.__defineGetter__("parent", function () {
113651         var _parts = _self.fullPath.split("/");
113652
113653         if (_parent === undefined) {
113654             if (_parts.length === 1) {
113655                 // virtual root's parent is null
113656                 _parent = null;
113657             } else {
113658                 _resolveSync(_parts.splice(0, _parts.length - 1).join("/"), 
113659                         function (file) {
113660                             _parent = file;
113661                         },
113662                         function () {},
113663                         _mode);
113664             }
113665             return _parent;
113666         } else { 
113667             return _parent;
113668         }
113669     });
113670
113671     _self.__defineGetter__("readOnly", function () {
113672         return false;
113673     });
113674
113675     _self.__defineGetter__("isFile", function () {
113676         return !_entry.isDirectory;
113677     });
113678
113679     _self.__defineGetter__("isDirectory", function () {
113680         return _entry.isDirectory;
113681     });
113682
113683     _self.__defineGetter__("created", function () {
113684         return undefined;
113685     });
113686
113687     _self.__defineGetter__("modified", function () {
113688         if (_entry.isDirectory) {
113689             return undefined;
113690         } else {
113691             return _entry.lastModifiedDate;
113692         }
113693     });
113694
113695     _self.__defineGetter__("path", function () {
113696         var _parts = _self.fullPath.split("/");
113697
113698         if (_parts.length === 1) {
113699             // virtual root
113700             return _parts.join("");
113701         } else {
113702             return _parts.splice(0, _parts.length - 1).join("/") + "/";
113703         }
113704     });
113705
113706     _self.__defineGetter__("name", function () {
113707         return _entry.name;
113708     });
113709
113710     _self.__defineGetter__("fullPath", function () {
113711         return _r2v(_entry.fullPath);
113712     });
113713
113714     _self.__defineGetter__("fileSize", function () {
113715         if (_entry.isDirectory) {
113716             return undefined;
113717         } else {
113718             return _entry.data.length;
113719         }
113720     });
113721
113722     _self.__defineGetter__("length", function () {
113723         var _l = 0;
113724         if (_entry.isDirectory) {
113725             utils.forEach(_entry.children, function () {
113726                 _l++;
113727             });
113728             return _l;
113729         } else {
113730             return undefined;
113731         }
113732     });
113733
113734     return _self;
113735 };
113736
113737 FileStream = function (entry, mode, encoding) {
113738     var _entry = entry,
113739         _data = entry.data,
113740         _mode = mode,
113741         _position = (_mode === "a" ? _data.length : 0),
113742         _self;
113743
113744     _self = {
113745         close: function () {
113746             var _element;
113747             if (mode === "a" || mode === "w") {
113748                 dbfs.write(_entry.fullPath, _data, function () {}, function () {});
113749             }
113750             for (_element in _self) {
113751                 delete _self[_element];
113752             }
113753         },
113754         read: function (charCount) {
113755             var _count  = charCount | 0,
113756                 _substr = _data.substring(_position, _position + _count);
113757
113758             if (_position + _count > _data.length) {
113759                 _position = _data.length;
113760             } else {
113761                 _position += _count;
113762             }
113763
113764             return _substr; 
113765         },
113766         readBytes: function (byteCount) {
113767             var _substr = _self.read(byteCount),
113768                 _bytes = [],
113769                 _i;
113770
113771             for (_i = 0; _i < _substr.length; _i++) {
113772                 _bytes.push(_substr.charCodeAt(_i));
113773             }
113774
113775             return _bytes;
113776         },
113777         readBase64: function (byteCount) {
113778             var _substr = _self.read(byteCount);
113779
113780             return window.atob(_substr);
113781         },
113782         write: function (stringData) {
113783             var _stringData = String(stringData),
113784                 _substr = _data.substring(0, _position);
113785
113786             _data = _substr.concat(_stringData);
113787             _position = _data.length;
113788         },
113789         writeBytes: function (byteData) {
113790             _self.write(String.fromCharCode.apply(String, byteData));
113791         },
113792         writeBase64: function (base64Data) {
113793             _self.write(window.btoa(String(base64Data)));
113794         }
113795     };
113796
113797     _self.__defineGetter__("eof", function () {
113798         return _position === _data.length;
113799     });
113800
113801     _self.__defineGetter__("position", function () {
113802         return _position;
113803     });
113804
113805     _self.__defineSetter__("position", function (value) {
113806         var _value = value | 0;
113807
113808         if (_value >= 0 && _value <= _data.length) {
113809             _position = _value;
113810         } else {
113811             throw new DeviceApiError(errorcode.INVALID_VALUES_ERR);
113812         }
113813     });
113814
113815     _self.__defineGetter__("bytesAvailable", function () {
113816         return (_data.length - _position) || -1;
113817     });
113818
113819     return _self;
113820 };
113821
113822 module.exports = function () {
113823     return {
113824         maxPathLength: _maxPathLength,
113825         resolve: function (onSuccess, onError, srcLocation, accessMode) {
113826             function _resolve() {
113827                 var _mode = accessMode ? String(accessMode) : _defaultMode;
113828
113829                 if (_mode === "r" || _mode === "rw") {
113830                     _resolveAsync(onSuccess, onError, String(srcLocation), _mode);
113831                     return null;
113832                 } else {
113833                     if (onError) {
113834                         setTimeout(function () {
113835                             onError(new DeviceApiError(errorcode.INVALID_VALUES_ERR));
113836                         }, 1);
113837                     }
113838                 }
113839                 return undefined;
113840             }
113841
113842             return wac2_utils.validateTypeMismatch(onSuccess, onError, "resolve", _resolve);
113843         },
113844         handleSubFeatures: function (subFeatures) {
113845             if (wac2_utils.isEmptyObject(subFeatures) ||
113846                 subFeatures["http://wacapps.net/api/filesystem"] ||
113847                 (subFeatures["http://wacapps.net/api/filesystem.read"] &&
113848                 subFeatures["http://wacapps.net/api/filesystem.write"])) {
113849                 return;
113850             }
113851             if (subFeatures["http://wacapps.net/api/filesystem.read"]) {
113852                 _readOnly = true;
113853                 return;
113854             }
113855             if (subFeatures["http://wacapps.net/api/filesystem.write"]) {
113856                 _writeOnly = true;
113857                 return;
113858             }
113859             _console.warn("WAC-2.0-Filesystem: something wrong in handleSubFeatures");
113860         }
113861     }; 
113862 };
113863
113864
113865 });
113866 define('ripple/platform/wac/2.0/geolocation', function (require, exports, module) {
113867 /*
113868  *  Copyright 2011 Intel Corporation.
113869  *
113870  * Licensed under the Apache License, Version 2.0 (the "License");
113871  * you may not use this file except in compliance with the License.
113872  * You may obtain a copy of the License at
113873  *
113874  * http://www.apache.org/licenses/LICENSE-2.0
113875  *
113876  * Unless required by applicable law or agreed to in writing, software
113877  * distributed under the License is distributed on an "AS IS" BASIS,
113878  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
113879  * See the License for the specific language governing permissions and
113880  * limitations under the License.
113881  */
113882
113883 var geo = require('ripple/geo'),
113884     Position = require('ripple/platform/w3c/1.0/Position'),
113885     PositionError = require('ripple/platform/w3c/1.0/PositionError'),
113886     _lastPosition = null,
113887     _watches = {},
113888     _defaultInterval = 100,
113889     _defaultDelay = 50,
113890     _self;
113891
113892 function _createPosition() {
113893     var position = new Position(),
113894         positionInfo = geo.getPositionInfo();
113895
113896     position.coords.latitude = positionInfo.latitude;
113897     position.coords.longitude = positionInfo.longitude;
113898     position.coords.altitude = positionInfo.altitude;
113899     position.coords.altitudeAccuracy = positionInfo.altitudeAccuracy;
113900     position.coords.accuracy = positionInfo.accuracy;
113901     position.coords.heading = positionInfo.heading;
113902     position.coords.speed = positionInfo.speed;
113903     position.timestamp = positionInfo.timeStamp.getTime();
113904
113905     return position;
113906 }
113907
113908 function _isValid(onSuccess, onError, options, argLength) {
113909     if (argLength < 1 || argLength > 3)
113910         return false;
113911
113912     if (typeof onSuccess !== "function")   // imply onSuccess == null
113913         return false;
113914
113915     if (onError && (typeof onError !== "function"))
113916         return false;
113917
113918     if ((options !== undefined) &&
113919         ((typeof options !== "object") ||
113920         (options.enableHighAccuracy !== undefined) && (typeof options.enableHighAccuracy !== "boolean") ||
113921         (options.timeout            !== undefined) && (typeof options.timeout            !== "number") ||
113922         (options.maximumAge         !== undefined) && (typeof options.maximumAge         !== "number")))
113923         return false;
113924
113925     return true;
113926 }
113927
113928 function _processOptions(options) {
113929     var validOptions = {
113930         enableHighAccuracy: false,
113931         timeout: 0,
113932         maximumAge: 0
113933     };
113934
113935     if (options !== undefined &&
113936         options.maximumAge !== undefined &&
113937         options.maximumAge === Math.floor(options.maximumAge) &&
113938         options.maximumAge >= 0) {
113939         validOptions.maximumAge = options.maximumAge | 0;
113940     } else {
113941         validOptions.maximumAge = 0;
113942     }
113943
113944     if (options !== undefined &&
113945         options.timeout !== undefined &&
113946         options.timeout === Math.floor(options.timeout)) {
113947         validOptions.timeout = (options.timeout >= 0) ? (options.timeout | 0) : 0;
113948     } else {
113949         validOptions.timeout = Infinity;
113950     }
113951
113952     if (options !== undefined && options.enableHighAccuracy !== undefined) {
113953         validOptions.enableHighAccuracy = options.enableHighAccuracy;
113954     } else {
113955         validOptions.enableHighAccuracy = false;
113956     }
113957
113958     validOptions.delay = geo.delay * 1000 || _defaultDelay;
113959
113960     return validOptions;
113961 }
113962
113963 function _errorOccur(code, onError) {
113964     if (!onError)
113965         return;
113966
113967     var error = new PositionError();
113968
113969     error.code = code;
113970     switch (code) {
113971     case PositionError.POSITION_UNAVAILABLE:
113972         error.message = "Position unavailable";
113973         break;
113974
113975     case PositionError.TIMEOUT:
113976         error.message = "Position timed out";
113977         break;
113978     }
113979
113980     onError(error);
113981 }
113982
113983 function _execute(data) {
113984     return function () {
113985         if (_lastPosition !== null &&
113986             ((new Date()).getTime() - _lastPosition.timestamp <= data.maximumAge)) {
113987             window.setTimeout(function () {
113988                 data.onSuccess(_lastPosition);
113989             }, 1);
113990         } else if (data.timeout === 0) {
113991             _errorOccur(PositionError.TIMEOUT, data.onError);
113992         } else {
113993             window.setTimeout(function () {
113994                 if (data.delay <= data.timeout) {
113995                     _lastPosition = _createPosition();
113996
113997                     if (_lastPosition !== null) {
113998                         data.onSuccess(_lastPosition);
113999                     } else {
114000                         _errorOccur(PositionError.POSITION_UNAVAILABLE, data.onError);
114001                     }
114002                 } else {
114003                     _errorOccur(PositionError.TIMEOUT, data.onError);
114004                 }
114005             }, Math.min(data.delay, data.timeout));
114006         }
114007     };
114008 }
114009
114010 function _interval(k, n) { 
114011     return k * Math.floor((n + k - 1) / k) || k;
114012 }
114013
114014 _self = {
114015     getCurrentPosition: function (onSuccess, onError, options) {
114016         if (!_isValid(onSuccess, onError, options, arguments.length))
114017             return;
114018
114019         var validData = _processOptions(options);
114020
114021         validData.onSuccess = onSuccess;
114022         validData.onError   = onError;
114023
114024         _execute(validData)();
114025     },
114026
114027     watchPosition: function (geolocationSuccess, geolocationError, geolocationOptions) {
114028         if (!_isValid(geolocationSuccess, geolocationError, geolocationOptions, arguments.length))
114029             return undefined;
114030
114031         var validData = _processOptions(geolocationOptions),
114032             watchId = (new Date()).getTime() | 0,
114033             watchObj = {
114034                 onSuccess:          geolocationSuccess,
114035                 onError:            geolocationError,
114036                 enableHighAccuracy: validData.enableHighAccuracy,
114037                 timeout:            validData.timeout,
114038                 maximumAge:         validData.maximumAge,
114039                 delay:              validData.delay,
114040                 interval:           _interval(validData.maximumAge || _defaultInterval,
114041                                         Math.min(validData.delay, validData.timeout)),
114042             };
114043
114044         _watches[watchId] = watchObj;
114045
114046         _watches[watchId].intervalId = window.setInterval(_execute(_watches[watchId]),
114047             _watches[watchId].interval);
114048
114049         return watchId;
114050     },
114051
114052     clearWatch: function (watchId) {
114053         if (arguments.length !== 1)
114054             return undefined;
114055
114056         var id = watchId | 0;
114057
114058         if (_watches[id]) {
114059             window.clearInterval(_watches[id].intervalId);
114060             delete _watches[id];
114061
114062             return null;
114063         }
114064
114065         return undefined;
114066     }
114067 };
114068
114069 module.exports = _self;
114070
114071 });
114072 define('ripple/platform/wac/2.0/messagefilter', function (require, exports, module) {
114073 /*
114074  *  Copyright 2011 Intel Corporation.
114075  *
114076  * Licensed under the Apache License, Version 2.0 (the "License");
114077  * you may not use this file except in compliance with the License.
114078  * You may obtain a copy of the License at
114079  *
114080  * http://www.apache.org/licenses/LICENSE-2.0
114081  *
114082  * Unless required by applicable law or agreed to in writing, software
114083  * distributed under the License is distributed on an "AS IS" BASIS,
114084  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
114085  * See the License for the specific language governing permissions and
114086  * limitations under the License.
114087  */
114088
114089 var _self;
114090
114091 _self = function (criteria) {
114092     var pattern,
114093         messageFilter;
114094
114095     messageFilter = {
114096         match: function (target) {
114097             var result = false, index;
114098
114099             if (Object.prototype.toString.call(criteria) === "[object Array]") {
114100                 for (index in criteria) {
114101                     if (_self(criteria[index]).match(target))
114102                         return true;
114103                 }
114104                 return false;
114105             }
114106
114107             switch (Object.prototype.toString.call(target)) {
114108             case "[object Number]":
114109                 result = (criteria === target);
114110                 break;
114111
114112             case "[object String]":
114113                 result = pattern.test(target);
114114                 break;
114115
114116             case "[object Array]":
114117                 for (index in target) {
114118                     if (messageFilter.match(target[index]))
114119                         return true;
114120                 }
114121                 break;
114122             }
114123
114124             return result;
114125         }
114126     };
114127
114128     if (typeof criteria === "string")
114129         pattern = new RegExp(criteria.replace(/(^|[^\\])%+/g, "$1.*").replace(/\\%/g, "%").replace(/.*/, "^$&$"), "i");
114130
114131     return messageFilter;
114132 };
114133
114134 module.exports = _self;
114135
114136 });
114137 define('ripple/platform/wac/2.0/messaging', function (require, exports, module) {
114138 /*
114139  *  Copyright 2011 Intel Corporation.
114140  *
114141  * Licensed under the Apache License, Version 2.0 (the "License");
114142  * you may not use this file except in compliance with the License.
114143  * You may obtain a copy of the License at
114144  *
114145  * http://www.apache.org/licenses/LICENSE-2.0
114146  *
114147  * Unless required by applicable law or agreed to in writing, software
114148  * distributed under the License is distributed on an "AS IS" BASIS,
114149  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
114150  * See the License for the specific language governing permissions and
114151  * limitations under the License.
114152  */
114153
114154 var utils = require('ripple/utils'),
114155     event = require('ripple/event'),
114156     db = require('ripple/db'),
114157     exception = require('ripple/exception'),
114158     errorcode = require('ripple/platform/wac/2.0/errorcode'),
114159     wac2_utils = require('ripple/platform/wac/2.0/wac2_utils'),
114160     DeviceApiError = require('ripple/platform/wac/2.0/deviceapierror'),
114161     PendingOperation = require('ripple/platform/wac/2.0/pendingoperation'),
114162     PendingObject = require('ripple/platform/wac/2.0/pendingObject'),
114163     TypeCoerce = require('ripple/platform/wac/2.0/typecoerce'),
114164     Filter = require('ripple/platform/wac/2.0/messagefilter'),
114165     FileSystem = require('ripple/platform/wac/2.0/filesystem'),
114166     MessageSendCallback,
114167     Message,
114168     MessageFilter,
114169     Recipients,
114170     _KEY = "wac2-pim-messaging",
114171     _PENDING_TIME = 600,
114172     _messages = {},
114173     _subscriber = {
114174         onSMS: {},
114175         onMMS: {},
114176         onEmail: {}
114177     },
114178     _sentStatus = {},
114179     _security = {
114180         "http://wacapps.net/api/messaging": [],
114181         "http://wacapps.net/api/messaging.send": ["sendMessage"],
114182         "http://wacapps.net/api/messaging.find": ["findMessages"],
114183         "http://wacapps.net/api/messaging.subscribe": ["onSMS", "onMMS", "onEmail"],
114184         "http://wacapps.net/api/messaging.write": ["update"],
114185         all: true
114186     },
114187     _fileSystem,
114188     _initialized = false,
114189     _self;
114190
114191 function _initialize() {
114192     _get();
114193     if (!_fileSystem) {
114194         _fileSystem = new FileSystem();
114195     }
114196     _initialized = true;
114197 }
114198
114199 function _get() {
114200     _messages = db.retrieveObject(_KEY) || {1: [], 2: [], 3: [], 4: []};
114201     utils.forEach(_messages, function (folder) {
114202         utils.forEach(folder, function (messageItem) {
114203             if (messageItem.timestamp)
114204                 messageItem.timestamp = new Date(messageItem.timestamp);
114205         });
114206     });
114207 }
114208
114209 function _save() {
114210     db.saveObject(_KEY, _messages);
114211 }
114212
114213 function _updateDB(message, duplicate) {
114214     _get();
114215     _messages[message.folder].push(message);
114216     if (duplicate)
114217         _messages[duplicate.folder].push(duplicate);
114218     _save();
114219 }
114220
114221 function _processAttachments(message) {
114222     var attachmentsFileName = [],
114223         attachmentsContent = [];
114224
114225     function _generateAttachmentFileName(attachment) {
114226         var lastDot = attachment.filename.lastIndexOf(".");
114227         return attachment.filename.substring(0, lastDot) + "_" + Math.uuid(8, 16) + attachment.filename.substring(lastDot);
114228     }
114229
114230     function _onResolveSuccess(file) {
114231         var fileAttachment = file.createFile(attachmentsFileName[0]);
114232
114233         fileAttachment.openStream(
114234             function (fs) {
114235                 fs.write(attachmentsContent[0]);
114236                 fs.close();
114237             }, null, "w");
114238     }
114239
114240     function _onResolveError() {
114241     }
114242
114243     if (message.attachments.length === 0)
114244         return;
114245
114246     attachmentsFileName.push(_generateAttachmentFileName(message.attachments[0]));
114247     attachmentsContent.push(message.attachments[0].content);
114248
114249     _fileSystem.resolve(_onResolveSuccess, _onResolveError, "attachments", "rw");
114250
114251     message.attachments = utils.copy(attachmentsFileName);
114252 }
114253
114254 function _errorOccurred(onError, code) {
114255     if (!onError)
114256         return;
114257
114258     setTimeout(function () {
114259         onError(new DeviceApiError(code));
114260     }, 1);
114261 }
114262
114263 function _pendingOperate(operate, scope) {
114264     var i, argumentVector = [];
114265
114266     for (i = 0; i < arguments.length - 2; i++)
114267         argumentVector[i] = arguments[i + 2];
114268
114269     return function () {
114270         var pendingObj, pendingOperation;
114271
114272         pendingObj = new PendingObject();
114273         pendingObj.pendingID = window.setTimeout(function () {
114274             pendingObj.setCancelFlag(false);
114275             if (operate)
114276                 operate.apply(scope, argumentVector);
114277         }, _PENDING_TIME);
114278
114279         pendingOperation = new PendingOperation(pendingObj);
114280
114281         return pendingOperation;
114282     };
114283 }
114284
114285 function _onMessage(onMessage, messageHandler) {
114286     if (!messageHandler)
114287         exception.raise(exception.types.Argument,
114288             onMessage + " invalid messageHandler parameter",
114289             new DeviceApiError(errorcode.INVALID_VALUES_ERR));
114290
114291     utils.validateArgumentType(messageHandler, "function", null,
114292         "messageHandler invalid function parameter",
114293         new DeviceApiError(errorcode.TYPE_MISMATCH_ERR));
114294
114295     if (!_security.all && !_security[onMessage])
114296         exception.raise(exception.types.Argument,
114297             onMessage + " access denied", new DeviceApiError(errorcode.SECURITY_ERR));
114298
114299     var idSubscribe = (new Date()).getTime() | 0;
114300     _subscriber[onMessage][idSubscribe] = messageHandler;
114301
114302     return idSubscribe;
114303 }
114304
114305 function _validateRecipients(message) {
114306     var i;
114307
114308     for (i = 0; i < message.to.length;) {
114309         message.to[i] = message.to[i].replace(/^\s*(\S*)\s*$/, '$1');
114310         if (message.to[i] === "")
114311             message.to.splice(i, 1);
114312         else
114313             i++;
114314     }
114315     for (i = 0; i < message.cc.length;) {
114316         message.cc[i] = message.cc[i].replace(/^\s*(\S*)\s*$/, '$1');
114317         if (message.cc[i] === "")
114318             message.cc.splice(i, 1);
114319         else
114320             i++;
114321     }
114322     for (i = 0; i < message.bcc.length;) {
114323         message.bcc[i] = message.bcc[i].replace(/^\s*(\S*)\s*$/, '$1');
114324         if (message.bcc[i] === "")
114325             message.bcc.splice(i, 1);
114326         else
114327             i++;
114328     }
114329     if (message.to.length + message.cc.length + message.bcc.length === 0)
114330         exception.raise(exception.types.Argument,
114331             "sendMessage invalid message.to parameter",
114332             new DeviceApiError(errorcode.INVALID_VALUES_ERR));
114333 }
114334
114335 function _isValid(onSuccess, onError, message) {
114336     if (onSuccess &&
114337         typeof onSuccess !== "function" &&
114338         typeof onSuccess !== "object") {
114339         exception.raise(exception.types.Argument,
114340             "sendMessage invalid successCallback parameter",
114341             new DeviceApiError(errorcode.TYPE_MISMATCH_ERR));
114342     }
114343
114344     if (onError) {
114345         utils.validateArgumentType(onError, "function", null,
114346             "sendMessage invalid errorCallback parameter",
114347             new DeviceApiError(errorcode.TYPE_MISMATCH_ERR));
114348     }
114349
114350     if (!onSuccess) {
114351         _errorOccurred(onError, errorcode.INVALID_VALUES_ERR);
114352         return false;
114353     }
114354
114355     if (message) {
114356         utils.validateArgumentType(message, "object", null,
114357             "sendMessage invalid message parameter",
114358             new DeviceApiError(errorcode.INVALID_VALUES_ERR));
114359     } else {
114360         _errorOccurred(onError, errorcode.INVALID_VALUES_ERR);
114361         return false;
114362     }
114363
114364     if (message.type !== _self().TYPE_SMS &&
114365         message.type !== _self().TYPE_MMS &&
114366         message.type !== _self().TYPE_EMAIL)
114367         exception.raise(exception.types.Argument,
114368             "sendMessage invalid message.type parameter",
114369             new DeviceApiError(errorcode.INVALID_VALUES_ERR));
114370
114371     if (!_security.all && !_security.sendMessage) {
114372         _errorOccurred(onError, errorcode.SECURITY_ERR);
114373         return false;
114374     }
114375
114376     TypeCoerce(Message(0)).cast(message);
114377     _validateRecipients(message);
114378
114379     return true;
114380 }
114381
114382 function _getEachSentStatus(onMessageSentSuccess, onMessageSentError, message,
114383                             sucRecipients, failRecipients, recType) {
114384     utils.forEach(message[recType], function (recipient) {
114385         if (_sentStatus[recipient]) {
114386             sucRecipients[recType].push(recipient);
114387             if (onMessageSentSuccess) {
114388                 onMessageSentSuccess(recipient);
114389             }
114390         } else {
114391             failRecipients[recType].push(recipient);
114392             if (onMessageSentError) {
114393                 onMessageSentError(new DeviceApiError(errorcode.UNKNOWN_ERR), recipient);
114394             }
114395         }
114396     });
114397 }
114398
114399 function _getSentStatus(onSuccess, onError, message, onMessageSentSuccess, onMessageSentError) {
114400     var allSentSuccess,
114401         sucRecipients = new Recipients(),
114402         failRecipients = new Recipients(),
114403         duplicate;
114404
114405     _getEachSentStatus(onMessageSentSuccess, onMessageSentError,
114406         message, sucRecipients, failRecipients, "to");
114407
114408     if (message.type === _self().TYPE_EMAIL) {
114409         _getEachSentStatus(onMessageSentSuccess, onMessageSentError,
114410             message, sucRecipients, failRecipients, "cc");
114411         _getEachSentStatus(onMessageSentSuccess, onMessageSentError,
114412             message, sucRecipients, failRecipients, "bcc");
114413     }
114414
114415     allSentSuccess = (failRecipients.total() === 0);
114416
114417     if (allSentSuccess) {
114418         message.folder = _self().FOLDER_SENTBOX;
114419     } else if (sucRecipients.total() === 0) {
114420         message.folder = _self().FOLDER_DRAFTS;
114421     } else {
114422         duplicate = utils.copy(message);
114423
114424         message.to = sucRecipients.to;
114425         message.cc = sucRecipients.cc;
114426         message.bcc = sucRecipients.bcc;
114427         message.folder = _self().FOLDER_SENTBOX;
114428
114429         duplicate.to = failRecipients.to;
114430         duplicate.cc = failRecipients.cc;
114431         duplicate.bcc = failRecipients.bcc;
114432         duplicate.folder = _self().FOLDER_DRAFTS;
114433     }
114434
114435     _updateDB(message, duplicate);
114436
114437     if (allSentSuccess) {
114438         onSuccess();
114439     } else if (onError) {
114440         onError(new DeviceApiError(errorcode.UNKNOWN_ERR));
114441     }
114442 }
114443
114444 _self = function () {
114445     var messaging = {
114446         createMessage: function (type) {
114447             type = type | 0;
114448
114449             if (type < _self().TYPE_SMS || type > _self().TYPE_EMAIL)
114450                 exception.raise(exception.types.Argument,
114451                 "type invalid value", new DeviceApiError(errorcode.INVALID_VALUES_ERR));
114452
114453             var msg = new Message(type);
114454
114455             return msg;
114456         },
114457
114458         sendMessage: function (successCallback, errorCallback, message) {
114459             var ret;
114460
114461             function _sendMessage() {
114462                 event.trigger("OutsideMessageReceived", [message]);
114463
114464                 return _pendingOperate(_getSentStatus, undefined,
114465                     successCallback, errorCallback, message)();
114466             }
114467
114468             function _sendEachMessage() {
114469                 utils.forEach(successCallback, function (value, key) {
114470                     utils.validateArgumentType(value, "function", null,
114471                         "sendMessage invalid successCallback." + key + " parameter",
114472                         new DeviceApiError(errorcode.TYPE_MISMATCH_ERR));
114473                 });
114474
114475                 event.trigger("OutsideMessageReceived", [message]);
114476
114477                 return _pendingOperate(_getSentStatus, undefined,
114478                     successCallback.onsuccess, errorCallback, message,
114479                     successCallback.onmessagesendsuccess, successCallback.onmessagesenderror)();
114480             }
114481
114482             if (!_isValid(successCallback, errorCallback, message))
114483                 return null;
114484
114485             switch (typeof successCallback) {
114486             case "function":
114487                 ret = _sendMessage();
114488                 break;
114489
114490             case "object":
114491                 ret = _sendEachMessage();
114492                 break;
114493             }
114494
114495             return ret;
114496         },
114497
114498         findMessages: function (successCallback, errorCallback, filter) {
114499             function _findMessages() {
114500                 var message, result = [];
114501
114502                 if (!_security.all && !_security.findMessages)
114503                     return _errorOccurred(errorCallback, errorcode.SECURITY_ERR);
114504
114505                 utils.forEach(_messages, function (folder) {
114506                     utils.forEach(folder, function (messageItem) {
114507                         if ((filter                 === undefined || filter === null) ||
114508                             (filter.id              === undefined || Filter(filter.id).match(messageItem.id)) &&
114509                             (filter.type            === undefined || Filter(filter.type).match(messageItem.type)) &&
114510                             (filter.folder          === undefined || Filter(filter.folder).match(messageItem.folder)) &&
114511                             (filter.startTimestamp  === undefined || (messageItem.timestamp >= filter.startTimestamp)) &&
114512                             (filter.endTimestamp    === undefined || (messageItem.timestamp <= filter.endTimestamp)) &&
114513                             (filter.from            === undefined || Filter(filter.from).match(messageItem.from)) &&
114514                             (filter.to              === undefined || Filter(filter.to).match(messageItem.to)) &&
114515                             (filter.cc              === undefined || Filter(filter.cc).match(messageItem.cc)) &&
114516                             (filter.bcc             === undefined || Filter(filter.bcc).match(messageItem.bcc)) &&
114517                             (filter.body            === undefined || Filter(filter.body).match(messageItem.body)) &&
114518                             (filter.isRead          === undefined || (messageItem.isRead === filter.isRead)) &&
114519                             (filter.messagePriority === undefined || (messageItem.priority === filter.messagePriority)) &&
114520                             (filter.subject         === undefined || Filter(filter.subject).match(messageItem.subject))) {
114521                             message = utils.copy(messageItem);
114522                             result.push(message);
114523                         }
114524                     });
114525                 });
114526                 successCallback(result);
114527             }
114528             return wac2_utils.validateTypeMismatch(successCallback, errorCallback, "findMessages", _pendingOperate(_findMessages));
114529         },
114530
114531         onSMS: function (messageHandler) {
114532             return _onMessage("onSMS", messageHandler);
114533         },
114534
114535         onMMS: function (messageHandler) {
114536             return _onMessage("onMMS", messageHandler);
114537         },
114538
114539         onEmail: function (messageHandler) {
114540             return _onMessage("onEmail", messageHandler);
114541         },
114542
114543         unsubscribe: function (subscriptionHandler) {
114544             var onMessage, idSubscribe;
114545
114546             utils.validateArgumentType(subscriptionHandler, "integer",
114547                 null, "subscriptionHandler invalid function parameter",
114548                 new DeviceApiError(errorcode.TYPE_MISMATCH_ERR));
114549
114550             for (onMessage in _subscriber) {
114551                 for (idSubscribe in _subscriber[onMessage]) {
114552                     if (idSubscribe == subscriptionHandler) {
114553                         delete _subscriber[onMessage][idSubscribe];
114554                         return;
114555                     }
114556                 }
114557             }
114558         },
114559
114560         handleSubFeatures: function (subFeatures) {
114561             for (var subFeature in subFeatures) {
114562                 if (_security[subFeature].length === 0) {
114563                     _security.all = true;
114564                     return;
114565                 }
114566                 _security.all = false;
114567                 utils.forEach(_security[subFeature], function (method) {
114568                     _security[method] = true;
114569                 });
114570             }
114571         }
114572     };
114573
114574     messaging.__defineGetter__("TYPE_SMS", function () {
114575         return 1;
114576     });
114577
114578     messaging.__defineGetter__("TYPE_MMS", function () {
114579         return 2;
114580     });
114581
114582     messaging.__defineGetter__("TYPE_EMAIL", function () {
114583         return 3;
114584     });
114585
114586     messaging.__defineGetter__("FOLDER_INBOX", function () {
114587         return 1;
114588     });
114589
114590     messaging.__defineGetter__("FOLDER_OUTBOX", function () {
114591         return 2;
114592     });
114593
114594     messaging.__defineGetter__("FOLDER_DRAFTS", function () {
114595         return 3;
114596     });
114597
114598     messaging.__defineGetter__("FOLDER_SENTBOX", function () {
114599         return 4;
114600     });
114601
114602     if (!_initialized)
114603         _initialize();
114604
114605     return messaging;
114606 };
114607
114608 MessageSendCallback = {
114609     onsuccess: function () {},
114610     onmessagesendsuccess: function (recipient) {},
114611     onmessagesenderror: function (error, recipient) {}
114612 };
114613
114614 Message = function (type) {
114615     this.id = Math.uuid(null, 16);
114616     this.type = type;
114617     this.folder = 0;
114618     this.timestamp = new Date();
114619     this.from = "";
114620     this.to = [""];
114621     this.cc = [""];
114622     this.bcc = [""];
114623     this.body = "";
114624     this.isRead = false;
114625     this.priority = false;
114626     this.subject = "";
114627     this.attachments = [""];
114628
114629     this.update = function (successCallback, errorCallback) {
114630         function _update() {
114631             var isFound = false;
114632
114633             if (!_security.all && !_security.update)
114634                 return _errorOccurred(errorCallback, errorcode.SECURITY_ERR);
114635
114636             TypeCoerce(new Message(0)).cast(this);
114637             _get();
114638             utils.forEach(_messages[this.folder], function (messageItem) {
114639                 if (messageItem.id === this.id) {
114640                     !this.isRead || (messageItem.isRead = this.isRead);
114641                     if (this.folder === _self().FOLDER_DRAFTS) {
114642                         !this.type        || (messageItem.type        = this.type);
114643                         !this.to          || (messageItem.to          = utils.copy(this.to));
114644                         !this.cc          || (messageItem.cc          = utils.copy(this.cc));
114645                         !this.bcc         || (messageItem.bcc         = utils.copy(this.bcc));
114646                         !this.body        || (messageItem.body        = this.body);
114647                         !this.priority    || (messageItem.priority    = this.priority);
114648                         !this.subject     || (messageItem.subject     = this.subject);
114649                         !this.attachments || (messageItem.attachments = utils.copy(this.attachments));
114650                     }
114651                     isFound = true;
114652                 }
114653             });
114654
114655             if (isFound) {
114656                 _save();
114657                 successCallback();
114658             } else {
114659                 _errorOccurred(errorCallback, errorcode.NOT_FOUND_ERR);
114660             }
114661         }
114662         return wac2_utils.validateTypeMismatch(successCallback, errorCallback, "update", _pendingOperate(_update, this));
114663     };
114664 };
114665
114666 MessageFilter = {
114667     id: "",
114668     type: [0],
114669     folder: [0],
114670     startTimestamp: new Date(),
114671     endTimestamp: new Date(),
114672     from: "",
114673     to: [""],
114674     cc: [""],
114675     bcc: [""],
114676     body: "",
114677     isRead: false,
114678     messagePriority: false,
114679     subject: ""
114680 };
114681
114682 Recipients = function () {
114683     this.to  = [];
114684     this.cc  = [];
114685     this.bcc = [];
114686
114687     this.total = function () {
114688         return (this.to.length + this.cc.length + this.bcc.length);
114689     };
114690 };
114691
114692 event.on("MessageReceived", function (message) {
114693     var onMessage;
114694
114695     switch (message.type) {
114696     case "sms":
114697         message.type = _self().TYPE_SMS;
114698         onMessage = "onSMS";
114699         break;
114700
114701     case "mms":
114702         message.type = _self().TYPE_MMS;
114703         onMessage = "onMMS";
114704         break;
114705
114706     case "email":
114707         message.type = _self().TYPE_EMAIL;
114708         onMessage = "onEmail";
114709         break;
114710
114711     default:
114712         break;
114713     }
114714
114715     message.folder = _self().FOLDER_INBOX;
114716     _processAttachments(message);
114717     _updateDB(message);
114718     utils.forEach(_subscriber[onMessage], function (subscriberCallback) {
114719         subscriberCallback(message);
114720     });
114721 });
114722
114723 event.on("MessageSent", function (sentStatus) {
114724     _sentStatus = sentStatus;
114725 });
114726
114727 module.exports = _self;
114728
114729 });
114730 define('ripple/platform/wac/2.0/orientation', function (require, exports, module) {
114731 /*
114732  *  Copyright 2011 Intel Corporation.
114733  *
114734  * Licensed under the Apache License, Version 2.0 (the "License");
114735  * you may not use this file except in compliance with the License.
114736  * You may obtain a copy of the License at
114737  *
114738  * http://www.apache.org/licenses/LICENSE-2.0
114739  *
114740  * Unless required by applicable law or agreed to in writing, software
114741  * distributed under the License is distributed on an "AS IS" BASIS,
114742  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
114743  * See the License for the specific language governing permissions and
114744  * limitations under the License.
114745  */
114746
114747 var utils = require('ripple/utils'),
114748     event = require('ripple/event'),
114749     Rotation = function (alpha, beta, gamma) {
114750         return {
114751             alpha: alpha || 0,
114752             beta:  beta  || 0,
114753             gamma: gamma || 0
114754         };
114755     },
114756     wac2_utils = require('ripple/platform/wac/2.0/wac2_utils'),
114757     _rotationInfo = new Rotation(),
114758     _defaultInterval = 100,
114759     _watches = {},
114760     _self;
114761
114762 module.exports = _self = {
114763     getCurrentOrientation: function (onSuccess, onError) {
114764         function _getCurrentOrientation() {
114765             setTimeout(function () {
114766                 onSuccess(utils.copy(_rotationInfo));
114767             }, 1);
114768             return null;
114769         }
114770
114771         return wac2_utils.validateTypeMismatch(onSuccess, onError, "getCurrentOrientation", _getCurrentOrientation);
114772     },
114773
114774     watchOrientation: function (orientationSuccess, orientationError, options) {
114775         function _watchOrientation() {
114776             var watchId = (new Date()).getTime() | 0,
114777                 watchObj = {},
114778                 opt = Object(options),
114779                 minNotificationInterval = opt.minNotificationInterval | 0,
114780                 orientationInterval = _defaultInterval;
114781
114782             if (minNotificationInterval > 0) {
114783                 orientationInterval = minNotificationInterval;
114784             }
114785
114786             watchObj = {
114787                 onSuccess: orientationSuccess,
114788                 onError: orientationError,
114789                 interval: orientationInterval
114790             };
114791
114792             _watches[watchId] = watchObj;
114793
114794             _watches[watchId].intervalId = setInterval(function () {
114795                 _self.getCurrentOrientation(_watches[watchId].onSuccess, _watches[watchId].onError);
114796             }, _watches[watchId].interval);
114797
114798             return watchId;
114799         }
114800
114801         return wac2_utils.validateTypeMismatch(orientationSuccess, orientationError, "watchOrientation", _watchOrientation);
114802     },
114803
114804     clearWatch: function (watchId) {
114805
114806         var id = watchId | 0;
114807         if (_watches[id]) {
114808             clearInterval(_watches[id].intervalId);
114809             delete(_watches[id]);
114810             return null;
114811         }
114812
114813         return undefined;
114814     }
114815 };
114816
114817 event.on("AccelerometerInfoChangedEvent", function (orientationInfo) {
114818     _rotationInfo.alpha = orientationInfo.orientation.alpha;
114819     _rotationInfo.beta  = orientationInfo.orientation.beta;
114820     _rotationInfo.gamma = orientationInfo.orientation.gamma;
114821 });
114822
114823
114824 });
114825 define('ripple/platform/wac/2.0/pendingObject', function (require, exports, module) {
114826 /*
114827  *  Copyright 2011 Intel Corporation.
114828  *
114829  * Licensed under the Apache License, Version 2.0 (the "License");
114830  * you may not use this file except in compliance with the License.
114831  * You may obtain a copy of the License at
114832  *
114833  * http://www.apache.org/licenses/LICENSE-2.0
114834  *
114835  * Unless required by applicable law or agreed to in writing, software
114836  * distributed under the License is distributed on an "AS IS" BASIS,
114837  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
114838  * See the License for the specific language governing permissions and
114839  * limitations under the License.
114840  */
114841
114842 module.exports = function (pendingObj) {
114843     var cancelFlag = true;
114844     this.setCancelFlag = function (flag) {
114845         cancelFlag = flag;
114846     };
114847     this.getCancelFlag = function () {
114848         return cancelFlag;
114849     };
114850     this.userCancel = null;
114851     this.pendingID = null;
114852 };
114853
114854 });
114855 define('ripple/platform/wac/2.0/pendingoperation', function (require, exports, module) {
114856 /*
114857  *  Copyright 2011 Intel Corporation.
114858  *
114859  * Licensed under the Apache License, Version 2.0 (the "License");
114860  * you may not use this file except in compliance with the License.
114861  * You may obtain a copy of the License at
114862  *
114863  * http://www.apache.org/licenses/LICENSE-2.0
114864  *
114865  * Unless required by applicable law or agreed to in writing, software
114866  * distributed under the License is distributed on an "AS IS" BASIS,
114867  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
114868  * See the License for the specific language governing permissions and
114869  * limitations under the License.
114870  */
114871
114872 module.exports = function (pendingObj) {
114873     var pending = true;
114874     this.cancel = function () {
114875         if (pending === true) {
114876             if (typeof (pendingObj.getCancelFlag) === "function" && pendingObj.getCancelFlag() === false) {
114877                 pending = false;
114878                 // this clearTimeout is for the case when a 3rd party is invoked to do the task, and it's finished sooner than the intended timeout. therefore, the 3rd party set CancelFlag false, and this cancel is called before timeout
114879                 clearTimeout(pendingObj.pendingID);
114880                 return false;
114881             }
114882             if (typeof (pendingObj.userCancel) === "function") {
114883                 pendingObj.userCancel();
114884             }
114885             clearTimeout(pendingObj.pendingID);
114886             pending = false;
114887             return true;
114888         } else {
114889             return false;
114890         }
114891     };
114892 };
114893
114894
114895 });
114896 define('ripple/platform/wac/2.0/spec/config', function (require, exports, module) {
114897 /*
114898  *  Copyright 2011 Research In Motion Limited.
114899  *
114900  * Licensed under the Apache License, Version 2.0 (the "License");
114901  * you may not use this file except in compliance with the License.
114902  * You may obtain a copy of the License at
114903  *
114904  * http://www.apache.org/licenses/LICENSE-2.0
114905  *
114906  * Unless required by applicable law or agreed to in writing, software
114907  * distributed under the License is distributed on an "AS IS" BASIS,
114908  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
114909  * See the License for the specific language governing permissions and
114910  * limitations under the License.
114911  */
114912 var platform = require('ripple/platform'),
114913     utils = require('ripple/utils'),
114914     db = require('ripple/db'),
114915     constants = require('ripple/constants');
114916
114917 module.exports = {
114918     fileName: "config.xml",
114919     validateVersion: function (configValidationObject) {
114920         var valid = true;
114921         // no xmlns:JIL in wac 2.0 spec
114922         valid = !!configValidationObject.widget.validationResult[0].attributes.xmlns.valid;
114923
114924         return valid;
114925     },
114926     extractInfo: function (configValidationObject) {
114927         if (!configValidationObject) {
114928             return null;
114929         }
114930
114931         var widgetInfo = {},
114932             configFeatures,
114933             configPreferences,
114934             preferenceName,
114935             platform;
114936
114937         widgetInfo.id = configValidationObject.widget.validationResult[0].attributes.id.value || "";
114938         widgetInfo.name = configValidationObject.widget.children.name.validationResult[0].value;
114939         widgetInfo.icon = configValidationObject.widget.children.icon.validationResult[0].attributes.src.value;
114940         widgetInfo.version = configValidationObject.widget.validationResult[0].attributes.version.value;
114941
114942         widgetInfo.features = {};
114943
114944         configFeatures = configValidationObject.widget.children.feature.validationResult;
114945         utils.forEach(configFeatures, function (f) {
114946             if (f.valid === true) {
114947                 var feature = {id: f.attributes.name.value,
114948                          required: f.attributes.required.valid};
114949                 widgetInfo.features[feature.id] = feature;
114950             }
114951         });
114952
114953         widgetInfo.preferences = {};
114954
114955         configPreferences = configValidationObject.widget.children.preference.validationResult;
114956
114957         platform = require('ripple/platform');
114958         utils.forEach(configPreferences, function (preference) {
114959             preferenceName = preference.attributes.name.value;
114960             if (preferenceName) {
114961                 widgetInfo.preferences[preferenceName] = {
114962                     "key": preferenceName,
114963                     "value": preference.attributes.value.value || "",
114964                     "readonly": preference.attributes.readonly.value === "true"
114965                 };
114966
114967                 db.save(preferenceName,
114968                         widgetInfo.preferences[preferenceName].value,
114969                         platform.getPersistencePrefix(widgetInfo.id));
114970             }
114971         });
114972
114973         return widgetInfo;
114974     },
114975     schema: {
114976         rootElement: "widget",
114977         widget: {
114978             nodeName: "widget",
114979             required: true,
114980             occurrence: 1,
114981             helpText: "\"widget\" element describes widget information in configuration documents and serves as a container for other elements. It must be used in configuration document and may have following child elments: name,description,icon,author,license,content,feature and preference. \"widget\" element MAY have following attributes: id,version,height,width, defaultlocale, xml:lang and dir",
114982             attributes: {
114983                 xmlns: {
114984                     attributeName: "xmlns",
114985                     required: true,
114986                     type: "list",
114987                     listValues: ["http://www.w3.org/ns/widgets"]
114988                 },
114989                 "xml:lang": {
114990                     attributeName: "xml:lang",
114991                     required: false,
114992                     type: "iso-language"
114993                 },
114994                 dir: {
114995                     attributeName: "dir",
114996                     required: false,
114997                     type: "list",
114998                     listValues: ["ltr", "rtl", "lro", "rlo"]
114999                 },
115000                 id: {
115001                     attributeName: "id",
115002                     required: false,
115003                     type: "string"
115004                 },
115005                 version: {
115006                     attributeName: "version",
115007                     required: false,
115008                     type: "string"
115009                 },
115010                 height: {
115011                     attributeName: "height",
115012                     required: false,
115013                     type: "integer"
115014                 },
115015                 width: {
115016                     attributeName: "width",
115017                     required: false,
115018                     type: "integer"
115019                 },
115020                 viewmodes: {
115021                     attributeName: "viewmodes",
115022                     required: false,
115023                     type: "list",
115024                     listValues: ["windowed", "floating", "fullscreen", "maximized", "minimized"]
115025                 },
115026                 defaultlocale: {
115027                     attributeName: "defaultlocale",
115028                     required: false,
115029                     type: "iso-language"
115030                 },
115031             },
115032             children: {
115033                 name: {
115034                     nodeName: "name",
115035                     required: false,
115036                     occurrence: 0,
115037                     type: "string",
115038                     attributes: {
115039                         "xml:lang": {
115040                             attributeName: "xml:lang",
115041                             required: false,
115042                             type: "iso-language",
115043                             unique: true
115044                         },
115045                         dir: {
115046                             attributeName: "dir",
115047                             required: false,
115048                             type: "list",
115049                             listValues: ["ltr", "rtl", "lro", "rlo"]
115050                         },
115051                         "short": {
115052                             attributeName: "short",
115053                             required: false,
115054                             type: "string"
115055                         }
115056                     },
115057                     children: {
115058                         span: {
115059                             nodeName: "span",
115060                             required: false,
115061                             type: "string",
115062                             attributes: {
115063                                 "xml:lang": {
115064                                     attributeName: "xml:lang",
115065                                     required: false,
115066                                     type: "iso-language",
115067                                     unique: true
115068                                 },
115069                                 dir: {
115070                                     attributeName: "dir",
115071                                     required: false,
115072                                     type: "list",
115073                                     listValues: ["ltr", "rtl", "lro", "rlo"]
115074                                 }
115075                             }
115076                         }
115077                     }
115078                 },
115079                 description: {
115080                     nodeName: "description",
115081                     required: false,
115082                     occurrence: 0,
115083                     type: "string",
115084                     attributes: {
115085                         "xml:lang": {
115086                             attributeName: "xml:lang",
115087                             required: false,
115088                             type: "iso-language",
115089                             unique: true
115090                         },
115091                         dir: {
115092                             attributeName: "dir",
115093                             required: false,
115094                             type: "list",
115095                             listValues: ["ltr", "rtl", "lro", "rlo"]
115096                         }
115097                     },
115098                     children: {
115099                         span: {
115100                             nodeName: "span",
115101                             required: false,
115102                             type: "string",
115103                             attributes: {
115104                                 "xml:lang": {
115105                                     attributeName: "xml:lang",
115106                                     required: false,
115107                                     type: "iso-language",
115108                                     unique: true
115109                                 },
115110                                 dir: {
115111                                     attributeName: "dir",
115112                                     required: false,
115113                                     type: "list",
115114                                     listValues: ["ltr", "rtl", "lro", "rlo"]
115115                                 }
115116                             }
115117                         }
115118                     }
115119                 },
115120                 author: {
115121                     nodeName: "author",
115122                     required: false,
115123                     occurrence: 0,
115124                     type: "string",
115125                     attributes: {
115126                         "xml:lang": {
115127                             attributeName: "xml:lang",
115128                             required: false,
115129                             type: "iso-language",
115130                         },
115131                         dir: {
115132                             attributeName: "dir",
115133                             required: false,
115134                             type: "list",
115135                             listValues: ["ltr", "rtl", "lro", "rlo"]
115136                         },
115137                         href: {
115138                             attributeName: "href",
115139                             required: false,
115140                             type: "regex",
115141                             regex: constants.REGEX.URL
115142                         },
115143                         email: {
115144                             attributeName: "email",
115145                             required: false,
115146                             type: "regex",
115147                             regex: constants.REGEX.EMAIL
115148                         }
115149                     },
115150                     children: {
115151                         span: {
115152                             nodeName: "span",
115153                             required: false,
115154                             type: "string",
115155                             attributes: {
115156                                 "xml:lang": {
115157                                     attributeName: "xml:lang",
115158                                     required: false,
115159                                     type: "iso-language",
115160                                     unique: true
115161                                 },
115162                                 dir: {
115163                                     attributeName: "dir",
115164                                     required: false,
115165                                     type: "list",
115166                                     listValues: ["ltr", "rtl", "lro", "rlo"]
115167                                 }
115168                             }
115169                         }
115170                     }
115171                 },
115172                 license: {
115173                     nodeName: "license",
115174                     required: false,
115175                     occurrence: 0,
115176                     type: "string",
115177                     attributes: {
115178                         "xml:lang": {
115179                             attributeName: "xml:lang",
115180                             required: false,
115181                             type: "iso-language",
115182                         },
115183                         dir: {
115184                             attributeName: "dir",
115185                             required: false,
115186                             type: "list",
115187                             listValues: ["ltr", "rtl", "lro", "rlo"]
115188                         },
115189                         href: {
115190                             attributeName: "href",
115191                             type: "regex",
115192                             required: false,
115193                             regex: constants.REGEX.URL
115194                         }
115195                     },
115196                     children: {
115197                         span: {
115198                             nodeName: "span",
115199                             required: false,
115200                             type: "string",
115201                             attributes: {
115202                                 "xml:lang": {
115203                                     attributeName: "xml:lang",
115204                                     required: false,
115205                                     type: "iso-language",
115206                                     unique: true
115207                                 },
115208                                 dir: {
115209                                     attributeName: "dir",
115210                                     required: false,
115211                                     type: "list",
115212                                     listValues: ["ltr", "rtl", "lro", "rlo"]
115213                                 }
115214                             }
115215                         }
115216                     }
115217                 },
115218                 icon: {
115219                     nodeName: "icon",
115220                     required: false,
115221                     occurrence: 0,
115222                     attributes: {
115223                         "xml:lang": {
115224                             attributeName: "xml:lang",
115225                             required: false,
115226                             type: "iso-language",
115227                         },
115228                         dir: {
115229                             attributeName: "dir",
115230                             required: false,
115231                             type: "list",
115232                             listValues: ["ltr", "rtl", "lro", "rlo"]
115233                         },
115234                         src: {
115235                             attributeName: "src",
115236                             required: true,
115237                             type: "string"
115238                         },
115239                         width: {
115240                             attributeName: "width",
115241                             required: false,
115242                             type: "integer"
115243                         },
115244                         height: {
115245                             attributeName: "height",
115246                             required: false,
115247                             type: "integer"
115248                         }
115249                     }
115250                 },
115251                 content: {
115252                     nodeName: "content",
115253                     required: false,
115254                     occurrence: 1,
115255                     attributes: {
115256                         "xml:lang": {
115257                             attributeName: "xml:lang",
115258                             required: false,
115259                             type: "iso-language",
115260                             unique: true
115261                         },
115262                         dir: {
115263                             attributeName: "dir",
115264                             required: false,
115265                             type: "list",
115266                             listValues: ["ltr", "rtl", "lro", "rlo"]
115267                         },
115268                         src: {
115269                             attributeName: "src",
115270                             required: true,
115271                             type: "string"
115272                         },
115273                         encoding: {
115274                             attributeName: "encoding",
115275                             required: false,
115276                             type: "string"
115277                         },
115278                         type: {
115279                             attributeName: "type",
115280                             required: false,
115281                             type: "string"
115282                         }
115283                     }
115284                 },
115285                 feature: {
115286                     nodeName: "feature",
115287                     required: false,
115288                     occurrence: 0,
115289                     attributes: {
115290                         "xml:lang": {
115291                             attributeName: "xml:lang",
115292                             required: false,
115293                             type: "iso-language",
115294                         },
115295                         dir: {
115296                             attributeName: "dir",
115297                             required: false,
115298                             type: "list",
115299                             listValues: ["ltr", "rtl", "lro", "rlo"]
115300                         },
115301                         name: {
115302                             attributeName: "name",
115303                             required: true,
115304                             type: "list",
115305                             listValues: ["http://www.w3.org/TR/geolocation-API/",
115306                                             "http://wacapps.net/api/deviceapis", "http://wacapps.net/api/accelerometer",
115307                                             "http://wacapps.net/api/orientation", "http://wacapps.net/api/camera",
115308                                             "http://wacapps.net/api/camera.show", "http://wacapps.net/api/camera.capture",
115309                                             "http://wacapps.net/api/devicestatus", "http://wacapps.net/api/devicestatus.deviceinfo",
115310                                             "http://wacapps.net/api/devicestatus.networkinfo", "http://wacapps.net/api/filesystem",
115311                                             "http://wacapps.net/api/filesystem.read", "http://wacapps.net/api/filesystem.write",
115312                                             "http://wacapps.net/api/messaging", "http://wacapps.net/api/messaging.send", 
115313                                             "http://wacapps.net/api/messaging.find", "http://wacapps.net/api/messaging.subscribe",
115314                                             "http://wacapps.net/api/messaging.write", "http://wacapps.net/api/pim.contact",
115315                                             "http://wacapps.net/api/pim.contact.read", "http://wacapps.net/api/pim.contact.write",
115316                                             "http://wacapps.net/api/pim.calendar", "http://wacapps.net/api/pim.calendar.read",
115317                                             "http://wacapps.net/api/pim.calendar.write", "http://wacapps.net/api/pim.task", 
115318                                             "http://wacapps.net/api/pim.task.read", "http://wacapps.net/api/pim.task.write",
115319                                             "http://wacapps.net/api/deviceinteraction"]
115320                         },
115321                         required: {
115322                             attributeName: "required",
115323                             type: "boolean",
115324                             required: false
115325                         }
115326                     },
115327                     children: {
115328                         param: {
115329                             nodeName: "param",
115330                             required: false,
115331                             occurrence: 0,
115332                             attributes: {
115333                                 "xml:lang": {
115334                                     attributeName: "xml:lang",
115335                                     required: false,
115336                                     type: "iso-language",
115337                                 },
115338                                 dir: {
115339                                     attributeName: "dir",
115340                                     required: false,
115341                                     type: "list",
115342                                     listValues: ["ltr", "rtl", "lro", "rlo"]
115343                                 },
115344                                 name: {
115345                                     attributeName: "name",
115346                                     required: true,
115347                                     type: "string",
115348                                 },
115349                                 value: {
115350                                     attributeName: "value",
115351                                     required: true,
115352                                     type: "string",
115353                                 }
115354                             }
115355                         }
115356                     }
115357                 },
115358                 preference: {
115359                     nodeName: "preference",
115360                     required: false,
115361                     occurrence: 0,
115362                     attributes: {
115363                         "xml:lang": {
115364                             attributeName: "xml:lang",
115365                             required: false,
115366                             type: "iso-language",
115367                         },
115368                         dir: {
115369                             attributeName: "dir",
115370                             required: false,
115371                             type: "list",
115372                             listValues: ["ltr", "rtl", "lro", "rlo"]
115373                         },
115374                         name: {
115375                             attributeName: "name",
115376                             required: true,
115377                             type: "string"
115378                         },
115379                         value: {
115380                             type: "string",
115381                             required: false,
115382                             attributeName: "value"
115383                         },
115384                         readonly: {
115385                             attributeName: "readonly",
115386                             type: "boolean",
115387                             required: false
115388                         }
115389                     }
115390                 }
115391             }
115392         }
115393     }
115394 };
115395
115396 });
115397 define('ripple/platform/wac/2.0/spec/device', function (require, exports, module) {
115398 /*
115399  *  Copyright 2011 Intel Corporation.
115400  *
115401  * Licensed under the Apache License, Version 2.0 (the "License");
115402  * you may not use this file except in compliance with the License.
115403  * You may obtain a copy of the License at
115404  *
115405  * http://www.apache.org/licenses/LICENSE-2.0
115406  *
115407  * Unless required by applicable law or agreed to in writing, software
115408  * distributed under the License is distributed on an "AS IS" BASIS,
115409  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
115410  * See the License for the specific language governing permissions and
115411  * limitations under the License.
115412  */
115413 var event = require('ripple/event');
115414
115415 function deviceStatusEventTrigger(setting) {
115416     event.trigger("DeviceStatusChanged", [setting]);
115417 }
115418
115419 module.exports = {
115420     "Config": {
115421         "vibratingMode": {
115422             "name": "Vibrator",
115423             "control": {
115424                 "type": "checkbox",
115425                 "value": true
115426             },
115427             "callback": function (setting) {
115428                 event.trigger("VibratingModeChanged", [setting]);
115429             }
115430         },
115431         "soundVolume": {
115432             "name": "Sound Volume",
115433             "control": {
115434                 "type": "range",
115435                 "value": 100,
115436                 "min": 0,
115437                 "max": 100
115438             },
115439             "callback": function (setting) {
115440                 event.trigger("VolumeChanged", [setting]);
115441             }
115442         },
115443         "backlight": {
115444             "name": "Backlight",
115445             "control": {
115446                 "type": "checkbox",
115447                 "value": true
115448             },
115449             "callback": function (setting) {
115450                 event.trigger("BacklightChanged", [setting]);
115451             }
115452         }
115453     },
115454     "Battery": {
115455         "batteryLevel": {
115456             "name": "Battery Remaining %",
115457             "control": {
115458                 "type": "select",
115459                 "value": 100
115460             },
115461             "options": (function () {
115462                 var i,
115463                     optionList = {};
115464
115465                 for (i = 0; i <= 100; i += 10) {
115466                     optionList[i] = i;
115467                 }
115468
115469                 return optionList;
115470             }()),
115471             "event": "BatteryLevelChanged",
115472             "callback": function (setting) {
115473                 event.trigger("BatteryLevelChanged", [setting]);
115474             }
115475         },
115476
115477         "batteryBeingCharged": {
115478             "name": "Battery Is Charging",
115479             "control": {
115480                 "type": "checkbox",
115481                 "value": true
115482             },
115483             "event": "BatteryBeingChargedChanged",
115484             "callback": function (setting) {
115485                 event.trigger("BatteryBeingChargedChanged", [setting]);
115486             }
115487         },
115488     },
115489     "CellularHardware": {
115490         "status": {
115491             "name": "status",
115492             "control": {
115493                 "type": "checkbox",
115494                 "value": true
115495             },
115496             "event": "CellularHardwareStatusChanged",
115497             "callback": function (setting) {
115498                 event.trigger("CellularHardwareStatusChanged", [setting]);
115499             }
115500         }
115501     },
115502     "CellularNetwork": {
115503         "isInRoaming": {
115504             "name": "Roaming",
115505             "control": {
115506                 "type": "checkbox",
115507                 "value": true
115508             },
115509             "event": "CellularNetworkIsInRoamingChanged",
115510             "callback": function (setting) {
115511                 event.trigger("CellularNetworkIsInRoamingChanged", [setting]);
115512             }
115513         }, 
115514         "mcc": {
115515             "name": "mcc",
115516             "control": {
115517                 "type": "text",
115518                 "value": "460",
115519                 "readonly": "readonly"
115520             }
115521         }, 
115522         "mnc": {
115523             "name": "mnc",
115524             "control": {
115525                 "type": "text",
115526                 "value": "0",
115527                 "readonly": "readonly"
115528             }
115529         }, 
115530         "signalStrength": {
115531             "name": "Signal Strength",
115532             "control": {
115533                 "type": "select",
115534                 "value": 100
115535             },
115536             "options": (function () {
115537                 var i,
115538                     optionList = {};
115539
115540                 for (i = 0; i <= 100; i += 10) {
115541                     optionList[i] = i;
115542                 }
115543
115544                 return optionList;
115545             }()),
115546             "event": "CellularNetworkSignalStrengthChanged",
115547             "callback": function (setting) {
115548                 event.trigger("CellularNetworkSignalStrengthChanged", [setting]);
115549             }
115550         }, 
115551         "operatorName": {
115552             "name": "Operator Name",
115553             "control": {
115554                 "type": "text",
115555                 "value": "CMCC",
115556                 "readonly": "readonly"
115557             }
115558         }
115559     },
115560     "Device": {
115561         "imei": {
115562             "name": "IMEI",
115563             "control": {
115564                 "type": "text",
115565                 "value": "860398001689659",
115566                 "readonly": "readonly"
115567             }
115568         }, 
115569         "model": {
115570             "name": "Model",
115571             "control": {
115572                 "type": "text",
115573                 "value": "",
115574                 "readonly": "readonly"
115575             }
115576         }, 
115577         "version": {
115578             "name": "Version",
115579             "control": {
115580                 "type": "text",
115581                 "value": "",
115582                 "readonly": "readonly"
115583             }
115584         }, 
115585         "vendor": {
115586             "name": "Vendor.",
115587             "control": {
115588                 "type": "text",
115589                 "value": "",
115590                 "readonly": "readonly"
115591             }
115592         }
115593     },
115594     "Display": {
115595         "resolutionHeight": {
115596             "name": "Resolution Height",
115597             "control": {
115598                 "type": "number",
115599                 "value": 0,
115600                 "readonly": "readonly"
115601             }
115602         }, 
115603         "resolutionWidth": {
115604             "name": "Resolution Width",
115605             "control": {
115606                 "type": "number",
115607                 "value": 0,
115608                 "readonly": "readonly"
115609             }
115610         }, 
115611         "pixelAspectRatio": {
115612             "name": "Pixel Aspectratio",
115613             "control": {
115614                 "type": "number",
115615                 "value": 0,
115616                 "readonly": "readonly"
115617             }
115618         }, 
115619         "dpiY": {
115620             "name": "DPI-Y",
115621             "control": {
115622                 "type": "number",
115623                 "value": 0,
115624                 "readonly": "readonly"
115625             }
115626         },         
115627         "dpiX": {
115628             "name": "DPI-X",
115629             "control": {
115630                 "type": "number",
115631                 "value": 0,
115632                 "readonly": "readonly"
115633             }
115634         }, 
115635         "colorDepth": {
115636             "name": "Color Depth",
115637             "control": {
115638                 "type": "number",
115639                 "value": 32,
115640                 "readonly": "readonly"
115641             }
115642         }
115643     },
115644     "MemoryUnit": {
115645         "removable": {
115646             "name": "Removable",
115647             "control": {
115648                 "type": "checkbox",
115649                 "value": true,
115650                 "readonly": "readonly"
115651             }
115652         },
115653         "size": {
115654             "name": "Total Memory",
115655             "control": {
115656                 "type": "number",
115657                 "value": 262144,
115658                 "readonly": "readonly"
115659             }
115660         },        
115661         "availableSize": {
115662             "name": "Available Size",
115663             "control": {
115664                 "type": "range",
115665                 "value": 16384,
115666                 "min": 0,
115667                 "max": 262144
115668             },
115669             "event": "MemoryUnitAvailableSizeChanged",
115670             "callback": function (setting) {
115671                 event.trigger("MemoryUnitAvailableSizeChanged", [setting]);
115672             }
115673         }
115674     },
115675     "OperatingSystem": {
115676         "language": {
115677             "name": "Language",
115678             "control": {
115679                 "type": "text",
115680                 "value": "English",
115681                 "readonly": "readonly"
115682             }
115683         }, 
115684         "version": {
115685             "name": "Version",
115686             "control": {
115687                 "type": "text",
115688                 "value": "",
115689                 "readonly": "readonly"
115690             }
115691         }, 
115692         "name": {
115693             "name": "Name",
115694             "control": {
115695                 "type": "text",
115696                 "value": "",
115697                 "readonly": "readonly"
115698             }
115699         }, 
115700         "vendor": {
115701             "name": "Vendor",
115702             "control": {
115703                 "type": "text",
115704                 "value": "",
115705                 "readonly": "readonly"
115706             }
115707         }
115708     },
115709     "WebRuntime": {
115710         "wacVersion": {
115711             "name": "WAC Version",
115712             "control": {
115713                 "type": "text",
115714                 "value": "2.0",
115715                 "readonly": "readonly"
115716             }
115717         }, 
115718         "supportedImageFormats": {
115719             "name": "Image Formats",
115720             "control": {
115721                 "type": "text",
115722                 "value": "gif87, gif89, png, jpeg",
115723                 "readonly": "readonly"
115724             },
115725             "event": "WebRuntimeSupportedImageFormatsChanged",
115726             "callback": function (setting) {
115727                 event.trigger("WebRuntimeSupportedImageFormatsChanged", [setting]);
115728             }
115729         }, 
115730         "version": {
115731             "name": "Web Runtime Version",
115732             "control": {
115733                 "type": "text",
115734                 "value": "1.0",
115735                 "readonly": "readonly"
115736             }
115737         }, 
115738         "name": {
115739             "name": "Web Runtime Name",
115740             "control": {
115741                 "type": "text",
115742                 "value": "Tizen Web Simulator",
115743                 "readonly": "readonly"
115744             }
115745         }, 
115746         "vendor": {
115747             "name": "Vendor Name",
115748             "control": {
115749                 "type": "text",
115750                 "value": "Tizen SDK team",
115751                 "readonly": "readonly"
115752             }
115753         }
115754     },
115755     "WiFiHardware": {
115756         "status": {
115757             "name": "Status",
115758             "control": {
115759                 "type": "checkbox",
115760                 "value": true
115761             },
115762             "event": "WiFiHardwareStatusChanged",
115763             "callback": function (setting) {
115764                 event.trigger("WiFiHardwareStatusChanged", [setting]);
115765             }
115766         }
115767     },
115768     "WiFiNetwork": {
115769         "ssid": {
115770             "name": "SSID",
115771             "control": {
115772                 "type": "text",
115773                 "value": "OfficeWLAN"
115774             },
115775             "event": "WiFiHardwareSsidChanged",
115776             "callback": function (setting) {
115777                 event.trigger("WiFiHardwareSsidChanged", [setting]);
115778             }
115779         }, 
115780         "signalStrength": {
115781             "name": "Signal Strength",
115782             "control": {
115783                 "type": "select",
115784                 "value": 10
115785             },
115786             "options": (function () {
115787                 var i,
115788                     optionList = {};
115789
115790                 for (i = 0; i <= 10; i++) {
115791                     optionList[i] = i;
115792                 }
115793
115794                 return optionList;
115795             }()),
115796             "event": "WiFiHardwareSignalStrengthChanged",
115797             "callback": function (setting) {
115798                 event.trigger("WiFiHardwareSignalStrengthChanged", [setting]);
115799             }
115800         }, 
115801         "networkStatus": {
115802             "name": "Network Status",
115803             "control": {
115804                 "type": "checkbox",
115805                 "value": true
115806             },
115807             "event": "WiFiHardwareNetworkStatusChanged",
115808             "callback": function (setting) {
115809                 event.trigger("WiFiHardwareNetworkStatusChanged", [setting]);
115810             }
115811         }
115812     }
115813 };
115814
115815
115816 });
115817 define('ripple/platform/wac/2.0/spec/ui', function (require, exports, module) {
115818 /*
115819  *  Copyright 2011 Intel Corporation.
115820  *
115821  * Licensed under the Apache License, Version 2.0 (the "License");
115822  * you may not use this file except in compliance with the License.
115823  * You may obtain a copy of the License at
115824  *
115825  * http://www.apache.org/licenses/LICENSE-2.0
115826  *
115827  * Unless required by applicable law or agreed to in writing, software
115828  * distributed under the License is distributed on an "AS IS" BASIS,
115829  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
115830  * See the License for the specific language governing permissions and
115831  * limitations under the License.
115832  */
115833 module.exports = {
115834     plugins: [
115835         "accelerometer",
115836         "messaging",
115837         "geoView",
115838         "widgetConfig",
115839         "deviceSettings"
115840     ]
115841 };
115842
115843 });
115844 define('ripple/platform/wac/2.0/spec', function (require, exports, module) {
115845 /*
115846  *  Copyright 2011 Intel Corporation.
115847  *
115848  * Licensed under the Apache License, Version 2.0 (the "License");
115849  * you may not use this file except in compliance with the License.
115850  * You may obtain a copy of the License at
115851  *
115852  * http://www.apache.org/licenses/LICENSE-2.0
115853  *
115854  * Unless required by applicable law or agreed to in writing, software
115855  * distributed under the License is distributed on an "AS IS" BASIS,
115856  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
115857  * See the License for the specific language governing permissions and
115858  * limitations under the License.
115859  */
115860
115861 module.exports = {
115862
115863     id: "wac",
115864     version: "2.0",
115865     name: "WAC",
115866
115867     persistencePrefix: "wac2-",
115868
115869     config: require('ripple/platform/wac/2.0/spec/config'),
115870     ui: require('ripple/platform/wac/2.0/spec/ui'),
115871     device: require('ripple/platform/wac/2.0/spec/device'),
115872
115873     objects: {
115874         Coordinates: {
115875             path: "w3c/1.0/Coordinates"
115876         },
115877         Position: {
115878             path: "w3c/1.0/Position"
115879         },
115880         PositionError: {
115881             path: "w3c/1.0/PositionError"
115882         },
115883         navigator: {
115884             path: "w3c/1.0/navigator",
115885             children: {
115886                 geolocation: {
115887                     path: "wac/2.0/geolocation",
115888                     feature: "http://www.w3.org/TR/geolocation-API/"
115889                 }
115890             }
115891         },
115892         deviceapis: {
115893             path: "wac/2.0/deviceapis",
115894             feature: "http://wacapps.net/api/deviceapis",
115895             /*
115896              * Before we inject those cloned objects into the simulated application
115897              * namespace, we will handle the feature requests from config.xml.
115898              * Especially for:
115899              * - camera.show, camera.capture
115900              * - devicestatus.deviceinfo, devicestatus.networkinfo
115901              * - filesystem.read, filesystem.write
115902              * - messaging.send, messaging.find, messaging.subscribe, messaging.write
115903              * - pim
115904              *  - contact.read, contact.write
115905              *  - calendar.read, calendar.write
115906              *  - task.read, task.write
115907              */
115908             children: {
115909                 accelerometer: {
115910                     path: "wac/2.0/accelerometer",
115911                     feature: "http://wacapps.net/api/accelerometer"
115912                 },
115913                 orientation: {
115914                     path: "wac/2.0/orientation",
115915                     feature: "http://wacapps.net/api/orientation"
115916                 },
115917                 camera: {
115918                     path: "wac/2.0/camera",
115919                     feature: "http://wacapps.net/api/camera|http://wacapps.net/api/camera.show|http://wacapps.net/api/camera.capture",
115920                     handleSubfeatures: true
115921                 },
115922                 devicestatus: {
115923                     path: "wac/2.0/devicestatus",
115924                     feature: "http://wacapps.net/api/devicestatus|http://wacapps.net/api/devicestatus.deviceinfo|http://wacapps.net/api/devicestatus.networkinfo",
115925                     handleSubfeatures: true
115926                 },
115927                 filesystem: {
115928                     path: "wac/2.0/filesystem",
115929                     feature: "http://wacapps.net/api/filesystem|http://wacapps.net/api/filesystem.read|http://wacapps.net/api/filesystem.write",
115930                     handleSubfeatures: true
115931                 },
115932                 messaging: {
115933                     path: "wac/2.0/messaging",
115934                     feature: "http://wacapps.net/api/messaging|http://wacapps.net/api/messaging.send|http://wacapps.net/api/messaging.find|http://wacapps.net/api/messaging.subscribe|http://wacapps.net/api/messaging.write",
115935                     handleSubfeatures: true
115936                 },
115937                 pim: {
115938                     children: {
115939                         contact: {
115940                             path: "wac/2.0/contact",
115941                             feature: "http://wacapps.net/api/pim.contact|http://wacapps.net/api/pim.contact.read|http://wacapps.net/api/pim.contact.write",
115942                             handleSubfeatures: true
115943                         },
115944                         calendar: {
115945                             path: "wac/2.0/calendar",
115946                             feature: "http://wacapps.net/api/pim.calendar.write|http://wacapps.net/api/pim.calendar.read|http://wacapps.net/api/pim.calendar",
115947                             handleSubfeatures: true
115948                         },
115949                         task: {
115950                             path: "wac/2.0/task",
115951                             feature: "http://wacapps.net/api/pim.task|http://wacapps.net/api/pim.task.read|http://wacapps.net/api/pim.task.write",
115952                             handleSubfeatures: true
115953                         }
115954                     }
115955                 },
115956                 deviceinteraction: {
115957                     path: "wac/2.0/deviceinteraction",
115958                     feature: "http://wacapps.net/api/deviceinteraction"
115959                 }
115960             }
115961         }
115962     }
115963 };
115964
115965
115966 });
115967 define('ripple/platform/wac/2.0/task', function (require, exports, module) {
115968 /*
115969  *  Copyright 2011 Intel Corporation.
115970  *
115971  * Licensed under the Apache License, Version 2.0 (the "License");
115972  * you may not use this file except in compliance with the License.
115973  * You may obtain a copy of the License at
115974  *
115975  * http://www.apache.org/licenses/LICENSE-2.0
115976  *
115977  * Unless required by applicable law or agreed to in writing, software
115978  * distributed under the License is distributed on an "AS IS" BASIS,
115979  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
115980  * See the License for the specific language governing permissions and
115981  * limitations under the License.
115982  */
115983
115984 var db = require('ripple/db'),
115985     utils = require('ripple/utils'),
115986     _console = require('ripple/console'),
115987     exception = require('ripple/exception'),
115988     errorcode = require('ripple/platform/wac/2.0/errorcode'),
115989     wac2_utils = require('ripple/platform/wac/2.0/wac2_utils'),
115990     PendingObject = require('ripple/platform/wac/2.0/pendingObject'),
115991     DeviceApiError = require('ripple/platform/wac/2.0/deviceapierror'),
115992     PendingOperation = require('ripple/platform/wac/2.0/pendingoperation'),
115993     Task, TaskList, _get,
115994     _ID_WITHOUT = 0, _ID_GEN_NEW = 1, _ID_FROM_PROP = 2,
115995     _SIM_TASK_LIST = 0, _DEVICE_TASK_LIST = 1,
115996     _HIGH_PRIORITY = 0, _MEDIUM_PRIORITY = 1, _LOW_PRIORITY = 2,
115997     _STATUS_COMPLETED = 0, _STATUS_NEEDS_ACTION = 1, _STATUS_IN_PROCESS = 2, _STATUS_CANCELLED = 3,
115998     _TASK_OBJECTS = "wac2.0-pim-task-objects",
115999     _addTaskAllowed = true, _deleteTaskAllowed = true,
116000     _updateTaskAllowed = true, _findTasksAllowed = true;
116001
116002
116003 module.exports = function () {
116004     var _taskListArray = [],
116005         _PENDING_TIME = 10;
116006
116007     function _pendingOperate(operate) {
116008         var pendingObj, pendingOperation, i, argumentVector = [];
116009
116010         for (i = 0; i < arguments.length - 1; i++)
116011             argumentVector[i] = arguments[i + 1];
116012
116013         pendingObj = new PendingObject();
116014
116015         pendingObj.pendingID = window.setTimeout(function () {
116016             pendingObj.setCancelFlag(false);
116017             operate.apply(this, argumentVector);
116018         }, _PENDING_TIME);
116019
116020         pendingOperation = new PendingOperation(pendingObj);
116021
116022         return pendingOperation;
116023     }
116024
116025     /* taskProperties attribute check & paste */
116026     function _checkAndPasteProperties(p, dst) {
116027
116028         if (p.summary !== null && p.summary !== undefined)
116029             dst.summary = String(p.summary);
116030
116031         if (p.description !== null && p.description !== undefined)
116032             dst.description = String(p.description);
116033
116034         if (p.status !== null && p.status !== undefined) {
116035             if (p.status === _STATUS_COMPLETED ||
116036                 p.status === _STATUS_NEEDS_ACTION ||
116037                 p.status === _STATUS_IN_PROCESS ||
116038                 p.status === _STATUS_CANCELLED) {
116039                 dst.status = p.status;
116040             } else
116041                 return false;
116042         }
116043
116044         if (p.priority !== null && p.priority !== undefined) {
116045             if (p.priority === _HIGH_PRIORITY ||
116046                 p.priority === _MEDIUM_PRIORITY ||
116047                 p.priority === _LOW_PRIORITY) {
116048                 dst.priority = p.priority;
116049             } else
116050                 return false;
116051         }
116052
116053         if (p.dueDate !== null && p.dueDate !== undefined) {
116054             if (!wac2_utils.isValidDate(p.dueDate))
116055                 return false;
116056             dst.dueDate = new Date(p.dueDate);
116057         }
116058
116059         /* dueDate is a option properties.
116060            "The default value is undefined.
116061              If no value is provided, the task has no due date."
116062            If p.dueDate is set its default value 'undefined',
116063            we assign default value to dst.dueDate */
116064         if (p.dueDate === undefined) {
116065             dst.dueDate = undefined;
116066         }
116067
116068         return true;
116069     }
116070
116071     function _taskFilterCheck(filter) {
116072         var i;
116073         if (filter.id !== undefined && filter.id !== null) {
116074             filter.id = String(filter.id);
116075         } else {
116076             filter.id = undefined;
116077         }
116078         if (filter.summary !== undefined && filter.summary !== null) {
116079             filter.summary = String(filter.summary);
116080         } else {
116081             filter.summary = undefined;
116082         }
116083         if (filter.description !== undefined && filter.description !== null) {
116084             filter.description = String(filter.description);
116085         } else {
116086             filter.description = undefined;
116087         }
116088         if (filter.status !== undefined && filter.status !== null) {
116089             if (!wac2_utils.isValidArray(filter.status))  {
116090                 return false;
116091             }
116092             for (i = 0; i < filter.status.length; i++) {
116093                 filter.status[i] = filter.status[i] | 0;
116094                 if (filter.status[i] !== _STATUS_COMPLETED &&
116095                     filter.status[i] !== _STATUS_NEEDS_ACTION &&
116096                     filter.status[i] !== _STATUS_IN_PROCESS &&
116097                     filter.status[i] !== _STATUS_CANCELLED) {
116098                     return false;
116099                 }
116100             }
116101         } else {
116102             filter.status = undefined;
116103         }
116104         if (filter.priority !== undefined && filter.priority !== null) {
116105             if (!wac2_utils.isValidArray(filter.priority))  {
116106                 return false;
116107             }
116108             for (i = 0; i < filter.priority.length; i++) {
116109                 filter.priority[i] = filter.priority[i] | 0;
116110                 if (filter.priority[i] !== _HIGH_PRIORITY &&
116111                     filter.priority[i] !== _MEDIUM_PRIORITY &&
116112                     filter.priority[i] !== _LOW_PRIORITY) {
116113                     return false;
116114                 }
116115             }
116116         } else {
116117             filter.priority = undefined;
116118         }
116119         if (filter.dueDate !== undefined && filter.dueDate !== null) {
116120             if (!wac2_utils.isValidDate(filter.dueDate)) {
116121                 return false;
116122             }
116123             filter.dueDate = new Date(filter.dueDate);
116124         } else {
116125             filter.dueDate = undefined;
116126         }
116127         return true;
116128     }
116129
116130     function TaskProperties(prop) {
116131         var _self;
116132         _self = {
116133             priority : _LOW_PRIORITY,
116134             description : "",
116135             summary : "",
116136             dueDate : undefined,
116137             status : _STATUS_NEEDS_ACTION
116138         };
116139         if (prop) {
116140             if (_checkAndPasteProperties(prop, _self) === false)
116141                 return undefined;
116142         }
116143         return _self;
116144     }
116145
116146     function Task(prop, idChoice) {
116147         var id, _self = new TaskProperties(prop);
116148         /* if error occurs during checking, _self is an empty object.
116149            so i randomly pick description to check if property check fails */
116150         if (_self.description === undefined)
116151             return undefined;
116152
116153         switch (idChoice) {
116154         case _ID_WITHOUT:
116155             // do nothing
116156             break;
116157         case _ID_GEN_NEW:
116158             id = Math.uuid(undefined, 16);
116159             _self.__defineGetter__("id", function () {
116160                 return id;
116161             });
116162             break;
116163         case _ID_FROM_PROP:
116164             id = String(prop.id);
116165             _self.__defineGetter__("id", function () {
116166                 return id;
116167             });
116168             break;
116169         }
116170
116171         return _self;
116172     }
116173
116174     function _get() {
116175         var taskListArray = [],
116176             data = db.retrieveObject(_TASK_OBJECTS);
116177         utils.forEach(data, function (taskList) {
116178             for (var t in taskList._list) {
116179                 if (taskList._list[t].dueDate !== undefined &&
116180                     taskList._list[t].dueDate !== null)
116181                     taskList._list[t].dueDate = new Date(taskList._list[t].dueDate);
116182             }
116183             taskListArray.push(new TaskList(taskList._list, taskList.type, taskList.name));
116184         });
116185
116186         /* add default taskList if taskListArray is empty */
116187         if (taskListArray.length === 0) {
116188             taskListArray = [new TaskList({}, 0, "Office tasks"), new TaskList({}, 1, "Home tasks")];
116189         }
116190
116191         return taskListArray;
116192     }
116193
116194     function _save() {
116195         db.saveObject(_TASK_OBJECTS, _taskListArray);
116196     }
116197
116198     function TaskList(taskList, type, name) {
116199         var task;
116200         this._list = taskList;
116201         this.type = type;
116202         this.name = name;
116203
116204         this.createTask = function (properties) {
116205             task = new Task(properties, _ID_WITHOUT);
116206             /* if error occurs during checking, task is an empty object.
116207                so i randomly pick summary to check if property check fails */
116208             if (task.summary === undefined) {
116209                 exception.raise(exception.types.Argument,
116210                         "EventProperties: input parameter contains invalid values",
116211                         new DeviceApiError(errorcode.INVALID_VALUES_ERR));
116212                 return undefined;
116213             }
116214             return task;
116215         };
116216
116217         this.addTask = function (onSuccess, onError, task) {
116218             var inner = this,
116219                 newTask, _task = Object(task);
116220             function _addTask() {
116221                 var ret;
116222                 if (!_addTaskAllowed) {
116223                     if (onError) {
116224                         setTimeout(function () {
116225                             onError(new DeviceApiError(errorcode.SECURITY_ERR));
116226                         }, 1);
116227                     }
116228                     return undefined;
116229                 }
116230                 newTask = new Task(_task, _ID_GEN_NEW);
116231                 /* if error occurs during checking, newTask is an empty object.
116232                     so i randomly pick id to check if property check fails */
116233                 if (newTask.id === undefined) {
116234                     if (onError) {
116235                         setTimeout(function () {
116236                             onError(new DeviceApiError(errorcode.INVALID_VALUES_ERR));
116237                         }, 1);
116238                     }
116239                     return undefined;
116240                 }
116241                 ret = _pendingOperate(function () {
116242                     inner._list[newTask.id] = newTask;
116243                     _save();
116244                     onSuccess(new Task(newTask, _ID_FROM_PROP));
116245                 });
116246             }
116247
116248             return wac2_utils.validateTypeMismatch(onSuccess, onError, "addTask", _addTask);
116249         };
116250
116251         this.updateTask = function (onSuccess, onError, task) {
116252             var inner = this,
116253                 newTask, _task = Object(task);
116254             function _updateTask() {
116255                 var ret;
116256                 if (!_updateTaskAllowed) {
116257                     if (onError) {
116258                         setTimeout(function () {
116259                             onError(new DeviceApiError(errorcode.SECURITY_ERR));
116260                         }, 1);
116261                     }
116262                     return undefined;
116263                 }
116264
116265                 if (_checkAndPasteProperties(_task, _task) === false) {
116266                     if (onError) {
116267                         setTimeout(function () {
116268                             onError(new DeviceApiError(errorcode.INVALID_VALUES_ERR));
116269                         }, 1);
116270                     }
116271                     return undefined;
116272                 }
116273
116274                 ret = _pendingOperate(function () {
116275                     if (inner._list[_task.id]) {
116276                         newTask = new Task(inner._list[_task.id], _ID_FROM_PROP);
116277                         /* Don't need to double check the return of _checkAndPasteProperties 
116278                            _task has been checked & pasted already */
116279                         _checkAndPasteProperties(_task, newTask);
116280                         inner._list[newTask.id] = newTask;
116281                         _save();
116282                         onSuccess();
116283                     } else {
116284                         if (onError) {
116285                             onError(new DeviceApiError(errorcode.NOT_FOUND_ERR));
116286                         }
116287                     }
116288                 });
116289                 return ret;
116290             }
116291
116292             return wac2_utils.validateTypeMismatch(onSuccess, onError, "updateTask", _updateTask);
116293         };
116294
116295         this.deleteTask = function (onSuccess, onError, id) {
116296             var inner = this;
116297             function _deleteTask() {
116298                 var ret;
116299                 /* according to spec  "If any of the input parameters are not 
116300                    compatible with the expected type for that parameter, 
116301                    a DeviceAPIError with code TYPE_MISMATCH_ERR MUST be 
116302                    synchronously thrown." so an error is raised synchronously */
116303                 utils.validateArgumentType(id, "string", null,
116304                         "Task:deleteTask: " + " invalid id parameter",
116305                         new DeviceApiError(errorcode.TYPE_MISMATCH_ERR));
116306                 if (!_deleteTaskAllowed) {
116307                     if (onError) {
116308                         setTimeout(function () {
116309                             onError(new DeviceApiError(errorcode.SECURITY_ERR));
116310                         }, 1);
116311                     }
116312                     return undefined;
116313                 }
116314                 ret = _pendingOperate(function () {
116315                     if (inner._list[id]) {
116316                         delete inner._list[id];
116317                         _save();
116318                         onSuccess();
116319                     } else {
116320                         if (onError)
116321                             onError(new DeviceApiError(errorcode.NOT_FOUND_ERR));
116322                     }
116323                 });
116324                 return ret;
116325             }
116326
116327             return wac2_utils.validateTypeMismatch(onSuccess, onError, "deleteTask", _deleteTask);
116328         };
116329
116330         this.findTasks = function (onSuccess, onError, filter) {
116331             var inner = this, _filter = Object(filter), tmp = [], rst = [], valid_tmp = false;
116332             function _findTasks() {
116333                 var ret;
116334                 if (!_taskFilterCheck(_filter)) {
116335                     if (onError) {
116336                         setTimeout(function () {
116337                             onError(new DeviceApiError(errorcode.INVALID_VALUES_ERR));
116338                         }, 1);
116339                     }
116340                     return undefined;
116341                 }
116342                 if (!_findTasksAllowed) {
116343                     if (onError) {
116344                         setTimeout(function () {
116345                             onError(new DeviceApiError(errorcode.SECURITY_ERR));
116346                         }, 1);
116347                     }
116348                     return undefined;
116349                 }
116350                 ret = _pendingOperate(function () {
116351                     var i, e;
116352                     if (_filter.id !== undefined) {
116353                         tmp = wac2_utils.matchOptionString(inner._list, "id", _filter.id);
116354                         valid_tmp = true;
116355                     }
116356                     if (_filter.summary !== undefined) {
116357                         if (valid_tmp) {
116358                             tmp = wac2_utils.matchOptionString(tmp, "summary", _filter.summary);
116359                         } else {
116360                             tmp = wac2_utils.matchOptionString(inner._list, "summary", _filter.summary);
116361                             valid_tmp = true;
116362                         }
116363                     }
116364                     if (_filter.description !== undefined) {
116365                         if (valid_tmp) {
116366                             tmp = wac2_utils.matchOptionString(tmp, "description", _filter.description);
116367                         } else {
116368                             tmp = wac2_utils.matchOptionString(inner._list, "description", _filter.description);
116369                             valid_tmp = true;
116370                         }
116371                     }
116372                     if (_filter.status !== undefined) {
116373                         if (valid_tmp) {
116374                             tmp = wac2_utils.matchOptionShortArray(tmp, "status", _filter.status);
116375                         } else {
116376                             tmp = wac2_utils.matchOptionShortArray(inner._list, "status", _filter.status);
116377                             valid_tmp = true;
116378                         }
116379                     }
116380                     if (_filter.priority !== undefined) {
116381                         if (valid_tmp) {
116382                             tmp = wac2_utils.matchOptionShortArray(tmp, "priority", _filter.priority);
116383                         } else {
116384                             tmp = wac2_utils.matchOptionShortArray(inner._list, "priority", _filter.priority);
116385                             valid_tmp = true;
116386                         }
116387                     }
116388                     if (_filter.initialDueDate !== undefined ||
116389                         _filter.endDueDate !== undefined) {
116390                         if (valid_tmp) {
116391                             tmp = wac2_utils.matchOptionDate(tmp, "dueDate", _filter.initialDueDate, _filter.endDueDate);
116392                         } else {
116393                             tmp = wac2_utils.matchOptionDate(inner._list, "dueDate", _filter.initialDueDate, _filter.endDueDate);
116394                             valid_tmp = true;
116395                         }
116396                     }
116397
116398                     if (valid_tmp) {
116399                         for (i = 0; i < tmp.length; i++) {
116400                             rst.push(new Task(tmp[i], _ID_FROM_PROP));
116401                         } 
116402                     } else {
116403                         for (e in inner._list) {
116404                             rst.push(new Task(inner._list[e], _ID_FROM_PROP));
116405                         }
116406                     }
116407                     onSuccess(rst);
116408                 });
116409                 return ret;
116410             }
116411
116412             return wac2_utils.validateTypeMismatch(onSuccess, onError, "findTasks", _findTasks);
116413         };
116414     }
116415
116416     this.getTaskLists = function (onSuccess, onError) {
116417         function _getTaskLists() {
116418             var ret;
116419             ret = _pendingOperate(function () {
116420                 if (_taskListArray.length === 0) {
116421                     _taskListArray = _get();
116422                 }
116423                 onSuccess(_taskListArray);
116424             }, 1);
116425             return ret;
116426         }
116427
116428         return wac2_utils.validateTypeMismatch(onSuccess, onError, "getTaskLists", _getTaskLists);
116429     };
116430
116431     this.__defineGetter__("SIM_TASK_LIST", function () {
116432         return 0;
116433     });
116434     this.__defineGetter__("DEVICE_TASK_LIST", function () {
116435         return 1;
116436     });
116437     this.__defineGetter__("HIGH_PRIORITY", function () {
116438         return 0;
116439     });
116440     this.__defineGetter__("MEDIUM_PRIORITY", function () {
116441         return 1;
116442     });
116443     this.__defineGetter__("LOW_PRIORITY", function () {
116444         return 2;
116445     });
116446     this.__defineGetter__("STATUS_COMPLETED", function () {
116447         return 0;
116448     });
116449     this.__defineGetter__("STATUS_NEEDS_ACTION", function () {
116450         return 1;
116451     });
116452     this.__defineGetter__("STATUS_IN_PROCESS", function () {
116453         return 2;
116454     });
116455     this.__defineGetter__("STATUS_CANCELLED", function () {
116456         return 3;
116457     });
116458
116459     this.handleSubFeatures = function (subFeatures) {
116460         if (wac2_utils.isEmptyObject(subFeatures) ||
116461             subFeatures["http://wacapps.net/api/pim.task"] ||
116462             (subFeatures["http://wacapps.net/api/pim.task.read"] &&
116463             subFeatures["http://wacapps.net/api/pim.task.write"])) {
116464             return;
116465         }
116466         if (subFeatures["http://wacapps.net/api/pim.task.read"] &&
116467            !subFeatures["http://wacapps.net/api/pim.task.write"]) {
116468             _addTaskAllowed = false;
116469             _deleteTaskAllowed = false;
116470             _updateTaskAllowed = false;
116471             return;
116472         }
116473         if (subFeatures["http://wacapps.net/api/pim.task.write"] &&
116474            !subFeatures["http://wacapps.net/api/pim.task.read"]) {
116475             _findTasksAllowed = false;
116476             return;
116477         }
116478         _console.warn("WAC-2.0-Task-handleSubFeatures: something wrong");
116479     };
116480
116481 };
116482
116483
116484 });
116485 define('ripple/platform/wac/2.0/typecoerce', function (require, exports, module) {
116486 /*\r
116487  *  Copyright 2011 Intel Corporation.\r
116488  *\r
116489  * Licensed under the Apache License, Version 2.0 (the "License");\r
116490  * you may not use this file except in compliance with the License.\r
116491  * You may obtain a copy of the License at\r
116492  *\r
116493  * http://www.apache.org/licenses/LICENSE-2.0\r
116494  *\r
116495  * Unless required by applicable law or agreed to in writing, software\r
116496  * distributed under the License is distributed on an "AS IS" BASIS,\r
116497  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
116498  * See the License for the specific language governing permissions and\r
116499  * limitations under the License.\r
116500  */\r
116501 \r
116502 var utils = require('ripple/utils'),\r
116503     _self;\r
116504 \r
116505 _self = function (pattern) {\r
116506     var typeCoerce,\r
116507         typeOfPattern = Object.prototype.toString.call(pattern);\r
116508 \r
116509     typeCoerce = {\r
116510         cast: function (obj) {\r
116511             var validObj,\r
116512                 validValue,\r
116513                 elementType,\r
116514                 typeOfObj = Object.prototype.toString.call(obj);\r
116515 \r
116516             switch (typeOfPattern) {\r
116517             case "[object String]":\r
116518                 validObj = (typeOfObj !== typeOfPattern) ? String(obj) : obj;\r
116519                 break;\r
116520 \r
116521             case "[object Number]":\r
116522                 validObj = (typeOfObj !== typeOfPattern) ? (Number(obj) | 0) : obj;\r
116523                 break;\r
116524 \r
116525             case "[object Object]":\r
116526                 if (typeOfObj !== typeOfPattern) {\r
116527                     validObj = {};\r
116528                 } else {\r
116529                     validObj = obj;\r
116530                     utils.forEach(validObj, function (value, key) {\r
116531                         if (pattern[key] === undefined) {\r
116532                             delete validObj[key];\r
116533                         } else {\r
116534                             validValue = _self(pattern[key]).cast(value);\r
116535                             if (validObj[key] !== validValue)\r
116536                                 validObj[key] = validValue;\r
116537                         }\r
116538                     });\r
116539                 }\r
116540                 break;\r
116541 \r
116542             case "[object Array]":\r
116543                 if (typeOfObj !== typeOfPattern) {\r
116544                     validObj = [];\r
116545                 } else {\r
116546                     validObj = obj;\r
116547                     elementType = _self(pattern[0]);\r
116548                     utils.forEach(validObj, function (element, index) {\r
116549                         validObj[index] = elementType.cast(element);\r
116550                     });\r
116551                 }\r
116552                 break;\r
116553             }\r
116554 \r
116555             return validObj;\r
116556         }\r
116557     };\r
116558 \r
116559     return typeCoerce;\r
116560 };\r
116561 \r
116562 module.exports = _self;\r
116563
116564 });
116565 define('ripple/platform/wac/2.0/wac2_utils', function (require, exports, module) {
116566 /*
116567  *  Copyright 2011 Intel Corporation.
116568  *
116569  * Licensed under the Apache License, Version 2.0 (the "License");
116570  * you may not use this file except in compliance with the License.
116571  * You may obtain a copy of the License at
116572  *
116573  * http://www.apache.org/licenses/LICENSE-2.0
116574  *
116575  * Unless required by applicable law or agreed to in writing, software
116576  * distributed under the License is distributed on an "AS IS" BASIS,
116577  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
116578  * See the License for the specific language governing permissions and
116579  * limitations under the License.
116580  */
116581
116582 var utils = require('ripple/utils'),
116583     errorcode = require('ripple/platform/wac/2.0/errorcode'),
116584     DeviceApiError = require('ripple/platform/wac/2.0/deviceapierror');
116585
116586 module.exports = {
116587     _wac2_regexSanitize: function (regexString) {
116588         var escapePattern = /([^\\]|^)(%)/g, percentPattern = /\\%/g;
116589         return regexString.replace("^", "\\^")
116590                 .replace("$", "\\$")
116591                 .replace("(", "\\(")
116592                 .replace(")", "\\)")
116593                 .replace("<", "\\<")
116594                 .replace("[", "\\[")
116595                 .replace("{", "\\{")
116596                 .replace(/\\([^%])/, "\\\\$1")    /* don't replace \\% */
116597                 .replace("|", "\\|")
116598                 .replace(">", "\\>")
116599                 .replace(".", "\\.")
116600                 .replace("*", "\\*")
116601                 .replace("+", "\\+")
116602                 .replace("?", "\\?")
116603                 .replace(escapePattern, "$1.*")  /* replace % with .* */
116604                 .replace(percentPattern, "%");   /* strip excape of % */ 
116605     }, 
116606
116607     isValidDate: function (d) {
116608         if (Object.prototype.toString.call(d) !== "[object Date]")
116609             return false;
116610         return !isNaN(d.getTime());
116611     },
116612
116613     isValidArray: function (a) {
116614         return (Object.prototype.toString.call(a) === "[object Array]");
116615     },
116616     
116617     matchOptionArrayString: function (src, attr, pattern) {
116618         /* src.obj[attr] is a StringArray */
116619         var _pattern, re, _stringMatch;
116620         _pattern = this._wac2_regexSanitize(pattern); 
116621         re = new RegExp("^" + _pattern + "$", "i");
116622
116623         _stringMatch = function (obj, index) {
116624             if (pattern.search(/^%*$/i) === 0) 
116625                 return true;
116626             if (obj[attr] === undefined || obj[attr] === null)
116627                 return false;
116628             return obj[attr].some(function (f) {
116629                 return f.search(re) !== -1;
116630             });
116631         };
116632         return utils.filter(src, _stringMatch);
116633     },
116634
116635     matchOptionString: function (src, attr, pattern) {
116636         /* src.obj[attr] is a string */
116637         var _stringMatch, _pattern, _re;
116638         _pattern = this._wac2_regexSanitize(pattern); 
116639         _re = new RegExp("^" + _pattern + "$", "mi");
116640
116641         _stringMatch = function (obj, index) {
116642             return (obj[attr].search(_re) !== -1);
116643         };
116644         return utils.filter(src, _stringMatch);
116645     },
116646
116647     matchOptionDate: function (src, attr, filterStart, filterEnd) {
116648         var _dateMatch;
116649         _dateMatch = function (obj, index) {
116650             var matched = true, valueDate = obj[attr];
116651     
116652             if (filterStart !== undefined && filterStart !== null) {
116653                 matched = (valueDate.getTime() >= filterStart.getTime());
116654             }
116655             if (matched && (filterEnd !== undefined && filterEnd !== null)) {
116656                 matched = (valueDate.getTime() <= filterEnd.getTime());
116657             }
116658             return matched;
116659         };
116660         return utils.filter(src, _dateMatch);
116661     },
116662
116663     matchOptionShortArray: function (src, attr, filterArray) {
116664         /* src.obj[attr] is a short, filterArray is an array 
116665            i.e. find status is [CONFRIMED or TENTATIVE] */
116666         var arraySome = function (obj, index) {
116667             return filterArray.some(function (f) {
116668                 return f === obj[attr];  
116669             });
116670         };
116671         return utils.filter(src, arraySome);
116672     },
116673
116674     validateTypeMismatch: function (onSuccess, onError, name, callback) {
116675         if (onSuccess) {
116676             utils.validateArgumentType(onSuccess, "function", null,
116677                                        name + " invalid successCallback parameter",
116678                                        new DeviceApiError(errorcode.TYPE_MISMATCH_ERR));
116679         }
116680
116681         if (onError) {
116682             utils.validateArgumentType(onError, "function", null,
116683                                        name + " invalid errorCallback parameter",
116684                                        new DeviceApiError(errorcode.TYPE_MISMATCH_ERR));
116685         }
116686
116687         if (onSuccess) {
116688             return callback && callback();
116689         } else {
116690             if (onError) {
116691                 setTimeout(function () {
116692                     onError(new DeviceApiError(errorcode.INVALID_VALUES_ERR));
116693                 }, 1);
116694             }
116695         }
116696         return undefined;
116697     },
116698
116699     isEmptyObject: function (obj) {
116700         var prop;
116701
116702         for (prop in obj) {
116703             return false;
116704         }
116705         return true;
116706     }
116707 };
116708
116709
116710 });
116711 define('ripple/platform/web/default/device', function (require, exports, module) {
116712 /*
116713  *  Copyright 2011 Research In Motion Limited.
116714  *
116715  * Licensed under the Apache License, Version 2.0 (the "License");
116716  * you may not use this file except in compliance with the License.
116717  * You may obtain a copy of the License at
116718  *
116719  * http://www.apache.org/licenses/LICENSE-2.0
116720  *
116721  * Unless required by applicable law or agreed to in writing, software
116722  * distributed under the License is distributed on an "AS IS" BASIS,
116723  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
116724  * See the License for the specific language governing permissions and
116725  * limitations under the License.
116726  */
116727 window.addEventListener("load", function () {
116728     var event = require('ripple/event');
116729
116730     event.on("HardwareKey", function (key) {
116731         event.trigger("HardwareKeyDefault", [key]);
116732     });
116733
116734     //HACK: Remove this guy from namespace since we are just hacking this in as a bootstrapper
116735     delete window.device;
116736 });
116737
116738 });
116739 define('ripple/platform/web/default/spec/ui', function (require, exports, module) {
116740 module.exports = {
116741     plugins: [
116742         "accelerometer",
116743         "geoView"
116744     ]
116745 };
116746
116747 });
116748 define('ripple/platform/web/default/spec', function (require, exports, module) {
116749 /*
116750  *  Copyright 2011 Research In Motion Limited.
116751  *
116752  * Licensed under the Apache License, Version 2.0 (the "License");
116753  * you may not use this file except in compliance with the License.
116754  * You may obtain a copy of the License at
116755  *
116756  * http://www.apache.org/licenses/LICENSE-2.0
116757  *
116758  * Unless required by applicable law or agreed to in writing, software
116759  * distributed under the License is distributed on an "AS IS" BASIS,
116760  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
116761  * See the License for the specific language governing permissions and
116762  * limitations under the License.
116763  */
116764
116765 module.exports = {
116766
116767     id: "web",
116768     version: "default",
116769     name: "Mobile Web",
116770
116771     ui: require('ripple/platform/web/default/spec/ui'),
116772     device: {},
116773
116774     persistencePrefix: "tinyhippos-",
116775
116776     initialize: function () {},
116777
116778     objects: {
116779         Coordinates: {
116780             path: "w3c/1.0/Coordinates"
116781         },
116782         Position: {
116783             path: "w3c/1.0/Position"
116784         },
116785         PositionError: {
116786             path: "w3c/1.0/PositionError"
116787         },
116788         navigator: {
116789             path: "w3c/1.0/navigator",
116790             children: {
116791                 geolocation: {
116792                     path: "w3c/1.0/geolocation"
116793                 }
116794             }
116795         },
116796         device: {
116797             path: "web/default/device"
116798         }
116799     },
116800 };
116801
116802 });
116803 define('ripple/platform/webworks.bb10/1.0.0/app', function (require, exports, module) {
116804 /*
116805  *  Copyright 2011 Research In Motion Limited.
116806  *
116807  * Licensed under the Apache License, Version 2.0 (the "License");
116808  * you may not use this file except in compliance with the License.
116809  * You may obtain a copy of the License at
116810  *
116811  * http://www.apache.org/licenses/LICENSE-2.0
116812  *
116813  * Unless required by applicable law or agreed to in writing, software
116814  * distributed under the License is distributed on an "AS IS" BASIS,
116815  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
116816  * See the License for the specific language governing permissions and
116817  * limitations under the License.
116818  */
116819 var transport = require('ripple/platform/webworks.core/2.0.0/client/transport'),
116820     app = require('ripple/app'),
116821     notifications = require('ripple/notifications'),
116822     _uri = "blackberry/app/",
116823     _self;
116824
116825 _self = {
116826     exit: function () {
116827         notifications.openNotification("normal", "blackberry.app.exit() was called, in the real world your app will exit, here... you get this notification");
116828     }
116829 };
116830
116831 _self.__defineGetter__("author", function () {
116832     return app.getInfo().author;
116833 });
116834
116835 _self.__defineGetter__("authorEmail", function () {
116836     return app.getInfo().authorEmail;
116837 });
116838
116839 _self.__defineGetter__("authorURL", function () {
116840     return app.getInfo().authorURL;
116841 });
116842
116843 _self.__defineGetter__("copyright", function () {
116844     return app.getInfo().copyright;
116845 });
116846
116847 _self.__defineGetter__("description", function () {
116848     return app.getInfo().description;
116849 });
116850
116851 _self.__defineGetter__("id", function () {
116852     return app.getInfo().id;
116853 });
116854
116855 _self.__defineGetter__("license", function () {
116856     return app.getInfo().license;
116857 });
116858
116859 _self.__defineGetter__("licenseURL", function () {
116860     return app.getInfo().licenseURL;
116861 });
116862
116863 _self.__defineGetter__("name", function () {
116864     return app.getInfo().name;
116865 });
116866
116867 _self.__defineGetter__("version", function () {
116868     return app.getInfo().version;
116869 });
116870
116871 module.exports = _self;
116872
116873 });
116874 define('ripple/platform/webworks.bb10/1.0.0/connection', function (require, exports, module) {
116875 /*
116876  *  Copyright 2011 Research In Motion Limited.
116877  *
116878  * Licensed under the Apache License, Version 2.0 (the "License");
116879  * you may not use this file except in compliance with the License.
116880  * You may obtain a copy of the License at
116881  *
116882  * http://www.apache.org/licenses/LICENSE-2.0
116883  *
116884  * Unless required by applicable law or agreed to in writing, software
116885  * distributed under the License is distributed on an "AS IS" BASIS,
116886  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
116887  * See the License for the specific language governing permissions and
116888  * limitations under the License.
116889  */
116890 var deviceSettings = require('ripple/deviceSettings'),
116891     _self = {};
116892
116893 _self.__defineGetter__("type", function () {
116894     return deviceSettings.retrieve("NetworkStatus.connectionType");
116895 });
116896
116897 _self.__defineGetter__("UNKNOWN", function () { return "unknown"; });
116898 _self.__defineGetter__("ETHERNET", function () { return "ethernet"; });
116899 _self.__defineGetter__("WIFI", function () { return "wifi"; });
116900 _self.__defineGetter__("BLUETOOTH_DUN", function () { return "bluetooth_dun"; });
116901 _self.__defineGetter__("USB", function () { return "usb"; });
116902 _self.__defineGetter__("VPN", function () { return "vpn"; });
116903 _self.__defineGetter__("BB", function () { return "rim-bb"; });
116904 _self.__defineGetter__("CELL_2G", function () { return "2g"; });
116905 _self.__defineGetter__("CELL_3G", function () { return "3g"; });
116906 _self.__defineGetter__("CELL_4G", function () { return "4g"; });
116907 _self.__defineGetter__("NONE", function () { return "none"; });
116908
116909 module.exports = _self;
116910
116911 });
116912 define('ripple/platform/webworks.bb10/1.0.0/device', function (require, exports, module) {
116913 /*
116914  *  Copyright 2011 Research In Motion Limited.
116915  *
116916  * Licensed under the Apache License, Version 2.0 (the "License");
116917  * you may not use this file except in compliance with the License.
116918  * You may obtain a copy of the License at
116919  *
116920  * http://www.apache.org/licenses/LICENSE-2.0
116921  *
116922  * Unless required by applicable law or agreed to in writing, software
116923  * distributed under the License is distributed on an "AS IS" BASIS,
116924  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
116925  * See the License for the specific language governing permissions and
116926  * limitations under the License.
116927  */
116928 var devices = require('ripple/devices'),
116929     _self = {};
116930
116931 _self.__defineGetter__("softwareVersion", function () {
116932     return devices.getCurrentDevice().osVersion;
116933 });
116934
116935 _self.__defineGetter__("hardwareId", function () {
116936     return devices.getCurrentDevice().hardwareId;
116937 });
116938 module.exports = _self;
116939
116940 });
116941 define('ripple/platform/webworks.bb10/1.0.0/dialog', function (require, exports, module) {
116942 /*
116943  *  Copyright 2011 Research In Motion Limited.
116944  *
116945  * Licensed under the Apache License, Version 2.0 (the "License");
116946  * you may not use this file except in compliance with the License.
116947  * You may obtain a copy of the License at
116948  *
116949  * http://www.apache.org/licenses/LICENSE-2.0
116950  *
116951  * Unless required by applicable law or agreed to in writing, software
116952  * distributed under the License is distributed on an "AS IS" BASIS,
116953  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
116954  * See the License for the specific language governing permissions and
116955  * limitations under the License.
116956  */
116957 var _self,
116958     ui = require('ripple/ui'),
116959     event = require('ripple/event'),
116960     isDialogVisible = false,
116961     visibleDialogArgs,
116962     utils = require('ripple/utils');
116963
116964 function getButtonsForDialogType(dialogType) {
116965     switch (dialogType) {
116966     case _self.D_OK:
116967         return ["Ok"];
116968     case _self.D_SAVE:
116969         return ["Save", "Discard"];
116970     case _self.D_DELETE:
116971         return ["Delete", "Cancel"];
116972     case _self.D_YES_NO:
116973         return ["Yes", "No"];
116974     case _self.D_OK_CANCEL:
116975         return ["Ok", "Cancel"];
116976     default:
116977         throw new Error("Invalid dialog type: " + dialogType);
116978     }
116979 }
116980
116981 event.on("LayoutChanged", function () {
116982     if (isDialogVisible) {
116983         closeDialog();
116984         //Used to resize dialog on orientation change
116985         _self.ask(visibleDialogArgs);
116986     }
116987 });
116988
116989 function closeDialog() {
116990     var buttonsDiv = document.getElementById("dialog-buttons"),
116991         messageDiv = document.getElementById("dialog-message");
116992
116993     ui.hideOverlay("dialog-window", function (dialog) {
116994         buttonsDiv.innerHTML = "";
116995         messageDiv.innerHTML = "";
116996         isDialogVisible = false;
116997     });
116998 }
116999
117000 function ask(args, callback) {
117001     if (!args) {
117002         throw ("No arguments provided");
117003     } else if (!args.buttons || !args.message) {
117004         throw ("Invalid arguments");
117005     }
117006     visibleDialogArgs = args;
117007
117008     ui.showOverlay("dialog-window", function (dialog) {
117009         var container = document.getElementById("viewport-container"),
117010             height = window.getComputedStyle(container, null).getPropertyValue("height"),
117011             width = window.getComputedStyle(container, null).getPropertyValue("width"),
117012             sizeDiv = document.getElementById("dialog-wrapper"),
117013             positionDiv = document.getElementById("dialog-window"),
117014             titleDiv = document.getElementById("dialog-title"),
117015             buttonsDiv = document.getElementById("dialog-buttons"),
117016             messageDiv = document.getElementById("dialog-message"),
117017             position, size;
117018
117019         if (!messageDiv || !buttonsDiv) {
117020             return;
117021         }
117022
117023         dialog.setAttribute("style", "display:-webkit-box;height:" + height + "; width:" + width + ";");
117024
117025         position = "overlay-dialog";
117026         size = "overlay-dialog-wrapper";
117027
117028         if (args.settings && args.settings.position) {
117029             position += " overlay-dialog-" + args.settings.position;
117030         }
117031
117032         if (args.settings && args.settings.size) {
117033             size += " overlay-dialog-wrapper-" + args.settings.size;
117034         }
117035
117036         positionDiv.setAttribute("class", position);
117037         sizeDiv.setAttribute("class", size);
117038
117039         titleDiv.innerHTML = args.settings && args.settings.title ? args.settings.title : "";
117040         messageDiv.innerHTML = args.message;
117041         isDialogVisible = true;
117042
117043         args.buttons.forEach(function (button) {
117044             var buttonElement = utils.createElement("input", {
117045                 "type": "button",
117046                 "value": button
117047             });
117048             buttonElement.addEventListener("click", function () {
117049                 var buttonIndex = args.buttons.indexOf(button);
117050                 closeDialog();
117051                 callback(buttonIndex);
117052             });
117053             buttonsDiv.appendChild(buttonElement);
117054         });
117055     }, true);
117056 }
117057
117058 _self = {
117059     customAskAsync: function (message, choices, callback, settings) {
117060         ask({
117061             message: message,
117062             buttons: choices,
117063             settings: settings
117064         }, function (response) {
117065             if (callback) {
117066                 callback(response);
117067             }
117068         });
117069     },
117070
117071     standardAskAsync: function (message, type, callback, settings) {
117072         var choices = getButtonsForDialogType(type);
117073         ask({ 
117074             message: message, 
117075             buttons: choices, 
117076             settings: settings
117077         }, function (response) {
117078             if (callback) {
117079                 callback(response);
117080             }
117081         });
117082     }
117083 };
117084
117085 _self.__defineGetter__("D_OK", function () {
117086     return 0;
117087 });
117088
117089 _self.__defineGetter__("D_SAVE", function () {
117090     return 1;
117091 });
117092
117093 _self.__defineGetter__("D_DELETE", function () {
117094     return 2;
117095 });
117096
117097 _self.__defineGetter__("D_YES_NO", function () {
117098     return 3;
117099 });
117100
117101 _self.__defineGetter__("D_OK_CANCEL", function () {
117102     return 4;
117103 });
117104
117105 _self.__defineGetter__("BOTTOM", function () {
117106     return "bottomCenter";
117107 });
117108
117109 _self.__defineGetter__("CENTER", function () {
117110     return "middleCenter";
117111 });
117112
117113 _self.__defineGetter__("TOP", function () {
117114     return "topCenter";
117115 });
117116
117117 _self.__defineGetter__("SIZE_FULL", function () {
117118     return "full";
117119 });
117120
117121 _self.__defineGetter__("SIZE_LARGE", function () {
117122     return "large";
117123 });
117124
117125 _self.__defineGetter__("SIZE_MEDIUM", function () {
117126     return "medium";
117127 });
117128
117129 _self.__defineGetter__("SIZE_SMALL", function () {
117130     return "small";
117131 });
117132
117133 _self.__defineGetter__("SIZE_TALL", function () {
117134     return "tall";
117135 });
117136
117137 module.exports = _self;
117138
117139 });
117140 define('ripple/platform/webworks.bb10/1.0.0/event', function (require, exports, module) {
117141 /*
117142  *  Copyright 2011 Research In Motion Limited.
117143  *
117144  * Licensed under the Apache License, Version 2.0 (the "License");
117145  * you may not use this file except in compliance with the License.
117146  * You may obtain a copy of the License at
117147  *
117148  * http://www.apache.org/licenses/LICENSE-2.0
117149  *
117150  * Unless required by applicable law or agreed to in writing, software
117151  * distributed under the License is distributed on an "AS IS" BASIS,
117152  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
117153  * See the License for the specific language governing permissions and
117154  * limitations under the License.
117155  */
117156
117157 var event = require('ripple/event'),
117158     settings = require('ripple/deviceSettings'),
117159     app = require('ripple/app'),
117160     cons = require('ripple/console'),
117161     utils = require('ripple/utils'),
117162     events = {
117163         batterystatus: {
117164             callbacks: [],
117165             feature: 'blackberry.system' 
117166         },
117167         batterylow: {
117168             callbacks: [],
117169             feature: 'blackberry.system'
117170         },
117171         batterycritical: {
117172             callbacks: [],
117173             feature: 'blackberry.system'
117174         },
117175         connectionchange: {
117176             callbacks: [],
117177             feature: 'blackberry.connection'
117178         },
117179         invoked: {
117180             callbacks: [],
117181             feature: 'blackberry.invoked'
117182         },
117183         swipedown: {
117184             callbacks: [],
117185             feature: 'blackberry.app'
117186         },
117187         resume: {
117188             callbacks: [],
117189             feature: 'blackberry.app'
117190         },
117191         pause: {
117192             callbacks: [],
117193             feature: 'blackberry.app'
117194         },
117195         languagechange: {
117196             callbacks: [],
117197             feature: "blackberry.system"
117198         },
117199         regionchange: {
117200             callbacks: [],
117201             feature: "blackberry.system"
117202         }
117203     };
117204
117205 function _apply(eventName, args) {
117206     events[eventName].callbacks.forEach(function (cb) {
117207         cb.apply(null, args);
117208     });
117209 }
117210
117211 event.on('DeviceBatteryStateChanged', function (charging) {
117212     var info = {
117213         isPlugged: charging,
117214         level: parseInt(settings.retrieve('battery.level'), 10)
117215     };
117216
117217     _apply('batterystatus', [info]);
117218 });
117219
117220 event.on('DeviceBatteryLevelChanged', function (level) {
117221     var info = {
117222         isPlugged: settings.retrieve('battery.state'),
117223         level: parseInt(level, 10)
117224     };
117225
117226     _apply('batterystatus', [info]);
117227     
117228     if (level === '14') {
117229         _apply('batterylow', [info]);
117230     }
117231
117232     if (level === '4') {
117233         _apply('batterycritical', [info]);
117234     }
117235 });
117236
117237 event.on('DeviceConnectionChanged', function (info) {
117238     _apply('connectionchange', [info]);
117239 });
117240
117241 event.on("LanguageChanged", function (lang) {
117242     _apply("languagechange", [lang]);
117243 });
117244
117245 event.on("RegionChanged", function (lang) {
117246     _apply("regionchange", [lang]);
117247 });
117248
117249 event.on("AppInvoke", function (invokeInfo) {
117250     var invokeTargets = app.getInfo().invokeTargets;
117251
117252     if (!invokeTargets) {
117253         cons.log("The application cannot be invoked, please add a rim:invoke-target node in config.xml");
117254         return;
117255     }
117256
117257     if (invokeTargets.some(function (target) {
117258         return target.filter.some(function (filter) {
117259             return (
117260                 (!filter.property ||
117261                 (filter.property && filter.property[0]["@attributes"].var === "exts" && filter.property[0]["@attributes"].value.split(",").some(function (value) {
117262                     return invokeInfo.extension.match(value);
117263                 })) ||
117264                 (filter.property && filter.property[0]["@attributes"].var === "uris" && filter.property[0]["@attributes"].value.split(",").some(function (value) {
117265                     return invokeInfo.uri.match(value);
117266                 }))) &&
117267                 filter.action.some(function (action) {
117268                     return invokeInfo.action.match(action["#text"][0].replace("*", ""));
117269                 }) &&
117270                 filter["mime-type"].some(function (type) {
117271                     return invokeInfo.type.match(type["#text"][0].replace("*", ""));
117272                 })
117273             );
117274         });
117275     })) {
117276         _apply('invoked', [invokeInfo]);
117277     }
117278     else {
117279         cons.log("Cannot invoke application, values enter to not match values in rim:invoke-target in config.xml");
117280     }
117281 });
117282
117283 event.on('AppSwipeDown', function () {
117284     _apply('swipedown');
117285 });
117286
117287 event.on('AppResume', function () {
117288     _apply('resume');
117289 });
117290
117291 event.on('AppPause', function () {
117292     _apply('pause');
117293 });
117294
117295 module.exports = {
117296     addEventListener: function (type, func) {
117297         this.removeEventListener(type, func);
117298
117299         if (!app.getInfo().features || app.getInfo().features[events[type].feature]) {
117300             events[type].callbacks.push(func);
117301         }
117302         else {
117303             throw ("Cannot register a hanlder for the " + type + " event. Please add the '" + 
117304                   events[type].feature + "' to your config.xml.");
117305         }
117306     },
117307
117308     removeEventListener: function (type, func) {
117309         var idx = events[type].callbacks.indexOf(func);
117310         if (idx >= 0) {
117311             delete events[type].callbacks[idx];
117312         }
117313     }
117314 };
117315
117316 });
117317 define('ripple/platform/webworks.bb10/1.0.0/identity', function (require, exports, module) {
117318 /*
117319  *  Copyright 2011 Research In Motion Limited.
117320  *
117321  * Licensed under the Apache License, Version 2.0 (the "License");
117322  * you may not use this file except in compliance with the License.
117323  * You may obtain a copy of the License at
117324  *
117325  * http://www.apache.org/licenses/LICENSE-2.0
117326  *
117327  * Unless required by applicable law or agreed to in writing, software
117328  * distributed under the License is distributed on an "AS IS" BASIS,
117329  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
117330  * See the License for the specific language governing permissions and
117331  * limitations under the License.
117332  */
117333 var deviceSettings = require('ripple/deviceSettings'),
117334     _self = {};
117335
117336 _self.__defineGetter__("uuid", function () {
117337     return deviceSettings.retrieve("identity.uuid");
117338 });
117339
117340 module.exports = _self;
117341
117342 });
117343 define('ripple/platform/webworks.bb10/1.0.0/invoke', function (require, exports, module) {
117344 /*\r
117345  *  Copyright 2011 Research In Motion Limited.\r
117346  *\r
117347  * Licensed under the Apache License, Version 2.0 (the "License");\r
117348  * you may not use this file except in compliance with the License.\r
117349  * You may obtain a copy of the License at\r
117350  *\r
117351  * http://www.apache.org/licenses/LICENSE-2.0\r
117352  *\r
117353  * Unless required by applicable law or agreed to in writing, software\r
117354  * distributed under the License is distributed on an "AS IS" BASIS,\r
117355  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
117356  * See the License for the specific language governing permissions and\r
117357  * limitations under the License.\r
117358  */\r
117359 \r
117360 var notifications = require('ripple/notifications'),\r
117361     utils = require('ripple/utils'),\r
117362     _self = {};\r
117363 \r
117364 function _fail(onError) {\r
117365     if (onError && typeof onError === "function") {\r
117366         onError("invalid invocation request");\r
117367     }\r
117368 }\r
117369 \r
117370 _self.invoke = function (request, onSuccess, onError) {\r
117371     var argsString = "";\r
117372 \r
117373     if (!request) { // is this check even needed?\r
117374         _fail(onError);\r
117375         return;\r
117376     } else {\r
117377         if (request) {\r
117378             utils.forEach(request, function (arg, key) {\r
117379                 argsString += key + " = " + arg + "</br>";\r
117380             });\r
117381 \r
117382             notifications.openNotification("normal", "Requested to invoke external application with the following arguments:</br> " +\r
117383                                            argsString + "</br>");\r
117384         }\r
117385         else {\r
117386             _fail(onError);\r
117387             return;\r
117388         }\r
117389     }\r
117390 };\r
117391 \r
117392 _self.__defineGetter__("ACTION_OPEN", function () {\r
117393     return "bb.action.OPEN";\r
117394 });\r
117395 _self.__defineGetter__("ACTION_VIEW", function () { \r
117396     return "bb.action.VIEW"; \r
117397 });\r
117398 _self.__defineGetter__("ACTION_SHARE", function () {\r
117399     return "bb.action.SHARE";\r
117400 });\r
117401 \r
117402 module.exports = _self;\r
117403
117404 });
117405 define('ripple/platform/webworks.bb10/1.0.0/navigator', function (require, exports, module) {
117406 /*
117407  *  Copyright 2011 Research In Motion Limited.
117408  *
117409  * Licensed under the Apache License, Version 2.0 (the "License");
117410  * you may not use this file except in compliance with the License.
117411  * You may obtain a copy of the License at
117412  *
117413  * http://www.apache.org/licenses/LICENSE-2.0
117414  *
117415  * Unless required by applicable law or agreed to in writing, software
117416  * distributed under the License is distributed on an "AS IS" BASIS,
117417  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
117418  * See the License for the specific language governing permissions and
117419  * limitations under the License.
117420  */
117421 var nav = require('ripple/platform/w3c/1.0/navigator'),
117422     utils = require('ripple/utils'),
117423     deviceSettings = require('ripple/deviceSettings'),
117424     _self = {};
117425
117426 utils.mixin(nav, _self);
117427
117428 _self.__defineGetter__("language", function () {
117429     return deviceSettings.retrieve("system.language");
117430 });
117431
117432 module.exports = _self;
117433
117434 });
117435 define('ripple/platform/webworks.bb10/1.0.0/spec/config', function (require, exports, module) {
117436 /*
117437  *  Copyright 2011 Research In Motion Limited.
117438  *
117439  * Licensed under the Apache License, Version 2.0 (the "License");
117440  * you may not use this file except in compliance with the License.
117441  * You may obtain a copy of the License at
117442  *
117443  * http://www.apache.org/licenses/LICENSE-2.0
117444  *
117445  * Unless required by applicable law or agreed to in writing, software
117446  * distributed under the License is distributed on an "AS IS" BASIS,
117447  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
117448  * See the License for the specific language governing permissions and
117449  * limitations under the License.
117450  */
117451 var utils = require('ripple/utils');
117452
117453 module.exports = {
117454     fileName: "config.xml",
117455     validateVersion: function (config) {
117456         return true;
117457     },
117458     extractInfo: function (config) {
117459         if (!config) {
117460             return null;
117461         }
117462
117463         var widgetInfo = {},
117464             widgetFeatures = config.widget.children.feature.validationResult,
117465             accessUrls = config.widget.children.access.validationResult,
117466             invokeTargets = config.rawJSON.widget[0]["rim:invoke-target"],
117467             accessFeatures = config.widget.children.access.children.feature.validationResult,
117468             toFeature = function (validationResult) {
117469                 return {
117470                     id: validationResult.attributes.id.value,
117471                     required: !validationResult.attributes.required || validationResult.attributes.required.value,
117472                     URIs: []
117473                 };
117474             };
117475
117476         widgetInfo.id = config.widget.validationResult[0].attributes.id.value;
117477         widgetInfo.name = config.widget.children.name.validationResult[0].value;
117478         widgetInfo.icon = config.widget.children.icon.validationResult[0].attributes.src.value;
117479         widgetInfo.version = config.widget.validationResult[0].attributes.version.value;
117480         widgetInfo.author = config.widget.children.author.validationResult[0].value;
117481         widgetInfo.authorEmail = config.widget.children.author.validationResult[0].attributes.email.value;
117482         widgetInfo.authorURL = config.widget.children.author.validationResult[0].attributes.href.value;
117483         widgetInfo.copyright = config.widget.children.author.validationResult[0].attributes["rim:copyright"].value;
117484         widgetInfo.description = config.widget.children.description.validationResult[0].value;
117485         widgetInfo.invokeTargets = invokeTargets;
117486         if (config.widget.children.license.validationResult[0]) {
117487             widgetInfo.license = config.widget.children.license.validationResult[0].value;
117488             widgetInfo.licenseURL = config.widget.children.license.validationResult[0].attributes.href.value;
117489         }
117490
117491         widgetInfo.features = widgetFeatures.reduce(function (features, validationResult) {
117492             if (validationResult.valid) {
117493                 var feature = toFeature(validationResult);
117494                 feature.URIs.push({
117495                     value: utils.location().href,
117496                     subdomains: true
117497                 });
117498                 features = features || {};
117499                 features[feature.id] = feature;
117500             }
117501             return features;
117502         }, {});
117503
117504         widgetInfo.features = accessUrls.map(function (access) {
117505             return {
117506                 uri: access.attributes.uri.value,
117507                 subdomains: access.attributes.subdomains.value,
117508                 features: accessFeatures ? accessFeatures.filter(function (f) {
117509                     return f.node && f.node.parentNode && f.node.parentNode.attributes.uri.value === access.attributes.uri.value;
117510                 }) : null
117511             };
117512         }).reduce(function (result, access) {
117513             return access.features ? access.features.reduce(function (features, validationResult) {
117514                 var feature = features[validationResult.attributes.id.value] || toFeature(validationResult);
117515                 feature.URIs.push({
117516                     value: access.uri,
117517                     subdomains: access.subdomains
117518                 });
117519                 features[feature.id] = feature;
117520                 return features;
117521             }, result) : result;
117522         }, widgetInfo.features);
117523
117524         return widgetInfo;
117525     },
117526     schema: {
117527         rootElement: "widget",
117528         widget: {
117529             nodeName: "widget",
117530             required: true,
117531             occurrence: 1,
117532             attributes: {
117533                 xmlns: {
117534                     attributeName: "xmlns",
117535                     required: true,
117536                     type: "list",
117537                     listValues: ["http://www.w3.org/ns/widgets"]
117538                 },
117539                 "xmlns:rim": {
117540                     attributeName: "xmlns:rim",
117541                     required: true,
117542                     type: "list",
117543                     listValues: ["http://www.blackberry.com/ns/widgets"]
117544                 },
117545                 "xml:lang": {
117546                     attributeName: "xml:lang",
117547                     required: false,
117548                     type: "iso-language"
117549                 },
117550                 id: {
117551                     attributeName: "id",
117552                     required: false,
117553                     type: "string"
117554                 },
117555                 version: {
117556                     attributeName: "version",
117557                     required: false,
117558                     type: "string"
117559                 },
117560                 "rim:header": {
117561                     attributeName: "rim:header",
117562                     required: false,
117563                     type: "string"
117564                 },
117565                 "rim:backButton": {
117566                     attributeName: "rim:backButton",
117567                     required: false,
117568                     type: "string"
117569                 }
117570             },
117571             children: {
117572                 name: {
117573                     nodeName: "name",
117574                     required: true,
117575                     occurrence: 1,
117576                     attributes: {
117577                         "xml:lang": {
117578                             attributeName: "xml:lang",
117579                             required: false,
117580                             type: "iso-language"
117581                         },
117582                         "its:dir": {
117583                             attributeName: "its:dir",
117584                             required: false,
117585                             type: "list",
117586                             listValues: ["rtl", "ltr", "lro", "rlo"]
117587                         }
117588                     }
117589                 },
117590                 description: {
117591                     nodeName: "description",
117592                     required: false,
117593                     occurrence: 1,
117594                     attributes: {
117595                         "xml:lang": {
117596                             attributeName: "xml:lang",
117597                             required: false,
117598                             type: "iso-language"
117599                         },
117600                         "its:dir": {
117601                             attributeName: "its:dir",
117602                             required: false,
117603                             type: "list",
117604                             listValues: ["rtl", "ltr", "lro", "rlo"]
117605                         }
117606                     }
117607                 },
117608                 icon: {
117609                     nodeName: "icon",
117610                     required: false,
117611                     occurrence: 0,
117612                     attributes: {
117613                         src: {
117614                             attributeName: "src",
117615                             type: "string",
117616                             required: true
117617                         },
117618                         "rim:hover": {
117619                             attributeName: "rim:hover",
117620                             type: "boolean",
117621                             required: false
117622                         }
117623                     }
117624                 },
117625                 author: {
117626                     nodeName: "author",
117627                     required: false,
117628                     occurrence: 1,
117629                     attributes: {
117630                         href: {
117631                             attributeName: "href",
117632                             type: "string",
117633                             required: false
117634                         },
117635                         "rim:copyright": {
117636                             attributeName: "rim:copyright",
117637                             type: "string",
117638                             required: false
117639                         },
117640                         email: {
117641                             attributeName: "email",
117642                             type: "string",
117643                             required: false
117644                         },
117645                         "xml:lang": {
117646                             attributeName: "xml:lang",
117647                             required: false,
117648                             type: "iso-language"
117649                         },
117650                         "its:dir": {
117651                             attributeName: "its:dir",
117652                             required: false,
117653                             type: "list",
117654                             listValues: ["rtl", "ltr", "lro", "rlo"]
117655                         }
117656                     }
117657                 },
117658                 license: {
117659                     nodeName: "license",
117660                     required: false,
117661                     occurrence: 1,
117662                     attributes : {
117663                         href: {
117664                             attributeName: "href",
117665                             type: "string",
117666                             required: false
117667                         },
117668                         "xml:lang": {
117669                             attributeName: "xml:lang",
117670                             required: false,
117671                             type: "iso-language"
117672                         },
117673                         "its:dir": {
117674                             attributeName: "its:dir",
117675                             required: false,
117676                             type: "list",
117677                             listValues: ["rtl", "ltr", "lro", "rlo"]
117678                         }
117679                     }
117680                 },
117681                 "rim:cache": {
117682                     nodeName: "rim:cache",
117683                     required: false,
117684                     occurrence: 1,
117685                     attributes: {
117686                         disableAllCache: {
117687                             attributeName: "disableAllCache",
117688                             required: false,
117689                             type: "boolean"
117690                         },
117691                         aggressiveCacheAge: {
117692                             attributeName: "aggressiveCacheAge",
117693                             required: false,
117694                             type: "number"
117695                         },
117696                         maxCacheSizeTotal: {
117697                             attributeName: "maxCacheSizeTotal",
117698                             required: false,
117699                             type: "number"
117700                         },
117701                         maxCacheSizeItem: {
117702                             attributeName: "maxCacheSizeItem",
117703                             required: false,
117704                             type: "number"
117705                         }
117706                     }
117707                 },
117708                 access: {
117709                     nodeName: "access",
117710                     required: false,
117711                     occurrence: 0,
117712                     attributes: {
117713                         uri: {
117714                             attributeName: "uri",
117715                             required: true,
117716                             type: "string"
117717                         },
117718                         subdomains: {
117719                             attributeName: "subdomains",
117720                             required: false,
117721                             type: "boolean"
117722                         }
117723                     },
117724                     children: {
117725                         feature: {
117726                             nodeName: "feature",
117727                             required: false,
117728                             occurrence: 0,
117729                             attributes: {
117730                                 id: {
117731                                     attributeName: "id",
117732                                     required: true,
117733                                     //TODO: this should be a list
117734                                     type: "string"
117735                                 },
117736                                 required: {
117737                                     attributeName: "required",
117738                                     required: false,
117739                                     type: "boolean"
117740                                 },
117741                                 version: {
117742                                     attributeName: "version",
117743                                     required: false,
117744                                     type: "string"
117745                                 }
117746                             }
117747                         }
117748                     }
117749                 },
117750                 feature: {
117751                     nodeName: "feature",
117752                     required: false,
117753                     occurrence: 0,
117754                     attributes: {
117755                         id: {
117756                             attributeName: "id",
117757                             required: true,
117758                             //TODO: this should be a list
117759                             type: "string"
117760                         },
117761                         required: {
117762                             attributeName: "required",
117763                             required: false,
117764                             type: "boolean"
117765                         },
117766                         version: {
117767                             attributeName: "version",
117768                             required: false,
117769                             type: "string"
117770                         }
117771                     }
117772                 },
117773                 "rim:loadingScreen": {
117774                     nodeName: "rim:loadingScreen",
117775                     required: false,
117776                     occurrence: 1,
117777                     attributes: {
117778                         backgroundColor: {
117779                             attributeName: "backgroundColor",
117780                             required: false,
117781                             type: "string"
117782                         },
117783                         backgroundImage: {
117784                             attributeName: "backgroundImage",
117785                             required: false,
117786                             type: "string"
117787                         },
117788                         foregroundImage: {
117789                             attributeName: "foregroundImage",
117790                             required: false,
117791                             type: "string"
117792                         },
117793                         onRemotePageLoad: {
117794                             attributeName: "onRemotePageLoad",
117795                             required: false,
117796                             type: "boolean"
117797                         },
117798                         onLocalPageLoad: {
117799                             attributeName: "onLocalPageLoad",
117800                             required : false,
117801                             type: "boolean"
117802                         },
117803                         onFirstLaunch: {
117804                             attributeName: "onFirstLaunch",
117805                             required: false,
117806                             type: "boolean"
117807                         }
117808                     },
117809                     children: {
117810                         "rim:transitionEffect": {
117811                             nodeName: "rim:transitionEffect",
117812                             required: false,
117813                             occurrence: 1,
117814                             attributes: {
117815                                 "type": {
117816                                     attributeName: "type",
117817                                     required: true,
117818                                     type: "list",
117819                                     listValues: ["slidePush", "slideOver", "fadeIn", "fadeOut", "wipeIn", "wipeOut", "zoomIn", "zoomOut"]
117820                                 },
117821                                 duration: {
117822                                     attributeName: "duration",
117823                                     required: false,
117824                                     type: "number"
117825                                 },
117826                                 direction: {
117827                                     attributeName: "direction",
117828                                     required: false,
117829                                     type: "list",
117830                                     listValues: ["left", "right", "up", "down"]
117831                                 }
117832                             }
117833                         }
117834                     }
117835                 },
117836                 "rim:invoke-target": {
117837                     nodeName: "rim:invoke-target",
117838                     required: false,
117839                     occurrence: 0,
117840                     attributes: {
117841                         id: {
117842                             attributeName: "id",
117843                             required: true,
117844                             type: "string"
117845                         }
117846                     },
117847                     children: {
117848                         "type": {
117849                             nodeName: "type",
117850                             required: true,
117851                             occurrence: 1
117852                         },
117853                         "require-source-permissions": {
117854                             nodeName: "require-source-permissions",
117855                             required: false,
117856                             occurence: 0
117857                         },
117858                         "filter": {
117859                             nodeName: "filter",
117860                             required: false,
117861                             occurence: 0,
117862                             children: {
117863                                 "action": {
117864                                     nodeName: "action",
117865                                     required: true,
117866                                     occurence: 0
117867                                 },
117868                                 "mime-type": {
117869                                     nodeName: "mime-type",
117870                                     required: true,
117871                                     occurence: 0
117872                                 },
117873                                 "property": {
117874                                     nodeName: "property",
117875                                     required: false,
117876                                     occurenc: 0,
117877                                     attributes: {
117878                                         "var": {
117879                                             attributeName: "var",
117880                                             required: false,
117881                                             type: "string"
117882                                         },
117883                                         "value": {
117884                                             attributeName: "value",
117885                                             required: false,
117886                                             type: "string"
117887                                         }
117888                                     }
117889                                 }
117890                             },
117891                         }
117892                     }
117893                 },
117894                 "rim:connection": {
117895                     nodeName: "rim:connection",
117896                     required: false,
117897                     occurrence: 1,
117898                     attributes: {
117899                         timeout: {
117900                             attributeName: "timeout",
117901                             required: false,
117902                             type: "number"
117903                         }
117904                     },
117905                     children: {
117906                         id: {
117907                             nodeName: "id",
117908                             required: false,
117909                             occurrence: 0
117910                         }
117911                     }
117912                 },
117913                 "rim:navigation": {
117914                     nodeName: "rim:navigation",
117915                     required: false,
117916                     occurrence: 1,
117917                     attributes: {
117918                         mode: {
117919                             attributeName: "mode",
117920                             required: false,
117921                             type: "list",
117922                             listValues: ["focus"]
117923                         }
117924                     }
117925                 },
117926                 "content": {
117927                     nodeName: "content",
117928                     required: true,
117929                     occurrence: 1,
117930                     attributes: {
117931                         src: {
117932                             attributeName: "src",
117933                             required: true,
117934                             type: "string"
117935                         },
117936                         type: {
117937                             attributeName: "type",
117938                             required: false,
117939                             type: "string"
117940                         },
117941                         charset: {
117942                             attributeName: "charset",
117943                             required: false,
117944                             type: "string"
117945                         }
117946                     }
117947                 }
117948             }
117949         }
117950     }
117951 };
117952
117953 });
117954 define('ripple/platform/webworks.bb10/1.0.0/spec/device', function (require, exports, module) {
117955 /*
117956  *  Copyright 2011 Research In Motion Limited.
117957  *
117958  * Licensed under the Apache License, Version 2.0 (the "License");
117959  * you may not use this file except in compliance with the License.
117960  * You may obtain a copy of the License at
117961  *
117962  * http://www.apache.org/licenses/LICENSE-2.0
117963  *
117964  * Unless required by applicable law or agreed to in writing, software
117965  * distributed under the License is distributed on an "AS IS" BASIS,
117966  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
117967  * See the License for the specific language governing permissions and
117968  * limitations under the License.
117969  */
117970 var event = require('ripple/event');
117971
117972 module.exports = {
117973     "NetworkStatus": {
117974         "connectionType": {
117975             "name": "Connection Type",
117976             "control": {
117977                 "type": "select",
117978                 "value": "ethernet"
117979             },
117980             "options": {
117981                 "unknown": "UNKNOWN",
117982                 "ethernet": "ETHERNET",
117983                 "wifi": "WIFI",
117984                 "bluetooth_dun": "BLUETOOTH_DUN",
117985                 "usb": "USB",
117986                 "vpn": "VPN",
117987                 "rim-bb": "BB",
117988                 "2g": "CELL_2G",
117989                 "3g": "CELL_3G",
117990                 "4g": "CELL_4G",
117991                 "none": "NONE"
117992             },
117993             "callback": function (setting, oldSetting) {
117994                 event.trigger("DeviceConnectionChanged", [{oldType: oldSetting, newType: setting}]);
117995             }
117996         }
117997     },
117998     "identity": {
117999         "uuid": {
118000             "name": "uuid",
118001             "control": {
118002                 "type": "text",
118003                 "value": "43A8C489"
118004             }
118005         }
118006     },
118007     "system": {
118008         "language": {
118009             "name": "language",
118010             "control": {
118011                 "type": "text",
118012                 "value": "en_US"
118013             },
118014             "callback": function (setting) {
118015                 event.trigger("LanguageChanged", [setting]);
118016             }
118017         },
118018         "region": {
118019             "name": "region",
118020             "control": {
118021                 "type": "text",
118022                 "value": "en_CA"
118023             },
118024             "callback": function (setting) {
118025                 event.trigger("RegionChanged", [setting]);
118026             }
118027         }
118028     },
118029     "battery": {
118030         "state": {
118031             "name": "Handset is Charging",
118032             "control": {
118033                 "type": "checkbox",
118034                 "value": true
118035             },
118036             "callback": function (setting) {
118037                 event.trigger("DeviceBatteryStateChanged", [setting]);
118038             }
118039         },
118040         "level":  {
118041             "name": "Charge Level (% remaining)",
118042             "control": {
118043                 "type": "select",
118044                 "value": 100
118045             },
118046             "options": (function () {
118047                 var i,
118048                     optionList = {};
118049
118050                 for (i = 0; i <= 100; i++) {
118051                     optionList[i] = i;
118052                 }
118053
118054                 return optionList;
118055             }()),
118056             "callback": function (setting) {
118057                 event.trigger("DeviceBatteryLevelChanged", [setting]);
118058             }
118059         }
118060     },
118061     "Perimeters": {
118062         "perimeter": {
118063             "name": "Perimeter",
118064             "control": {
118065                 "type": "select",
118066                 "value": "Consumer"
118067             },
118068             "options": {
118069                 "Enterprise": "Enterprise",
118070                 "Consumer": "Consumer"
118071             }
118072         }
118073     }
118074 };
118075
118076 });
118077 define('ripple/platform/webworks.bb10/1.0.0/spec/events', function (require, exports, module) {
118078 /*
118079  *  Copyright 2011 Research In Motion Limited.
118080  *
118081  * Licensed under the Apache License, Version 2.0 (the "License");
118082  * you may not use this file except in compliance with the License.
118083  * You may obtain a copy of the License at
118084  *
118085  * http://www.apache.org/licenses/LICENSE-2.0
118086  *
118087  * Unless required by applicable law or agreed to in writing, software
118088  * distributed under the License is distributed on an "AS IS" BASIS,
118089  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
118090  * See the License for the specific language governing permissions and
118091  * limitations under the License.
118092  */
118093 var _self,
118094     event = require('ripple/event');
118095
118096 module.exports = {
118097     "blackberry.event.swipedown": {
118098         callback: function () {
118099             event.trigger("AppSwipeDown");
118100         }
118101     },
118102     "blackberry.event.resume": {
118103         callback: function () {
118104             event.trigger("AppResume");
118105         }
118106     },
118107     "blackberry.event.pause": {
118108         callback: function () {
118109             event.trigger("AppPause");
118110         }
118111     }
118112 };
118113
118114 });
118115 define('ripple/platform/webworks.bb10/1.0.0/spec/ui', function (require, exports, module) {
118116 /*
118117  *  Copyright 2011 Research In Motion Limited.
118118  *
118119  * Licensed under the Apache License, Version 2.0 (the "License");
118120  * you may not use this file except in compliance with the License.
118121  * You may obtain a copy of the License at
118122  *
118123  * http://www.apache.org/licenses/LICENSE-2.0
118124  *
118125  * Unless required by applicable law or agreed to in writing, software
118126  * distributed under the License is distributed on an "AS IS" BASIS,
118127  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
118128  * See the License for the specific language governing permissions and
118129  * limitations under the License.
118130  */
118131 module.exports = {
118132     plugins: [
118133         "accelerometer",
118134         "deviceSettings",
118135         "geoView",
118136         "platformEvents",
118137         "widgetConfig",
118138         "build",
118139         "invoke"
118140     ]
118141 };
118142
118143 });
118144 define('ripple/platform/webworks.bb10/1.0.0/spec', function (require, exports, module) {
118145 /*
118146  *  Copyright 2011 Research In Motion Limited.
118147  *
118148  * Licensed under the Apache License, Version 2.0 (the "License");
118149  * you may not use this file except in compliance with the License.
118150  * You may obtain a copy of the License at
118151  *
118152  * http://www.apache.org/licenses/LICENSE-2.0
118153  *
118154  * Unless required by applicable law or agreed to in writing, software
118155  * distributed under the License is distributed on an "AS IS" BASIS,
118156  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
118157  * See the License for the specific language governing permissions and
118158  * limitations under the License.
118159  */
118160 module.exports = {
118161
118162     id: "webworks.bb10",
118163     version: "1.0.0",
118164     name: "BlackBerry 10 WebWorks",
118165
118166     persistencePrefix: "rim-bb10-",
118167
118168     ui: require('ripple/platform/webworks.bb10/1.0.0/spec/ui'),
118169     device: require('ripple/platform/webworks.bb10/1.0.0/spec/device'),
118170     config: require('ripple/platform/webworks.bb10/1.0.0/spec/config'),
118171     events: require('ripple/platform/webworks.bb10/1.0.0/spec/events'),
118172
118173     initialize: function () {
118174         var event = require('ripple/event'),
118175             _console = require('ripple/console'),
118176             emulatorBridge = require('ripple/emulatorBridge');
118177
118178         event.on("TinyHipposLoaded", function () {
118179             var doc = emulatorBridge.document(),
118180                 evt = doc.createEvent("Events");
118181             evt.initEvent("webworksready", true, true);
118182             doc.dispatchEvent(evt);
118183             _console.log("fired webworksready event!");
118184         });
118185     },
118186
118187     objects: {
118188         Coordinates: {
118189             path: "w3c/1.0/Coordinates"
118190         },
118191         Position: {
118192             path: "w3c/1.0/Position"
118193         },
118194         PositionError: {
118195             path: "w3c/1.0/PositionError"
118196         },
118197         navigator: {
118198             path: "webworks.bb10/1.0.0/navigator",
118199             children: {
118200                 geolocation: {
118201                     path: "w3c/1.0/geolocation"
118202                 }
118203             }
118204         },
118205         blackberry: {
118206             children: {
118207                 event: {
118208                     path: "webworks.bb10/1.0.0/event"
118209                 },
118210                 app: {
118211                     path: "webworks.bb10/1.0.0/app",
118212                     feature: "blackberry.app"
118213                 },
118214                 invoke: {
118215                     path: "webworks.bb10/1.0.0/invoke",
118216                     feature: "blackberry.invoke"
118217                 },
118218                 identity: {
118219                     path: "webworks.bb10/1.0.0/identity",
118220                     feature: "blackberry.identity"
118221                 },
118222                 system: {
118223                     path: "webworks.bb10/1.0.0/system"
118224                 },
118225                 connection: {
118226                     path: "webworks.bb10/1.0.0/connection"
118227                 },
118228                 ui: {
118229                     children: {
118230                         dialog: {
118231                             path: "webworks.bb10/1.0.0/dialog",
118232                             feature: "blackberry.ui.dialog"
118233                         }
118234                     }
118235                 },
118236             }
118237         }
118238     }
118239 };
118240
118241 });
118242 define('ripple/platform/webworks.bb10/1.0.0/system', function (require, exports, module) {
118243 /*\r
118244  *  Copyright 2011 Research In Motion Limited.\r
118245  *\r
118246  * Licensed under the Apache License, Version 2.0 (the "License");\r
118247  * you may not use this file except in compliance with the License.\r
118248  * You may obtain a copy of the License at\r
118249  *\r
118250  * http://www.apache.org/licenses/LICENSE-2.0\r
118251  *\r
118252  * Unless required by applicable law or agreed to in writing, software\r
118253  * distributed under the License is distributed on an "AS IS" BASIS,\r
118254  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
118255  * See the License for the specific language governing permissions and\r
118256  * limitations under the License.\r
118257  */\r
118258 var deviceSettings = require('ripple/deviceSettings'),\r
118259     devices = require('ripple/devices'),\r
118260     app = require('ripple/app'),\r
118261     utils = require('ripple/utils'),\r
118262     _self;\r
118263 \r
118264 function _is(feature) {\r
118265     return {\r
118266         allowedFor: function (location) {\r
118267             return feature && feature.URIs.some(function (uri) {\r
118268                 return uri.value === location ||\r
118269                       (location.indexOf(uri.value) >= 0 && uri.subdomains);\r
118270             });\r
118271         }\r
118272     };\r
118273 }\r
118274 \r
118275 _self = {\r
118276     hasCapability: function (capability) {\r
118277         var capabilities = devices.getCurrentDevice().capabilities;\r
118278         return capabilities ? capabilities.some(function (type) {\r
118279                 return type === capability;\r
118280             }) : false;\r
118281     },\r
118282     hasPermission: function (desiredModule) {\r
118283         var info = app.getInfo(),\r
118284             feature = info.features ? info.features[desiredModule] : null;\r
118285 \r
118286         return feature === null || _is(feature).allowedFor(utils.location().href) ? _self.ALLOW : _self.DENY;\r
118287     }\r
118288 };\r
118289 \r
118290 _self.__defineGetter__("ALLOW", function () {\r
118291     return 0;\r
118292 });\r
118293 \r
118294 _self.__defineGetter__("DENY", function () {\r
118295     return 1;\r
118296 });\r
118297 \r
118298 _self.__defineGetter__("softwareVersion", function () {\r
118299     return devices.getCurrentDevice().osVersion;\r
118300 });\r
118301 \r
118302 _self.__defineGetter__("hardwareId", function () {\r
118303     return devices.getCurrentDevice().hardwareId;\r
118304 });\r
118305 \r
118306 _self.__defineGetter__("language", function () {\r
118307     return deviceSettings.retrieve("system.language");\r
118308 });\r
118309 \r
118310 _self.__defineGetter__("region", function () {\r
118311     return deviceSettings.retrieve("system.region");\r
118312 });\r
118313 \r
118314 module.exports = _self;\r
118315
118316 });
118317 define('ripple/platform/webworks.core/2.0.0/XMLHttpRequest', function (require, exports, module) {
118318 /*
118319  *  Copyright 2011 Research In Motion Limited.
118320  *
118321  * Licensed under the Apache License, Version 2.0 (the "License");
118322  * you may not use this file except in compliance with the License.
118323  * You may obtain a copy of the License at
118324  *
118325  * http://www.apache.org/licenses/LICENSE-2.0
118326  *
118327  * Unless required by applicable law or agreed to in writing, software
118328  * distributed under the License is distributed on an "AS IS" BASIS,
118329  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
118330  * See the License for the specific language governing permissions and
118331  * limitations under the License.
118332  */
118333 module.exports = {
118334     create: function (server) {
118335         var XHR = window.XMLHttpRequest,
118336             webworks = require(server);
118337
118338         return function () {
118339             var _url,
118340                 _async,
118341                 xhr = new XHR(),
118342                 origMethods = {
118343                     open: xhr.open,
118344                     send: xhr.send,
118345                     setRequestHeader: xhr.setRequestHeader
118346                 };
118347
118348             function onreadystatechange() {
118349                 if (typeof xhr.onreadystatechange === "function") {
118350                     xhr.onreadystatechange();
118351                 }
118352             }
118353
118354             function statemachine(getResult) {
118355                 var state = 0,
118356                     incState = function (prev, baton) {
118357                         state++;
118358                         if (_async) {
118359                             baton.take();
118360                             window.setTimeout(baton.pass, 1);
118361                         }
118362                     },
118363                     setResponse = function (result) {
118364                         xhr.__defineGetter__("status", function () {
118365                             return 200;
118366                         });
118367
118368                         xhr.__defineGetter__("responseText", function () {
118369                             return result !== null && result !== undefined ?
118370                                 JSON.stringify(result) : null;
118371                         });
118372                     };
118373
118374                 xhr.__defineGetter__("readyState", function () {
118375                     return state;
118376                 });
118377
118378                 jWorkflow.order(incState)
118379                          .andThen(onreadystatechange)
118380                          .andThen(incState)
118381                          .andThen(onreadystatechange)
118382                          .andThen(incState)
118383                          .andThen(onreadystatechange)
118384                          .andThen(getResult)
118385                          .andThen(setResponse)
118386                          .andThen(incState)
118387                          .andThen(onreadystatechange)
118388                          .start();
118389             }
118390
118391             xhr.setRequestHeader = function (header, value) {
118392                 if (!_url.match(/^webworks:\/\//)) {
118393                     origMethods.setRequestHeader.apply(xhr, Array.prototype.slice.call(arguments));
118394                 }
118395             };
118396
118397             xhr.open = function (method, url, async, user, password) {
118398                 _url = url;
118399                 _async = async;
118400
118401                 if (!_url.match(/^webworks:\/\//)) {
118402                     origMethods.open.apply(xhr, Array.prototype.slice.call(arguments));
118403                 }
118404             };
118405
118406             xhr.send = function (post) {
118407                 if (!_url.match(/^webworks:\/\//)) {
118408                     origMethods.send.apply(xhr, Array.prototype.slice.call(arguments));
118409                     return;
118410                 }
118411
118412                 var params = _url.match(/\?(.*)$/),
118413                     objPath = _url.match(/^webworks:\/\/([^\?]*)/)[1].split("/"),
118414                     apiMethod = objPath.reduce(function (obj, name) {
118415                         return obj[name];
118416                     }, webworks),
118417                     postParams = {},
118418                     get = {};
118419
118420                 if (params) {
118421                     params[1].split("&").forEach(function (param) {
118422                             var pair = param.split("="),
118423                                 key = decodeURIComponent(pair[0]),
118424                                 value = decodeURIComponent(pair[1]);
118425                             // parsing undefied with JSON throws exception
118426                             get[key] = value === "undefined" ? undefined : JSON.parse(value);
118427                         });
118428                 }
118429
118430                 if (post) {
118431                     post.split("&").forEach(function (param) {
118432                             var pair = param.split("="),
118433                                 value;
118434                             try {
118435                                 value = JSON.parse(decodeURIComponent(pair[1]));
118436                             } catch (e) {
118437                                 value = pair[1] === "undefined" ? undefined : pair[1];
118438                             }
118439
118440                             postParams[pair[0]] = value;
118441                         });
118442                 }
118443
118444                 statemachine(function (prev, baton) {
118445                     return apiMethod(get, postParams, baton);
118446                 });
118447             };
118448
118449             return xhr;
118450         };
118451     }
118452 };
118453
118454 });
118455 define('ripple/platform/webworks.core/2.0.0/client/FileProperties', function (require, exports, module) {
118456 /*
118457  * Copyright 2011 Research In Motion Limited.
118458  *
118459  * Licensed under the Apache License, Version 2.0 (the "License");
118460  * you may not use this file except in compliance with the License.
118461  * You may obtain a copy of the License at
118462  *
118463  *     http://www.apache.org/licenses/LICENSE-2.0
118464  *
118465  * Unless required by applicable law or agreed to in writing, software
118466  * distributed under the License is distributed on an "AS IS" BASIS,
118467  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
118468  * See the License for the specific language governing permissions and
118469  * limitations under the License.
118470  */
118471 function FileProperties(props) {
118472     props = props || {};
118473
118474     function _get(val) {
118475         return function () {
118476             return props[val];
118477         };
118478     }
118479
118480     this.__defineGetter__("dateCreated", _get("dateCreated")); //tablet only
118481     this.__defineGetter__("dateModified", _get("dateModified"));
118482     this.__defineGetter__("directory", _get("directory"));
118483     this.__defineGetter__("fileExtension", _get("fileExtension"));
118484     this.__defineGetter__("isHidden", _get("isHidden"));
118485     this.__defineGetter__("isReadonly", _get("isReadonly")); //handset only
118486     this.__defineGetter__("mimeType", _get("mimeType")); //handset only
118487     this.__defineGetter__("size", _get("size"));
118488 }
118489
118490 module.exports = FileProperties;
118491
118492 });
118493 define('ripple/platform/webworks.core/2.0.0/client/dialog', function (require, exports, module) {
118494 /*\r
118495  *  Copyright 2011 Research In Motion Limited.\r
118496  *\r
118497  * Licensed under the Apache License, Version 2.0 (the "License");\r
118498  * you may not use this file except in compliance with the License.\r
118499  * You may obtain a copy of the License at\r
118500  *\r
118501  * http://www.apache.org/licenses/LICENSE-2.0\r
118502  *\r
118503  * Unless required by applicable law or agreed to in writing, software\r
118504  * distributed under the License is distributed on an "AS IS" BASIS,\r
118505  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
118506  * See the License for the specific language governing permissions and\r
118507  * limitations under the License.\r
118508  */\r
118509 var transport = require('ripple/platform/webworks.core/2.0.0/client/transport'),\r
118510     _uri = "blackberry/ui/dialog/",\r
118511     _self;\r
118512 \r
118513 function getButtonsForDialogType(dialogType) {\r
118514     switch (dialogType) {\r
118515     case _self.D_OK:\r
118516         return ["Ok"];\r
118517     case _self.D_SAVE:\r
118518         return ["Save", "Discard"];\r
118519     case _self.D_DELETE:\r
118520         return ["Delete", "Cancel"];\r
118521     case _self.D_YES_NO:\r
118522         return ["Yes", "No"];\r
118523     case _self.D_OK_CANCEL:\r
118524         return ["Ok", "Cancel"];\r
118525     default:\r
118526         throw new Error("Invalid dialog type: " + dialogType);\r
118527     }\r
118528 }\r
118529 \r
118530 _self = {\r
118531     customAskAsync: function (message, choices, callback, settings) {\r
118532         return transport.call(_uri + "ask", {\r
118533             async: true,\r
118534             get: {\r
118535                 message: message,\r
118536                 buttons: choices,\r
118537                 settings: settings\r
118538             }\r
118539         }, function (response) {\r
118540             if (callback) {\r
118541                 callback(response);\r
118542             }\r
118543         });\r
118544     },\r
118545 \r
118546     standardAskAsync: function (message, type, callback, settings) {\r
118547         var choices = getButtonsForDialogType(type);\r
118548         return transport.call(_uri + "ask", {\r
118549             async: true,\r
118550             get: {\r
118551                 message: message,\r
118552                 buttons: choices,\r
118553                 settings: settings\r
118554             }\r
118555         }, function (response) {\r
118556             if (callback) {\r
118557                 callback(response);\r
118558             }\r
118559         });\r
118560     }\r
118561 };\r
118562 \r
118563 _self.__defineGetter__("D_OK", function () {\r
118564     return 0;\r
118565 });\r
118566 \r
118567 _self.__defineGetter__("D_SAVE", function () {\r
118568     return 1;\r
118569 });\r
118570 \r
118571 _self.__defineGetter__("D_DELETE", function () {\r
118572     return 2;\r
118573 });\r
118574 \r
118575 _self.__defineGetter__("D_YES_NO", function () {\r
118576     return 3;\r
118577 });\r
118578 \r
118579 _self.__defineGetter__("D_OK_CANCEL", function () {\r
118580     return 4;\r
118581 });\r
118582 \r
118583 _self.__defineGetter__("BOTTOM", function () {\r
118584     return "bottomCenter";\r
118585 });\r
118586 \r
118587 _self.__defineGetter__("CENTER", function () {\r
118588     return "middleCenter";\r
118589 });\r
118590 \r
118591 _self.__defineGetter__("TOP", function () {\r
118592     return "topCenter";\r
118593 });\r
118594 \r
118595 _self.__defineGetter__("SIZE_FULL", function () {\r
118596     return "full";\r
118597 });\r
118598 \r
118599 _self.__defineGetter__("SIZE_LARGE", function () {\r
118600     return "large";\r
118601 });\r
118602 \r
118603 _self.__defineGetter__("SIZE_MEDIUM", function () {\r
118604     return "medium";\r
118605 });\r
118606 \r
118607 _self.__defineGetter__("SIZE_SMALL", function () {\r
118608     return "small";\r
118609 });\r
118610 \r
118611 _self.__defineGetter__("SIZE_TALL", function () {\r
118612     return "tall";\r
118613 });\r
118614 \r
118615 module.exports = _self;\r
118616
118617 });
118618 define('ripple/platform/webworks.core/2.0.0/client/events', function (require, exports, module) {
118619 /*
118620  * Copyright 2011 Research In Motion Limited.
118621  *
118622  * Licensed under the Apache License, Version 2.0 (the "License");
118623  * you may not use this file except in compliance with the License.
118624  * You may obtain a copy of the License at
118625  *
118626  *     http://www.apache.org/licenses/LICENSE-2.0
118627  *
118628  * Unless required by applicable law or agreed to in writing, software
118629  * distributed under the License is distributed on an "AS IS" BASIS,
118630  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
118631  * See the License for the specific language governing permissions and
118632  * limitations under the License.
118633  */
118634 var _handlers = [],
118635     _self;
118636
118637 _self = {
118638     eventsMap: {
118639         getHandlerById: function (handlerId) {
118640             return _handlers[handlerId];
118641         },
118642         addHandler: function (handler) {
118643             _handlers.push(handler);
118644             return _handlers.length - 1;
118645         },
118646         removeHandler: function (handlerId) {
118647             if (handlerId > -1 && handlerId < _handlers.length) {
118648                 delete _handlers[handlerId]; //cannot splice because all published IDs would refer to the wrong handler
118649             }
118650         }
118651     },
118652
118653     registerEventHandler : function (eventName, eventCallback, eventParams) {
118654         return _self.eventsMap.addHandler(eventCallback);
118655     },
118656
118657     getEventHandler : function (handlerId) {
118658         return _self.eventsMap.getHandlerById(handlerId);
118659     }
118660 };
118661
118662 module.exports = _self;
118663
118664 });
118665 define('ripple/platform/webworks.core/2.0.0/client/io/dir', function (require, exports, module) {
118666 /*
118667  * Copyright 2011 Research In Motion Limited.
118668  *
118669  * Licensed under the Apache License, Version 2.0 (the "License");
118670  * you may not use this file except in compliance with the License.
118671  * You may obtain a copy of the License at
118672  *
118673  *     http://www.apache.org/licenses/LICENSE-2.0
118674  *
118675  * Unless required by applicable law or agreed to in writing, software
118676  * distributed under the License is distributed on an "AS IS" BASIS,
118677  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
118678  * See the License for the specific language governing permissions and
118679  * limitations under the License.
118680  */
118681 var transport = require('ripple/platform/webworks.core/2.0.0/client/transport'),
118682     _uri = "blackberry/io/dir/",
118683     FILE = "file://";
118684
118685 function _prunePrefix(path) {
118686     return path.replace(new RegExp("^" + FILE), '');
118687 }
118688
118689 function _addPrefix(path) {
118690     return FILE + path;
118691 }
118692
118693 module.exports = {
118694     createNewDir: function (path) {
118695         transport.call(_uri + "createNewDir", {
118696             post: {path: _prunePrefix(path)}
118697         });
118698     },
118699     deleteDirectory: function (path, recursive) {
118700         transport.call(_uri + "deleteDirectory", {
118701             post: {path: _prunePrefix(path), recursive: recursive}
118702         });
118703     },
118704     exists: function (path) {
118705         return transport.call(_uri + "exists", {
118706             post: {path: _prunePrefix(path)}
118707         });
118708     },
118709     getParentDirectory: function (path) {
118710         return _addPrefix(transport.call(_uri + "getParentDirectory", {
118711             post: {path: _prunePrefix(path)}
118712         }));
118713     },
118714     listDirectories: function (path) {
118715         return transport.call(_uri + "listDirectories", {
118716             post: {path: _prunePrefix(path)}
118717         });
118718     },
118719     listFiles: function (path) {
118720         return transport.call(_uri + "listFiles", {
118721             post: {path: _prunePrefix(path)}
118722         });
118723     },
118724     rename: function (path, newName) {
118725         transport.call(_uri + "rename", {
118726             post: {path: _prunePrefix(path), newName: newName}
118727         });
118728     }
118729 };
118730
118731 });
118732 define('ripple/platform/webworks.core/2.0.0/client/io/file', function (require, exports, module) {
118733 /*
118734  * Copyright 2011 Research In Motion Limited.
118735  *
118736  * Licensed under the Apache License, Version 2.0 (the "License");
118737  * you may not use this file except in compliance with the License.
118738  * You may obtain a copy of the License at
118739  *
118740  *     http://www.apache.org/licenses/LICENSE-2.0
118741  *
118742  * Unless required by applicable law or agreed to in writing, software
118743  * distributed under the License is distributed on an "AS IS" BASIS,
118744  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
118745  * See the License for the specific language governing permissions and
118746  * limitations under the License.
118747  */
118748 var transport = require('ripple/platform/webworks.core/2.0.0/client/transport'),
118749     _uri = "blackberry/io/file/",
118750     FILE = "file://",
118751     _onFileOpened;
118752
118753 function _prunePrefix(path) {
118754     return path.replace(new RegExp("^" + FILE), '');
118755 }
118756
118757 module.exports = {
118758     copy: function (from, to) {
118759         transport.call(_uri + "copy", {
118760             post: {from: _prunePrefix(from), to: _prunePrefix(to)}
118761         });
118762     },
118763     deleteFile: function (path) {
118764         transport.call(_uri + "deleteFile", {
118765             post: {path: _prunePrefix(path)}
118766         });
118767     },
118768     exists: function (path) {
118769         return transport.call(_uri + "exists", {
118770             post: {path: _prunePrefix(path)}
118771         });
118772     },
118773     getFileProperties: function (path) {
118774         var properties = transport.call(_uri + "getFileProperties", {
118775             post: {path: _prunePrefix(path)}
118776         });
118777         properties.directory = FILE + properties.directory;
118778         return properties;
118779     },
118780     open: function (path, newName) {
118781         transport.call(_uri + "open", {
118782             post: {path: _prunePrefix(path)}
118783         });
118784     },
118785     readFile: function (path, onFileOpened, async) {
118786         async = async === false ? false : true;
118787
118788         var uri = _uri + "readFile",
118789             args = {
118790                 post: {path: _prunePrefix(path), async: async}
118791             },
118792             callResult;
118793
118794         _onFileOpened = onFileOpened;
118795
118796         if (async) {
118797             transport.poll(uri, args, function (data, res) {
118798                 if (_onFileOpened) {
118799                     _onFileOpened(FILE + data.fullPath, data.blobData);
118800                 }
118801                 return false;
118802             });
118803         } else {
118804             callResult = transport.call(uri, args);
118805             _onFileOpened(FILE + callResult.fullPath, callResult.blobData);
118806         }
118807     },
118808     rename: function (path, newName) {
118809         transport.call(_uri + "rename", {
118810             post: {path: _prunePrefix(path), newName: newName}
118811         });
118812     },
118813     saveFile: function (path, blob) {
118814         transport.call(_uri + "saveFile", {
118815             post: {path: _prunePrefix(path), blob: blob}
118816         });
118817     }
118818 };
118819
118820 });
118821 define('ripple/platform/webworks.core/2.0.0/client/system', function (require, exports, module) {
118822 /*\r
118823  *  Copyright 2011 Research In Motion Limited.\r
118824  *\r
118825  * Licensed under the Apache License, Version 2.0 (the "License");\r
118826  * you may not use this file except in compliance with the License.\r
118827  * You may obtain a copy of the License at\r
118828  *\r
118829  * http://www.apache.org/licenses/LICENSE-2.0\r
118830  *\r
118831  * Unless required by applicable law or agreed to in writing, software\r
118832  * distributed under the License is distributed on an "AS IS" BASIS,\r
118833  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
118834  * See the License for the specific language governing permissions and\r
118835  * limitations under the License.\r
118836  */\r
118837 var transport = require('ripple/platform/webworks.core/2.0.0/client/transport'),\r
118838     _uri = "blackberry/system/",\r
118839     _self;\r
118840 \r
118841 _self = {\r
118842     hasCapability: function (capability) {\r
118843         return transport.call(_uri + "hasCapability", {\r
118844             get: {capability: capability}\r
118845         });\r
118846     },\r
118847 \r
118848     hasDataCoverage: function () {\r
118849         return transport.call(_uri + "hasDataCoverage");\r
118850     },\r
118851 \r
118852     hasPermission: function (desiredModule) {\r
118853         return transport.call(_uri + "hasPermission", {\r
118854             get: {desiredModule: desiredModule}\r
118855         });\r
118856     },\r
118857 \r
118858     isMassStorageActive: function () {\r
118859         return transport.call(_uri + "isMassStorageActive");\r
118860     }\r
118861 };\r
118862 \r
118863 _self.__defineGetter__("model", function () {\r
118864     return transport.call(_uri + "model");\r
118865 });\r
118866 _self.__defineGetter__("scriptApiVersion", function () {\r
118867     return transport.call(_uri + "scriptApiVersion");\r
118868 });\r
118869 _self.__defineGetter__("softwareVersion", function () {\r
118870     return transport.call(_uri + "softwareVersion");\r
118871 });\r
118872 \r
118873 _self.__defineGetter__("ALLOW", function () {\r
118874     return 0;\r
118875 });\r
118876 _self.__defineGetter__("DENY", function () {\r
118877     return 1;\r
118878 });\r
118879 _self.__defineGetter__("PROMPT", function () {\r
118880     return 2;\r
118881 });\r
118882 _self.__defineGetter__("NOT_SET", function () {\r
118883     return 3;\r
118884 });\r
118885 \r
118886 module.exports = _self;\r
118887
118888 });
118889 define('ripple/platform/webworks.core/2.0.0/client/transport', function (require, exports, module) {
118890 /*
118891  * Copyright 2011 Research In Motion Limited.
118892  *
118893  * Licensed under the Apache License, Version 2.0 (the "License");
118894  * you may not use this file except in compliance with the License.
118895  * You may obtain a copy of the License at
118896  *
118897  *     http://www.apache.org/licenses/LICENSE-2.0
118898  *
118899  * Unless required by applicable law or agreed to in writing, software
118900  * distributed under the License is distributed on an "AS IS" BASIS,
118901  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
118902  * See the License for the specific language governing permissions and
118903  * limitations under the License.
118904  */
118905 var _self;
118906
118907 function RemoteFunctionCall(functionUri) {
118908     var params = {},
118909         postString = "",
118910         postParams = {};
118911
118912     function composeUri() {
118913         var uri = "webworks://" + functionUri,
118914             paramCount = 1,
118915             param;
118916
118917         for (param in params) {
118918             if (params.hasOwnProperty(param)) {
118919                 if (paramCount === 1) {
118920                     uri += "?";
118921                 } else {
118922                     uri += "&";
118923                 }
118924                 uri += param + "=" + params[param];
118925                 paramCount++;
118926             }
118927
118928             uri = uri.replace(/\&$/, "");
118929         }
118930
118931         return uri;
118932     }
118933
118934     function createXhrRequest(uri, isAsync) {
118935         var request = new XMLHttpRequest(),
118936             paramCount = 1,
118937             param;
118938
118939         for (param in postParams) {
118940             if (postParams.hasOwnProperty(param)) {
118941                 postString += param + "=" + postParams[param] + "&";
118942                 paramCount++;
118943             }
118944         }
118945
118946         postString = postString.replace(/\&$/, "");
118947
118948         // TODO: make get/post
118949         request.open("POST", uri, isAsync);
118950         request.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
118951
118952         return request;
118953     }
118954
118955     this.addParam = function (name, value) {
118956         params[name] = encodeURIComponent(JSON.stringify(value));
118957     };
118958
118959     this.addPostParam = function (name, value) {
118960         postParams[name] = encodeURIComponent(JSON.stringify(value));
118961     };
118962
118963     this.makeSyncCall = function (success, error) {
118964         var requestUri = composeUri(),
118965             request = createXhrRequest(requestUri, false),
118966             response, errored, cb, data;
118967
118968         request.send(postString);
118969
118970         response = JSON.parse(request.responseText || "null");
118971         errored = response.code < 0;
118972         cb = errored ? error : success;
118973         data = errored ? response.msg : response.data;
118974
118975         if (cb) {
118976             cb(data, response);
118977         }
118978         else if (errored) {
118979             throw data;
118980         }
118981
118982         return data;
118983     };
118984
118985     this.makeAsyncCall = function (success, error) {
118986         var requestUri = composeUri(),
118987             request = createXhrRequest(requestUri, true);
118988
118989         request.onreadystatechange = function () {
118990             if (request.readyState === 4 && request.status === 200) {
118991                 var response = JSON.parse(request.responseText || "null"),
118992                     cb = response.code < 0 ? error : success,
118993                     data = response.code < 0 ? response.msg : response.data;
118994
118995                 return cb && cb(data, response);
118996             }
118997         };
118998
118999         request.send(postString);
119000     };
119001 }
119002
119003 _self = {
119004     call: function (url, opts, success, error) {
119005         var request = new RemoteFunctionCall(url),
119006             name;
119007
119008         opts = opts || {};
119009
119010         if (opts.get) {
119011             for (name in opts.get) {
119012                 if (Object.hasOwnProperty.call(opts.get, name)) {
119013                     request.addParam(name, opts.get[name]);
119014                 }
119015             }
119016         }
119017
119018         if (opts.post) {
119019             for (name in opts.post) {
119020                 if (Object.hasOwnProperty.call(opts.post, name)) {
119021                     request.addPostParam(name, opts.post[name]);
119022                 }
119023             }
119024         }
119025
119026         return opts.async ? request.makeAsyncCall(success, error) : request.makeSyncCall(success, error);
119027     },
119028
119029     poll: function (url, opts, callback) {
119030         opts = opts || {};
119031         opts.async = true;
119032
119033         _self.call(url, opts, function (data, response) {
119034             if (callback(data, response)) {
119035                 _self.poll(url, opts, callback);
119036             }
119037         });
119038     }
119039 };
119040
119041 module.exports = _self;
119042
119043 });
119044 define('ripple/platform/webworks.core/2.0.0/client/utils', function (require, exports, module) {
119045 /*
119046  * Copyright 2011 Research In Motion Limited.
119047  *
119048  * Licensed under the Apache License, Version 2.0 (the "License");
119049  * you may not use this file except in compliance with the License.
119050  * You may obtain a copy of the License at
119051  *
119052  *     http://www.apache.org/licenses/LICENSE-2.0
119053  *
119054  * Unless required by applicable law or agreed to in writing, software
119055  * distributed under the License is distributed on an "AS IS" BASIS,
119056  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
119057  * See the License for the specific language governing permissions and
119058  * limitations under the License.
119059  */
119060 var _blobs = {};
119061
119062 function _blobBuilder() {
119063     var BlobBuilder = BlobBuilder || WebKitBlobBuilder;
119064     return new BlobBuilder();
119065 }
119066
119067 module.exports = {
119068     parseURL: function (theUrl) {
119069         /********START IDEA BORROWING*******/
119070         // parseUri 1.2.2
119071         // (c) Steven Levithan <stevenlevithan.com>
119072         // MIT License
119073
119074         function parseUri(str) {
119075             var o   = parseUri.options,
119076                 m   = o.parser[o.strictMode ? "strict" : "loose"].exec(str),
119077                 uri = {},
119078                 i   = 14;
119079
119080             while (i--) {
119081                 uri[o.key[i]] = m[i] || "";
119082             }
119083
119084             uri[o.q.name] = {};
119085             uri[o.q.arrayName] = [];
119086             uri[o.key[12]].replace(o.q.parser, function ($0, $1, $2) {
119087                 if ($1) {
119088                     uri[o.q.name][$1] = $2;
119089                     uri[o.q.arrayName].push($2);
119090                 }
119091             });
119092
119093             return uri;
119094         }
119095
119096         parseUri.options = {
119097                 strictMode: false,
119098                 key: ["source", "protocol", "authority", "userInfo", "user", "password", "host", "port", "relative", "path", "directory", "file", "query", "anchor"],
119099                 q:   {
119100                     name:   "queryKey",
119101                     arrayName:   "queryArray",
119102                     parser: /(?:^|&)([^&=]*)=?([^&]*)/g
119103                 },
119104                 parser: {
119105                     strict: /^(?:([^:\/?#]+):)?(?:\/\/((?:(([^:@]*)(?::([^:@]*))?)?@)?([^:\/?#]*)(?::(\d*))?))?((((?:[^?#\/]*\/)*)([^?#]*))(?:\?([^#]*))?(?:#(.*))?)/,
119106                     loose:  /^(?:(?![^:@]+:[^:@\/]*@)([^:\/?#.]+):)?(?:\/\/)?((?:(([^:@]*)(?::([^:@]*))?)?@)?([^:\/?#]*)(?::(\d*))?)(((\/(?:[^?#](?![^?#\/]*\.[^?#\/.]+(?:[?#]|$)))*\/?)?([^?#\/]*))(?:\?([^#]*))?(?:#(.*))?)/
119107                 }
119108             };
119109         /********END IDEA BORROWING*******/
119110
119111         parseUri.strictMode = "strict";
119112         var uri = parseUri(theUrl),
119113             retVal = {
119114                 getURLParameter : function (key) {
119115                     return uri.queryKey[key];
119116                 },
119117
119118                 getURLParameterByIndex : function (index) {
119119                     return uri.queryArray[index];
119120                 }
119121             };
119122
119123         //Add default values for the http/https port if they weren't specified in the URL. The above parser returns undefined. We need the values
119124         //to be compatible with the BB version of API.
119125         if (uri["port"] === "") {
119126             if (uri["protocol"] === "http") {
119127                 uri["port"] = "80";
119128             }
119129             else if (uri["protocol"] === "https") {
119130                 uri["port"] = "443";
119131             }
119132             else {
119133                 uri["port"] = "0";
119134             }
119135         }
119136
119137         retVal.__defineGetter__("host", function () {
119138             return uri["host"];
119139         });
119140         retVal.__defineGetter__("port", function () {
119141             return parseInt(uri["port"], 10);
119142         });
119143
119144         return retVal;
119145     },
119146
119147     generateUniqueId: function () {
119148         return Math.floor(Math.random() * Number.MAX_VALUE);
119149     },
119150
119151     blobToString: function (blob, encoding) {
119152         return _blobs[blob.id];
119153     },
119154
119155     stringToBlob: function (string, encoding) {
119156         var id = Math.uuid(undefined, 16),
119157             blob = _blobBuilder(),
119158             finalBlob;
119159
119160         _blobs[id] = string;
119161         blob.append(string);
119162
119163         finalBlob = blob.getBlob();
119164         finalBlob.id = id;
119165         finalBlob.length = finalBlob.size;
119166
119167         return finalBlob;
119168     }
119169 };
119170
119171 });
119172 define('ripple/platform/webworks.core/2.0.0/fsCache', function (require, exports, module) {
119173 /*
119174  * Copyright 2011 Research In Motion Limited.
119175  *
119176  * Licensed under the Apache License, Version 2.0 (the "License");
119177  * you may not use this file except in compliance with the License.
119178  * You may obtain a copy of the License at
119179  *
119180  *     http://www.apache.org/licenses/LICENSE-2.0
119181  *
119182  * Unless required by applicable law or agreed to in writing, software
119183  * distributed under the License is distributed on an "AS IS" BASIS,
119184  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
119185  * See the License for the specific language governing permissions and
119186  * limitations under the License.
119187  */
119188 var fs = require('ripple/dbfs'),
119189     utils = require('ripple/utils'),
119190     _console = require('ripple/console'),
119191     constants = require('ripple/constants'),
119192     event = require('ripple/event'),
119193     bbUtils = require('ripple/platform/webworks.core/2.0.0/client/utils'),
119194     FileProperties = require('ripple/platform/webworks.core/2.0.0/client/FileProperties'),
119195     _cache = {},
119196     _self;
119197
119198 function _createPath(path) {
119199     var parts = path.replace(/^\//, '').replace(/\/$/, '').split("/"),
119200         workflow = jWorkflow.order();
119201
119202     parts.forEach(function (part, index) {
119203         var dir = "/" + utils.copy(parts).splice(0, index + 1).join("/");
119204
119205         workflow.andThen(function (prev, baton) {
119206             baton.take();
119207             fs.mkdir(dir, baton.pass, baton.pass);
119208         });
119209     });
119210
119211     workflow.start(_self.refresh);
119212 }
119213 event.on("FileSystemInitialized", function () {
119214     _createPath("/SDCard");
119215     _createPath("/store/home/user/music");
119216     _createPath("/store/home/user/pictures");
119217     _createPath("/store/home/user/videos");
119218     _createPath("/store/home/user/videos");
119219     _createPath("/accounts/1000/appdata/emulatedapp/data");
119220     _createPath("/accounts/1000/appdata/emulatedapp/shared/bookmarks");
119221     _createPath("/accounts/1000/appdata/emulatedapp/shared/books");
119222     _createPath("/accounts/1000/appdata/emulatedapp/shared/camera");
119223     _createPath("/accounts/1000/appdata/emulatedapp/shared/documents");
119224     _createPath("/accounts/1000/appdata/emulatedapp/shared/downloads");
119225     _createPath("/accounts/1000/appdata/emulatedapp/shared/misc");
119226     _createPath("/accounts/1000/appdata/emulatedapp/shared/music");
119227     _createPath("/accounts/1000/appdata/emulatedapp/shared/photos");
119228     _createPath("/accounts/1000/appdata/emulatedapp/shared/print");
119229     _createPath("/accounts/1000/appdata/emulatedapp/shared/videos");
119230     _createPath("/accounts/1000/appdata/emulatedapp/shared/voice");
119231 });
119232
119233 function _fsError(e) {
119234     _self.refresh();
119235     if (e.code !== 1) { // suppress file not found error
119236         _console.error("FileSystem error (code " + e.code + ")");
119237     }
119238 }
119239
119240 function _walk(path, parent) {
119241     fs.ls(path, function (entries) {
119242         parent.children = parent.children || {};
119243
119244         entries.forEach(function (entry) {
119245             parent.children[entry.name] = entry;
119246             parent.children[entry.name].properties = {};
119247
119248             if (entry.isDirectory) {
119249                 _walk(entry.fullPath, entry);
119250             } else {
119251                 entry.file(function (file) {
119252                     utils.mixin(file, parent.children[entry.name].properties);
119253                 });
119254                 fs.read(entry.fullPath, function (data) {
119255                     parent.children[entry.name].data = data;
119256                 }, function (e) {
119257                     console.error(e);
119258                 });
119259             }
119260         });
119261     }, function (e) {
119262         console.error(e);
119263     });
119264 }
119265
119266 function _get(path) {
119267     return path.replace(/^\//, '').split("/").reduce(function (obj, token) {
119268         return token === "" ? obj : (obj && obj.children ? obj.children[token] || null : null);
119269     }, _cache);
119270 }
119271
119272 function _getInfo(path) {
119273     var parent = ("/" + path.replace(/^\//, '').replace(/\/$/, '')).split("/"),
119274         name = parent.splice(parent.length - 1, 1).join(""),
119275         ext = name.split(".");
119276
119277     return {
119278         name: name,
119279         extension: ext.length > 1 ? ext[ext.length - 1] : "",
119280         hidden: (name.length > 0 && name[0] === ".") || false,
119281         parent: parent.join("/") || "/"
119282     };
119283 }
119284
119285 function _set(path, obj) {
119286     var parent = _cache,
119287         tokens = path.replace(/^\//, '').replace(/\/$/, '').split("/"),
119288         child = tokens.splice(tokens.length - 1, 1).join("");
119289
119290     tokens.forEach(function (token) {
119291         parent = parent.children[token];
119292     });
119293
119294     parent.children = parent.children || {};
119295     obj.properties = obj.properties || {};
119296     parent.children[child] = obj;
119297 }
119298
119299 function _delete(path) {
119300     var parent = _cache,
119301         tokens = path.replace(/^\//, '').replace(/\/$/, '').split("/"),
119302         child = tokens.splice(tokens.length - 1, 1).join("");
119303
119304     tokens.forEach(function (token) {
119305         parent = parent.children[token];
119306     });
119307
119308     delete parent.children[child];
119309 }
119310
119311 // TODO: handle exceptions so that any respective fs command can error out
119312 // TODO: dateCreated is always dateModified
119313
119314 _self = {
119315     refresh: function () {
119316         _cache = {};
119317         _walk("/", _cache);
119318     },
119319     file: {
119320         exists: function (path) {
119321             var entry = _get(path);
119322             return !!(entry && !entry.isDirectory);
119323         },
119324
119325         deleteFile: function (path) {
119326             _delete(path);
119327             fs.rm(path, function () {}, _fsError);
119328         },
119329
119330         copy: function (from, to) {
119331             var fromEntry = _get(from);
119332
119333             _set(to, {
119334                 fullPath: to,
119335                 properties: fromEntry.properties,
119336                 data: fromEntry.data
119337             });
119338
119339             fs.cp(from, to, function (entry) {
119340                 entry.file(function (file) {
119341                     entry.properties = entry.properties || {};
119342                     utils.mixin(file, entry.properties);
119343                     _set(to, entry);
119344                 });
119345             }, _fsError);
119346         },
119347
119348         getFileProperties: function (path) {
119349             var entry = _get(path),
119350                 info = _getInfo(path);
119351
119352             fs.stat(path, function () {}, _fsError);
119353
119354             return new FileProperties({
119355                 //HACK: not sure where these should come from so check both for now.
119356                 dateCreated: entry.properties.lastModifiedDate || entry.lastModifiedDate,
119357                 dateModified: entry.properties.lastModifiedDate || entry.lastModifiedDate,
119358                 directory: info.parent,
119359                 fileExtension: info.extension,
119360                 isHidden: info.hidden,
119361                 isReadonly: false,
119362                 mimeType: entry.properties.type,
119363                 size: entry.properties.size
119364             });
119365         },
119366
119367         rename: function (path, newName) {
119368             _self.dir.rename(path, newName);
119369         },
119370
119371         readFile: function (path, success, async) {
119372             var entry = _get(path);
119373
119374             async = async === false ? async : true;
119375
119376             if (!async) {
119377                 success(bbUtils.stringToBlob(entry.data));
119378             }
119379             else {
119380                 fs.read(path, function (data) {
119381                     var blob = bbUtils.stringToBlob(data);
119382                     if (async) {
119383                         success(blob);
119384                     }
119385                     entry.data = data;
119386                     _set(path, entry);
119387                 }, _fsError);
119388             }
119389         },
119390
119391         saveFile: function (path, blob) {
119392             var data = bbUtils.blobToString(blob);
119393
119394             _set(path, {
119395                 lastModifiedDate: new Date(),
119396                 fullPath: path,
119397                 isDirectory: false,
119398                 properties: {
119399                     type: "",
119400                     size: blob.size
119401                 },
119402                 data: data
119403             });
119404
119405             fs.write(path, data, function (entry) {
119406                 entry.data = data;
119407                 entry.file(function (file) {
119408                     entry.properties = entry.properties || {};
119409                     utils.mixin(file, entry.properties);
119410                     _set(path, entry);
119411                 });
119412             }, _fsError);
119413         }
119414     },
119415     dir: {
119416         createNewDir: function (path) {
119417             var entry = _get(path),
119418                 info = _getInfo(path);
119419
119420             if (!entry) {
119421                 _set(path, {
119422                     name: info.name,
119423                     isDirectory: true,
119424                     fullPath: path
119425                 });
119426             }
119427
119428             fs.mkdir(path, function (entry) {
119429                 _set(path, entry);
119430             }, _fsError);
119431         },
119432
119433         deleteDirectory: function (path, recursive) {
119434             _delete(path);
119435             if (recursive) {
119436                 fs.rm(path, function () {}, _fsError, {recursive: recursive});
119437             } else {
119438                 fs.rmdir(path, function () {}, _fsError);
119439             }
119440         },
119441
119442         exists: function (path) {
119443             var entry = _get(path);
119444             return !!(entry && entry.isDirectory);
119445         },
119446
119447         getFreeSpaceForRoot: function (path) {
119448             function _du(obj, size) {
119449                 utils.forEach(obj, function (child, key) {
119450                     if (child.isDirectory && child.children) {
119451                         size += _du(child.children, size);
119452                     } else if (child.properties && child.properties.size) {
119453                         size += child.properties.size;
119454                     }
119455                 });
119456                 return size;
119457             }
119458
119459             return constants.FS_SIZE - _du(_cache.children, 0);
119460         },
119461
119462         getParentDirectory: function (path) {
119463             path = "/" + path.replace(/^\//, '').replace(/\/$/, '');
119464
119465             var entry = _get(path),
119466                 array = path.split("/");
119467
119468             return entry ? array.splice(0, array.length - 1).join("/") || "/" : null;
119469         },
119470
119471         listDirectories: function (path) {
119472             var dir = _get(path),
119473                 directories = [];
119474
119475             utils.forEach(dir.children, function (item) {
119476                 if (item.isDirectory) {
119477                     directories.push(item.name);
119478                 }
119479             });
119480
119481             fs.ls(path, function () {}, _fsError);
119482
119483             return directories;
119484         },
119485
119486         listFiles: function (path) {
119487             var dir = _get(path),
119488                 files = [];
119489
119490             if (dir) {
119491                 utils.forEach(dir.children, function (item) {
119492                     if (!item.isDirectory) {
119493                         files.push(item.name);
119494                     }
119495                 });
119496             }
119497
119498             fs.ls(path, function () {}, _fsError);
119499
119500             return files;
119501         },
119502
119503         rename: function (path, newName) {
119504             var info = _getInfo(path),
119505                 parent = info.parent,
119506                 oldName = info.name,
119507                 from = (parent === "/" ? "" : parent) + "/" + oldName,
119508                 to =  (parent === "/" ? "" : parent) + "/" + newName;
119509
119510             _delete(from);
119511             _set(to, {
119512                 name: info.name,
119513                 fullPath: path
119514             });
119515
119516             fs.mv(from, to, function (entry) {
119517                 _set(to, entry);
119518             }, _fsError);
119519         },
119520
119521         getRootDirs: function () {
119522             return _self.dir.listDirectories("/");
119523         }
119524     }
119525 };
119526
119527 module.exports = _self;
119528
119529 });
119530 define('ripple/platform/webworks.core/2.0.0/select', function (require, exports, module) {
119531 /*
119532  *  Copyright 2011 Research In Motion Limited.
119533  *
119534  * Licensed under the Apache License, Version 2.0 (the "License");
119535  * you may not use this file except in compliance with the License.
119536  * You may obtain a copy of the License at
119537  *
119538  * http://www.apache.org/licenses/LICENSE-2.0
119539  *
119540  * Unless required by applicable law or agreed to in writing, software
119541  * distributed under the License is distributed on an "AS IS" BASIS,
119542  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
119543  * See the License for the specific language governing permissions and
119544  * limitations under the License.
119545  */
119546 var utils = require('ripple/utils'),
119547     _select,
119548     _predicates = {
119549         "==": function (left, right) {
119550             return left === right;
119551         },
119552         "!=": function (left, right) {
119553             return left !== right;
119554         },
119555         "<": function (left, right) {
119556             return left < right;
119557         },
119558         ">": function (left, right) {
119559             return left > right;
119560         },
119561         "<=": function (left, right) {
119562             return left <= right;
119563         },
119564         ">=": function (left, right) {
119565             return left >= right;
119566         },
119567         "REGEX": function (left, right) {
119568             return left && left.match(new RegExp(right));
119569         },
119570         "CONTAINS": function (left, right) {
119571             return left.indexOf(right) >= 0;
119572         }
119573     };
119574
119575 function isFilter(field) {
119576     return field && field.operator !== undefined && field.operator !== null;
119577 }
119578
119579 function extractValue(item, field) {
119580     return field.split(".").reduce(function (value, prop) {
119581         return value[prop];
119582     }, item);
119583 }
119584
119585 function copy(items) {
119586     //use a reduce to ensure that we always just return an array
119587     //not the most performant but will whitewash the result
119588     return utils.reduce(items, function (array, item) {
119589         array.push(item);
119590         return array;
119591     }, []);
119592 }
119593
119594 _select = {
119595     ops: {
119596         find: {
119597             0: "!=",
119598             1: "==",
119599             2: "<",
119600             3: "<=",
119601             4: ">",
119602             5: ">=",
119603             8: "REGEX",
119604             16: "AND",
119605             32: "OR",
119606             64: "CONTAINS"
119607         },
119608         phone: {
119609             0: "!=",
119610             1: "==",
119611             2: "<",
119612             3: "<=",
119613             4: ">",
119614             5: ">=",
119615             8: "AND",
119616             16: "OR",
119617             32: "CONTAINS"
119618         }
119619     },
119620     from: function (items) {
119621         var _getPredicate = function (filter, operators) {
119622
119623                 var noOp = function () {
119624                         return false;
119625                     },
119626                     operator = (function () {
119627                         var result = operators[filter.operator] || filter.operator,
119628                             exists = function (op) {
119629                                 return result === op;
119630                             };
119631
119632                         return utils.some(operators, exists) ? result : "";
119633                     }());
119634
119635                 return function (item) {
119636                     var left = extractValue(item, filter.leftField),
119637                         right = filter.rightField,
119638                         predicate = _predicates[operator] || noOp;
119639
119640                     return filter.negate ? !predicate(left, right) : predicate(left, right);
119641                 };
119642
119643             },
119644             _applyFilter = function (filter, operators) {
119645                 var result = [],
119646                     left,
119647                     right,
119648                     op;
119649
119650                 if (isFilter(filter.leftField) && isFilter(filter.rightField)) {
119651
119652                     left = _select.from(items).where(filter.leftField);
119653                     right = _select.from(items).where(filter.rightField);
119654                     op = operators[filter.operator] || filter.operator;
119655
119656                     switch (op) {
119657                     case "AND":
119658                         result = left.filter(function (item) {
119659                             return right.indexOf(item) >= 0;
119660                         });
119661                         break;
119662                     case "OR":
119663                         result = left.concat(right.filter(function (item) {
119664                             return left.indexOf(item) < 0;
119665                         }));
119666                         break;
119667                     }
119668
119669                     if (filter.negate) {
119670                         //reverse the result set.
119671                         result = utils.filter(items, function (item) {
119672                             return result.indexOf(item) < 0;
119673                         });
119674                     }
119675                 }
119676                 else {
119677                     result = utils.filter(items, _getPredicate(filter, operators));
119678                 }
119679
119680                 return result;
119681             },
119682             _orderBy,
119683             _max,
119684             _direction,
119685             _self = {
119686                 orderBy: function (prop, dir) {
119687                     _orderBy = prop;
119688                     _direction = dir || "asc";
119689                     return _self;
119690                 },
119691                 max: function (max) {
119692                     _max = max;
119693                     return _self;
119694                 },
119695                 where: function (filter, ops) {
119696                     var result = isFilter(filter) ? _applyFilter(filter, ops || _select.ops.find) : copy(items);
119697
119698                     result.sort(function (a, b) {
119699                         if (a[_orderBy] < b[_orderBy]) {
119700                             return _direction === "asc" ? -1 : 1;
119701                         }
119702                         else if (a[_orderBy] > b[_orderBy]) {
119703                             return _direction === "asc" ? 1: -1;
119704                         }
119705                         return 0;
119706                     });
119707
119708                     return result.slice(0, _max === null || _max === -1 ? undefined : _max); // slice in V8 returns empty array if null
119709                 }
119710             };
119711
119712         return _self;
119713     }
119714 };
119715
119716 module.exports = _select;
119717
119718 });
119719 define('ripple/platform/webworks.core/2.0.0/server/dialog', function (require, exports, module) {
119720 /*
119721  *  Copyright 2011 Research In Motion Limited.
119722  *
119723  * Licensed under the Apache License, Version 2.0 (the "License");
119724  * you may not use this file except in compliance with the License.
119725  * You may obtain a copy of the License at
119726  *
119727  * http://www.apache.org/licenses/LICENSE-2.0
119728  *
119729  * Unless required by applicable law or agreed to in writing, software
119730  * distributed under the License is distributed on an "AS IS" BASIS,
119731  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
119732  * See the License for the specific language governing permissions and
119733  * limitations under the License.
119734  */
119735 var event = require('ripple/event'),
119736     devices = require('ripple/devices'),
119737     ui = require('ripple/ui'),
119738     utils = require('ripple/utils'),
119739     isDialogVisible = false,
119740     visibleDialogArgs,
119741     _self;
119742
119743 function closeDialog() {
119744     var buttonsDiv = document.getElementById("dialog-buttons"),
119745         messageDiv = document.getElementById("dialog-message");
119746
119747     ui.hideOverlay("dialog-window", function (dialog) {
119748         buttonsDiv.innerHTML = "";
119749         messageDiv.innerHTML = "";
119750         isDialogVisible = false;
119751     });
119752 }
119753
119754 event.on("LayoutChanged", function () {
119755     if (isDialogVisible) {
119756         closeDialog();
119757         //Used to resize dialog on orientation change
119758         _self.ask(visibleDialogArgs);
119759     }
119760 });
119761
119762 _self = {
119763
119764     ask: function (args, post, baton) {
119765         if (!args) {
119766             throw ("No arguments provided");
119767         } else if (!args.buttons || !args.message) {
119768             throw ("Invalid arguments");
119769         }
119770         baton.take();
119771         visibleDialogArgs = args;
119772
119773         ui.showOverlay("dialog-window", function (dialog) {
119774             var container = document.getElementById("viewport-container"),
119775                 height = window.getComputedStyle(container, null).getPropertyValue("height"),
119776                 width = window.getComputedStyle(container, null).getPropertyValue("width"),
119777                 sizeDiv = document.getElementById("dialog-wrapper"),
119778                 positionDiv = document.getElementById("dialog-window"),
119779                 titleDiv = document.getElementById("dialog-title"),
119780                 buttonsDiv = document.getElementById("dialog-buttons"),
119781                 messageDiv = document.getElementById("dialog-message"),
119782                 position, size;
119783
119784             if (!messageDiv || !buttonsDiv) {
119785                 return;
119786             }
119787
119788             dialog.setAttribute("style", "display:-webkit-box;height:" + height + "; width:" + width + ";");
119789
119790             position = "overlay-dialog";
119791             size = "overlay-dialog-wrapper";
119792
119793             if (args.settings && args.settings.position) {
119794                 position += " overlay-dialog-" + args.settings.position;
119795             }
119796
119797             if (args.settings && args.settings.size) {
119798                 size += " overlay-dialog-wrapper-" + args.settings.size;
119799             }
119800
119801             positionDiv.setAttribute("class", position);
119802             sizeDiv.setAttribute("class", size);
119803
119804             titleDiv.innerHTML = args.settings && args.settings.title ? args.settings.title : "";
119805             messageDiv.innerHTML = args.message;
119806             isDialogVisible = true;
119807
119808             args.buttons.forEach(function (button) {
119809                 var buttonElement = utils.createElement("input", {
119810                     "type": "button",
119811                     "value": button
119812                 });
119813                 buttonElement.addEventListener("click", function () {
119814                     var buttonIndex = args.buttons.indexOf(button);
119815                     closeDialog();
119816                     baton.pass({code: 1, data: buttonIndex});
119817                 });
119818                 buttonsDiv.appendChild(buttonElement);
119819             });
119820         }, true);
119821     }
119822 };
119823
119824 module.exports = _self;
119825
119826 });
119827 define('ripple/platform/webworks.core/2.0.0/server/io/dir', function (require, exports, module) {
119828 /*
119829  * Copyright 2011 Research In Motion Limited.
119830  *
119831  * Licensed under the Apache License, Version 2.0 (the "License");
119832  * you may not use this file except in compliance with the License.
119833  * You may obtain a copy of the License at
119834  *
119835  *     http://www.apache.org/licenses/LICENSE-2.0
119836  *
119837  * Unless required by applicable law or agreed to in writing, software
119838  * distributed under the License is distributed on an "AS IS" BASIS,
119839  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
119840  * See the License for the specific language governing permissions and
119841  * limitations under the License.
119842  */
119843 var cache = require('ripple/platform/webworks.core/2.0.0/fsCache');
119844
119845 function _packet(data) {
119846     return {
119847         code: 1,
119848         data: data
119849     };
119850 }
119851
119852 module.exports = {
119853     createNewDir: function (get, post, baton) {
119854         cache.dir.createNewDir(post.path);
119855         return _packet();
119856     },
119857     deleteDirectory: function (get, post, baton) {
119858         cache.dir.deleteDirectory(post.path, post.recursive);
119859         return _packet();
119860     },
119861     exists: function (get, post, baton) {
119862         return _packet(cache.dir.exists(post.path));
119863     },
119864     getParentDirectory: function (get, post, baton) {
119865         return _packet(cache.dir.getParentDirectory(post.path));
119866     },
119867     listDirectories: function (get, post, baton) {
119868         return _packet(cache.dir.listDirectories(post.path));
119869     },
119870     listFiles: function (get, post, baton) {
119871         return _packet(cache.dir.listFiles(post.path));
119872     },
119873     rename: function (get, post, baton) {
119874         cache.dir.rename(post.path, post.newName);
119875         return _packet();
119876     }
119877 };
119878
119879 });
119880 define('ripple/platform/webworks.core/2.0.0/server/io/file', function (require, exports, module) {
119881 /*
119882  *  Copyright 2011 Research In Motion Limited.
119883  *
119884  * Licensed under the Apache License, Version 2.0 (the "License");
119885  * you may not use this file except in compliance with the License.
119886  * You may obtain a copy of the License at
119887  *
119888  * http://www.apache.org/licenses/LICENSE-2.0
119889  *
119890  * Unless required by applicable law or agreed to in writing, software
119891  * distributed under the License is distributed on an "AS IS" BASIS,
119892  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
119893  * See the License for the specific language governing permissions and
119894  * limitations under the License.
119895  */
119896 var cache = require('ripple/platform/webworks.core/2.0.0/fsCache'),
119897     constants = require('ripple/constants'),
119898     notifications = require('ripple/notifications');
119899
119900 function _packet(data) {
119901     return {
119902         code: 1,
119903         data: data
119904     };
119905 }
119906
119907 module.exports = {
119908     copy: function (get, post, baton) {
119909         cache.file.copy(post.from, post.to);
119910         return _packet();
119911     },
119912     deleteFile: function (get, post, baton) {
119913         cache.file.deleteFile(post.path);
119914         return _packet();
119915     },
119916     exists: function (get, post, baton) {
119917         return _packet(cache.file.exists(post.path));
119918     },
119919     getFileProperties: function (get, post, baton) {
119920         return _packet(cache.file.getFileProperties(post.path));
119921     },
119922     open: function (get, post, baton) {
119923         var msg = "Attempting to open file: " + post.path;
119924         notifications.openNotification("normal", msg);
119925         return _packet(cache.file.exists(post.path));
119926     },
119927     readFile: function (get, post, baton) {
119928         var val;
119929
119930         if (post.async) {
119931             baton.take();
119932         }
119933
119934         cache.file.readFile(post.path, function (data) {
119935             if (post.async) {
119936                 baton.pass(_packet({
119937                     fullPath: post.path,
119938                     blobData: data
119939                 }));
119940             } else {
119941                 val = data;
119942             }
119943         }, post.async);
119944
119945         if (!post.async) {
119946             return _packet({
119947                 fullPath: post.path,
119948                 blobData: val
119949             });
119950         }
119951     },
119952     rename: function (get, post, baton) {
119953         cache.file.rename(post.path, post.newName);
119954         return _packet();
119955     },
119956     saveFile: function (get, post, baton) {
119957         cache.file.saveFile(post.path, post.blob);
119958         return _packet();
119959     }
119960 };
119961
119962 });
119963 define('ripple/platform/webworks.core/2.0.0/server/system', function (require, exports, module) {
119964 /*
119965  *  Copyright 2011 Research In Motion Limited.
119966  *
119967  * Licensed under the Apache License, Version 2.0 (the "License");
119968  * you may not use this file except in compliance with the License.
119969  * You may obtain a copy of the License at
119970  *
119971  * http://www.apache.org/licenses/LICENSE-2.0
119972  *
119973  * Unless required by applicable law or agreed to in writing, software
119974  * distributed under the License is distributed on an "AS IS" BASIS,
119975  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
119976  * See the License for the specific language governing permissions and
119977  * limitations under the License.
119978  */
119979 var deviceSettings = require('ripple/deviceSettings'),
119980     devices = require('ripple/devices'),
119981     app = require('ripple/app'),
119982     client = require('ripple/platform/webworks.core/2.0.0/client/system'),
119983     utils = require('ripple/utils'),
119984     notifications = require('ripple/notifications'),
119985     constants = require('ripple/constants'),
119986     platform = require('ripple/platform'),
119987     _self;
119988
119989 function _is(feature) {
119990     return {
119991         allowedFor: function (location) {
119992             return feature && feature.URIs.some(function (uri) {
119993                 return uri.value === location ||
119994                       (location.indexOf(uri.value) >= 0 && uri.subdomains);
119995             });
119996         }
119997     };
119998 }
119999
120000 _self = {
120001     hasCapability: function (args) {
120002         var capabilities = devices.getCurrentDevice().capabilities;
120003         return {
120004             code: 1,
120005             data: capabilities ? capabilities.some(function (type) {
120006                 return type === args.capability;
120007             }) : false
120008         };
120009     },
120010     isMassStorageActive: function () {
120011         return {code: 1, data: deviceSettings.retrieveAsBoolean("system.isMassStorageActive")};
120012     },
120013     hasDataCoverage: function () {
120014         return {code: 1, data: deviceSettings.retrieveAsBoolean("system.hasDataCoverage")};
120015     },
120016     softwareVersion: function () {
120017         return {code: 1, data: devices.getCurrentDevice().osVersion};
120018     },
120019     model: function () {
120020         return {code: 1, data: devices.getCurrentDevice().model};
120021     },
120022     scriptApiVersion: function () {
120023         return {code: 1, data: platform.current().version};
120024     },
120025     setHomeScreenBackground: function (args) {
120026         var path = args.filePath,
120027             msg = "Set home screen background to " + path + ".";
120028         notifications.openNotification("normal", msg);
120029         return {code: 1};
120030     },
120031     hasPermission: function (args) {
120032         var info = app.getInfo(),
120033             feature = info.features ? info.features[args.desiredModule] : null;
120034
120035         return {code: 1, data: feature === null || _is(feature).allowedFor(utils.location().href) ? client.ALLOW : client.DENY};
120036     },
120037     network: function () {
120038         return {code: 1, data: deviceSettings.retrieve("system.network")};
120039     }
120040 };
120041
120042 module.exports = _self;
120043
120044 });
120045 define('ripple/platform/webworks.core/2.0.0/spec/config', function (require, exports, module) {
120046 /*
120047  *  Copyright 2011 Research In Motion Limited.
120048  *
120049  * Licensed under the Apache License, Version 2.0 (the "License");
120050  * you may not use this file except in compliance with the License.
120051  * You may obtain a copy of the License at
120052  *
120053  * http://www.apache.org/licenses/LICENSE-2.0
120054  *
120055  * Unless required by applicable law or agreed to in writing, software
120056  * distributed under the License is distributed on an "AS IS" BASIS,
120057  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
120058  * See the License for the specific language governing permissions and
120059  * limitations under the License.
120060  */
120061 var utils = require('ripple/utils');
120062
120063 module.exports = {
120064     fileName: "config.xml",
120065     validateVersion: function (config) {
120066         return true;
120067     },
120068     extractInfo: function (config) {
120069         if (!config) {
120070             return null;
120071         }
120072
120073         var widgetInfo = {},
120074             widgetFeatures = config.widget.children.feature.validationResult,
120075             accessUrls = config.widget.children.access.validationResult,
120076             accessFeatures = config.widget.children.access.children.feature.validationResult,
120077             toFeature = function (validationResult) {
120078                 return {
120079                     id: validationResult.attributes.id.value,
120080                     required: !validationResult.attributes.required || validationResult.attributes.required.value,
120081                     URIs: []
120082                 };
120083             };
120084
120085         widgetInfo.id = config.widget.validationResult[0].attributes.id.value;
120086         widgetInfo.name = config.widget.children.name.validationResult[0].value;
120087         widgetInfo.icon = config.widget.children.icon.validationResult[0].attributes.src.value;
120088         widgetInfo.version = config.widget.validationResult[0].attributes.version.value;
120089         widgetInfo.author = config.widget.children.author.validationResult[0].value;
120090         widgetInfo.authorEmail = config.widget.children.author.validationResult[0].attributes.email.value;
120091         widgetInfo.authorURL = config.widget.children.author.validationResult[0].attributes.href.value;
120092         widgetInfo.copyright = config.widget.children.author.validationResult[0].attributes["rim:copyright"].value;
120093         widgetInfo.description = config.widget.children.description.validationResult[0].value;
120094         if (config.widget.children.license.validationResult[0]) {
120095             widgetInfo.license = config.widget.children.license.validationResult[0].value;
120096             widgetInfo.licenseURL = config.widget.children.license.validationResult[0].attributes.href.value;
120097         }
120098
120099         widgetInfo.features = widgetFeatures.reduce(function (features, validationResult) {
120100             if (validationResult.valid) {
120101                 var feature = toFeature(validationResult);
120102                 feature.URIs.push({
120103                     value: utils.location().href,
120104                     subdomains: true
120105                 });
120106                 features = features || {};
120107                 features[feature.id] = feature;
120108             }
120109             return features;
120110         }, {});
120111
120112         widgetInfo.features = accessUrls.map(function (access) {
120113             return {
120114                 uri: access.attributes.uri.value,
120115                 subdomains: access.attributes.subdomains.value,
120116                 features: accessFeatures ? accessFeatures.filter(function (f) {
120117                     return f.node && f.node.parentNode && f.node.parentNode.attributes.uri.value === access.attributes.uri.value;
120118                 }) : null
120119             };
120120         }).reduce(function (result, access) {
120121             return access.features ? access.features.reduce(function (features, validationResult) {
120122                 var feature = features[validationResult.attributes.id.value] || toFeature(validationResult);
120123                 feature.URIs.push({
120124                     value: access.uri,
120125                     subdomains: access.subdomains
120126                 });
120127                 features[feature.id] = feature;
120128                 return features;
120129             }, result) : result;
120130         }, widgetInfo.features);
120131
120132         return widgetInfo;
120133     },
120134     schema: {
120135         rootElement: "widget",
120136         widget: {
120137             nodeName: "widget",
120138             required: true,
120139             occurrence: 1,
120140             attributes: {
120141                 xmlns: {
120142                     attributeName: "xmlns",
120143                     required: true,
120144                     type: "list",
120145                     listValues: ["http://www.w3.org/ns/widgets"]
120146                 },
120147                 "xmlns:rim": {
120148                     attributeName: "xmlns:rim",
120149                     required: true,
120150                     type: "list",
120151                     listValues: ["http://www.blackberry.com/ns/widgets"]
120152                 },
120153                 "xml:lang": {
120154                     attributeName: "xml:lang",
120155                     required: false,
120156                     type: "iso-language"
120157                 },
120158                 id: {
120159                     attributeName: "id",
120160                     required: false,
120161                     type: "string"
120162                 },
120163                 version: {
120164                     attributeName: "version",
120165                     required: false,
120166                     type: "string"
120167                 },
120168                 "rim:header": {
120169                     attributeName: "rim:header",
120170                     required: false,
120171                     type: "string"
120172                 },
120173                 "rim:backButton": {
120174                     attributeName: "rim:backButton",
120175                     required: false,
120176                     type: "string"
120177                 }
120178             },
120179             children: {
120180                 name: {
120181                     nodeName: "name",
120182                     required: true,
120183                     occurrence: 1,
120184                     attributes: {
120185                         "xml:lang": {
120186                             attributeName: "xml:lang",
120187                             required: false,
120188                             type: "iso-language"
120189                         },
120190                         "its:dir": {
120191                             attributeName: "its:dir",
120192                             required: false,
120193                             type: "list",
120194                             listValues: ["rtl", "ltr", "lro", "rlo"]
120195                         }
120196                     }
120197                 },
120198                 description: {
120199                     nodeName: "description",
120200                     required: false,
120201                     occurrence: 1,
120202                     attributes: {
120203                         "xml:lang": {
120204                             attributeName: "xml:lang",
120205                             required: false,
120206                             type: "iso-language"
120207                         },
120208                         "its:dir": {
120209                             attributeName: "its:dir",
120210                             required: false,
120211                             type: "list",
120212                             listValues: ["rtl", "ltr", "lro", "rlo"]
120213                         }
120214                     }
120215                 },
120216                 icon: {
120217                     nodeName: "icon",
120218                     required: false,
120219                     occurrence: 0,
120220                     attributes: {
120221                         src: {
120222                             attributeName: "src",
120223                             type: "string",
120224                             required: true
120225                         },
120226                         "rim:hover": {
120227                             attributeName: "rim:hover",
120228                             type: "boolean",
120229                             required: false
120230                         }
120231                     }
120232                 },
120233                 author: {
120234                     nodeName: "author",
120235                     required: false,
120236                     occurrence: 1,
120237                     attributes: {
120238                         href: {
120239                             attributeName: "href",
120240                             type: "string",
120241                             required: false
120242                         },
120243                         "rim:copyright": {
120244                             attributeName: "rim:copyright",
120245                             type: "string",
120246                             required: false
120247                         },
120248                         email: {
120249                             attributeName: "email",
120250                             type: "string",
120251                             required: false
120252                         },
120253                         "xml:lang": {
120254                             attributeName: "xml:lang",
120255                             required: false,
120256                             type: "iso-language"
120257                         },
120258                         "its:dir": {
120259                             attributeName: "its:dir",
120260                             required: false,
120261                             type: "list",
120262                             listValues: ["rtl", "ltr", "lro", "rlo"]
120263                         }
120264                     }
120265                 },
120266                 license: {
120267                     nodeName: "license",
120268                     required: false,
120269                     occurrence: 1,
120270                     attributes : {
120271                         href: {
120272                             attributeName: "href",
120273                             type: "string",
120274                             required: false
120275                         },
120276                         "xml:lang": {
120277                             attributeName: "xml:lang",
120278                             required: false,
120279                             type: "iso-language"
120280                         },
120281                         "its:dir": {
120282                             attributeName: "its:dir",
120283                             required: false,
120284                             type: "list",
120285                             listValues: ["rtl", "ltr", "lro", "rlo"]
120286                         }
120287                     }
120288                 },
120289                 "rim:cache": {
120290                     nodeName: "rim:cache",
120291                     required: false,
120292                     occurrence: 1,
120293                     attributes: {
120294                         disableAllCache: {
120295                             attributeName: "disableAllCache",
120296                             required: false,
120297                             type: "boolean"
120298                         },
120299                         aggressiveCacheAge: {
120300                             attributeName: "aggressiveCacheAge",
120301                             required: false,
120302                             type: "number"
120303                         },
120304                         maxCacheSizeTotal: {
120305                             attributeName: "maxCacheSizeTotal",
120306                             required: false,
120307                             type: "number"
120308                         },
120309                         maxCacheSizeItem: {
120310                             attributeName: "maxCacheSizeItem",
120311                             required: false,
120312                             type: "number"
120313                         }
120314                     }
120315                 },
120316                 access: {
120317                     nodeName: "access",
120318                     required: false,
120319                     occurrence: 0,
120320                     attributes: {
120321                         uri: {
120322                             attributeName: "uri",
120323                             required: true,
120324                             type: "string"
120325                         },
120326                         subdomains: {
120327                             attributeName: "subdomains",
120328                             required: false,
120329                             type: "boolean"
120330                         }
120331                     },
120332                     children: {
120333                         feature: {
120334                             nodeName: "feature",
120335                             required: false,
120336                             occurrence: 0,
120337                             attributes: {
120338                                 id: {
120339                                     attributeName: "id",
120340                                     required: true,
120341                                     //TODO: this should be a list
120342                                     type: "string"
120343                                 },
120344                                 required: {
120345                                     attributeName: "required",
120346                                     required: false,
120347                                     type: "boolean"
120348                                 },
120349                                 version: {
120350                                     attributeName: "version",
120351                                     required: false,
120352                                     type: "string"
120353                                 }
120354                             }
120355                         }
120356                     }
120357                 },
120358                 feature: {
120359                     nodeName: "feature",
120360                     required: false,
120361                     occurrence: 0,
120362                     attributes: {
120363                         id: {
120364                             attributeName: "id",
120365                             required: true,
120366                             //TODO: this should be a list
120367                             type: "string"
120368                         },
120369                         required: {
120370                             attributeName: "required",
120371                             required: false,
120372                             type: "boolean"
120373                         },
120374                         version: {
120375                             attributeName: "version",
120376                             required: false,
120377                             type: "string"
120378                         }
120379                     }
120380                 },
120381                 "rim:loadingScreen": {
120382                     nodeName: "rim:loadingScreen",
120383                     required: false,
120384                     occurrence: 1,
120385                     attributes: {
120386                         backgroundColor: {
120387                             attributeName: "backgroundColor",
120388                             required: false,
120389                             type: "string"
120390                         },
120391                         backgroundImage: {
120392                             attributeName: "backgroundImage",
120393                             required: false,
120394                             type: "string"
120395                         },
120396                         foregroundImage: {
120397                             attributeName: "foregroundImage",
120398                             required: false,
120399                             type: "string"
120400                         },
120401                         onRemotePageLoad: {
120402                             attributeName: "onRemotePageLoad",
120403                             required: false,
120404                             type: "boolean"
120405                         },
120406                         onLocalPageLoad: {
120407                             attributeName: "onLocalPageLoad",
120408                             required : false,
120409                             type: "boolean"
120410                         },
120411                         onFirstLaunch: {
120412                             attributeName: "onFirstLaunch",
120413                             required: false,
120414                             type: "boolean"
120415                         }
120416                     },
120417                     children: {
120418                         "rim:transitionEffect": {
120419                             nodeName: "rim:transitionEffect",
120420                             required: false,
120421                             occurrence: 1,
120422                             attributes: {
120423                                 "type": {
120424                                     attributeName: "type",
120425                                     required: true,
120426                                     type: "list",
120427                                     listValues: ["slidePush", "slideOver", "fadeIn", "fadeOut", "wipeIn", "wipeOut", "zoomIn", "zoomOut"]
120428                                 },
120429                                 duration: {
120430                                     attributeName: "duration",
120431                                     required: false,
120432                                     type: "number"
120433                                 },
120434                                 direction: {
120435                                     attributeName: "direction",
120436                                     required: false,
120437                                     type: "list",
120438                                     listValues: ["left", "right", "up", "down"]
120439                                 }
120440                             }
120441                         }
120442                     }
120443                 },
120444                 "rim:connection": {
120445                     nodeName: "rim:connection",
120446                     required: false,
120447                     occurrence: 1,
120448                     attributes: {
120449                         timeout: {
120450                             attributeName: "timeout",
120451                             required: false,
120452                             type: "number"
120453                         }
120454                     },
120455                     children: {
120456                         id: {
120457                             nodeName: "id",
120458                             required: false,
120459                             occurrence: 0
120460                         }
120461                     }
120462                 },
120463                 "rim:navigation": {
120464                     nodeName: "rim:navigation",
120465                     required: false,
120466                     occurrence: 1,
120467                     attributes: {
120468                         mode: {
120469                             attributeName: "mode",
120470                             required: false,
120471                             type: "list",
120472                             listValues: ["focus"]
120473                         }
120474                     }
120475                 },
120476                 "content": {
120477                     nodeName: "content",
120478                     required: true,
120479                     occurrence: 1,
120480                     attributes: {
120481                         src: {
120482                             attributeName: "src",
120483                             required: true,
120484                             type: "string"
120485                         },
120486                         type: {
120487                             attributeName: "type",
120488                             required: false,
120489                             type: "string"
120490                         },
120491                         charset: {
120492                             attributeName: "charset",
120493                             required: false,
120494                             type: "string"
120495                         }
120496                     }
120497                 }
120498             }
120499         }
120500     }
120501 };
120502
120503 });
120504 define('ripple/platform/webworks.core/2.0.0/spec/events', function (require, exports, module) {
120505 /*
120506  *  Copyright 2011 Research In Motion Limited.
120507  *
120508  * Licensed under the Apache License, Version 2.0 (the "License");
120509  * you may not use this file except in compliance with the License.
120510  * You may obtain a copy of the License at
120511  *
120512  * http://www.apache.org/licenses/LICENSE-2.0
120513  *
120514  * Unless required by applicable law or agreed to in writing, software
120515  * distributed under the License is distributed on an "AS IS" BASIS,
120516  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
120517  * See the License for the specific language governing permissions and
120518  * limitations under the License.
120519  */
120520 var event = require('ripple/event');
120521
120522 module.exports = {
120523     "app.event.onBackground": {
120524         callback: function () {
120525             event.trigger("AppRequestBackground");
120526         }
120527     },
120528     "app.event.onForeground": {
120529         callback: function () {
120530             event.trigger("AppRequestForeground");
120531         }
120532     }
120533 };
120534
120535 });
120536 define('ripple/platform/webworks.handset/2.0.0/XMLHttpRequest', function (require, exports, module) {
120537 /*
120538  *  Copyright 2011 Research In Motion Limited.
120539  *
120540  * Licensed under the Apache License, Version 2.0 (the "License");
120541  * you may not use this file except in compliance with the License.
120542  * You may obtain a copy of the License at
120543  *
120544  * http://www.apache.org/licenses/LICENSE-2.0
120545  *
120546  * Unless required by applicable law or agreed to in writing, software
120547  * distributed under the License is distributed on an "AS IS" BASIS,
120548  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
120549  * See the License for the specific language governing permissions and
120550  * limitations under the License.
120551  */
120552
120553 var xhr = require("ripple/platform/webworks.core/2.0.0/XMLHttpRequest");
120554 module.exports = xhr.create("ripple/platform/webworks.handset/2.0.0/server");
120555
120556 });
120557 define('ripple/platform/webworks.handset/2.0.0/client/Address', function (require, exports, module) {
120558 /*
120559  *  Copyright 2011 Research In Motion Limited.
120560  *
120561  * Licensed under the Apache License, Version 2.0 (the "License");
120562  * you may not use this file except in compliance with the License.
120563  * You may obtain a copy of the License at
120564  *
120565  * http://www.apache.org/licenses/LICENSE-2.0
120566  *
120567  * Unless required by applicable law or agreed to in writing, software
120568  * distributed under the License is distributed on an "AS IS" BASIS,
120569  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
120570  * See the License for the specific language governing permissions and
120571  * limitations under the License.
120572  */
120573 function Address() {
120574     return {
120575         //readwrite  property  String   address1
120576         //readwrite  property  String   address2
120577         //readwrite  property  String   city
120578         //readwrite  property  String   country
120579         //readwrite  property  String   stateProvince
120580         //readwrite  property  String   zipPostal
120581
120582         address1: null,
120583         address2: null,
120584         city: null,
120585         country: null,
120586         stateProvince: null,
120587         zipPostal: null
120588     };
120589 }
120590
120591 module.exports = Address;
120592
120593 });
120594 define('ripple/platform/webworks.handset/2.0.0/client/AddressBookArguments', function (require, exports, module) {
120595 /*
120596  *  Copyright 2011 Research In Motion Limited.
120597  *
120598  * Licensed under the Apache License, Version 2.0 (the "License");
120599  * you may not use this file except in compliance with the License.
120600  * You may obtain a copy of the License at
120601  *
120602  * http://www.apache.org/licenses/LICENSE-2.0
120603  *
120604  * Unless required by applicable law or agreed to in writing, software
120605  * distributed under the License is distributed on an "AS IS" BASIS,
120606  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
120607  * See the License for the specific language governing permissions and
120608  * limitations under the License.
120609  */
120610 //blackberry.invoke.AddressBookArguments ( [contact : blackberry.pim.Contact ] )
120611 var _self = function (contact) {
120612     return {
120613         contact: contact,
120614         //readwrite  property  Number   view
120615         view: 0
120616     };
120617 };
120618
120619 //const Number  VIEW_NEW  = 0
120620 _self.__defineGetter__("VIEW_NEW", function () {
120621     return 0;
120622 });
120623 //const Number  VIEW_COMPOSE  = 1
120624 _self.__defineGetter__("VIEW_COMPOSE", function () {
120625     return 1;
120626 });
120627 //const Number  VIEW_DISPLAY  = 2
120628 _self.__defineGetter__("VIEW_DISPLAY", function () {
120629     return 2;
120630 });
120631
120632 module.exports = _self;
120633
120634 });
120635 define('ripple/platform/webworks.handset/2.0.0/client/Appointment', function (require, exports, module) {
120636 /*
120637  *  Copyright 2011 Research In Motion Limited.
120638  *
120639  * Licensed under the Apache License, Version 2.0 (the "License");
120640  * you may not use this file except in compliance with the License.
120641  * You may obtain a copy of the License at
120642  *
120643  * http://www.apache.org/licenses/LICENSE-2.0
120644  *
120645  * Unless required by applicable law or agreed to in writing, software
120646  * distributed under the License is distributed on an "AS IS" BASIS,
120647  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
120648  * See the License for the specific language governing permissions and
120649  * limitations under the License.
120650  */
120651 var transport = require('ripple/platform/webworks.core/2.0.0/client/transport'),
120652     utils = require('ripple/utils'),
120653     _uri = "blackberry/pim/appointment/";
120654
120655 function Appointment(service) {
120656     var _self = {
120657         allDay: false,
120658         attendees: [],
120659         end: null,
120660         freeBusy: null,
120661         location: null,
120662         note: null,
120663         recurrence: null,
120664         reminder: null,
120665         start: null,
120666         summary: null,
120667         uid: null,
120668         remove: function () {
120669             transport.call(_uri + "remove", {get: {uid: _self.uid}});
120670         },
120671         save: function () {
120672             if (_self.uid === null) {
120673                 _self.uid  = Number(Math.uuid(8, 10));
120674             }
120675             transport.call(_uri + "save", {post: {appointment: _self}});
120676         }
120677     };
120678
120679     return _self;
120680 }
120681
120682 function _massage(property, name) {
120683     if (name === "recurrence" && property) {
120684         if (property.end) {
120685             property.end = new Date(property.end);
120686         }
120687     }
120688     if (name === "reminder" && property) {
120689         if (property.date) {
120690             property.date = new Date(property.date);
120691         }
120692     }
120693     if ((name === "end" || name === "start") && property) {
120694         property = new Date(property);
120695     }
120696     return property;
120697 }
120698
120699 Appointment.find = function (filter, orderBy, maxReturn, service, isAscending) {
120700     var opts = {
120701         post: {
120702             filter: filter,
120703             orderBy: orderBy,
120704             maxReturn: maxReturn,
120705             service: service,
120706             isAscending: isAscending
120707         }
120708     };
120709
120710     return transport.call(_uri + "find", opts).map(function (obj) {
120711         var appt = new Appointment();
120712         appt.allDay = obj.allDay;
120713         appt.attendees = obj.attendees;
120714         appt.end = _massage(obj.end, "end");
120715         appt.freeBusy = obj.freeBusy;
120716         appt.location = obj.location;
120717         appt.note = obj.note;
120718         appt.recurrence = _massage(obj.recurrence, "recurrence");
120719         appt.reminder = _massage(obj.reminder, "reminder");
120720         appt.start = _massage(obj.start, "start");
120721         appt.summary = obj.summary;
120722         appt.uid = obj.uid;
120723         return appt;
120724     });
120725 };
120726
120727 Appointment.__defineGetter__("FREE", function () {
120728     return 0;
120729 });
120730 Appointment.__defineGetter__("TENTATIVE", function () {
120731     return 1;
120732 });
120733 Appointment.__defineGetter__("BUSY", function () {
120734     return 2;
120735 });
120736 Appointment.__defineGetter__("OUT_OF_OFFICE", function () {
120737     return 3;
120738 });
120739
120740 module.exports = Appointment;
120741
120742 });
120743 define('ripple/platform/webworks.handset/2.0.0/client/Attendee', function (require, exports, module) {
120744 /*
120745  *  Copyright 2011 Research In Motion Limited.
120746  *
120747  * Licensed under the Apache License, Version 2.0 (the "License");
120748  * you may not use this file except in compliance with the License.
120749  * You may obtain a copy of the License at
120750  *
120751  * http://www.apache.org/licenses/LICENSE-2.0
120752  *
120753  * Unless required by applicable law or agreed to in writing, software
120754  * distributed under the License is distributed on an "AS IS" BASIS,
120755  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
120756  * See the License for the specific language governing permissions and
120757  * limitations under the License.
120758  */
120759 function Attendee() {
120760     return {
120761         //readwrite  property  String   address
120762         //readwrite  property  Number   type
120763
120764         address: null,
120765         type: null
120766     };
120767 }
120768
120769 Attendee.__defineGetter__("ORGANIZER", function () {
120770     return 0;
120771 });
120772
120773 Attendee.__defineGetter__("INVITED", function () {
120774     return 1;
120775 });
120776
120777 Attendee.__defineGetter__("ACCEPTED", function () {
120778     return 2;
120779 });
120780
120781 Attendee.__defineGetter__("DECLINED", function () {
120782     return 3;
120783 });
120784
120785 Attendee.__defineGetter__("TENTATIVE", function () {
120786     return 4;
120787 });
120788
120789 module.exports =  Attendee;
120790
120791 });
120792 define('ripple/platform/webworks.handset/2.0.0/client/AudioPlayer', function (require, exports, module) {
120793 /*
120794  *  Copyright 2011 Research In Motion Limited.
120795  *
120796  * Licensed under the Apache License, Version 2.0 (the "License");
120797  * you may not use this file except in compliance with the License.
120798  * You may obtain a copy of the License at
120799  *
120800  * http://www.apache.org/licenses/LICENSE-2.0
120801  *
120802  * Unless required by applicable law or agreed to in writing, software
120803  * distributed under the License is distributed on an "AS IS" BASIS,
120804  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
120805  * See the License for the specific language governing permissions and
120806  * limitations under the License.
120807  */
120808 var transport = require('ripple/platform/webworks.core/2.0.0/client/transport'),
120809     _uri = "blackberry/audio/player/";
120810
120811 function Player(locator, type, async) {
120812     //we can't use the async prop since we need the ID before we can do anything else.
120813     var _id = transport.call(_uri + "create", {
120814             get: {locator: locator, type: type},
120815             async: false
120816         }),
120817         _listener,
120818         _closed,
120819         _self,
120820         _poll = function (path) {
120821             transport.poll(_uri + path, {
120822                 get: {id: _id}
120823             }, function (response) {
120824                 if (_listener) {
120825                     _listener(_self, response.event, response.eventData);
120826                 }
120827
120828                 return !!_listener;
120829             });
120830         };
120831
120832     _self = {
120833         addPlayerListener: function (callback) {
120834             if (!_closed && callback) {
120835                 _listener = callback;
120836                 _poll("onStart");
120837                 _poll("onStopped");
120838                 _poll("onBufferingStarted");
120839                 _poll("onBufferingStopped");
120840                 _poll("onDurationUpdated");
120841                 _poll("onEnd");
120842                 _poll("onError");
120843                 _poll("onVolumeChange");
120844                 _poll("onClose");
120845             }
120846             else {
120847                 _listener = null;
120848             }
120849
120850             return !_closed;
120851         },
120852
120853         close: function () {
120854             _listener = null;
120855             _closed = true;
120856             return transport.call(_uri + "close", {get: {id: _id}});
120857         },
120858
120859         pause: function () {
120860             return transport.call(_uri + "pause", {get: {id: _id}});
120861         },
120862
120863         play: function () {
120864             return transport.call(_uri + "play", {get: {id: _id}});
120865         }
120866     };
120867
120868     _self.__defineGetter__("duration", function () {
120869         return transport.call(_uri + "getDuration", {get: {id: _id}});
120870     });
120871
120872     _self.__defineGetter__("mediaTime", function () {
120873         return transport.call(_uri + "getMediaTime", {get: {id: _id}});
120874     });
120875
120876     _self.__defineSetter__("mediaTime", function (val) {
120877         transport.call(_uri + "setMediaTime", {get: {id: _id, value: val}});
120878     });
120879
120880     _self.__defineGetter__("state", function () {
120881         return transport.call(_uri + "getState", {get: {id: _id}});
120882     });
120883
120884     _self.__defineGetter__("volumeLevel", function () {
120885         return transport.call(_uri + "getVolumeLevel", {get: {id: _id}});
120886     });
120887
120888     _self.__defineSetter__("volumeLevel", function (val) {
120889         transport.call(_uri + "setVolumeLevel", {get: {id: _id, value: val}});
120890     });
120891
120892     _self.__defineGetter__("EVENT_BUFFERING_STARTED", function () {
120893         return "EVENT_BUFFERING_STARTED";
120894     });
120895     _self.__defineGetter__("EVENT_BUFFERING_STOPPED", function () {
120896         return "EVENT_BUFFERING_STOPPED";
120897     });
120898     _self.__defineGetter__("EVENT_CLOSED", function () {
120899         return "EVENT_CLOSED";
120900     });
120901     _self.__defineGetter__("EVENT_DEVICE_AVAILABLE", function () {
120902         return "EVENT_DEVICE_AVAILABLE";
120903     });
120904     _self.__defineGetter__("EVENT_DEVICE_UNAVAILABLE", function () {
120905         return "EVENT_DEVICE_UNAVAILABLE";
120906     });
120907     _self.__defineGetter__("EVENT_DURATION_UPDATED", function () {
120908         return "EVENT_DURATION_UPDATED";
120909     });
120910     _self.__defineGetter__("EVENT_END_OF_MEDIA", function () {
120911         return "EVENT_END_OF_MEDIA";
120912     });
120913     _self.__defineGetter__("EVENT_ERROR", function () {
120914         return "EVENT_ERROR";
120915     });
120916     _self.__defineGetter__("EVENT_RECORD_ERROR", function () {
120917         return "EVENT_ERROR";
120918     });
120919     _self.__defineGetter__("EVENT_RECORD_STARTED", function () {
120920         return "EVENT_RECORD_STARTED";
120921     });
120922     _self.__defineGetter__("EVENT_RECORD_STOPPED", function () {
120923         return "EVENT_RECORD_STOPPED";
120924     });
120925     _self.__defineGetter__("EVENT_SIZE_CHANGED", function () {
120926         return "EVENT_SIZE_CHANGED";
120927     });
120928     _self.__defineGetter__("EVENT_STARTED", function () {
120929         return "EVENT_STARTED";
120930     });
120931     _self.__defineGetter__("EVENT_STOPPED", function () {
120932         return "EVENT_STOPPED";
120933     });
120934     _self.__defineGetter__("EVENT_STOPPED_AT_TIME", function () {
120935         return "EVENT_STOPPED_AT_TIME";
120936     });
120937     _self.__defineGetter__("EVENT_VOLUME_CHANGED", function () {
120938         return "EVENT_VOLUME_CHANGED";
120939     });
120940
120941     return _self;
120942 }
120943
120944 Player.__defineGetter__("TIME_UNKNOWN", function () {
120945     return -1;
120946 });
120947 Player.__defineGetter__("CLOSED", function () {
120948     return 0;
120949 });
120950 Player.__defineGetter__("UNREALIZED", function () {
120951     return 100;
120952 });
120953 Player.__defineGetter__("REALIZED", function () {
120954     return 200;
120955 });
120956 Player.__defineGetter__("PREFETCHED", function () {
120957     return 300;
120958 });
120959 Player.__defineGetter__("STARTED", function () {
120960     return 400;
120961 });
120962
120963 module.exports = Player;
120964
120965 });
120966 define('ripple/platform/webworks.handset/2.0.0/client/BrowserArguments', function (require, exports, module) {
120967 /*
120968  *  Copyright 2011 Research In Motion Limited.
120969  *
120970  * Licensed under the Apache License, Version 2.0 (the "License");
120971  * you may not use this file except in compliance with the License.
120972  * You may obtain a copy of the License at
120973  *
120974  * http://www.apache.org/licenses/LICENSE-2.0
120975  *
120976  * Unless required by applicable law or agreed to in writing, software
120977  * distributed under the License is distributed on an "AS IS" BASIS,
120978  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
120979  * See the License for the specific language governing permissions and
120980  * limitations under the License.
120981  */
120982 //blackberry.invoke.BrowserArguments ( url : String ,  [transport : blackberry.identity.Transport ] )
120983 module.exports = function (url, transport) {
120984     return {
120985         url: url
120986     };
120987 };
120988
120989 });
120990 define('ripple/platform/webworks.handset/2.0.0/client/CalendarArguments', function (require, exports, module) {
120991 /*
120992  *  Copyright 2011 Research In Motion Limited.
120993  *
120994  * Licensed under the Apache License, Version 2.0 (the "License");
120995  * you may not use this file except in compliance with the License.
120996  * You may obtain a copy of the License at
120997  *
120998  * http://www.apache.org/licenses/LICENSE-2.0
120999  *
121000  * Unless required by applicable law or agreed to in writing, software
121001  * distributed under the License is distributed on an "AS IS" BASIS,
121002  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
121003  * See the License for the specific language governing permissions and
121004  * limitations under the License.
121005  */
121006 //blackberry.invoke.CalendarArguments ( )
121007 //blackberry.invoke.CalendarArguments ( date : Date )
121008 //blackberry.invoke.CalendarArguments ( appointment : blackberry.pim.Appointment )
121009 var _self = function () {
121010     //readonly  property  Appointment   appointment
121011     //readonly  property  Date   date
121012     //readwrite  property  Number   view
121013     return {
121014         appointment: undefined,
121015         date: undefined,
121016         view: 0
121017     };
121018 };
121019
121020 //const Number  VIEW_NEW  = 0
121021 _self.__defineGetter__("VIEW_NEW", function () {
121022     return 0;
121023 });
121024 //const Number  VIEW_VIEW  = 1
121025 _self.__defineGetter__("VIEW_VIEW", function () {
121026     return 1;
121027 });
121028 //const Number  VIEW_AGENDA  = 2
121029 _self.__defineGetter__("VIEW_AGENDA", function () {
121030     return 2;
121031 });
121032 //const Number  VIEW_DAY  = 3
121033 _self.__defineGetter__("VIEW_DAY", function () {
121034     return 3;
121035 });
121036 //const Number  VIEW_DEFAULT  = 4
121037 _self.__defineGetter__("VIEW_DEFAULT", function () {
121038     return 4;
121039 });
121040 //const Number  VIEW_MONTH  = 5
121041 _self.__defineGetter__("VIEW_MONTH", function () {
121042     return 5;
121043 });
121044 //const Number  VIEW_WEEK  = 6
121045 _self.__defineGetter__("VIEW_WEEK", function () {
121046     return 6;
121047 });
121048
121049 module.exports = _self;
121050
121051 });
121052 define('ripple/platform/webworks.handset/2.0.0/client/CallLog', function (require, exports, module) {
121053 /*
121054  *  Copyright 2011 Research In Motion Limited.
121055  *
121056  * Licensed under the Apache License, Version 2.0 (the "License");
121057  * you may not use this file except in compliance with the License.
121058  * You may obtain a copy of the License at
121059  *
121060  * http://www.apache.org/licenses/LICENSE-2.0
121061  *
121062  * Unless required by applicable law or agreed to in writing, software
121063  * distributed under the License is distributed on an "AS IS" BASIS,
121064  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
121065  * See the License for the specific language governing permissions and
121066  * limitations under the License.
121067  */
121068 function CallLog() {
121069     // readwrite  property  String   addressBookNumber
121070     // readwrite  property  String   addressBookType
121071     // readwrite  property  Date   date
121072     // readwrite  property  Number   duration
121073     // readwrite  property  String   name
121074     // readwrite  property  String   notes
121075     // readwrite  property  String   number
121076     // readwrite  property  Number   status
121077     // readwrite  property  Number   type
121078     this.addressBookNumber = null;
121079     this.addressBookType = null;
121080     this.date = null;
121081     this.duration = null;
121082     this.name = null;
121083     this.notes = null;
121084     this.number = null;
121085     this.status = null;
121086     this.type = null;
121087 }
121088
121089 function _get(val) {
121090     return function () {
121091         return val;
121092     };
121093 }
121094
121095 CallLog.__defineGetter__("STATUS_NORMAL", _get(0));
121096 CallLog.__defineGetter__("STATUS_BUSY", _get(1));
121097 CallLog.__defineGetter__("STATUS_CONGESTION", _get(2));
121098 CallLog.__defineGetter__("STATUS_PATH_UNAVAILABLE", _get(3));
121099 CallLog.__defineGetter__("STATUS_NUMBER_UNOBTAINABLE", _get(4));
121100 CallLog.__defineGetter__("STATUS_AUTHENTICATION_FAILURE", _get(5));
121101 CallLog.__defineGetter__("STATUS_EMERGENCY_CALLS_ONLY", _get(6));
121102 CallLog.__defineGetter__("STATUS_HOLD_ERROR", _get(7));
121103 CallLog.__defineGetter__("STATUS_OUTGOING_CALLS_BARRED", _get(8));
121104 CallLog.__defineGetter__("STATUS_GENERAL_ERROR", _get(9));
121105 CallLog.__defineGetter__("STATUS_MAINTENANCE_REQUIRED", _get(10));
121106 CallLog.__defineGetter__("STATUS_SERVICE_NOT_AVAILABLE", _get(11));
121107 CallLog.__defineGetter__("STATUS_CALL_FAIL_DUE_TO_FADING", _get(12));
121108 CallLog.__defineGetter__("STATUS_CALL_LOST_DUE_TO_FADING", _get(13));
121109 CallLog.__defineGetter__("STATUS_CALL_FAILED_TRY_AGAIN", _get(14));
121110 CallLog.__defineGetter__("STATUS_FDN_MISMATCH", _get(15));
121111 CallLog.__defineGetter__("STATUS_CONNECTION_DENIED", _get(16));
121112 CallLog.__defineGetter__("STATUS_INCOMING_CALL_BARRED", _get(17));
121113 CallLog.__defineGetter__("TYPE_RECEIVED_CALL", _get(0));
121114 CallLog.__defineGetter__("TYPE_PLACED_CALL", _get(1));
121115 CallLog.__defineGetter__("TYPE_MISSED_CALL_UNOPENED", _get(2));
121116 CallLog.__defineGetter__("TYPE_MISSED_CALL_OPENED", _get(3));
121117
121118 module.exports = CallLog;
121119
121120 });
121121 define('ripple/platform/webworks.handset/2.0.0/client/CameraArguments', function (require, exports, module) {
121122 /*
121123  *  Copyright 2011 Research In Motion Limited.
121124  *
121125  * Licensed under the Apache License, Version 2.0 (the "License");
121126  * you may not use this file except in compliance with the License.
121127  * You may obtain a copy of the License at
121128  *
121129  * http://www.apache.org/licenses/LICENSE-2.0
121130  *
121131  * Unless required by applicable law or agreed to in writing, software
121132  * distributed under the License is distributed on an "AS IS" BASIS,
121133  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
121134  * See the License for the specific language governing permissions and
121135  * limitations under the License.
121136  */
121137 //blackberry.invoke.CameraArguments ( )
121138 var _self = function () {
121139     return {
121140         //readwrite  property  Number   view
121141         view: 0
121142     };
121143 };
121144
121145 //const Number  VIEW_CAMERA  = 0
121146 _self.__defineGetter__("VIEW_CAMERA", function () {
121147     return 0;
121148 });
121149 //const Number  VIEW_RECORDER  = 1
121150 _self.__defineGetter__("VIEW_RECORDER", function () {
121151     return 1;
121152 });
121153
121154 module.exports = _self;
121155
121156 });
121157 define('ripple/platform/webworks.handset/2.0.0/client/Contact', function (require, exports, module) {
121158 /*
121159  *  Copyright 2011 Research In Motion Limited.
121160  *
121161  * Licensed under the Apache License, Version 2.0 (the "License");
121162  * you may not use this file except in compliance with the License.
121163  * You may obtain a copy of the License at
121164  *
121165  * http://www.apache.org/licenses/LICENSE-2.0
121166  *
121167  * Unless required by applicable law or agreed to in writing, software
121168  * distributed under the License is distributed on an "AS IS" BASIS,
121169  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
121170  * See the License for the specific language governing permissions and
121171  * limitations under the License.
121172  */
121173 var transport = require('ripple/platform/webworks.core/2.0.0/client/transport'),
121174     _uri = "blackberry/pim/contact/";
121175
121176 function Contact(service) {
121177     var _self = {
121178         anniversary: null,
121179         birthday: null,
121180         categories: [],
121181         company: null,
121182         email1: "",
121183         email2: "",
121184         email3: "",
121185         faxPhone: null,
121186         firstName: null,
121187         homeAddress: null,
121188         homePhone: null,
121189         homePhone2: null,
121190         jobTitle: null,
121191         lastName: null,
121192         mobilePhone: null,
121193         note: null,
121194         otherPhone: null,
121195         pagerPhone: null,
121196         picture: null,
121197         pin: null,
121198         title: null,
121199         uid: null,
121200         user1: null,
121201         user2: null,
121202         user3: null,
121203         user4: null,
121204         webpage: null,
121205         workAddress: null,
121206         workPhone: null,
121207         workPhone2: null,
121208         remove: function () {
121209             if (!_self.uid) {
121210                 throw "task has not yet been saved (has no uid)";
121211             }
121212             transport.call(_uri + "remove", {
121213                 get: { id: _self.uid }
121214             });
121215         },
121216         save: function () {
121217             if (!_self.uid) {
121218                 _self.uid = Math.uuid(null, 16);
121219             }
121220             transport.call(_uri + "save", {
121221                 post: { contact: _self }
121222             });
121223         },
121224         setPicture: function (picture) {
121225             throw "not implemented";
121226         }
121227     };
121228
121229     return _self;
121230 }
121231
121232 function _massage(property, name) {
121233     if ((name === "anniversary" || name === "birthday") && property) {
121234         return new Date(property);
121235     }
121236     return property;
121237 }
121238
121239 Contact.find = function (fieldFilter, orderBy, maxReturn, service, isAscending) {
121240     return transport.call(_uri + "find", {
121241         post: {
121242             fieldFilter: fieldFilter,
121243             orderBy: orderBy,
121244             maxReturn: maxReturn,
121245             service: service,
121246             isAscending: isAscending
121247         }
121248     }).map(function (properties) {
121249         var contact = new Contact(),
121250             key;
121251         for (key in properties) {
121252             if (contact.hasOwnProperty(key)) {
121253                 contact[key] = _massage(properties[key], key);
121254             }
121255         }
121256         return contact;
121257     });
121258 };
121259
121260 module.exports = Contact;
121261
121262 });
121263 define('ripple/platform/webworks.handset/2.0.0/client/FilterExpression', function (require, exports, module) {
121264 /*
121265  *  Copyright 2011 Research In Motion Limited.
121266  *
121267  * Licensed under the Apache License, Version 2.0 (the "License");
121268  * you may not use this file except in compliance with the License.
121269  * You may obtain a copy of the License at
121270  *
121271  * http://www.apache.org/licenses/LICENSE-2.0
121272  *
121273  * Unless required by applicable law or agreed to in writing, software
121274  * distributed under the License is distributed on an "AS IS" BASIS,
121275  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
121276  * See the License for the specific language governing permissions and
121277  * limitations under the License.
121278  */
121279 //blackberry.find.FilterExpression ( leftField  : object ,  operator  : object ,  rightField : object ,  [negate : Boolean ] )
121280 var FilterExpression = function (leftField, operator, rightField, negate) {
121281     this.__defineGetter__("leftField", function () {
121282         return leftField;
121283     });
121284
121285     this.__defineGetter__("operator", function () {
121286         return operator;
121287     });
121288
121289     this.__defineGetter__("rightField", function () {
121290         return rightField;
121291     });
121292
121293     this.__defineGetter__("negate", function () {
121294         return negate ? true : false;
121295     });
121296 };
121297
121298 module.exports = FilterExpression;
121299
121300 });
121301 define('ripple/platform/webworks.handset/2.0.0/client/JavaArguments', function (require, exports, module) {
121302 /*
121303  *  Copyright 2011 Research In Motion Limited.
121304  *
121305  * Licensed under the Apache License, Version 2.0 (the "License");
121306  * you may not use this file except in compliance with the License.
121307  * You may obtain a copy of the License at
121308  *
121309  * http://www.apache.org/licenses/LICENSE-2.0
121310  *
121311  * Unless required by applicable law or agreed to in writing, software
121312  * distributed under the License is distributed on an "AS IS" BASIS,
121313  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
121314  * See the License for the specific language governing permissions and
121315  * limitations under the License.
121316  */
121317 //blackberry.invoke.JavaArguments ( uri : String ,  [params : String [ ] ] )
121318 var _self = function (uri, params) {
121319     return {
121320         uri: uri,
121321         params: params,
121322         args: arguments
121323     };
121324 };
121325
121326 module.exports = _self;
121327
121328 });
121329 define('ripple/platform/webworks.handset/2.0.0/client/MapsArguments', function (require, exports, module) {
121330 /*
121331  *  Copyright 2011 Research In Motion Limited.
121332  *
121333  * Licensed under the Apache License, Version 2.0 (the "License");
121334  * you may not use this file except in compliance with the License.
121335  * You may obtain a copy of the License at
121336  *
121337  * http://www.apache.org/licenses/LICENSE-2.0
121338  *
121339  * Unless required by applicable law or agreed to in writing, software
121340  * distributed under the License is distributed on an "AS IS" BASIS,
121341  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
121342  * See the License for the specific language governing permissions and
121343  * limitations under the License.
121344  */
121345 //blackberry.invoke.MapsArguments ( )
121346 //blackberry.invoke.MapsArguments ( latitude : Number ,  longitude : Number )
121347 //blackberry.invoke.MapsArguments ( locationDocument : Document ) - Supported in 5.0.0 only
121348 //blackberry.invoke.MapsArguments ( locationDocument : String ) - Supported in 6.0.0 only
121349 //blackberry.invoke.MapsArguments ( address : blackberry.pim.Address )
121350 var _self = function () {
121351     return {};
121352 };
121353
121354 module.exports = _self;
121355
121356 });
121357 define('ripple/platform/webworks.handset/2.0.0/client/Memo', function (require, exports, module) {
121358 /*
121359  *  Copyright 2011 Research In Motion Limited.
121360  *
121361  * Licensed under the Apache License, Version 2.0 (the "License");
121362  * you may not use this file except in compliance with the License.
121363  * You may obtain a copy of the License at
121364  *
121365  * http://www.apache.org/licenses/LICENSE-2.0
121366  *
121367  * Unless required by applicable law or agreed to in writing, software
121368  * distributed under the License is distributed on an "AS IS" BASIS,
121369  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
121370  * See the License for the specific language governing permissions and
121371  * limitations under the License.
121372  */
121373 var transport = require('ripple/platform/webworks.core/2.0.0/client/transport'),
121374     _uri = "blackberry/pim/memo/";
121375
121376 function Memo() {
121377     var _self = {
121378         categories: [],
121379         note: null,
121380         title: null,
121381         uid: null,
121382         remove: function () {
121383             transport.call(_uri + "remove", {
121384                 get: {uid: _self.uid}
121385             });
121386         },
121387         save: function () {
121388             if (_self.uid  === null) {
121389                 _self.uid  = Number(Math.uuid(8, 10));
121390             }
121391             transport.call(_uri + "save", {
121392                 post: {memo: _self}
121393             });
121394         }
121395     };
121396
121397     return _self;
121398 }
121399
121400 Memo.find = function (filter, orderBy, maxReturn, service, isAscending) {
121401     var opts = {
121402         post: {
121403             filter: filter,
121404             orderBy: orderBy,
121405             maxReturn: maxReturn,
121406             isAscending: isAscending,
121407             service: service
121408         }
121409     };
121410
121411     return transport.call(_uri + "find", opts).map(function (obj) {
121412         var memo = new Memo();
121413         memo.uid = obj.uid;
121414         memo.categories = obj.categories || [];
121415         memo.note = obj.note;
121416         memo.title = obj.title;
121417         return memo;
121418     });
121419 };
121420
121421 module.exports = Memo;
121422
121423 });
121424 define('ripple/platform/webworks.handset/2.0.0/client/MemoArguments', function (require, exports, module) {
121425 /*
121426  *  Copyright 2011 Research In Motion Limited.
121427  *
121428  * Licensed under the Apache License, Version 2.0 (the "License");
121429  * you may not use this file except in compliance with the License.
121430  * You may obtain a copy of the License at
121431  *
121432  * http://www.apache.org/licenses/LICENSE-2.0
121433  *
121434  * Unless required by applicable law or agreed to in writing, software
121435  * distributed under the License is distributed on an "AS IS" BASIS,
121436  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
121437  * See the License for the specific language governing permissions and
121438  * limitations under the License.
121439  */
121440 //blackberry.invoke.MemoArguments ( [memo : blackberry.pim.Memo ] )
121441 var _self = function (memo) {
121442     return {
121443         memo: memo,
121444         view: 0
121445     };
121446 };
121447
121448 //const Number  VIEW_NEW  = 0
121449 _self.__defineGetter__("VIEW_NEW", function () {
121450     return 0;
121451 });
121452 //const Number  VIEW_EDIT  = 1
121453 _self.__defineGetter__("VIEW_EDIT", function () {
121454     return 1;
121455 });
121456
121457 module.exports = _self;
121458
121459 });
121460 define('ripple/platform/webworks.handset/2.0.0/client/MenuItem', function (require, exports, module) {
121461 /*
121462  *  Copyright 2011 Research In Motion Limited.
121463  *
121464  * Licensed under the Apache License, Version 2.0 (the "License");
121465  * you may not use this file except in compliance with the License.
121466  * You may obtain a copy of the License at
121467  *
121468  * http://www.apache.org/licenses/LICENSE-2.0
121469  *
121470  * Unless required by applicable law or agreed to in writing, software
121471  * distributed under the License is distributed on an "AS IS" BASIS,
121472  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
121473  * See the License for the specific language governing permissions and
121474  * limitations under the License.
121475  */
121476 var transport = require('ripple/platform/webworks.core/2.0.0/client/transport'),
121477     event = require('ripple/event');
121478
121479 function MenuItem(isSeparator, ordinal, caption, callback) {
121480     var _isDefault = false,
121481         id = Math.uuid();
121482
121483     if (ordinal < 0) {
121484         throw "Ordinal cannot be less than 0";
121485     } else if (isSeparator) {
121486         if (caption !== undefined) {
121487             throw "caption must not be supplied";
121488         } else if (callback !== undefined) {
121489             throw "callback must not be supplied";
121490         }
121491     } else if (!isSeparator) {
121492         if (caption === undefined) {
121493             throw "caption must be supplied";
121494         }
121495     }
121496
121497     this.callback = callback;
121498
121499     this.__defineSetter__("id", function (i) {
121500         id = i;
121501     });
121502
121503     this.__defineGetter__("id", function () {
121504         return id;
121505     });
121506
121507     this.__defineSetter__("caption", function (c) {
121508         caption = c;
121509         event.trigger("MenuItemChanged", [this]);
121510     });
121511
121512     this.__defineGetter__("caption", function () {
121513         return caption;
121514     });
121515
121516     this.__defineSetter__("ordinal", function (o) {
121517         ordinal = o;
121518         event.trigger("MenuItemChanged", [this]);
121519     });
121520
121521     this.__defineGetter__("ordinal", function () {
121522         return ordinal;
121523     });
121524
121525     this.__defineGetter__("isSeparator", function () {
121526         return isSeparator;
121527     });
121528
121529     this.__defineSetter__("isDefault", function (d) {
121530         _isDefault = d;
121531         event.trigger("MenuItemChanged", [this]);
121532     });
121533
121534     this.__defineGetter__("isDefault", function () {
121535         return _isDefault;
121536     });
121537
121538     this.__defineGetter__("id", function () {
121539         return id;
121540     });
121541 }
121542
121543 module.exports = MenuItem;
121544
121545 });
121546 define('ripple/platform/webworks.handset/2.0.0/client/Message', function (require, exports, module) {
121547 /*
121548  *  Copyright 2011 Research In Motion Limited.
121549  *
121550  * Licensed under the Apache License, Version 2.0 (the "License");
121551  * you may not use this file except in compliance with the License.
121552  * You may obtain a copy of the License at
121553  *
121554  * http://www.apache.org/licenses/LICENSE-2.0
121555  *
121556  * Unless required by applicable law or agreed to in writing, software
121557  * distributed under the License is distributed on an "AS IS" BASIS,
121558  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
121559  * See the License for the specific language governing permissions and
121560  * limitations under the License.
121561  */
121562 var utils = require('ripple/platform/webworks.core/2.0.0/client/utils'),
121563     identity = require('ripple/platform/webworks.handset/2.0.0/client/identity'),
121564     transport = require('ripple/platform/webworks.core/2.0.0/client/transport'),
121565     Service = require('ripple/platform/webworks.handset/2.0.0/client/identity/Service'),
121566     select = require('ripple/platform/webworks.core/2.0.0/select'),
121567     _uri = "blackberry/message/message/";
121568
121569 function Message(service) {
121570     var _service = service,
121571         _msg = {
121572             uid: 0,
121573             status: Message.STATUS_DRAFT,
121574             from: "",
121575             folder: Message.FOLDER_DRAFT,
121576             replyTo: "",
121577             bccRecipients: "",
121578             body: "",
121579             ccRecipients: "",
121580             priority: Message.PRIORITY_MEDIUM, //default to med priority
121581             subject: "",
121582             toRecipients: "",
121583
121584             remove: function () {
121585                 _msg.folder = Message.FOLDER_DELETED;
121586                 transport.call(_uri + "remove", {
121587                     get: {uid: _msg.uid}
121588                 });
121589             },
121590
121591             save: function () {
121592                 if (_msg.uid === 0) {
121593                     _msg.uid = Number(Math.uuid(8, 10));
121594                 }
121595
121596                 _msg.replyTo  = _msg.from = _service.emailAddress;
121597                 _msg.status =  Message.STATUS_SAVED;
121598                 transport.call(_uri + "save", {
121599                     post: {message: _msg}
121600                 });
121601             },
121602
121603             send: function () {
121604                 if (_msg.toRecipients) {
121605                     if (_msg.uid === 0) {
121606                         _msg.uid = Number(Math.uuid(8, 10));
121607                     }
121608
121609                     _msg.folder = Message.FOLDER_DRAFT;
121610                     _msg.status = Message.STATUS_UNKNOWN;
121611                     transport.call(_uri + "send", {
121612                         get: {message: _msg}
121613                     });
121614                 } else {
121615                     throw "message has no recipients";
121616                 }
121617             }
121618         };
121619
121620     if (!_service) {
121621         _service = identity.getDefaultService().reduce(function (email, service) {
121622             return service.type === Service.TYPE_EMAIL ? service : email;
121623         }, null);
121624     }
121625
121626     return _msg;
121627 }
121628
121629 Message.find = function (filter, maxReturn, service) {
121630     var opts = {
121631         post: {
121632             filter: filter,
121633             maxReturn: maxReturn,
121634             service: service
121635         }
121636     };
121637
121638     return transport.call(_uri + "find", opts).map(function (obj) {
121639         var msg = new Message();
121640
121641         msg.uid = obj.uid;
121642         msg.status = obj.status;
121643         msg.from = obj.from;
121644         msg.folder = obj.folder;
121645         msg.replyTo = obj.replyTo;
121646         msg.bccRecipients = obj.bccRecipients;
121647         msg.body = obj.body;
121648         msg.ccRecipients = obj.ccRecipients;
121649         msg.priority = obj.priority;
121650         msg.subject = obj.subject;
121651         msg.toRecipients = obj.toRecipients;
121652
121653         return msg;
121654     });
121655 };
121656
121657
121658 Message.__defineGetter__("STATUS_UNKNOWN", function () {
121659     return -1;
121660 });
121661 Message.__defineGetter__("STATUS_SAVED", function () {
121662     return 0;
121663 });
121664 Message.__defineGetter__("STATUS_DRAFT", function () {
121665     return 1;
121666 });
121667 Message.__defineGetter__("STATUS_SENT", function () {
121668     return 2;
121669 });
121670 Message.__defineGetter__("STATUS_ERROR_OCCURED", function () {
121671     return 3;
121672 });
121673 Message.__defineGetter__("PRIORITY_HIGH", function () {
121674     return 0;
121675 });
121676 Message.__defineGetter__("PRIORITY_MEDIUM", function () {
121677     return 1;
121678 });
121679 Message.__defineGetter__("PRIORITY_LOW", function () {
121680     return 2;
121681 });
121682 Message.__defineGetter__("FOLDER_INBOX", function () {
121683     return 0;
121684 });
121685 Message.__defineGetter__("FOLDER_SENT", function () {
121686     return 1;
121687 });
121688 Message.__defineGetter__("FOLDER_DRAFT", function () {
121689     return 2;
121690 });
121691 Message.__defineGetter__("FOLDER_OUTBOX", function () {
121692     return 3;
121693 });
121694 Message.__defineGetter__("FOLDER_DELETED", function () {
121695     return 4;
121696 });
121697 Message.__defineGetter__("FOLDER_OTHER", function () {
121698     return 5;
121699 });
121700
121701 module.exports = Message;
121702
121703 });
121704 define('ripple/platform/webworks.handset/2.0.0/client/MessageArguments', function (require, exports, module) {
121705 /*
121706  *  Copyright 2011 Research In Motion Limited.
121707  *
121708  * Licensed under the Apache License, Version 2.0 (the "License");
121709  * you may not use this file except in compliance with the License.
121710  * You may obtain a copy of the License at
121711  *
121712  * http://www.apache.org/licenses/LICENSE-2.0
121713  *
121714  * Unless required by applicable law or agreed to in writing, software
121715  * distributed under the License is distributed on an "AS IS" BASIS,
121716  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
121717  * See the License for the specific language governing permissions and
121718  * limitations under the License.
121719  */
121720 //blackberry.invoke.MessageArguments ( )
121721 //blackberry.invoke.MessageArguments ( message : blackberry.message.Message )
121722 //blackberry.invoke.MessageArguments ( to : String ,  subject : String ,  body : String )
121723 var _self = function () {
121724     return {
121725         view: 1
121726     };
121727 };
121728
121729 //const Number  VIEW_NEW  = 0
121730 _self.__defineGetter__("VIEW_NEW", function () {
121731     return 0;
121732 });
121733 //const Number  VIEW_DEFAULT  = 1
121734 _self.__defineGetter__("VIEW_DEFAULT", function () {
121735     return 1;
121736 });
121737 //const Number  VIEW_SAVED  = 2
121738 _self.__defineGetter__("VIEW_SAVED", function () {
121739     return 2;
121740 });
121741 //const Number  VIEW_SEARCH  = 3
121742 _self.__defineGetter__("VIEW_SEARCH", function () {
121743     return 3;
121744 });
121745
121746 module.exports = _self;
121747
121748 });
121749 define('ripple/platform/webworks.handset/2.0.0/client/Phone', function (require, exports, module) {
121750 /*
121751  *  Copyright 2011 Research In Motion Limited.
121752  *
121753  * Licensed under the Apache License, Version 2.0 (the "License");
121754  * you may not use this file except in compliance with the License.
121755  * You may obtain a copy of the License at
121756  *
121757  * http://www.apache.org/licenses/LICENSE-2.0
121758  *
121759  * Unless required by applicable law or agreed to in writing, software
121760  * distributed under the License is distributed on an "AS IS" BASIS,
121761  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
121762  * See the License for the specific language governing permissions and
121763  * limitations under the License.
121764  */
121765 var transport = require('ripple/platform/webworks.core/2.0.0/client/transport'),
121766     _uri = "blackberry/phone/",
121767     _listeners = {},
121768     _self;
121769
121770 _self = {
121771     activeCalls: function () {
121772         return transport.call(_uri + "activeCalls");
121773     },
121774
121775     addPhoneListener: function (callback, eventType) {
121776         var assigned = false;
121777
121778         if (callback && typeof eventType === "number") {
121779             _listeners[eventType] = callback;
121780             assigned = true;
121781         } else if (eventType && callback === null) {
121782             delete _listeners[eventType];
121783         } else {
121784             _listeners = {};
121785         }
121786
121787         transport.poll(_uri + "onPhoneEvent", {
121788             get: {eventType: eventType}
121789         }, function (response) {
121790             var func = _listeners[eventType];
121791
121792             if (func) {
121793                 func(response.callId, response.error);
121794             }
121795
121796             return !!func;
121797         });
121798
121799         // hackish (return true that event was assigned, this is a disconnect between transport poll api and server)
121800         return assigned;
121801     },
121802
121803     inActiveCall: function () {
121804         return transport.call(_uri + "inActiveCall");
121805     }
121806 };
121807
121808 _self.__defineGetter__("CB_CALL_INITIATED", function () {
121809     return 0;
121810 });
121811 _self.__defineGetter__("CB_CALL_WAITING", function () {
121812     return 1;
121813 });
121814 _self.__defineGetter__("CB_CALL_INCOMING", function () {
121815     return 2;
121816 });
121817 _self.__defineGetter__("CB_CALL_ANSWERED", function () {
121818     return 3;
121819 });
121820 _self.__defineGetter__("CB_CALL_CONNECTED", function () {
121821     return 4;
121822 });
121823 _self.__defineGetter__("CB_CALL_CONFERENCECALL_ESTABLISHED", function () {
121824     return 5;
121825 });
121826 _self.__defineGetter__("CB_CONFERENCECALL_DISCONNECTED", function () {
121827     return 6;
121828 });
121829 _self.__defineGetter__("CB_CALL_DISCONNECTED", function () {
121830     return 7;
121831 });
121832 _self.__defineGetter__("CB_CALL_DIRECTCONNECT_CONNECTED", function () {
121833     return 8;
121834 });
121835 _self.__defineGetter__("CB_CALL_DIRECTCONNECT_DISCONNECTED", function () {
121836     return 9;
121837 });
121838 _self.__defineGetter__("CB_CALL_ENDED_BYUSER", function () {
121839     return 10;
121840 });
121841 _self.__defineGetter__("CB_CALL_FAILED", function () {
121842     return 11;
121843 });
121844 _self.__defineGetter__("CB_CALL_RESUMED", function () {
121845     return 12;
121846 });
121847 _self.__defineGetter__("CB_CALL_HELD", function () {
121848     return 13;
121849 });
121850 _self.__defineGetter__("CB_CALL_ADDED", function () {
121851     return 14;
121852 });
121853 _self.__defineGetter__("CB_CALL_REMOVED", function () {
121854     return 15;
121855 });
121856 _self.__defineGetter__("CALL_ERROR_SUBSCRIBER_BUSY", function () {
121857     return 1;
121858 });
121859 _self.__defineGetter__("CALL_ERROR_CONGESTION", function () {
121860     return 2;
121861 });
121862 _self.__defineGetter__("CALL_ERROR_RADIO_PATH_UNAVAILABLE", function () {
121863     return 3;
121864 });
121865 _self.__defineGetter__("CALL_ERROR_NUMBER_UNOBTAINABLE", function () {
121866     return 4;
121867 });
121868 _self.__defineGetter__("CALL_ERROR_AUTHORIZATION_FAILURE", function () {
121869     return 5;
121870 });
121871 _self.__defineGetter__("CALL_ERROR_EMERGENCY_CALLS_ONLY", function () {
121872     return 6;
121873 });
121874 _self.__defineGetter__("CALL_ERROR_HOLD_ERROR", function () {
121875     return 7;
121876 });
121877 _self.__defineGetter__("CALL_ERROR_OUTGOING_CALLS_BARRED", function () {
121878     return 8;
121879 });
121880 _self.__defineGetter__("CALL_ERROR_GENERAL", function () {
121881     return 9;
121882 });
121883 _self.__defineGetter__("CALL_ERROR_MAINTENANCE_REQUIRED", function () {
121884     return 10;
121885 });
121886 _self.__defineGetter__("CALL_ERROR_SERVICE_NOT_AVAILABLE", function () {
121887     return 11;
121888 });
121889 _self.__defineGetter__("CALL_ERROR_DUE_TO_FADING", function () {
121890     return 12;
121891 });
121892 _self.__defineGetter__("CALL_ERROR_LOST_DUE_TO_FADING", function () {
121893     return 13;
121894 });
121895 _self.__defineGetter__("CALL_ERROR_TRY_AGAIN", function () {
121896     return 14;
121897 });
121898 _self.__defineGetter__("CALL_ERROR_FDN_MISMATCH", function () {
121899     return 15;
121900 });
121901 _self.__defineGetter__("CALL_ERROR_CONNECTION_DENIED_BY_NETWORK", function () {
121902     return 16;
121903 });
121904 _self.__defineGetter__("CALL_ERROR_NUMBER_NOT_IN_SERVICE", function () {
121905     return 17;
121906 });
121907 _self.__defineGetter__("CALL_ERROR_PLEASE_TRY_LATER", function () {
121908     return 18;
121909 });
121910 _self.__defineGetter__("CALL_ERROR_SERVICE_CONFLICT", function () {
121911     return 19;
121912 });
121913 _self.__defineGetter__("CALL_ERROR_SYSTEM_BUSY_TRY_LATER", function () {
121914     return 20;
121915 });
121916 _self.__defineGetter__("CALL_ERROR_USER_BUSY_IN_PRIVATE", function () {
121917     return 21;
121918 });
121919 _self.__defineGetter__("CALL_ERROR_USER_BUSY_IN_DATA", function () {
121920     return 22;
121921 });
121922 _self.__defineGetter__("CALL_ERROR_USER_NOT_AUTHORIZED", function () {
121923     return 23;
121924 });
121925 _self.__defineGetter__("CALL_ERROR_USER_NOT_AVAILABLE", function () {
121926     return 24;
121927 });
121928 _self.__defineGetter__("CALL_ERROR_USER_UNKNOWN", function () {
121929     return 25;
121930 });
121931 _self.__defineGetter__("CALL_ERROR_USER_NOT_REACHABLE", function () {
121932     return 26;
121933 });
121934 _self.__defineGetter__("CALL_ERROR_INCOMING_CALL_BARRED", function () {
121935     return 27;
121936 });
121937 _self.__defineGetter__("CALL_ERROR_CALL_REPLACED_BY_STK", function () {
121938     return 28;
121939 });
121940 _self.__defineGetter__("CALL_ERROR_STK_CALL_NOT_ALLOWED", function () {
121941     return 29;
121942 });
121943
121944 module.exports = _self;
121945
121946 });
121947 define('ripple/platform/webworks.handset/2.0.0/client/PhoneArguments', function (require, exports, module) {
121948 /*
121949  *  Copyright 2011 Research In Motion Limited.
121950  *
121951  * Licensed under the Apache License, Version 2.0 (the "License");
121952  * you may not use this file except in compliance with the License.
121953  * You may obtain a copy of the License at
121954  *
121955  * http://www.apache.org/licenses/LICENSE-2.0
121956  *
121957  * Unless required by applicable law or agreed to in writing, software
121958  * distributed under the License is distributed on an "AS IS" BASIS,
121959  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
121960  * See the License for the specific language governing permissions and
121961  * limitations under the License.
121962  */
121963 //blackberry.invoke.PhoneArguments ( [dialString : String ] ,  [smartDialing : Boolean ] ,  [lineId : Number ] )
121964 var _self = function (dialString, smartDialing, lineId) {
121965     return {
121966         dialString: dialString,
121967         smartDialing: smartDialing,
121968         lineId: (lineId ? lineId : -1),
121969         view: 0
121970     };
121971 };
121972
121973 //const Number  VIEW_NEW  = 0
121974 _self.__defineGetter__("VIEW_CALL", function () {
121975     return 0;
121976 });
121977 //const Number  VIEW_DEFAULT  = 1
121978 _self.__defineGetter__("VIEW_VOICEMAIL", function () {
121979     return 1;
121980 });
121981
121982 module.exports = _self;
121983
121984 });
121985 define('ripple/platform/webworks.handset/2.0.0/client/PhoneCall', function (require, exports, module) {
121986 /*
121987  *  Copyright 2011 Research In Motion Limited.
121988  *
121989  * Licensed under the Apache License, Version 2.0 (the "License");
121990  * you may not use this file except in compliance with the License.
121991  * You may obtain a copy of the License at
121992  *
121993  * http://www.apache.org/licenses/LICENSE-2.0
121994  *
121995  * Unless required by applicable law or agreed to in writing, software
121996  * distributed under the License is distributed on an "AS IS" BASIS,
121997  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
121998  * See the License for the specific language governing permissions and
121999  * limitations under the License.
122000  */
122001 function PhoneCall(onhold) {
122002     return {
122003         //Boolean   isOnHold ( )
122004         //readonly  property  Boolean   outgoing
122005         //readonly  property  String   recipientName
122006         //readonly  property  String   recipientNumber
122007
122008         outgoing: false,
122009         recipientName: null,
122010         recipientNumber: null,
122011
122012         isOnHold: function () {
122013             return onhold;
122014         }
122015     };
122016 }
122017
122018 module.exports = PhoneCall;
122019
122020 });
122021 define('ripple/platform/webworks.handset/2.0.0/client/PhoneLogs', function (require, exports, module) {
122022 /*
122023  *  Copyright 2011 Research In Motion Limited.
122024  *
122025  * Licensed under the Apache License, Version 2.0 (the "License");
122026  * you may not use this file except in compliance with the License.
122027  * You may obtain a copy of the License at
122028  *
122029  * http://www.apache.org/licenses/LICENSE-2.0
122030  *
122031  * Unless required by applicable law or agreed to in writing, software
122032  * distributed under the License is distributed on an "AS IS" BASIS,
122033  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
122034  * See the License for the specific language governing permissions and
122035  * limitations under the License.
122036  */
122037 var transport = require('ripple/platform/webworks.core/2.0.0/client/transport'),
122038     CallLog = require('ripple/platform/webworks.handset/2.0.0/client/CallLog'),
122039     utils = require('ripple/utils'),
122040     _onCallLog = {
122041         Added: null,
122042         Removed: null,
122043         Updated: null,
122044         Reset: null,
122045     },
122046     _uri = "blackberry/phone/logs/",
122047     _self;
122048
122049 function _massage(property, name) {
122050     if (name === "date" && property) {
122051         return new Date(property);
122052     }
122053     return property;
122054 }
122055
122056 function _toCallLog(log) {
122057     var callLog = new CallLog(),
122058         prop;
122059     for (prop in log) {
122060         if (log.hasOwnProperty(prop)) {
122061             callLog[prop] = _massage(log[prop], prop);
122062         }
122063     }
122064     return callLog;
122065 }
122066
122067 function handle(evt) {
122068     return function (response) {
122069         var func = _onCallLog[evt], args;
122070
122071         if (func) {
122072             args = utils.map(response, function (value) {
122073                 return _toCallLog(value);
122074             });
122075             func.apply(null, args);
122076         }
122077
122078         return !!func;
122079     };
122080 }
122081
122082 function poll(path) {
122083     transport.poll(_uri + path, {}, handle(path.replace("onCallLog", "")));
122084 }
122085
122086 _self = {
122087     addPhoneLogListener: function (onCallLogAdded, onCallLogRemoved, onCallLogUpdated, onCallLogReset) {
122088         _onCallLog.Added = onCallLogAdded;
122089         _onCallLog.Removed = onCallLogRemoved;
122090         _onCallLog.Updated = onCallLogUpdated;
122091         _onCallLog.Reset = onCallLogReset;
122092
122093         if (onCallLogAdded) {
122094             poll("onCallLogAdded");
122095         }
122096
122097         if (onCallLogRemoved) {
122098             poll("onCallLogRemoved");
122099         }
122100
122101         if (onCallLogUpdated) {
122102             poll("onCallLogUpdated");
122103         }
122104
122105         if (onCallLogReset) {
122106             poll("onCallLogReset");
122107         }
122108
122109         return !!(onCallLogAdded || onCallLogRemoved ||
122110                   onCallLogUpdated || onCallLogRemoved);
122111     },
122112
122113     callAt: function (index, folderID) {
122114         var log = transport.call(_uri + "callAt", {
122115             get: {
122116                 index: index,
122117                 folderID: folderID
122118             }
122119         });
122120
122121         if (log && log.date) {
122122             log.date = new Date(log.date);
122123         }
122124
122125         return log;
122126     },
122127
122128     deleteCallAt: function (index, folderID) {
122129         return transport.call(_uri + "deleteCallAt", {
122130             get: {
122131                 index: index,
122132                 folderID: folderID
122133             }
122134         });
122135     },
122136
122137     find: function (filter, folderID, orderBy, maxReturn, isAscending) {
122138         return transport.call(_uri + "find", {
122139             post: {
122140                 filter: filter,
122141                 folderID: folderID,
122142                 orderBy: orderBy,
122143                 maxReturn: maxReturn,
122144                 isAscending: isAscending
122145             }
122146         }).map(_toCallLog);
122147     },
122148
122149     numberOfCalls: function (folderID) {
122150         return transport.call(_uri + "numberOfCalls", {
122151             get: {
122152                 folderID: folderID
122153             }
122154         });
122155     }
122156 };
122157
122158 _self.__defineGetter__("FOLDER_MISSED_CALLS", function () {
122159     return 0;
122160 });
122161
122162 _self.__defineGetter__("FOLDER_NORMAL_CALLS", function () {
122163     return 1;
122164 });
122165
122166 module.exports = _self;
122167
122168 });
122169 define('ripple/platform/webworks.handset/2.0.0/client/PushData', function (require, exports, module) {
122170 /*
122171  *  Copyright 2011 Research In Motion Limited.
122172  *
122173  * Licensed under the Apache License, Version 2.0 (the "License");
122174  * you may not use this file except in compliance with the License.
122175  * You may obtain a copy of the License at
122176  *
122177  * http://www.apache.org/licenses/LICENSE-2.0
122178  *
122179  * Unless required by applicable law or agreed to in writing, software
122180  * distributed under the License is distributed on an "AS IS" BASIS,
122181  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
122182  * See the License for the specific language governing permissions and
122183  * limitations under the License.
122184  */
122185 function PushData(data, port) {
122186     this.port = port;
122187     this.data = data;
122188
122189     this.getHeaderField = function (field) {
122190         if (field === undefined || field === null) {
122191             throw "no field specified";
122192         }
122193         else if (!(typeof field === 'number' && field >= 0) && typeof field !== 'string') {
122194             throw "field is not valid";
122195         }
122196
122197         return data.headerField[field];
122198     };
122199
122200     this.getRequestURI =  function () {
122201         return data.requestURI;
122202     };
122203
122204     this.getSource = function () {
122205         return data.source;
122206     };
122207
122208     this.isChannelEncrypted = data.isChannelEncrypted;
122209
122210     this.payload = data.payload;
122211
122212     this.__defineGetter__("ACCEPT", function () {
122213         return 0;
122214     });
122215     this.__defineGetter__("DECLINE_USERDCR", function () {
122216         return 1;
122217     });
122218     this.__defineGetter__("DECLINE_USERDCU", function () {
122219         return 2;
122220     });
122221     this.__defineGetter__("DECLINE_USERPND", function () {
122222         return 3;
122223     });
122224     this.__defineGetter__("DECLINE_USERREQ", function () {
122225         return 4;
122226     });
122227     this.__defineGetter__("DECLINE_USERRFS", function () {
122228         return 5;
122229     });
122230 }
122231
122232 module.exports = PushData;
122233
122234 });
122235 define('ripple/platform/webworks.handset/2.0.0/client/Recurrence', function (require, exports, module) {
122236 /*
122237  *  Copyright 2011 Research In Motion Limited.
122238  *
122239  * Licensed under the Apache License, Version 2.0 (the "License");
122240  * you may not use this file except in compliance with the License.
122241  * You may obtain a copy of the License at
122242  *
122243  * http://www.apache.org/licenses/LICENSE-2.0
122244  *
122245  * Unless required by applicable law or agreed to in writing, software
122246  * distributed under the License is distributed on an "AS IS" BASIS,
122247  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
122248  * See the License for the specific language governing permissions and
122249  * limitations under the License.
122250  */
122251 function Recurrence() {
122252     return {
122253         //readwrite  property  Number   count
122254         //readwrite  property  Number   dayInMonth
122255         //readwrite  property  Number   dayInWeek
122256         //readwrite  property  Number   dayInYear
122257         //readwrite  property  Date   end
122258         //readwrite  property  Number   frequency
122259         //readwrite  property  Number   interval
122260         //readwrite  property  Number   monthInYear
122261         //readwrite  property  Number   weekInMonth
122262
122263         count: null,
122264         dayInMonth: null,
122265         dayInWeek: null,
122266         dayInYear: null,
122267         end: null,
122268         frequency: null,
122269         interval: null,
122270         monthInYear: null,
122271         weekInMonth: null
122272     };
122273 }
122274
122275 Recurrence.__defineGetter__("NO_REPEAT", function () {
122276     return 0;
122277 });
122278 Recurrence.__defineGetter__("DAILY", function () {
122279     return 1;
122280 });
122281 Recurrence.__defineGetter__("WEEKLY", function () {
122282     return 2;
122283 });
122284 Recurrence.__defineGetter__("MONTHLY", function () {
122285     return 3;
122286 });
122287 Recurrence.__defineGetter__("YEARLY", function () {
122288     return 4;
122289 });
122290 Recurrence.__defineGetter__("JANUARY", function () {
122291     return 0x20000;
122292 });
122293 Recurrence.__defineGetter__("FEBRUARY", function () {
122294     return 0x40000;
122295 });
122296 Recurrence.__defineGetter__("MARCH", function () {
122297     return 0x80000;
122298 });
122299 Recurrence.__defineGetter__("APRIL", function () {
122300     return 0x100000;
122301 });
122302 Recurrence.__defineGetter__("MAY", function () {
122303     return 0x200000;
122304 });
122305 Recurrence.__defineGetter__("JUNE", function () {
122306     return 0x400000;
122307 });
122308 Recurrence.__defineGetter__("JULY", function () {
122309     return 0x800000;
122310 });
122311 Recurrence.__defineGetter__("AUGUST", function () {
122312     return 0x1000000;
122313 });
122314 Recurrence.__defineGetter__("SEPTEMBER", function () {
122315     return 0x2000000;
122316 });
122317 Recurrence.__defineGetter__("OCTOBER", function () {
122318     return 0x4000000;
122319 });
122320 Recurrence.__defineGetter__("NOVEMBER", function () {
122321     return 0x8000000;
122322 });
122323 Recurrence.__defineGetter__("DECEMBER", function () {
122324     return 0x10000000;
122325 });
122326 Recurrence.__defineGetter__("FIRST", function () {
122327     return 0x1;
122328 });
122329 Recurrence.__defineGetter__("SECOND", function () {
122330     return 0x2;
122331 });
122332 Recurrence.__defineGetter__("THIRD", function () {
122333     return 0x4;
122334 });
122335 Recurrence.__defineGetter__("FOURTH", function () {
122336     return 0x8;
122337 });
122338 Recurrence.__defineGetter__("FIFTH", function () {
122339     return 0x10;
122340 });
122341 Recurrence.__defineGetter__("LAST", function () {
122342     return 0x20;
122343 });
122344 Recurrence.__defineGetter__("SECONDLAST", function () {
122345     return 0x40;
122346 });
122347 Recurrence.__defineGetter__("THIRDLAST", function () {
122348     return 0x80;
122349 });
122350 Recurrence.__defineGetter__("FOURTHLAST", function () {
122351     return 0x100;
122352 });
122353 Recurrence.__defineGetter__("FIFTHLAST", function () {
122354     return 0x200;
122355 });
122356 Recurrence.__defineGetter__("SUNDAY", function () {
122357     return 0x10000;
122358 });
122359 Recurrence.__defineGetter__("MONDAY", function () {
122360     return 0x8000;
122361 });
122362 Recurrence.__defineGetter__("TUESDAY", function () {
122363     return 0x4000;
122364 });
122365 Recurrence.__defineGetter__("WEDNESDAY", function () {
122366     return 0x2000;
122367 });
122368 Recurrence.__defineGetter__("THURSDAY", function () {
122369     return 0x1000;
122370 });
122371 Recurrence.__defineGetter__("FRIDAY", function () {
122372     return 0x800;
122373 });
122374 Recurrence.__defineGetter__("SATURDAY", function () {
122375     return 0x400;
122376 });
122377
122378 module.exports = Recurrence;
122379
122380 });
122381 define('ripple/platform/webworks.handset/2.0.0/client/Reminder', function (require, exports, module) {
122382 /*
122383  *  Copyright 2011 Research In Motion Limited.
122384  *
122385  * Licensed under the Apache License, Version 2.0 (the "License");
122386  * you may not use this file except in compliance with the License.
122387  * You may obtain a copy of the License at
122388  *
122389  * http://www.apache.org/licenses/LICENSE-2.0
122390  *
122391  * Unless required by applicable law or agreed to in writing, software
122392  * distributed under the License is distributed on an "AS IS" BASIS,
122393  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
122394  * See the License for the specific language governing permissions and
122395  * limitations under the License.
122396  */
122397 var Reminder = function () {
122398
122399     return {
122400         //readwrite  property  Date   date
122401         //readwrite  property  Number   relativeHours
122402         //readwrite  property  Number   type
122403
122404         date: null,
122405         relativeHours: null,
122406         type: null
122407
122408     };
122409
122410 };
122411
122412 Reminder.__defineGetter__("DATE", function () {
122413     return 0;
122414 });
122415
122416 Reminder.__defineGetter__("RELATIVE", function () {
122417     return 1;
122418 });
122419
122420 module.exports = Reminder;
122421
122422 });
122423 define('ripple/platform/webworks.handset/2.0.0/client/SearchArguments', function (require, exports, module) {
122424 /*
122425  *  Copyright 2011 Research In Motion Limited.
122426  *
122427  * Licensed under the Apache License, Version 2.0 (the "License");
122428  * you may not use this file except in compliance with the License.
122429  * You may obtain a copy of the License at
122430  *
122431  * http://www.apache.org/licenses/LICENSE-2.0
122432  *
122433  * Unless required by applicable law or agreed to in writing, software
122434  * distributed under the License is distributed on an "AS IS" BASIS,
122435  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
122436  * See the License for the specific language governing permissions and
122437  * limitations under the License.
122438  */
122439 //blackberry.invoke.SearchArguments ( )
122440 //blackberry.invoke.SearchArguments ( text : String ,  name : String )
122441 var _self = function (text, name) {
122442
122443     return {
122444         text: text,
122445         name: name
122446     };
122447
122448 };
122449
122450 module.exports = _self;
122451
122452 });
122453 define('ripple/platform/webworks.handset/2.0.0/client/Task', function (require, exports, module) {
122454 /*
122455  *  Copyright 2011 Research In Motion Limited.
122456  *
122457  * Licensed under the Apache License, Version 2.0 (the "License");
122458  * you may not use this file except in compliance with the License.
122459  * You may obtain a copy of the License at
122460  *
122461  * http://www.apache.org/licenses/LICENSE-2.0
122462  *
122463  * Unless required by applicable law or agreed to in writing, software
122464  * distributed under the License is distributed on an "AS IS" BASIS,
122465  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
122466  * See the License for the specific language governing permissions and
122467  * limitations under the License.
122468  */
122469 var transport = require('ripple/platform/webworks.core/2.0.0/client/transport'),
122470     _uri = "blackberry/pim/Task/";
122471
122472 function Task() {
122473     var _self = {
122474         save: function () {
122475             if (!_self.uid) {
122476                 _self.uid = Math.uuid(null, 16);
122477             }
122478             transport.call(_uri + "save",  {
122479                 post: {
122480                     task: _self
122481                 }
122482             });
122483         },
122484         remove: function () {
122485             if (!_self.uid) {
122486                 throw "task has not yet been saved (has no uid)";
122487             }
122488             transport.call(_uri + "remove", {
122489                 get: {
122490                     id: _self.uid
122491                 }
122492             });
122493         },
122494         uid: null,
122495         categories: [],
122496         due: null,
122497         note: "",
122498         priority: Task.PRIORITY_NORMAL,
122499         recurrence: null,
122500         reminder: null,
122501         status: Task.NOT_STARTED,
122502         summary: ""
122503     };
122504
122505     return _self;
122506 }
122507
122508 function _massage(property, name) {
122509     if (name === "recurrence" && property) {
122510         if (property.end) {
122511             property.end = new Date(property.end);
122512         }
122513     }
122514     if (name === "reminder" && property) {
122515         if (property.date) {
122516             property.date = new Date(property.date);
122517         }
122518     }
122519     if (name === "due" && property) {
122520         property = new Date(property);
122521     }
122522     return property;
122523 }
122524
122525 Task.find = function (filter, orderBy, maxReturn, isAscending) {
122526     return transport.call(_uri + "find", {
122527         post: {
122528             filter: filter,
122529             orderBy: orderBy,
122530             maxReturn: maxReturn,
122531             isAscending: isAscending
122532         }
122533     }).map(function (properties) {
122534         var task = new Task(),
122535             key;
122536         for (key in properties) {
122537             if (task.hasOwnProperty(key)) {
122538                 task[key] = _massage(properties[key], key);
122539             }
122540         }
122541         return task;
122542     });
122543 };
122544
122545 Task.__defineGetter__("NOT_STARTED", function () {
122546     return 0;
122547 });
122548
122549 Task.__defineGetter__("IN_PROGRESS", function () {
122550     return 1;
122551 });
122552
122553 Task.__defineGetter__("COMPLETED", function () {
122554     return 2;
122555 });
122556
122557 Task.__defineGetter__("WAITING", function () {
122558     return 3;
122559 });
122560
122561 Task.__defineGetter__("DEFERRED", function () {
122562     return 4;
122563 });
122564
122565 Task.__defineGetter__("PRIORITY_HIGH", function () {
122566     return 0;
122567 });
122568
122569 Task.__defineGetter__("PRIORITY_NORMAL", function () {
122570     return 1;
122571 });
122572
122573 Task.__defineGetter__("PRIORITY_LOW", function () {
122574     return 2;
122575 });
122576
122577 module.exports = Task;
122578
122579 });
122580 define('ripple/platform/webworks.handset/2.0.0/client/TaskArguments', function (require, exports, module) {
122581 /*
122582  *  Copyright 2011 Research In Motion Limited.
122583  *
122584  * Licensed under the Apache License, Version 2.0 (the "License");
122585  * you may not use this file except in compliance with the License.
122586  * You may obtain a copy of the License at
122587  *
122588  * http://www.apache.org/licenses/LICENSE-2.0
122589  *
122590  * Unless required by applicable law or agreed to in writing, software
122591  * distributed under the License is distributed on an "AS IS" BASIS,
122592  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
122593  * See the License for the specific language governing permissions and
122594  * limitations under the License.
122595  */
122596 //blackberry.invoke.TaskArguments ( [task : blackberry.pim.Task ] )
122597 var _self = function (task) {
122598     return {
122599         view: 0,
122600         task: task
122601     };
122602 };
122603
122604 //const Number  VIEW_NEW  = 0
122605 _self.__defineGetter__("VIEW_NEW", function () {
122606     return 0;
122607 });
122608 //const Number  VIEW_EDIT  = 1
122609 _self.__defineGetter__("VIEW_EDIT", function () {
122610     return 1;
122611 });
122612
122613 module.exports = _self;
122614
122615 });
122616 define('ripple/platform/webworks.handset/2.0.0/client/app', function (require, exports, module) {
122617 /*\r
122618  *  Copyright 2011 Research In Motion Limited.\r
122619  *\r
122620  * Licensed under the Apache License, Version 2.0 (the "License");\r
122621  * you may not use this file except in compliance with the License.\r
122622  * You may obtain a copy of the License at\r
122623  *\r
122624  * http://www.apache.org/licenses/LICENSE-2.0\r
122625  *\r
122626  * Unless required by applicable law or agreed to in writing, software\r
122627  * distributed under the License is distributed on an "AS IS" BASIS,\r
122628  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
122629  * See the License for the specific language governing permissions and\r
122630  * limitations under the License.\r
122631  */\r
122632 var transport = require('ripple/platform/webworks.core/2.0.0/client/transport'),\r
122633     _uri = "blackberry/app/",\r
122634     _self;\r
122635 \r
122636 _self = {\r
122637     exit: function () {\r
122638         transport.call(_uri + "exit", {async: true});\r
122639     },\r
122640 \r
122641     setHomeScreenIcon: function (uri, hover) {\r
122642         transport.call(_uri + "setHomeScreenIcon", {\r
122643             get: {\r
122644                 uri: uri,\r
122645                 hover: hover\r
122646             },\r
122647             async: true\r
122648         });\r
122649 \r
122650         return true;\r
122651     },\r
122652 \r
122653     setHomeScreenName: function (text) {\r
122654         transport.call(_uri + "setHomeScreenName", {\r
122655             get: {text: text},\r
122656             async: true\r
122657         });\r
122658 \r
122659         return true;\r
122660     },\r
122661 \r
122662     requestForeground: function () {\r
122663         transport.call(_uri + "requestForeground", {async: true});\r
122664     },\r
122665 \r
122666     requestBackground: function () {\r
122667         transport.call(_uri + "requestBackground", {async: true});\r
122668     },\r
122669 \r
122670     removeBannerIndicator: function () {\r
122671         transport.call(_uri + "removeBannerIndicator", {async: true});\r
122672     },\r
122673 \r
122674     showBannerIndicator: function (icon, count) {\r
122675         transport.call(_uri + "showBannerIndicator", {\r
122676             get: {\r
122677                 icon: icon,\r
122678                 count: count\r
122679             },\r
122680             async: true\r
122681         });\r
122682     },\r
122683 };\r
122684 \r
122685 _self.__defineGetter__("author", function () {\r
122686     return transport.call(_uri + "author");\r
122687 });\r
122688 \r
122689 _self.__defineGetter__("authorEmail", function () {\r
122690     return transport.call(_uri + "authorEmail");\r
122691 });\r
122692 \r
122693 _self.__defineGetter__("authorURL", function () {\r
122694     return transport.call(_uri + "authorURL");\r
122695 });\r
122696 \r
122697 _self.__defineGetter__("copyright", function () {\r
122698     return transport.call(_uri + "copyright");\r
122699 });\r
122700 \r
122701 _self.__defineGetter__("description", function () {\r
122702     return transport.call(_uri + "description");\r
122703 });\r
122704 \r
122705 _self.__defineGetter__("id", function () {\r
122706     return transport.call(_uri + "id");\r
122707 });\r
122708 \r
122709 _self.__defineGetter__("isForeground", function () {\r
122710     return transport.call(_uri + "isForeground");\r
122711 });\r
122712 \r
122713 _self.__defineGetter__("license", function () {\r
122714     return transport.call(_uri + "license");\r
122715 });\r
122716 \r
122717 _self.__defineGetter__("licenseURL", function () {\r
122718     return transport.call(_uri + "licenseURL");\r
122719 });\r
122720 \r
122721 _self.__defineGetter__("name", function () {\r
122722     return transport.call(_uri + "name");\r
122723 });\r
122724 \r
122725 _self.__defineGetter__("version", function () {\r
122726     return transport.call(_uri + "version");\r
122727 });\r
122728 \r
122729 module.exports = _self;\r
122730
122731 });
122732 define('ripple/platform/webworks.handset/2.0.0/client/appEvent', function (require, exports, module) {
122733 /*
122734  *  Copyright 2011 Research In Motion Limited.
122735  *
122736  * Licensed under the Apache License, Version 2.0 (the "License");
122737  * you may not use this file except in compliance with the License.
122738  * You may obtain a copy of the License at
122739  *
122740  * http://www.apache.org/licenses/LICENSE-2.0
122741  *
122742  * Unless required by applicable law or agreed to in writing, software
122743  * distributed under the License is distributed on an "AS IS" BASIS,
122744  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
122745  * See the License for the specific language governing permissions and
122746  * limitations under the License.
122747  */
122748 var transport = require('ripple/platform/webworks.core/2.0.0/client/transport'),
122749     _callbacks = {},
122750     _self;
122751
122752 function _poll(evt, handler) {
122753     _callbacks[evt] = handler;
122754
122755     transport.poll("blackberry/app/event/" + evt, {}, function () {
122756         var func = _callbacks[evt];
122757
122758         if (func) {
122759             func();
122760         }
122761
122762         return !!func;
122763     });
122764 }
122765
122766 _self = {
122767     onBackground: function (handler) {
122768         _poll("onBackground", handler);
122769     },
122770
122771     onForeground: function (handler) {
122772         _poll("onForeground", handler);
122773     },
122774
122775     onExit: function (handler) {
122776         _poll("onExit", handler);
122777     }
122778 };
122779
122780 module.exports = _self;
122781
122782 });
122783 define('ripple/platform/webworks.handset/2.0.0/client/audio', function (require, exports, module) {
122784 /*
122785  *  Copyright 2011 Research In Motion Limited.
122786  *
122787  * Licensed under the Apache License, Version 2.0 (the "License");
122788  * you may not use this file except in compliance with the License.
122789  * You may obtain a copy of the License at
122790  *
122791  * http://www.apache.org/licenses/LICENSE-2.0
122792  *
122793  * Unless required by applicable law or agreed to in writing, software
122794  * distributed under the License is distributed on an "AS IS" BASIS,
122795  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
122796  * See the License for the specific language governing permissions and
122797  * limitations under the License.
122798  */
122799 module.exports = {
122800     supportedContentTypes: function (protocol) {
122801         return protocol === 'rtsp' ?
122802             ['audio/amr', 'audio/mp4', 'audio/aac'] :
122803             ['audio/midi', 'mpeg', 'x-wav', 'amr', 'basic', 'x-gsm', 'mp4', 'aac', 'x-ms-wma', 'flac', 'ogg'];
122804     },
122805     supportedProtocols: function (contentType) {
122806         return ['http', 'file', 'rtsp'];
122807     }
122808 };
122809
122810 });
122811 define('ripple/platform/webworks.handset/2.0.0/client/blackberry', function (require, exports, module) {
122812 /*
122813  * Copyright 2011 Research In Motion Limited.
122814  *
122815  * Licensed under the Apache License, Version 2.0 (the "License");
122816  * you may not use this file except in compliance with the License.
122817  * You may obtain a copy of the License at
122818  *
122819  *     http://www.apache.org/licenses/LICENSE-2.0
122820  *
122821  * Unless required by applicable law or agreed to in writing, software
122822  * distributed under the License is distributed on an "AS IS" BASIS,
122823  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
122824  * See the License for the specific language governing permissions and
122825  * limitations under the License.
122826  */
122827 var blackberry = {},
122828     transport = require('ripple/platform/webworks.core/2.0.0/client/transport');
122829
122830 blackberry.__defineGetter__("network", function () {
122831     return transport.call("blackberry/system/network");
122832 });
122833
122834 module.exports = blackberry;
122835
122836 });
122837 define('ripple/platform/webworks.handset/2.0.0/client/category', function (require, exports, module) {
122838 /*
122839  *  Copyright 2011 Research In Motion Limited.
122840  *
122841  * Licensed under the Apache License, Version 2.0 (the "License");
122842  * you may not use this file except in compliance with the License.
122843  * You may obtain a copy of the License at
122844  *
122845  * http://www.apache.org/licenses/LICENSE-2.0
122846  *
122847  * Unless required by applicable law or agreed to in writing, software
122848  * distributed under the License is distributed on an "AS IS" BASIS,
122849  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
122850  * See the License for the specific language governing permissions and
122851  * limitations under the License.
122852  */
122853 var transport = require('ripple/platform/webworks.core/2.0.0/client/transport'),
122854     _uri = "blackberry/pim/category/",
122855     _self;
122856
122857 _self = {
122858     addCategory: function (categoryName) {
122859         transport.call(_uri + "addCategory", {
122860             get: {categoryName: categoryName}
122861         });
122862     },
122863     deleteCategory: function (categoryName) {
122864         transport.call(_uri + "deleteCategory", {
122865             get: {categoryName: categoryName}
122866         });
122867     },
122868     getCategories: function () {
122869         return transport.call(_uri + "getCategories");
122870     }
122871 };
122872
122873 module.exports = _self;
122874
122875 });
122876 define('ripple/platform/webworks.handset/2.0.0/client/identity/Service', function (require, exports, module) {
122877 /*
122878  *  Copyright 2011 Research In Motion Limited.
122879  *
122880  * Licensed under the Apache License, Version 2.0 (the "License");
122881  * you may not use this file except in compliance with the License.
122882  * You may obtain a copy of the License at
122883  *
122884  * http://www.apache.org/licenses/LICENSE-2.0
122885  *
122886  * Unless required by applicable law or agreed to in writing, software
122887  * distributed under the License is distributed on an "AS IS" BASIS,
122888  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
122889  * See the License for the specific language governing permissions and
122890  * limitations under the License.
122891  */
122892 function Service() {
122893     return {
122894         emailAddress: null,
122895         isDefault: null,
122896         name: null,
122897         type: null
122898     };
122899 }
122900
122901 Service.__defineGetter__("TYPE_EMAIL", function () {
122902     return 0;
122903 });
122904
122905 Service.__defineGetter__("TYPE_CALENDAR", function () {
122906     return 1;
122907 });
122908
122909 Service.__defineGetter__("TYPE_CONTACT", function () {
122910     return 2;
122911 });
122912
122913 module.exports = Service;
122914
122915 });
122916 define('ripple/platform/webworks.handset/2.0.0/client/identity/Transport', function (require, exports, module) {
122917 /*
122918  *  Copyright 2011 Research In Motion Limited.
122919  *
122920  * Licensed under the Apache License, Version 2.0 (the "License");
122921  * you may not use this file except in compliance with the License.
122922  * You may obtain a copy of the License at
122923  *
122924  * http://www.apache.org/licenses/LICENSE-2.0
122925  *
122926  * Unless required by applicable law or agreed to in writing, software
122927  * distributed under the License is distributed on an "AS IS" BASIS,
122928  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
122929  * See the License for the specific language governing permissions and
122930  * limitations under the License.
122931  */
122932 function Transport(name, type) {
122933     this.__defineGetter__("name", function () {
122934         return name || "";
122935     });
122936     this.__defineGetter__("type", function () {
122937         return type || "";
122938     });
122939 }
122940
122941 module.exports = Transport;
122942
122943 });
122944 define('ripple/platform/webworks.handset/2.0.0/client/identity/phone', function (require, exports, module) {
122945 /*
122946  *  Copyright 2011 Research In Motion Limited.
122947  *
122948  * Licensed under the Apache License, Version 2.0 (the "License");
122949  * you may not use this file except in compliance with the License.
122950  * You may obtain a copy of the License at
122951  *
122952  * http://www.apache.org/licenses/LICENSE-2.0
122953  *
122954  * Unless required by applicable law or agreed to in writing, software
122955  * distributed under the License is distributed on an "AS IS" BASIS,
122956  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
122957  * See the License for the specific language governing permissions and
122958  * limitations under the License.
122959  */
122960 var transport = require('ripple/platform/webworks.core/2.0.0/client/transport'),
122961     _uri = "blackberry/identity/phone/",
122962     _self;
122963
122964 _self = {
122965     getLineIds: function () {
122966         return transport.call(_uri + "getLineIds");
122967     },
122968     getLineLabel: function (id) {
122969         return transport.call(_uri + "getLineLabel", {get: {id: id}});
122970     },
122971     getLineNumber: function (id) {
122972         return transport.call(_uri + "getLineNumber", {get: {id: id}});
122973     },
122974     getLineType: function (id) {
122975         return transport.call(_uri + "getLineType", {get: {id: id}});
122976     }
122977 };
122978
122979 module.exports = _self;
122980
122981 });
122982 define('ripple/platform/webworks.handset/2.0.0/client/identity', function (require, exports, module) {
122983 /*
122984  *  Copyright 2011 Research In Motion Limited.
122985  *
122986  * Licensed under the Apache License, Version 2.0 (the "License");
122987  * you may not use this file except in compliance with the License.
122988  * You may obtain a copy of the License at
122989  *
122990  * http://www.apache.org/licenses/LICENSE-2.0
122991  *
122992  * Unless required by applicable law or agreed to in writing, software
122993  * distributed under the License is distributed on an "AS IS" BASIS,
122994  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
122995  * See the License for the specific language governing permissions and
122996  * limitations under the License.
122997  */
122998 var transport = require('ripple/platform/webworks.core/2.0.0/client/transport'),
122999     _uri = "blackberry/identity/",
123000     _self;
123001
123002 _self = {
123003     getDefaultService: function () {
123004         return transport.call(_uri + "getDefaultService");
123005     },
123006     getServiceList: function () {
123007         return transport.call(_uri + "getServiceList");
123008     },
123009     getTransportList: function () {
123010         return transport.call(_uri + "getTransportList");
123011     }
123012 };
123013
123014 _self.__defineGetter__("IMEI", function () {
123015     return transport.call(_uri + "IMEI");
123016 });
123017
123018 _self.__defineGetter__("IMSI", function () {
123019     return transport.call(_uri + "IMSI");
123020 });
123021
123022 _self.__defineGetter__("PIN", function () {
123023     return transport.call(_uri + "PIN");
123024 });
123025
123026 module.exports = _self;
123027
123028 });
123029 define('ripple/platform/webworks.handset/2.0.0/client/invoke', function (require, exports, module) {
123030 /*\r
123031  *  Copyright 2011 Research In Motion Limited.\r
123032  *\r
123033  * Licensed under the Apache License, Version 2.0 (the "License");\r
123034  * you may not use this file except in compliance with the License.\r
123035  * You may obtain a copy of the License at\r
123036  *\r
123037  * http://www.apache.org/licenses/LICENSE-2.0\r
123038  *\r
123039  * Unless required by applicable law or agreed to in writing, software\r
123040  * distributed under the License is distributed on an "AS IS" BASIS,\r
123041  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
123042  * See the License for the specific language governing permissions and\r
123043  * limitations under the License.\r
123044  */\r
123045 var _uri = "blackberry/invoke/invoke",\r
123046     APP_URL_CAMERA = "camera://",\r
123047     APP_URL_CAMERA_VIDEO = "camera://video",\r
123048     APP_URL_MAP = "map://",\r
123049     APP_URL_MUSIC = "music://",\r
123050     APP_URL_PHOTOS = "photos://",\r
123051     APP_URL_VIDEOS = "videos://",\r
123052     APP_URL_APPWORLD = "appworld://",\r
123053     APP_URL_UPDATE = "update://",\r
123054     APP_BROWSER_ERROR = "Protocol specified in the url is not supported.",\r
123055     APP_ADDRESSBOOK_ERROR = "Invalid arguments specified",\r
123056     transport = require('ripple/platform/webworks.core/2.0.0/client/transport'),\r
123057     _self;\r
123058 \r
123059 _self = {\r
123060     invoke: function (appType, args) {\r
123061         var get = {};\r
123062 \r
123063         switch (appType) {\r
123064 \r
123065         //AddressBook\r
123066         case 0:\r
123067             if (args) {\r
123068                 if (args.view === 1 && args.contact) {\r
123069                     throw APP_ADDRESSBOOK_ERROR; //contact cannot be used with this view\r
123070                 }\r
123071                 else if (args.view === 2 && !args.contact) {\r
123072                     throw APP_ADDRESSBOOK_ERROR; //need contact for this view\r
123073                 }\r
123074             }\r
123075 \r
123076             get.appType = appType;\r
123077             break;\r
123078 \r
123079         //Bluetooth Config\r
123080         case 1:\r
123081             get.appType = appType;\r
123082             break;\r
123083 \r
123084         //Calculator\r
123085         case 2:\r
123086             get.appType = appType;\r
123087             break;\r
123088 \r
123089         //Calendar\r
123090         case 3:\r
123091             get.appType = appType;\r
123092             break;\r
123093 \r
123094         //Camera\r
123095         case 4:\r
123096             if (!args || args.view === 1) {\r
123097                 get.appType = APP_URL_CAMERA_VIDEO;\r
123098             } else {\r
123099                 get.appType = APP_URL_CAMERA;\r
123100             }\r
123101             break;\r
123102 \r
123103         //Maps\r
123104         case 5:\r
123105             get.appType = APP_URL_MAP;\r
123106             break;\r
123107 \r
123108         //Memopad\r
123109         case 6:\r
123110             get.appType = appType;\r
123111             break;\r
123112 \r
123113         //Messages\r
123114         case 7:\r
123115             get.appType = appType;\r
123116             break;\r
123117 \r
123118         //Phone\r
123119         case 8:\r
123120             get.appType = appType;\r
123121             break;\r
123122 \r
123123         //Search\r
123124         case 9:\r
123125             get.appType = appType;\r
123126             break;\r
123127 \r
123128         //Tasks\r
123129         case 10:\r
123130             get.appType = appType;\r
123131             break;\r
123132 \r
123133         //Browser\r
123134         case 11:\r
123135 \r
123136             if (!args) {\r
123137                 get.appType = "http://";\r
123138             } else {\r
123139                 if (args.url && !args.url.match(/^https?:\/\//)) {\r
123140                     throw APP_BROWSER_ERROR;\r
123141                 }\r
123142                 get.appType = args.url;\r
123143             }\r
123144 \r
123145             break;\r
123146 \r
123147         //Java\r
123148         case 12:\r
123149             get.appType = appType;\r
123150             break;\r
123151 \r
123152         default:\r
123153             throw "appType not supported";\r
123154         }\r
123155 \r
123156         transport.call(_uri, {\r
123157             get: get,\r
123158             async: true\r
123159         });\r
123160     }\r
123161 };\r
123162 \r
123163 _self.__defineGetter__("APP_ADDRESSBOOK", function () {\r
123164     return 0;\r
123165 });\r
123166 _self.__defineGetter__("APP_BLUETOOTH_CONFIG", function () {\r
123167     return 1;\r
123168 });\r
123169 _self.__defineGetter__("APP_CALCULATOR", function () {\r
123170     return 2;\r
123171 });\r
123172 _self.__defineGetter__("APP_CALENDAR", function () {\r
123173     return 3;\r
123174 });\r
123175 _self.__defineGetter__("APP_CAMERA", function () {\r
123176     return 4;\r
123177 });\r
123178 _self.__defineGetter__("APP_MAPS", function () {\r
123179     return 5;\r
123180 });\r
123181 _self.__defineGetter__("APP_MEMOPAD", function () {\r
123182     return 6;\r
123183 });\r
123184 _self.__defineGetter__("APP_MESSAGES", function () {\r
123185     return 7;\r
123186 });\r
123187 _self.__defineGetter__("APP_PHONE", function () {\r
123188     return 8;\r
123189 });\r
123190 _self.__defineGetter__("APP_SEARCH", function () {\r
123191     return 9;\r
123192 });\r
123193 _self.__defineGetter__("APP_TASKS", function () {\r
123194     return 10;\r
123195 });\r
123196 _self.__defineGetter__("APP_BROWSER", function () {\r
123197     return 11;\r
123198 });\r
123199 _self.__defineGetter__("APP_JAVA", function () {\r
123200     return 12;\r
123201 });\r
123202 \r
123203 module.exports = _self;\r
123204
123205 });
123206 define('ripple/platform/webworks.handset/2.0.0/client/io/dir', function (require, exports, module) {
123207 /*
123208  * Copyright 2011 Research In Motion Limited.
123209  *
123210  * Licensed under the Apache License, Version 2.0 (the "License");
123211  * you may not use this file except in compliance with the License.
123212  * You may obtain a copy of the License at
123213  *
123214  *     http://www.apache.org/licenses/LICENSE-2.0
123215  *
123216  * Unless required by applicable law or agreed to in writing, software
123217  * distributed under the License is distributed on an "AS IS" BASIS,
123218  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
123219  * See the License for the specific language governing permissions and
123220  * limitations under the License.
123221  */
123222 var transport = require('ripple/platform/webworks.core/2.0.0/client/transport'),
123223     dir = require('ripple/platform/webworks.core/2.0.0/client/io/dir'),
123224     utils = require('ripple/utils'),
123225     _uri = "blackberry/io/dir/",
123226     FILE = "file://",
123227     _self = {};
123228
123229 function _prunePrefix(path) {
123230     return path.replace(new RegExp("^" + FILE), '');
123231 }
123232
123233 utils.mixin({
123234     getFreeSpaceForRoot: function (path) {
123235         return transport.call(_uri + "getFreeSpaceForRoot", {
123236             post: {path: _prunePrefix(path)}
123237         });
123238     },
123239     getRootDirs: function () {
123240         return transport.call(_uri + "getRootDirs", {}).map(function (dir) {
123241             return FILE + dir;
123242         });
123243     }
123244 }, _self);
123245
123246 utils.mixin(dir, _self);
123247
123248 module.exports = _self;
123249
123250 });
123251 define('ripple/platform/webworks.handset/2.0.0/client/menu', function (require, exports, module) {
123252 /*
123253  *  Copyright 2011 Research In Motion Limited.
123254  *
123255  * Licensed under the Apache License, Version 2.0 (the "License");
123256  * you may not use this file except in compliance with the License.
123257  * You may obtain a copy of the License at
123258  *
123259  * http://www.apache.org/licenses/LICENSE-2.0
123260  *
123261  * Unless required by applicable law or agreed to in writing, software
123262  * distributed under the License is distributed on an "AS IS" BASIS,
123263  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
123264  * See the License for the specific language governing permissions and
123265  * limitations under the License.
123266  */
123267 var transport = require('ripple/platform/webworks.core/2.0.0/client/transport'),
123268     MenuItem = require('ripple/platform/webworks.handset/2.0.0/client/MenuItem'),
123269     utils = require('ripple/utils'),
123270     onSelect,
123271     _items = {},
123272     _uri = "blackberry/ui/menu/",
123273     _self;
123274
123275 _self = {
123276     addMenuItem: function (menuItem) {
123277         _items[menuItem.id] = menuItem;
123278
123279         transport.call(_uri + "addMenuItem", {
123280             get: {"item": menuItem}
123281         });
123282
123283         if (utils.count(_items) === 1) {
123284             transport.poll(_uri + "onSelect", {}, function (response) {
123285                 var item = _items[response];
123286
123287                 if (item && item.callback) {
123288                     item.callback();
123289                 }
123290
123291                 return !!utils.count(_items);
123292             });
123293         }
123294     },
123295
123296     clearMenuItems: function () {
123297         _items = {};
123298         transport.call(_uri + "clearMenuItems");
123299     },
123300
123301     getMenuItems: function () {
123302         return utils.map(_items, function (item) {
123303             var menuItem = new MenuItem(item.isSeparator, item.ordinal, item.caption, item.callback);
123304             menuItem.id = item.id;
123305             menuItem.isDefault = item.isDefault;
123306             return menuItem;
123307         });
123308     },
123309
123310     hasMenuItem: function (menuItem) {
123311         return !!_items[menuItem.id];
123312     },
123313
123314     open: function () {
123315         transport.call(_uri + "open", {async: true});
123316     },
123317
123318     removeMenuItem: function (menuItem) {
123319         delete _items[menuItem.id];
123320         transport.call(_uri + "removeMenuItem", {
123321             get: {item: menuItem}
123322         });
123323     },
123324
123325     setDefaultMenuItem: function (menuItem) {
123326         utils.forEach(_items, function (item) {
123327             item.isDefault = false;
123328         });
123329
123330         _items[menuItem.id].isDefault = true;
123331
123332         transport.call(_uri + "setDefaultMenuItem", {
123333             get: {id: menuItem.id}
123334         });
123335     }
123336 };
123337
123338 module.exports = _self;
123339
123340 });
123341 define('ripple/platform/webworks.handset/2.0.0/client/messaging', function (require, exports, module) {
123342 /*
123343  *  Copyright 2011 Research In Motion Limited.
123344  *
123345  * Licensed under the Apache License, Version 2.0 (the "License");
123346  * you may not use this file except in compliance with the License.
123347  * You may obtain a copy of the License at
123348  *
123349  * http://www.apache.org/licenses/LICENSE-2.0
123350  *
123351  * Unless required by applicable law or agreed to in writing, software
123352  * distributed under the License is distributed on an "AS IS" BASIS,
123353  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
123354  * See the License for the specific language governing permissions and
123355  * limitations under the License.
123356  */
123357 module.exports = {};
123358
123359 });
123360 define('ripple/platform/webworks.handset/2.0.0/client/pim', function (require, exports, module) {
123361 /*
123362  *  Copyright 2011 Research In Motion Limited.
123363  *
123364  * Licensed under the Apache License, Version 2.0 (the "License");
123365  * you may not use this file except in compliance with the License.
123366  * You may obtain a copy of the License at
123367  *
123368  * http://www.apache.org/licenses/LICENSE-2.0
123369  *
123370  * Unless required by applicable law or agreed to in writing, software
123371  * distributed under the License is distributed on an "AS IS" BASIS,
123372  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
123373  * See the License for the specific language governing permissions and
123374  * limitations under the License.
123375  */
123376 module.exports = {};
123377
123378 });
123379 define('ripple/platform/webworks.handset/2.0.0/client/push', function (require, exports, module) {
123380 /*
123381  *  Copyright 2011 Research In Motion Limited.
123382  *
123383  * Licensed under the Apache License, Version 2.0 (the "License");
123384  * you may not use this file except in compliance with the License.
123385  * You may obtain a copy of the License at
123386  *
123387  * http://www.apache.org/licenses/LICENSE-2.0
123388  *
123389  * Unless required by applicable law or agreed to in writing, software
123390  * distributed under the License is distributed on an "AS IS" BASIS,
123391  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
123392  * See the License for the specific language governing permissions and
123393  * limitations under the License.
123394  */
123395 var transport = require('ripple/platform/webworks.core/2.0.0/client/transport'),
123396     _self,
123397     _uri = "blackberry/push/onPush",
123398     callbacks = {},
123399     PushData = require('ripple/platform/webworks.handset/2.0.0/client/PushData');
123400
123401 _self = {
123402     openPushListener: function (callback, port, bbTransport, maxQueueCap) {
123403         callbacks["onPush" + port] = callback;
123404
123405         transport.poll(_uri, {
123406             get: {
123407                 port: port,
123408                 bbTransport: bbTransport,
123409                 maxQueueCap: maxQueueCap
123410             }
123411         }, function (response) {
123412             var func = callbacks["onPush" + port];
123413
123414             if (func) {
123415                 func(new PushData(response, port));
123416             }
123417
123418             return !!func;
123419         });
123420     },
123421
123422     closePushListener: function (port) {
123423         delete callbacks["onPush" + port];
123424     }
123425 };
123426
123427 module.exports = _self;
123428
123429 });
123430 define('ripple/platform/webworks.handset/2.0.0/client/sms', function (require, exports, module) {
123431 /*
123432  *  Copyright 2011 Research In Motion Limited.
123433  *
123434  * Licensed under the Apache License, Version 2.0 (the "License");
123435  * you may not use this file except in compliance with the License.
123436  * You may obtain a copy of the License at
123437  *
123438  * http://www.apache.org/licenses/LICENSE-2.0
123439  *
123440  * Unless required by applicable law or agreed to in writing, software
123441  * distributed under the License is distributed on an "AS IS" BASIS,
123442  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
123443  * See the License for the specific language governing permissions and
123444  * limitations under the License.
123445  */
123446 var transport = require('ripple/platform/webworks.core/2.0.0/client/transport'),
123447     _uri = "blackberry/message/sms/",
123448     onReceive,
123449     _self;
123450
123451 _self = {
123452     addReceiveListener: function (callback) {
123453         onReceive = callback;
123454         transport.poll(_uri + "onReceive", {}, function (response) {
123455             if (onReceive) {
123456                 onReceive(response.body, response.from, response.time);
123457             }
123458             return !!onReceive;
123459         });
123460     },
123461
123462     removeReceiveListener: function () {
123463         if (onReceive) {
123464             onReceive = null;
123465             return true;
123466         }
123467
123468         return false;
123469     },
123470
123471     send: function (message, address) {
123472         transport.call(_uri + "send", {
123473             get: {
123474                 message: message,
123475                 address: address
123476             },
123477             async: true
123478         });
123479     }
123480 };
123481
123482 _self.__defineGetter__("isListeningForMessage", function () {
123483     return transport.call(_uri + "isListeningForMessage", {async: false});
123484 });
123485
123486 _self.__defineSetter__("isListeningForMessage", function (value) {
123487     transport.call(_uri + "isListeningForMessage", {
123488         async: false,
123489         get: {isListeningForMessage: value}
123490     });
123491 });
123492
123493 module.exports = _self;
123494
123495 });
123496 define('ripple/platform/webworks.handset/2.0.0/client/system', function (require, exports, module) {
123497 /*
123498  *  Copyright 2011 Research In Motion Limited.
123499  *
123500  * Licensed under the Apache License, Version 2.0 (the "License");
123501  * you may not use this file except in compliance with the License.
123502  * You may obtain a copy of the License at
123503  *
123504  * http://www.apache.org/licenses/LICENSE-2.0
123505  *
123506  * Unless required by applicable law or agreed to in writing, software
123507  * distributed under the License is distributed on an "AS IS" BASIS,
123508  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
123509  * See the License for the specific language governing permissions and
123510  * limitations under the License.
123511  */
123512 var utils = require('ripple/utils'),
123513     transport = require('ripple/platform/webworks.core/2.0.0/client/transport'),
123514     system = require('ripple/platform/webworks.core/2.0.0/client/system'),
123515     _uri = "blackberry/system/",
123516     _self;
123517
123518 _self = {
123519     setHomeScreenBackground: function (filePath) {
123520         transport.call(_uri + "setHomeScreenBackground", {
123521             get: {filePath: filePath},
123522             async: true
123523         });
123524     },
123525 };
123526
123527 (function () {
123528     // HACK: can't type check if system[key] is a function, sets off getters
123529     // also can't use utils.mixin or forEach for the same reason
123530     function get(i) {
123531         return function () {
123532             return system[i];
123533         };
123534     }
123535
123536     for (var key in system) {
123537         if (system.hasOwnProperty(key)) {
123538             _self.__defineGetter__(key, get(key));
123539         }
123540     }
123541 }());
123542
123543 module.exports = _self;
123544
123545 });
123546 define('ripple/platform/webworks.handset/2.0.0/client/systemEvent', function (require, exports, module) {
123547 /*
123548  *  Copyright 2011 Research In Motion Limited.
123549  *
123550  * Licensed under the Apache License, Version 2.0 (the "License");
123551  * you may not use this file except in compliance with the License.
123552  * You may obtain a copy of the License at
123553  *
123554  * http://www.apache.org/licenses/LICENSE-2.0
123555  *
123556  * Unless required by applicable law or agreed to in writing, software
123557  * distributed under the License is distributed on an "AS IS" BASIS,
123558  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
123559  * See the License for the specific language governing permissions and
123560  * limitations under the License.
123561  */
123562 var transport = require('ripple/platform/webworks.core/2.0.0/client/transport'),
123563     utils = require('ripple/utils'),
123564     _self,
123565         _callbacks = {};
123566
123567 function _poll(evt, args, callback) {
123568     _callbacks[evt + args.key] = callback;
123569
123570     transport.poll("blackberry/system/event/" + evt, {get: args}, function () {
123571         var func = _callbacks[evt + args.key];
123572
123573         if (func) {
123574             func();
123575         }
123576
123577         return !!func;
123578     });
123579 }
123580
123581 _self = {
123582     onCoverageChange: function (callback) {
123583         _poll("onCoverageChange", {}, callback);
123584     },
123585
123586     onHardwareKey: function (key, callback) {
123587         _poll("onHardwareKey", {key: key}, callback);
123588     }
123589 };
123590
123591 _self.__defineGetter__("KEY_BACK", function () {
123592     return 0;
123593 });
123594 _self.__defineGetter__("KEY_MENU", function () {
123595     return 1;
123596 });
123597 _self.__defineGetter__("KEY_CONVENIENCE_1", function () {
123598     return 2;
123599 });
123600 _self.__defineGetter__("KEY_CONVENIENCE_2", function () {
123601     return 3;
123602 });
123603 _self.__defineGetter__("KEY_STARTCALL", function () {
123604     return 4;
123605 });
123606 _self.__defineGetter__("KEY_ENDCALL", function () {
123607     return 5;
123608 });
123609 _self.__defineGetter__("KEY_VOLUMEDOWN", function () {
123610     return 6;
123611 });
123612 _self.__defineGetter__("KEY_VOLUMEUP", function () {
123613     return 7;
123614 });
123615
123616 module.exports = _self;
123617
123618 });
123619 define('ripple/platform/webworks.handset/2.0.0/server/Task', function (require, exports, module) {
123620 /*
123621  *  Copyright 2011 Research In Motion Limited.
123622  *
123623  * Licensed under the Apache License, Version 2.0 (the "License");
123624  * you may not use this file except in compliance with the License.
123625  * You may obtain a copy of the License at
123626  *
123627  * http://www.apache.org/licenses/LICENSE-2.0
123628  *
123629  * Unless required by applicable law or agreed to in writing, software
123630  * distributed under the License is distributed on an "AS IS" BASIS,
123631  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
123632  * See the License for the specific language governing permissions and
123633  * limitations under the License.
123634  */
123635 var select = require('ripple/platform/webworks.core/2.0.0/select'),
123636     db = require('ripple/db'),
123637     utils = require('ripple/utils'),
123638     _KEY = "blackberry-pim-task",
123639     _self;
123640
123641 function _get() {
123642     return db.retrieveObject(_KEY) || {};
123643 }
123644
123645 function _save(tasks) {
123646     db.saveObject(_KEY, tasks);
123647 }
123648
123649 _self = {
123650     save: function (get, post) {
123651         var tasks = _get(),
123652             properties = post.task,
123653             id = properties.uid;
123654
123655         if (tasks[id]) {
123656             utils.mixin(properties, tasks[id]);
123657         } else {
123658             tasks[id] = properties;
123659         }
123660
123661         _save(tasks);
123662
123663         return {code: 1};
123664     },
123665
123666     remove: function (get, post) {
123667         var tasks = _get(),
123668             id = get.id;
123669
123670         delete tasks[id];
123671
123672         _save(tasks);
123673
123674         return {code: 1};
123675     },
123676
123677     find: function (get, post) {
123678         var tasks = _get(),
123679             match = select.from(tasks);
123680
123681         if (post.orderBy) {
123682             match.orderBy(post.orderBy, post.isAscending === false ? "desc" : "asc");
123683         }
123684
123685         if (post.maxReturn) {
123686             match.max(post.maxReturn);
123687         }
123688
123689         return {code: 1, data: match.where(post.filter)};
123690     }
123691 };
123692
123693 module.exports = _self;
123694
123695 });
123696 define('ripple/platform/webworks.handset/2.0.0/server/app', function (require, exports, module) {
123697 /*
123698  *  Copyright 2011 Research In Motion Limited.
123699  *
123700  * Licensed under the Apache License, Version 2.0 (the "License");
123701  * you may not use this file except in compliance with the License.
123702  * You may obtain a copy of the License at
123703  *
123704  * http://www.apache.org/licenses/LICENSE-2.0
123705  *
123706  * Unless required by applicable law or agreed to in writing, software
123707  * distributed under the License is distributed on an "AS IS" BASIS,
123708  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
123709  * See the License for the specific language governing permissions and
123710  * limitations under the License.
123711  */
123712 var event = require('ripple/event'),
123713     app = require('ripple/app'),
123714     notifications = require('ripple/notifications'),
123715     constants = require('ripple/constants'),
123716     ui = require('ripple/ui'),
123717     _isForeground = true,
123718     _self;
123719
123720 _self = {
123721     event: require('ripple/platform/webworks.handset/2.0.0/server/appEvent'),
123722
123723     exit: function () {
123724         event.trigger("AppExit");
123725         return {code: 1};
123726     },
123727
123728     author: function () {
123729         return {code: 1, data: app.getInfo().author};
123730     },
123731
123732     authorEmail: function () {
123733         return {code: 1, data: app.getInfo().authorEmail};
123734     },
123735
123736     authorURL: function () {
123737         return {code: 1, data: app.getInfo().authorURL};
123738     },
123739
123740     copyright: function () {
123741         return {code: 1, data: app.getInfo().copyright};
123742     },
123743
123744     description: function () {
123745         return {code: 1, data: app.getInfo().description};
123746     },
123747
123748     isForeground: function () {
123749         return {code: 1, data: _isForeground};
123750     },
123751
123752     id: function () {
123753         return {code: 1, data: app.getInfo().id};
123754     },
123755
123756     license: function () {
123757         return {code: 1, data: app.getInfo().license};
123758     },
123759
123760     licenseURL: function () {
123761         return {code: 1, data: app.getInfo().licenseURL};
123762     },
123763
123764     name: function () {
123765         return {code: 1, data: app.getInfo().name};
123766     },
123767
123768     version: function () {
123769         return {code: 1, data: app.getInfo().version};
123770     },
123771
123772     requestBackground: function () {
123773         ui.showOverlay("background-window", function (background) {
123774             var button = background.children["background-return"];
123775
123776             if (button) {
123777                 button.addEventListener("click", _self.requestForeground);
123778             }
123779             _isForeground = false;
123780             event.trigger("AppRequestBackground");
123781         });
123782
123783         return {code: 1};
123784     },
123785
123786     requestForeground: function () {
123787         ui.hideOverlay("background-window", function (background) {
123788             var button = background.children["background-return"];
123789
123790             if (button) {
123791                 button.removeEventListener("click", _self.requestForeground);
123792             }
123793             _isForeground = true;
123794             event.trigger("AppRequestForeground");
123795         });
123796
123797         return {code: 1};
123798     },
123799
123800     setHomeScreenIcon: function (args) {
123801         if (args.uri) {
123802             var msg = "The application set the home screen" +
123803                (args.hover ? " hover " : " ") +
123804                "icon to " + args.uri;
123805
123806             notifications.openNotification("normal", msg);
123807             return {code: 1};
123808         }
123809         else {
123810             return {code: 0};
123811         }
123812     },
123813
123814     setHomeScreenName: function (args) {
123815         if (args.text) {
123816             var msg = "The application set the home screen name to " + args.text;
123817             notifications.openNotification("normal", msg);
123818             return {code: 1};
123819         }
123820         else {
123821             return {code: 1};
123822         }
123823     },
123824
123825     removeBannerIndicator: function () {
123826         event.trigger("BannerUpdated", ["", 0]);
123827         return {code: 1};
123828     },
123829
123830     showBannerIndicator: function (args) {
123831         event.trigger("BannerUpdated", [args.icon, args.count]);
123832         return {code: 1};
123833     },
123834
123835 };
123836
123837 module.exports = _self;
123838
123839 });
123840 define('ripple/platform/webworks.handset/2.0.0/server/appEvent', function (require, exports, module) {
123841 /*
123842  *  Copyright 2011 Research In Motion Limited.
123843  *
123844  * Licensed under the Apache License, Version 2.0 (the "License");
123845  * you may not use this file except in compliance with the License.
123846  * You may obtain a copy of the License at
123847  *
123848  * http://www.apache.org/licenses/LICENSE-2.0
123849  *
123850  * Unless required by applicable law or agreed to in writing, software
123851  * distributed under the License is distributed on an "AS IS" BASIS,
123852  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
123853  * See the License for the specific language governing permissions and
123854  * limitations under the License.
123855  */
123856 var event = require('ripple/event'),
123857     notifications = require('ripple/notifications'),
123858     _bg,
123859     _fg,
123860     _exit;
123861
123862 event.on("AppRequestBackground", function () {
123863     var baton = _bg;
123864     _bg = null;
123865     return baton && baton.pass({code: 1});
123866 });
123867
123868 event.on("AppRequestForeground", function () {
123869     var baton = _fg;
123870     _fg = null;
123871     return baton && baton.pass({code: 1});
123872 });
123873
123874 event.on("AppExit", function () {
123875     var baton = _exit;
123876     _exit = null;
123877     notifications.openNotification("normal", "blackberry.app.exit() as called, in the real world your app will exit, here... you get this notification");
123878     return baton && baton.pass({code: 1});
123879 });
123880
123881 module.exports = {
123882     onBackground: function (get, post, baton) {
123883         baton.take();
123884         _bg = baton;
123885         return {code: 1};
123886     },
123887
123888     onForeground: function (get, post, baton) {
123889         baton.take();
123890         _fg = baton;
123891         return {code: 1};
123892     },
123893
123894     onExit: function (get, post, baton) {
123895         baton.take();
123896         _exit = baton;
123897         return {code: 1};
123898     }
123899 };
123900
123901 });
123902 define('ripple/platform/webworks.handset/2.0.0/server/appointment', function (require, exports, module) {
123903 /*
123904  *  Copyright 2011 Research In Motion Limited.
123905  *
123906  * Licensed under the Apache License, Version 2.0 (the "License");
123907  * you may not use this file except in compliance with the License.
123908  * You may obtain a copy of the License at
123909  *
123910  * http://www.apache.org/licenses/LICENSE-2.0
123911  *
123912  * Unless required by applicable law or agreed to in writing, software
123913  * distributed under the License is distributed on an "AS IS" BASIS,
123914  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
123915  * See the License for the specific language governing permissions and
123916  * limitations under the License.
123917  */
123918 var db = require('ripple/db'),
123919     select = require('ripple/platform/webworks.core/2.0.0/select'),
123920     _self;
123921
123922 function _get() {
123923     return db.retrieveObject("webworks-pim-appointment-list") || {};
123924 }
123925
123926 function _do(func) {
123927     var appointments = _get();
123928     func(appointments);
123929     db.saveObject("webworks-pim-appointment-list", appointments);
123930 }
123931
123932 _self = {
123933     find: function (get, post) {
123934         var appointments = _get(),
123935             data = select.from(appointments)
123936                     .orderBy(post.orderBy, post.isAscending === false ? "desc" : "asc")
123937                     .max(post.maxReturn)
123938                     .where(post.filter);
123939
123940         return {code: 1, data: data};
123941     },
123942
123943     remove: function (get) {
123944         _do(function (appointments) {
123945             if (!appointments[get.uid]) {
123946                 throw "attempting to delete a non existant appointment with uid: " + get.uid;
123947             }
123948             delete appointments[get.uid];
123949         });
123950
123951         return {code: 1};
123952     },
123953
123954     save: function (get, post) {
123955         _do(function (appointments) {
123956             appointments[post.appointment.uid] = post.appointment;
123957         });
123958
123959         return {code: 1};
123960     }
123961 };
123962
123963 module.exports = _self;
123964
123965 });
123966 define('ripple/platform/webworks.handset/2.0.0/server/audioPlayer', function (require, exports, module) {
123967 /*
123968  *  Copyright 2011 Research In Motion Limited.
123969  *
123970  * Licensed under the Apache License, Version 2.0 (the "License");
123971  * you may not use this file except in compliance with the License.
123972  * You may obtain a copy of the License at
123973  *
123974  * http://www.apache.org/licenses/LICENSE-2.0
123975  *
123976  * Unless required by applicable law or agreed to in writing, software
123977  * distributed under the License is distributed on an "AS IS" BASIS,
123978  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
123979  * See the License for the specific language governing permissions and
123980  * limitations under the License.
123981  */
123982 //create my dom collection node in UI
123983
123984 var utils = require('ripple/utils'),
123985     constants = require('ripple/constants'),
123986     notifications = require('ripple/notifications'),
123987     Player = require('ripple/platform/webworks.handset/2.0.0/client/AudioPlayer'),
123988     _handlers = {
123989         loadstart: {},
123990         canplaythrough: {},
123991         durationchange: {},
123992         ended: {},
123993         error: {},
123994         play: {},
123995         pause: {},
123996         volumechange: {},
123997         close: {}
123998     },
123999     extract = {
124000         time: function (audio) {
124001             return audio.currentTime;
124002         },
124003         duration: function (audio) {
124004             return audio.duration;
124005         },
124006         error: function (audio) {
124007             return audio.error;
124008         },
124009         nothing: function (audio) {
124010             return null;
124011         }
124012     },
124013     container;
124014
124015 container = utils.createElement("section", {
124016     id: "webworks-audio-players"
124017 });
124018
124019 document.getElementById("ui").appendChild(container);
124020
124021 function _errClosed(method) {
124022     notifications.openNotification("error",
124023        "attempted to call " + method + " on a player that is already closed. This is a very bad thing to do :)");
124024     return false;
124025 }
124026
124027 function _removeHandler(type, id) {
124028     var audio = document.getElementById(id);
124029
124030     if (audio && _handlers[type][id]) {
124031         audio.removeEventListener(type, _handlers[type][id]);
124032         delete _handlers[type][id];
124033     }
124034 }
124035
124036 function _addHandler(type, id, callback) {
124037     var audio = document.getElementById(id);
124038
124039     if (audio) {
124040         _removeHandler(type, id);
124041         audio.addEventListener(type, callback);
124042         _handlers[type][id] = callback;
124043     }
124044 }
124045
124046 function proxyEvent(from, map) {
124047     var audio = document.getElementById(map.id);
124048
124049     if (audio) {
124050         map.baton.take();
124051         _addHandler(from, map.id, function () {
124052             _removeHandler(from, map.id);
124053             map.baton.pass({code: 1, data: {
124054                 event: map.target,
124055                 eventData: map.data(this)
124056             }});
124057         });
124058     }
124059     else {
124060         return {code: -1, data: {event: "EVENT_ERROR", eventData: 5}};
124061     }
124062 }
124063
124064 module.exports = {
124065
124066     create: function (args) {
124067         var id = Math.uuid(),
124068             audio = utils.createElement("audio", {
124069                 id: id
124070             });
124071
124072         audio.setAttribute("src", args.locator);
124073
124074         if (args.type) {
124075             audio.setAttribute("type", args.type);
124076         }
124077
124078         container.appendChild(audio);
124079         audio.load();
124080
124081         if (audio.error) {
124082             throw "there was a problem opening the audio file";
124083         }
124084
124085         return {code: 1, data: id};
124086     },
124087
124088     play: function (args) {
124089         var audio = document.getElementById(args.id),
124090             playing;
124091
124092         if (audio) {
124093             audio.play();
124094             audio.rimState = Player.STARTED;
124095             playing = !!!audio.error;
124096         }
124097         else {
124098             playing = _errClosed("play");
124099         }
124100
124101         return {code: 1, data: playing};
124102     },
124103
124104     pause: function (args) {
124105         var audio = document.getElementById(args.id),
124106             paused;
124107
124108         if (audio) {
124109             audio.pause();
124110             paused = !!!audio.error;
124111         } else {
124112             paused = _errClosed("pause");
124113         }
124114
124115         return {code: 1, data: paused};
124116     },
124117
124118     close: function (args) {
124119         var audio = document.getElementById(args.id),
124120             callback = _handlers["close"][args.id],
124121             closed = true;
124122
124123         if (audio) {
124124             if (callback) {
124125                 callback();
124126             }
124127             container.removeChild(audio);
124128         }
124129         else {
124130             closed = _errClosed("close");
124131         }
124132
124133         return {code: 1, data: closed};
124134     },
124135
124136     onStart: function (args, post, baton) {
124137         return proxyEvent("play", {
124138             id: args.id,
124139             baton: baton,
124140             target: "EVENT_START",
124141             data: extract.time
124142         });
124143     },
124144
124145     onStopped: function (args, post, baton) {
124146         return proxyEvent("pause", {
124147             id: args.id,
124148             baton: baton,
124149             target: "EVENT_STOPPED",
124150             data: extract.time
124151         });
124152     },
124153
124154     onBufferingStarted: function (args, post, baton) {
124155         return proxyEvent("loadstart", {
124156             id: args.id,
124157             baton: baton,
124158             target: "EVENT_BUFFERING_STARTED",
124159             data: extract.time
124160         });
124161     },
124162
124163     onBufferingStopped: function (args, post, baton) {
124164         return proxyEvent("canplaythrough", {
124165             id: args.id,
124166             baton: baton,
124167             target: "EVENT_BUFFERING_STOPPED",
124168             data: extract.time
124169         });
124170     },
124171
124172     onDurationUpdated: function (args, post, baton) {
124173         return proxyEvent("durationchange", {
124174             id: args.id,
124175             baton: baton,
124176             target: "EVENT_DURATION_UPDATED",
124177             data: extract.duration
124178         });
124179     },
124180
124181     onEnd: function (args, post, baton) {
124182         return proxyEvent("ended", {
124183             id: args.id,
124184             baton: baton,
124185             target: "EVENT_END_OF_MEDIA",
124186             data: extract.duration
124187         });
124188     },
124189
124190     onError: function (args, post, baton) {
124191         return proxyEvent("error", {
124192             id: args.id,
124193             baton: baton,
124194             target: "EVENT_ERROR",
124195             data: extract.error
124196         });
124197     },
124198
124199     onVolumeChange: function (args, post, baton) {
124200         return proxyEvent("volumechange", {
124201             id: args.id,
124202             baton: baton,
124203             target: "EVENT_VOLUME_CHANGED",
124204             data: extract.nothing
124205         });
124206     },
124207
124208     onClose: function (args, post, baton) {
124209         return proxyEvent("close", {
124210             id: args.id,
124211             baton: baton,
124212             target: "EVENT_CLOSED",
124213             data: extract.nothing
124214         });
124215     },
124216
124217     getDuration: function (args) {
124218         var audio = document.getElementById(args.id),
124219             duration;
124220
124221         if (audio) {
124222             duration = audio.duration;
124223         }
124224         else {
124225             _errClosed("getDuration");
124226             duration = -1;
124227         }
124228
124229         return {code: 1, data: duration};
124230     },
124231
124232     getMediaTime: function (args) {
124233         var audio = document.getElementById(args.id),
124234             time;
124235
124236         if (audio) {
124237             time = audio.currentTime;
124238         }
124239         else {
124240             _errClosed("getMediaTime");
124241             time = -1;
124242         }
124243
124244         return {code: 1, data: time};
124245     },
124246
124247     setMediaTime: function (args) {
124248         var audio = document.getElementById(args.id);
124249
124250         if (audio) {
124251             audio.currentTime = args.value;
124252         }
124253         else {
124254             _errClosed("setMediaTime");
124255         }
124256
124257         return {code: 1};
124258     },
124259
124260     getVolumeLevel: function (args) {
124261         var audio = document.getElementById(args.id),
124262             level;
124263
124264         if (audio) {
124265             level = audio.volume * 100;
124266         }
124267         else {
124268             _errClosed("getVolumeLevel");
124269             level = -1;
124270         }
124271
124272         return {code: 1, data: level};
124273     },
124274
124275     setVolumeLevel: function (args) {
124276         var audio = document.getElementById(args.id);
124277
124278         if (audio) {
124279             audio.volume = args.value / 100;
124280         }
124281         else {
124282             _errClosed("setVolumeLevel");
124283         }
124284
124285         return {code: 1};
124286     },
124287
124288     getState: function (args) {
124289         var audio = document.getElementById(args.id),
124290             state = audio ? audio.rimState || Player.PREFETCHED : Player.CLOSED;
124291         return {code: 1, data: state};
124292     }
124293 };
124294
124295 });
124296 define('ripple/platform/webworks.handset/2.0.0/server/category', function (require, exports, module) {
124297 /*
124298  *  Copyright 2011 Research In Motion Limited.
124299  *
124300  * Licensed under the Apache License, Version 2.0 (the "License");
124301  * you may not use this file except in compliance with the License.
124302  * You may obtain a copy of the License at
124303  *
124304  * http://www.apache.org/licenses/LICENSE-2.0
124305  *
124306  * Unless required by applicable law or agreed to in writing, software
124307  * distributed under the License is distributed on an "AS IS" BASIS,
124308  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
124309  * See the License for the specific language governing permissions and
124310  * limitations under the License.
124311  */
124312 var db = require('ripple/db'),
124313     _KEY = "blackberry-pim-category",
124314     _self;
124315
124316 function _get() {
124317     return db.retrieveObject(_KEY) || [];
124318 }
124319
124320 function _save(category) {
124321     var categories = _get();
124322     if (!categories.some(function (item) {
124323         return item === category;
124324     })) {
124325         categories.push(category);
124326         db.saveObject(_KEY, categories);
124327     }
124328 }
124329
124330 function _remove(category) {
124331     var categories = _get(),
124332         index = categories.indexOf(category);
124333
124334     if (index >= 0) {
124335         categories.splice(index, 1);
124336         db.saveObject(_KEY, categories);
124337     }
124338 }
124339
124340 _self = {
124341     addCategory: function (args) {
124342         _save(args.categoryName);
124343         return {code: 1};
124344     },
124345     deleteCategory: function (args) {
124346         _remove(args.categoryName);
124347         return {code: 1};
124348     },
124349     getCategories: function () {
124350         return {code: 1, data: _get()};
124351     }
124352 };
124353
124354 module.exports = _self;
124355
124356 });
124357 define('ripple/platform/webworks.handset/2.0.0/server/contact', function (require, exports, module) {
124358 /*
124359  *  Copyright 2011 Research In Motion Limited.
124360  *
124361  * Licensed under the Apache License, Version 2.0 (the "License");
124362  * you may not use this file except in compliance with the License.
124363  * You may obtain a copy of the License at
124364  *
124365  * http://www.apache.org/licenses/LICENSE-2.0
124366  *
124367  * Unless required by applicable law or agreed to in writing, software
124368  * distributed under the License is distributed on an "AS IS" BASIS,
124369  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
124370  * See the License for the specific language governing permissions and
124371  * limitations under the License.
124372  */
124373 var select = require('ripple/platform/webworks.core/2.0.0/select'),
124374     db = require('ripple/db'),
124375     utils = require('ripple/utils'),
124376     _KEY = "blackberry-pim-contacts",
124377     _self;
124378
124379 function _defaultContacts() {
124380     var id1 = Math.uuid(null, 16),
124381         id2 = Math.uuid(null, 16),
124382         id3 = Math.uuid(null, 16),
124383         id4 = Math.uuid(null, 16),
124384         contacts = {};
124385
124386     contacts[id1] = {
124387         uuid: id1,
124388         firstName: "Leonardo",
124389         homePhone: "4567892345",
124390         email1: "leo@underground.com"
124391     };
124392     contacts[id2] = {
124393         uuid: id2,
124394         firstName: "Raphael",
124395         homePhone: "4563457890",
124396         email1: "raph@underground.com"
124397     };
124398     contacts[id3] = {
124399         uuid: id3,
124400         firstName: "Michelangelo",
124401         homePhone: "4563453425",
124402         email1: "mike@underground.com"
124403     };
124404     contacts[id4] = {
124405         uuid: id4,
124406         firstName: "Donatello",
124407         homePhone: "4563453425",
124408         email1: "don@undergound.com"
124409     };
124410
124411     return contacts;
124412 }
124413
124414 function _get() {
124415     return db.retrieveObject(_KEY) || _defaultContacts();
124416 }
124417
124418 function _save(contacts) {
124419     db.saveObject(_KEY, contacts);
124420 }
124421
124422 _self = {
124423     save: function (get, post) {
124424         var contacts = _get();
124425
124426         contacts[post.contact.uid] = post.contact;
124427         _save(contacts);
124428         return {code: 1};
124429     },
124430     remove: function (get, post) {
124431         var contacts = _get(),
124432             id = get.id;
124433
124434         delete contacts[id];
124435         _save(contacts);
124436         return {code: 1};
124437     },
124438     find: function (get, post) {
124439         var contacts = _get(),
124440             match = select.from(contacts);
124441
124442         if (post.orderBy) {
124443             match.orderBy(post.orderBy, post.isAscending === false ? "desc" : "asc");
124444         }
124445
124446         if (post.maxReturn) {
124447             match.max(post.maxReturn);
124448         }
124449
124450         return {code: 1, data: match.where(post.fieldFilter)};
124451     }
124452 };
124453
124454 module.exports = _self;
124455
124456 });
124457 define('ripple/platform/webworks.handset/2.0.0/server/identity/phone', function (require, exports, module) {
124458 /*
124459  *  Copyright 2011 Research In Motion Limited.
124460  *
124461  * Licensed under the Apache License, Version 2.0 (the "License");
124462  * you may not use this file except in compliance with the License.
124463  * You may obtain a copy of the License at
124464  *
124465  * http://www.apache.org/licenses/LICENSE-2.0
124466  *
124467  * Unless required by applicable law or agreed to in writing, software
124468  * distributed under the License is distributed on an "AS IS" BASIS,
124469  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
124470  * See the License for the specific language governing permissions and
124471  * limitations under the License.
124472  */
124473 var _lines = [
124474         {id: 1, number: 12345678910, label: "rogers", type: 1},
124475         {id: 2, number: 10987654321, label: "mystery", type: 0}
124476     ],
124477     _self;
124478
124479 function _filterLines(args) {
124480
124481     var result = _lines;
124482
124483     if (args && typeof args.id === "number") {
124484         result = _lines.filter(function (line) {
124485             return line.id === args.id;
124486         });
124487
124488         if (result.length === 0) {
124489             throw "invalid line id: " + args.id;
124490         }
124491     }
124492
124493     return result;
124494 }
124495
124496 _self = {
124497     getLineIds: function () {
124498         var lines = _lines.map(function (line) {
124499             return line.id;
124500         });
124501         return {
124502             code: 1,
124503             data: lines
124504         };
124505     },
124506     getLineLabel: function (args) {
124507         return {
124508             code: 1,
124509             data: _filterLines(args)[0].label
124510         };
124511     },
124512     getLineNumber: function (args) {
124513         return {
124514             code: 1,
124515             data: _filterLines(args)[0].number
124516         };
124517     },
124518     getLineType: function (args) {
124519         return {
124520             code: 1,
124521             data: _filterLines(args)[0].type
124522         };
124523     }
124524 };
124525
124526 module.exports = _self;
124527
124528 });
124529 define('ripple/platform/webworks.handset/2.0.0/server/identity', function (require, exports, module) {
124530 /*
124531  *  Copyright 2011 Research In Motion Limited.
124532  *
124533  * Licensed under the Apache License, Version 2.0 (the "License");
124534  * you may not use this file except in compliance with the License.
124535  * You may obtain a copy of the License at
124536  *
124537  * http://www.apache.org/licenses/LICENSE-2.0
124538  *
124539  * Unless required by applicable law or agreed to in writing, software
124540  * distributed under the License is distributed on an "AS IS" BASIS,
124541  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
124542  * See the License for the specific language governing permissions and
124543  * limitations under the License.
124544  */
124545 var _self,
124546     Service = require('ripple/platform/webworks.handset/2.0.0/client/identity/Service'),
124547     Transport = require('ripple/platform/webworks.handset/2.0.0/client/identity/Transport'),
124548     utils = require('ripple/utils'),
124549     platform = require('ripple/platform'),
124550     deviceSettings = require('ripple/deviceSettings'),
124551     _transportTypes = [
124552         {name: "TCP Cellular", type: "TCP Cellular"},
124553         {name: "Wap", type: "Wap"},
124554         {name: "Wap 2.0", type: "Wap 2.0"},
124555         {name: "MDS", type: "MDS"},
124556         {name: "BIS B", type: "Bis B"},
124557         {name: "Unite!", type: "Unite!"},
124558         {name: "TCP Wifi", type: "TCP Wifi"},
124559     ],
124560     _services = [
124561         new Service(),
124562         new Service()
124563     ];
124564
124565 function _isTransportAvailable(transport) {
124566     return deviceSettings.retrieveAsBoolean("transports." + transport.type);
124567 }
124568
124569 utils.mixin({
124570     name: "Super Dave Osborne",
124571     emailAddress: "dave@stunt.com",
124572     isDefault: true,
124573     type: Service.TYPE_EMAIL
124574 }, _services[0]);
124575
124576 utils.mixin({
124577     name: "Fred Penner",
124578     emailAddress: "fred@fredpenner.com",
124579     isDefault: false,
124580     type: Service.TYPE_CONTACT
124581 }, _services[1]);
124582
124583 _self = {
124584     getDefaultService: function () {
124585         var serices = _services.filter(function (service) {
124586             return service.isDefault === true;
124587         });
124588         return {code: 1, data: serices};
124589     },
124590     getServiceList: function () {
124591         return {code: 1, data: _services};
124592     },
124593     getTransportList: function () {
124594         var transports = _transportTypes.filter(function (transport) {
124595             return _isTransportAvailable(transport);
124596         }).map(function (transport) {
124597             return new Transport(transport.name, transport.type);
124598         });
124599         return {code: 1, data: transports};
124600     },
124601     IMEI: function () {
124602         return {code: 1, data: deviceSettings.retrieve("identity.IMEI")};
124603     },
124604     IMSI: function () {
124605         return {code: 1, data: deviceSettings.retrieve("identity.IMSI")};
124606     },
124607     PIN: function () {
124608         return {code: 1, data: deviceSettings.retrieve("identity.PIN")};
124609     },
124610     phone: require('ripple/platform/webworks.handset/2.0.0/server/identity/phone')
124611 };
124612
124613 module.exports = _self;
124614
124615 });
124616 define('ripple/platform/webworks.handset/2.0.0/server/invoke', function (require, exports, module) {
124617 /*
124618  *  Copyright 2011 Research In Motion Limited.
124619  *
124620  * Licensed under the Apache License, Version 2.0 (the "License");
124621  * you may not use this file except in compliance with the License.
124622  * You may obtain a copy of the License at
124623  *
124624  * http://www.apache.org/licenses/LICENSE-2.0
124625  *
124626  * Unless required by applicable law or agreed to in writing, software
124627  * distributed under the License is distributed on an "AS IS" BASIS,
124628  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
124629  * See the License for the specific language governing permissions and
124630  * limitations under the License.
124631  */
124632 var notifications = require('ripple/notifications'),
124633     constants = require('ripple/constants'),
124634     type = "normal",
124635     name = {
124636         "0": "Address Book",
124637         "1": "Bluetooth Config",
124638         "2": "Calculator",
124639         "3": "Calendar",
124640         "camera://": "Camera",
124641         "camera://video": "Video Camera",
124642         "map://": "Maps",
124643         "6": "Memopad",
124644         "7": "Messages",
124645         "8": "Phone",
124646         "9": "Search",
124647         "10": "Tasks",
124648         "11": "Browser",
124649         "http://": "Browser",
124650         "12": "Java",
124651     };
124652
124653 module.exports = {
124654     invoke: function (opts) {
124655         var app = name[opts.appType];
124656         if (app === undefined && opts.appType && opts.appType.match(/^http/i)) {
124657             app = "Browser";
124658         }
124659
124660         notifications.openNotification(type,
124661            "Requested to launch: " + app + " application.");
124662         return {code: 1};
124663     }
124664 };
124665
124666 });
124667 define('ripple/platform/webworks.handset/2.0.0/server/io/dir', function (require, exports, module) {
124668 /*
124669  * Copyright 2011 Research In Motion Limited.
124670  *
124671  * Licensed under the Apache License, Version 2.0 (the "License");
124672  * you may not use this file except in compliance with the License.
124673  * You may obtain a copy of the License at
124674  *
124675  *     http://www.apache.org/licenses/LICENSE-2.0
124676  *
124677  * Unless required by applicable law or agreed to in writing, software
124678  * distributed under the License is distributed on an "AS IS" BASIS,
124679  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
124680  * See the License for the specific language governing permissions and
124681  * limitations under the License.
124682  */
124683 var cache = require('ripple/platform/webworks.core/2.0.0/fsCache'),
124684     dir = require('ripple/platform/webworks.core/2.0.0/server/io/dir'),
124685     utils = require('ripple/utils'),
124686     _self = {};
124687
124688 function _packet(data) {
124689     return {
124690         code: 1,
124691         data: data
124692     };
124693 }
124694
124695 utils.mixin({
124696     getFreeSpaceForRoot: function (get, post, baton) {
124697         return _packet(cache.dir.getFreeSpaceForRoot(post.path));
124698     },
124699     getRootDirs: function (get, post, baton) {
124700         return _packet(cache.dir.getRootDirs());
124701     }
124702 }, _self);
124703
124704 utils.mixin(dir, _self);
124705
124706 module.exports = _self;
124707
124708 });
124709 define('ripple/platform/webworks.handset/2.0.0/server/memo', function (require, exports, module) {
124710 /*
124711  *  Copyright 2011 Research In Motion Limited.
124712  *
124713  * Licensed under the Apache License, Version 2.0 (the "License");
124714  * you may not use this file except in compliance with the License.
124715  * You may obtain a copy of the License at
124716  *
124717  * http://www.apache.org/licenses/LICENSE-2.0
124718  *
124719  * Unless required by applicable law or agreed to in writing, software
124720  * distributed under the License is distributed on an "AS IS" BASIS,
124721  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
124722  * See the License for the specific language governing permissions and
124723  * limitations under the License.
124724  */
124725 var db = require('ripple/db'),
124726     select = require('ripple/platform/webworks.core/2.0.0/select'),
124727     _self;
124728
124729 function _get() {
124730     return db.retrieveObject("webworks-pim-memo-list") || {};
124731 }
124732
124733 function _do(func) {
124734     var memos = _get();
124735     func(memos);
124736     db.saveObject("webworks-pim-memo-list", memos);
124737 }
124738
124739 _self = {
124740     find: function (get, post) {
124741         var memos = select.from(_get())
124742                     .orderBy(post.orderBy, post.isAscending === false ? "desc" : "asc")
124743                     .max(post.maxReturn)
124744                     .where(post.filter);
124745         return {code: 1, data: memos};
124746     },
124747     remove: function (get, post) {
124748         _do(function (memos) {
124749             if (!memos[get.uid]) {
124750                 throw "attempting to delete a non existant memo with uid: " + get.uid;
124751             }
124752             delete memos[get.uid];
124753         });
124754         return {code: 1};
124755     },
124756     save: function (get, post) {
124757         _do(function (memos) {
124758             memos[post.memo.uid] = post.memo;
124759         });
124760         return {code: 1};
124761     }
124762 };
124763
124764 module.exports = _self;
124765
124766 });
124767 define('ripple/platform/webworks.handset/2.0.0/server/menu', function (require, exports, module) {
124768 /*
124769  *  Copyright 2011 Research In Motion Limited.
124770  *
124771  * Licensed under the Apache License, Version 2.0 (the "License");
124772  * you may not use this file except in compliance with the License.
124773  * You may obtain a copy of the License at
124774  *
124775  * http://www.apache.org/licenses/LICENSE-2.0
124776  *
124777  * Unless required by applicable law or agreed to in writing, software
124778  * distributed under the License is distributed on an "AS IS" BASIS,
124779  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
124780  * See the License for the specific language governing permissions and
124781  * limitations under the License.
124782  */
124783 var _menuItems = {},
124784     event = require('ripple/event'),
124785     events = require('ripple/platform/webworks.core/2.0.0/client/events'),
124786     ui = require('ripple/ui'),
124787     devices = require('ripple/devices'),
124788     utils = require('ripple/utils'),
124789     tooltip = require('ripple/ui/plugins/tooltip'),
124790     _self,
124791     isMenuOpen = false,
124792     _baton,
124793     menuWindow = document ? document.getElementById("menu-window") : undefined;
124794
124795 if (menuWindow) {
124796     menuWindow.addEventListener("click", function () {
124797         _self.close();
124798     });
124799 }
124800
124801 event.on("LayoutChanged", function () {
124802     if (isMenuOpen) {
124803         _self.close();
124804         //Used to resize menu on orientation change
124805         _self.open();
124806     }
124807 });
124808
124809 event.on("HardwareKeyDefault", function (key) {
124810     if (key === 1 || key === "1") { //menu button key
124811         if (isMenuOpen) {
124812             _self.close();
124813         }
124814         else {
124815             _self.open();
124816         }
124817     }
124818 });
124819
124820 event.on("MenuItemSelected", function (menuItem) {
124821     var baton = _baton;
124822     _baton = null;
124823     return baton && baton.pass({code: 1, data: menuItem});
124824 });
124825
124826 event.on("MenuItemChanged", function (menuItem) {
124827     _menuItems[menuItem.id] = menuItem;
124828 });
124829
124830 _self = {
124831
124832     onSelect : function (args, post, baton) {
124833         baton.take();
124834         _baton = baton;
124835     },
124836
124837     addMenuItem: function (args) {
124838         if (!args) {
124839             throw "item not found";
124840         }
124841         _menuItems[args.item.id] = args.item;
124842         event.trigger("MenuChanged", [_menuItems]);
124843         return {code: 1};
124844     },
124845
124846     clearMenuItems: function () {
124847         _menuItems = {};
124848         event.trigger("MenuChanged", [utils.copy(_menuItems)]);
124849         return {code: 1};
124850     },
124851
124852     open: function () {
124853         function _return() {
124854             return {code: 1};
124855         }
124856
124857         if (utils.count(_menuItems) === 0) {
124858             _return();
124859         }
124860
124861         ui.showOverlay("menu-window", function (menu) {
124862             var container = document.getElementById("viewport-container"),
124863                 height = window.getComputedStyle(container, null).getPropertyValue("height"),
124864                 width = window.getComputedStyle(container, null).getPropertyValue("width"),
124865                 menuButtons = document.getElementById("menu-buttons"),
124866                 sorted,
124867                 menuItem;
124868
124869             if (!menuButtons) {
124870                 _return();
124871             }
124872
124873             menu.setAttribute("style", "display:block;height:" + height + "; width:" + width + ";");
124874             isMenuOpen = true;
124875
124876             sorted = utils.map(_menuItems, function (item) {
124877                 return item;
124878             }).sort(function (a, b) {
124879                 return a.ordinal - b.ordinal;
124880             });
124881
124882             menuButtons.innerHTML = "";
124883             sorted.forEach(function (item) {
124884                 if (!item.isSeparator) {
124885                     if (item.isDefault) {
124886                         menuItem = utils.createElement("div", {
124887                             "class": "overlay-menu-item-default",
124888                             "id": "default-menu-item"
124889                         });
124890                     }
124891                     else {
124892                         menuItem = utils.createElement("div", {
124893                             "class": "overlay-menu-item"
124894                         });
124895                     }
124896                     menuItem.innerHTML = item.caption;
124897
124898                     menuItem.addEventListener("click", function () {
124899                         _baton.pass({code: 1, data: item.id});
124900                     });
124901                 }
124902                 else {
124903                     menuItem = utils.createElement("hr", {});
124904                 }
124905                 menuButtons.appendChild(menuItem);
124906                 tooltip.create("#default-menu-item", "Default Item");
124907             });
124908         }, true);
124909
124910         event.trigger("MenuOpened", []);
124911
124912         _return();
124913     },
124914
124915     close: function () {
124916         ui.hideOverlay("menu-window", function (menu) {
124917             var menuButtons = document.getElementById("menu-buttons");
124918             menuButtons.innerHTML = "";
124919             isMenuOpen = false;
124920             menu.setAttribute("style", "display:none;");
124921
124922         });
124923         return {code: 1};
124924     },
124925
124926     removeMenuItem: function (args) {
124927         delete _menuItems[args.item.id];
124928         event.trigger("MenuChanged", [_menuItems]);
124929         return {code: 1};
124930     },
124931
124932     setDefaultMenuItem: function (args) {
124933
124934         utils.forEach(_menuItems, function (item) {
124935             item.isDefault = false;
124936         });
124937
124938         _menuItems[args.id].isDefault = true;
124939
124940         event.trigger("DefaultItemChanged", [_menuItems[args.id]]);
124941         return {code: 1};
124942     }
124943 };
124944
124945 module.exports = _self;
124946
124947 });
124948 define('ripple/platform/webworks.handset/2.0.0/server/message', function (require, exports, module) {
124949 /*
124950  *  Copyright 2011 Research In Motion Limited.
124951  *
124952  * Licensed under the Apache License, Version 2.0 (the "License");
124953  * you may not use this file except in compliance with the License.
124954  * You may obtain a copy of the License at
124955  *
124956  * http://www.apache.org/licenses/LICENSE-2.0
124957  *
124958  * Unless required by applicable law or agreed to in writing, software
124959  * distributed under the License is distributed on an "AS IS" BASIS,
124960  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
124961  * See the License for the specific language governing permissions and
124962  * limitations under the License.
124963  */
124964 var db = require('ripple/db'),
124965     utils = require('ripple/utils'),
124966     select = require('ripple/platform/webworks.core/2.0.0/select'),
124967     Message = require('ripple/platform/webworks.handset/2.0.0/client/Message'),
124968     _self;
124969
124970 function _get() {
124971     return db.retrieveObject("webworks-message-list") || {};
124972 }
124973
124974 function _do(func) {
124975     var messages = _get();
124976     func(messages);
124977     db.saveObject("webworks-message-list", messages);
124978 }
124979
124980 _self = {
124981     find: function (get, post) {
124982         var data = select
124983                 .from(_get())
124984                 .max(post.maxReturn)
124985                 .where(post.filter);
124986         return {code: 1, data: data};
124987     },
124988
124989     remove: function (get, post) {
124990         _do(function (messages) {
124991             if (!messages[get.uid]) {
124992                 throw "attempting to delete a non existant message with uid: " + get.uid;
124993             }
124994             delete messages[get.uid];
124995         });
124996         return {code: 1};
124997     },
124998
124999     save: function (get, post) {
125000         _do(function (messages) {
125001             var orig = messages[post.message.uid],
125002                 updated = utils.copy(post.message);
125003
125004             updated.folder = orig ? orig.folder : Message.FOLDER_DRAFT;
125005             updated.status = orig ? orig.status : Message.STATUS_DRAFT;
125006
125007             messages[post.message.uid] = updated;
125008         });
125009         return {code: 1};
125010     },
125011
125012     send: function (get, post) {
125013         _do(function (messages) {
125014             var updated = utils.copy(get.message);
125015
125016             updated.folder = Message.FOLDER_SENT;
125017             updated.status = Message.STATUS_SENT;
125018
125019             messages[updated.uid] = updated;
125020         });
125021         return {code: 1};
125022     }
125023 };
125024
125025 module.exports = _self;
125026
125027 });
125028 define('ripple/platform/webworks.handset/2.0.0/server/phone', function (require, exports, module) {
125029 /*
125030  *  Copyright 2011 Research In Motion Limited.
125031  *
125032  * Licensed under the Apache License, Version 2.0 (the "License");
125033  * you may not use this file except in compliance with the License.
125034  * You may obtain a copy of the License at
125035  *
125036  * http://www.apache.org/licenses/LICENSE-2.0
125037  *
125038  * Unless required by applicable law or agreed to in writing, software
125039  * distributed under the License is distributed on an "AS IS" BASIS,
125040  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
125041  * See the License for the specific language governing permissions and
125042  * limitations under the License.
125043  */
125044 var PhoneCall = require('ripple/platform/webworks.handset/2.0.0/client/PhoneCall'),
125045     PhoneLogs = require('ripple/platform/webworks.handset/2.0.0/client/PhoneLogs'),
125046     CallLog = require('ripple/platform/webworks.handset/2.0.0/client/CallLog'),
125047     select = require('ripple/platform/webworks.core/2.0.0/select'),
125048     event = require('ripple/event'),
125049     utils = require('ripple/utils'),
125050     db = require('ripple/db'),
125051     _KEY = "blackberry-phone-logs",
125052     _onPhoneEventListeners = {},
125053     _activeCalls = {},
125054     _onCallLogAdded,
125055     _onCallLogRemoved,
125056     _onCallLogUpdated,
125057     _onCallLogReset,
125058     _self;
125059
125060 function _defaultLogs() {
125061     var n1 = new CallLog(),
125062         n2 = new CallLog(),
125063         m1 = new CallLog(),
125064         m2 = new CallLog();
125065
125066     n1.number = "12344567";
125067     n1.name = "larry";
125068     n1.type = CallLog.TYPE_PLACED_CALL;
125069     n1.status = CallLog.STATUS_NORMAL;
125070
125071     n2.number = "14567890";
125072     n2.name = "curly";
125073     n2.type = CallLog.TYPE_RECEIVED_CALL;
125074     n2.status = CallLog.STATUS_NORMAL;
125075
125076     m1.number = "17659800";
125077     m1.name = "moe";
125078     m1.type = CallLog.TYPE_MISSED_CALL_UNOPENED;
125079     m1.status = CallLog.STATUS_NORMAL;
125080
125081     m2.number = "14567896";
125082     m2.name = "snarf";
125083     m2.type = CallLog.TYPE_MISSED_CALL_OPENED;
125084     m2.status = CallLog.STATUS_NORMAL;
125085
125086     return {
125087         normal: [n1, n2],
125088         missed: [m1, m2]
125089     };
125090 }
125091
125092 function _getLogs(folderID) {
125093     var logs = db.retrieveObject(_KEY) || _defaultLogs();
125094     return folderID === undefined || folderID === null ?
125095         logs : logs[folderID !== PhoneLogs.FOLDER_NORMAL_CALLS ? "missed" : "normal"];
125096 }
125097
125098 function _saveLogs(logs) {
125099     db.saveObject(_KEY, logs);
125100 }
125101
125102 function _isMissedCall(log) {
125103     return (log.type === CallLog.TYPE_MISSED_CALL_UNOPENED ||
125104             log.type === CallLog.TYPE_MISSED_CALL_OPENED) ? true : false;
125105 }
125106
125107 function _isNormalCall(log) {
125108     return (log.type === CallLog.TYPE_RECEIVED_CALL ||
125109             log.type === CallLog.TYPE_PLACED_CALL) ? true : false;
125110 }
125111
125112 event.on("PhoneEvent", function (type, callId, error) {
125113     var baton = _onPhoneEventListeners[type];
125114     delete _onPhoneEventListeners[type];
125115
125116     return baton && baton.pass({code: 1, data: {callId: callId, error: error}});
125117 });
125118
125119 event.on("PhoneCallLogAdded", function (log) {
125120     var logs = _getLogs(),
125121         baton = _onCallLogAdded;
125122
125123     logs[_isMissedCall(log) ? "missed" : "normal"].push(log);
125124     _saveLogs(logs);
125125
125126     _onCallLogAdded = null;
125127     return baton && baton.pass({code: 1, data: {log: log}});
125128 });
125129
125130 event.on("PhoneCallLogRemoved", function (log) {
125131     // TODO: make this be the only one responsible for deletion (instead of triggering internally)
125132     var baton = _onCallLogRemoved;
125133     _onCallLogRemoved = null;
125134     return baton && baton.pass({code: 1, data: {log: log}});
125135 });
125136
125137 event.on("PhoneCallLogUpdated", function (newLog, oldLog) {
125138     // TODO: implement way to update with just this event
125139     var baton = _onCallLogUpdated;
125140     _onCallLogUpdated = null;
125141     return baton && baton.pass({code: 1, data: {
125142         newLog: newLog,
125143         oldLog: oldLog
125144     }});
125145 });
125146
125147 event.on("PhoneCallLogReset", function () {
125148     _saveLogs(_defaultLogs());
125149     var baton = _onCallLogReset;
125150     _onCallLogReset = null;
125151     return baton && baton.pass({code: 1});
125152 });
125153
125154 event.on("PhoneCallInitiated", function (call) {
125155     _activeCalls[call.id] = call;
125156 });
125157
125158 event.on("PhoneCallEnded", function (call) {
125159     delete _activeCalls[call.id];
125160 });
125161
125162 _self = {
125163     logs: {
125164         onCallLogAdded: function (get, post, baton) {
125165             baton.take();
125166             _onCallLogAdded = baton;
125167         },
125168
125169         onCallLogRemoved: function (get, post, baton) {
125170             baton.take();
125171             _onCallLogRemoved = baton;
125172         },
125173
125174         onCallLogUpdated: function (get, post, baton) {
125175             baton.take();
125176             _onCallLogUpdated = baton;
125177         },
125178
125179         onCallLogReset: function (get, post, baton) {
125180             baton.take();
125181             _onCallLogReset = baton;
125182         },
125183
125184         callAt: function (get) {
125185             var logs = _getLogs(get.folderID !== null && get.folderID !== undefined ?
125186                                         get.folderID : PhoneLogs.FOLDER_MISSED_CALLS);
125187             return {code: 1, data: logs.length > get.index ? logs[get.index] : null};
125188         },
125189
125190         deleteCallAt: function (get) {
125191             var logs = _getLogs(),
125192                 subLog = _getLogs(get.folderID),
125193                 deleted = false,
125194                 type, log;
125195
125196             if (subLog.length > get.index &&
125197                (type = _isNormalCall(subLog[get.index]) ? "normal" : "missed") &&
125198                (log = logs[type].splice(get.index, 1))) {
125199                 event.trigger("PhoneCallLogRemoved", [log]);
125200                 _saveLogs(logs);
125201                 deleted = true;
125202             }
125203
125204             return {code: 1, data: deleted};
125205         },
125206
125207         find: function (get, post) {
125208             var data = select.from(_getLogs(post.folderID !== null && post.folderID !== undefined ?
125209                                         post.folderID : PhoneLogs.FOLDER_MISSED_CALLS))
125210                     .orderBy(post.orderBy, post.isAscending === false ? "desc" : "asc")
125211                     .max(post.maxReturn)
125212                     .where(post.filter, select.ops.phone);
125213             return {code: 1, data: data};
125214         },
125215
125216         numberOfCalls: function (get) {
125217             return {code: 1, data: _getLogs(get.folderID !== null && get.folderID !== undefined ?
125218                                         get.folderID : PhoneLogs.FOLDER_MISSED_CALLS).length};
125219         }
125220     },
125221
125222     onPhoneEvent: function (get, post, baton) {
125223         baton.take();
125224         _onPhoneEventListeners[get.eventType] = baton;
125225     },
125226
125227     activeCalls: function () {
125228         var data = utils.map(_activeCalls, function (callItem) {
125229             var call = new PhoneCall(callItem.onhold);
125230             call.outgoing = callItem.outgoing;
125231             call.recipientName = callItem.recipient.name;
125232             call.recipientNumber = callItem.recipient.number;
125233             return call;
125234         });
125235         return {code: 1, data: data};
125236     },
125237
125238     inActiveCall: function () {
125239         return {code: 1, data: utils.count(_activeCalls) > 0 ? true : false};
125240     }
125241 };
125242
125243 module.exports = _self;
125244
125245 });
125246 define('ripple/platform/webworks.handset/2.0.0/server/push', function (require, exports, module) {
125247 /*
125248  *  Copyright 2011 Research In Motion Limited.
125249  *
125250  * Licensed under the Apache License, Version 2.0 (the "License");
125251  * you may not use this file except in compliance with the License.
125252  * You may obtain a copy of the License at
125253  *
125254  * http://www.apache.org/licenses/LICENSE-2.0
125255  *
125256  * Unless required by applicable law or agreed to in writing, software
125257  * distributed under the License is distributed on an "AS IS" BASIS,
125258  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
125259  * See the License for the specific language governing permissions and
125260  * limitations under the License.
125261  */
125262 var event = require('ripple/event'),
125263     utils = require('ripple/utils'),
125264     _handlers = {},
125265     _self;
125266
125267 function listenersChanged() {
125268     var ports = utils.map(_handlers, function (handler) {
125269         return handler.port;
125270     });
125271     event.trigger("PushListenersChanged", [ports]);
125272 }
125273
125274 event.on("Push", function (data, port) {
125275     var handler = _handlers["port_" + port];
125276     delete _handlers["port_" + port];
125277     window.setTimeout(function () {
125278         if (!_handlers["port_" + port]) {
125279             //doesn't look like they are coming back ;)
125280             listenersChanged();
125281         }
125282     }, 100);
125283     return handler && handler.baton.pass({code: 1, data: data});
125284 });
125285
125286 _self = {
125287
125288     onPush: function (args, post, baton) {
125289         if (!args.port) {
125290             throw "no port specified";
125291         }
125292         else if (typeof args.port !== 'number') {
125293             throw "port is not a number";
125294         }
125295         baton.take();
125296         _handlers["port_" + args.port] = {
125297             port: args.port,
125298             baton: baton
125299         };
125300         listenersChanged();
125301     }
125302 };
125303
125304 module.exports = _self;
125305
125306 });
125307 define('ripple/platform/webworks.handset/2.0.0/server/sms', function (require, exports, module) {
125308 /*
125309  *  Copyright 2011 Research In Motion Limited.
125310  *
125311  * Licensed under the Apache License, Version 2.0 (the "License");
125312  * you may not use this file except in compliance with the License.
125313  * You may obtain a copy of the License at
125314  *
125315  * http://www.apache.org/licenses/LICENSE-2.0
125316  *
125317  * Unless required by applicable law or agreed to in writing, software
125318  * distributed under the License is distributed on an "AS IS" BASIS,
125319  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
125320  * See the License for the specific language governing permissions and
125321  * limitations under the License.
125322  */
125323 var _listener,
125324     _isListening = false,
125325     notifications = require('ripple/notifications'),
125326     constants = require('ripple/constants'),
125327     event = require('ripple/event'),
125328     _console = require('ripple/console'),
125329     _onReceive,
125330     _self;
125331
125332 event.on("MessageReceived", function (message) {
125333     if (!_isListening || message.type !== 'sms') {
125334         return;
125335     }
125336
125337     var baton = _onReceive;
125338     _onReceive = null;
125339     _isListening = false;
125340     return baton && baton.pass({code: 1, data: message});
125341 });
125342
125343 _self = {
125344     onReceive: function (args, post, baton) {
125345         baton.take();
125346         _onReceive = baton;
125347         _isListening = !!_onReceive;
125348     },
125349
125350     send: function (args) {
125351         var msg = "To " + args.address + ": " + args.message;
125352         notifications.openNotification("normal", msg);
125353         _console.log(msg);
125354         return {code: 1};
125355     },
125356
125357     isListeningForMessage: function (get, post, baton) {
125358         if (get && typeof get.isListeningForMessage === "boolean") {
125359             _isListening = get.isListeningForMessage;
125360         }
125361
125362         return {code: 1, data: _isListening};
125363     }
125364 };
125365
125366 module.exports = _self;
125367
125368 });
125369 define('ripple/platform/webworks.handset/2.0.0/server/systemEvent', function (require, exports, module) {
125370 /*
125371  *  Copyright 2011 Research In Motion Limited.
125372  *
125373  * Licensed under the Apache License, Version 2.0 (the "License");
125374  * you may not use this file except in compliance with the License.
125375  * You may obtain a copy of the License at
125376  *
125377  * http://www.apache.org/licenses/LICENSE-2.0
125378  *
125379  * Unless required by applicable law or agreed to in writing, software
125380  * distributed under the License is distributed on an "AS IS" BASIS,
125381  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
125382  * See the License for the specific language governing permissions and
125383  * limitations under the License.
125384  */
125385 var event = require('ripple/event'),
125386     _onCoverageChange,
125387     _onHardwareKey = {};
125388
125389 event.on("CoverageChange", function () {
125390     var baton = _onCoverageChange;
125391     _onCoverageChange = null;
125392     return baton && baton.pass({code: 1});
125393 });
125394
125395 event.on("HardwareKey", function (key) {
125396     var baton = _onHardwareKey["key_" + key];
125397     delete _onHardwareKey["key_" + key];
125398
125399     if (baton) {
125400         baton.pass({code: 1});
125401     }
125402     else {
125403         event.trigger("HardwareKeyDefault", [key]);
125404     }
125405 });
125406
125407 module.exports = {
125408     onCoverageChange: function (args, post, baton) {
125409         baton.take();
125410         _onCoverageChange = baton;
125411     },
125412
125413     onHardwareKey: function (args, post, baton) {
125414         baton.take();
125415         _onHardwareKey["key_" + args.key] = baton;
125416     }
125417 };
125418
125419 });
125420 define('ripple/platform/webworks.handset/2.0.0/server', function (require, exports, module) {
125421 /*
125422  *  Copyright 2011 Research In Motion Limited.
125423  *
125424  * Licensed under the Apache License, Version 2.0 (the "License");
125425  * you may not use this file except in compliance with the License.
125426  * You may obtain a copy of the License at
125427  *
125428  * http://www.apache.org/licenses/LICENSE-2.0
125429  *
125430  * Unless required by applicable law or agreed to in writing, software
125431  * distributed under the License is distributed on an "AS IS" BASIS,
125432  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
125433  * See the License for the specific language governing permissions and
125434  * limitations under the License.
125435  */
125436 var utils = require('ripple/utils'),
125437     platform = "ripple/platform/webworks.handset/2.0.0/server/",
125438     core = "ripple/platform/webworks.core/2.0.0/server/",
125439     systemEvent = require(platform + 'systemEvent'),
125440     system = {};
125441
125442 // ugh, thanks to the spec...
125443 system.event = systemEvent;
125444 utils.mixin(require(core + "system"), system);
125445
125446 module.exports = {
125447     blackberry: {
125448         invoke: require(platform + "invoke"),
125449         system: system,
125450         app: require(platform + "app"),
125451         identity: require(platform + "identity"),
125452         message: {
125453             sms: require(platform + "sms"),
125454             message: require(platform + "message")
125455         },
125456         push: require(platform + "push"),
125457         pim: {
125458             Task: require(platform + "Task"),
125459             category: require(platform + "category"),
125460             memo: require(platform + "memo"),
125461             appointment: require(platform + "appointment"),
125462             contact: require(platform + "contact")
125463         },
125464         audio: {
125465             player: require(platform + "audioPlayer")
125466         },
125467         ui: {
125468             menu: require(platform + "menu"),
125469             dialog: require(core + "dialog")
125470         },
125471         phone: require(platform + "phone"),
125472         io: {
125473             dir: require(platform + "io/dir"),
125474             file: require(core + "io/file")
125475         }
125476     }
125477 };
125478
125479 });
125480 define('ripple/platform/webworks.handset/2.0.0/spec/device', function (require, exports, module) {
125481 /*
125482  *  Copyright 2011 Research In Motion Limited.
125483  *
125484  * Licensed under the Apache License, Version 2.0 (the "License");
125485  * you may not use this file except in compliance with the License.
125486  * You may obtain a copy of the License at
125487  *
125488  * http://www.apache.org/licenses/LICENSE-2.0
125489  *
125490  * Unless required by applicable law or agreed to in writing, software
125491  * distributed under the License is distributed on an "AS IS" BASIS,
125492  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
125493  * See the License for the specific language governing permissions and
125494  * limitations under the License.
125495  */
125496 var event = require('ripple/event');
125497
125498 module.exports = {
125499     "transports": {
125500         "TCP Cellular": {
125501             "name": "Cellular TCP",
125502             "control": {
125503                 "type": "checkbox",
125504                 "value": true
125505             }
125506         },
125507         "Wap": {
125508             "name": "WAP",
125509             "control": {
125510                 "type": "checkbox",
125511                 "value": false
125512             }
125513         },
125514         "Wap 2.0": {
125515             "name": "WAP 2.0",
125516             "control": {
125517                 "type": "checkbox",
125518                 "value": false
125519             }
125520         },
125521         "MDS": {
125522             "name": "MDS",
125523             "control": {
125524                 "type": "checkbox",
125525                 "value": true
125526             }
125527         },
125528         "Bis B": {
125529             "name": "BIS B",
125530             "control": {
125531                 "type": "checkbox",
125532                 "value": true
125533             }
125534         },
125535         "Unite!": {
125536             "name": "Unite",
125537             "control": {
125538                 "type": "checkbox",
125539                 "value": false
125540             }
125541         },
125542         "TCP Wifi": {
125543             "name": "Wifi TCP",
125544             "control": {
125545                 "type": "checkbox",
125546                 "value": true
125547             }
125548         }
125549     },
125550     "identity": {
125551         "IMEI": {
125552             "name": "IMEI",
125553             "control": {
125554                 "type": "text",
125555                 "value": "123456786543210"
125556             }
125557         },
125558         "IMSI": {
125559             "name": "IMSI",
125560             "control": {
125561                 "type": "text",
125562                 "value": "310150123456789"
125563             }
125564         },
125565         "PIN": {
125566             "name": "PIN",
125567             "control": {
125568                 "type": "text",
125569                 "value": "43A8C489"
125570             }
125571         }
125572     },
125573     "system": {
125574         "isMassStorageActive": {
125575             "name": "Mass Storage Is Connected",
125576             "control": {
125577                 "type": "checkbox",
125578                 "value": true
125579             }
125580         },
125581         "hasDataCoverage": {
125582             "name": "Has Data Coverage",
125583             "control": {
125584                 "type": "checkbox",
125585                 "value": true
125586             },
125587             "callback": function (setting) {
125588                 event.trigger("CoverageChange");
125589                 require('ripple/bus').send("network", setting);
125590             }
125591         },
125592         "lag": {
125593             "name": "Lag the network",
125594             "control": {
125595                 type: "checkbox",
125596                 value: false
125597             },
125598             "callback": function (setting) {
125599                 require('ripple/bus').send("lag", setting);
125600             }
125601         },
125602         "network": {
125603             "name": "Data Network",
125604             "control": {
125605                 "type": "select",
125606                 "value": "3GPP"
125607             },
125608             "options": {
125609                 "3GPP" : "3GPP",
125610                 "CDMA": "CDMA",
125611                 "iDEN": "iDEN",
125612                 "Wi-Fi": "Wi-Fi"
125613             },
125614             "callback": function (setting) {
125615                 event.trigger("CoverageChange");
125616             }
125617         }
125618     }
125619 };
125620
125621 });
125622 define('ripple/platform/webworks.handset/2.0.0/spec/events', function (require, exports, module) {
125623 /*
125624  *  Copyright 2011 Research In Motion Limited.
125625  *
125626  * Licensed under the Apache License, Version 2.0 (the "License");
125627  * you may not use this file except in compliance with the License.
125628  * You may obtain a copy of the License at
125629  *
125630  * http://www.apache.org/licenses/LICENSE-2.0
125631  *
125632  * Unless required by applicable law or agreed to in writing, software
125633  * distributed under the License is distributed on an "AS IS" BASIS,
125634  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
125635  * See the License for the specific language governing permissions and
125636  * limitations under the License.
125637  */
125638 var _self,
125639     utils = require('ripple/utils'),
125640     event = require('ripple/event'),
125641     events = require('ripple/platform/webworks.core/2.0.0/spec/events');
125642
125643 _self = {
125644     "system.event.onExit": {
125645         callback: function () {
125646             event.trigger("AppExit");
125647         }
125648     },
125649     "system.event.onCoverageChange": {
125650         callback: function () {
125651             event.trigger("CoverageChange");
125652         }
125653     },
125654     "system.event.onHardwareKey": {
125655         args: [
125656             "Back",
125657             "Menu",
125658             "Convenience 1",
125659             "Convenience 2",
125660             "Start Call",
125661             "End Call",
125662             "Volume Down",
125663             "Volume Up"
125664         ],
125665         callback: function (key) {
125666             event.trigger("HardwareKey", [key]);
125667         }
125668     }
125669 };
125670
125671 utils.mixin(events, _self);
125672
125673 module.exports = _self;
125674
125675 });
125676 define('ripple/platform/webworks.handset/2.0.0/spec/ui', function (require, exports, module) {
125677 /*
125678  *  Copyright 2011 Research In Motion Limited.
125679  *
125680  * Licensed under the Apache License, Version 2.0 (the "License");
125681  * you may not use this file except in compliance with the License.
125682  * You may obtain a copy of the License at
125683  *
125684  * http://www.apache.org/licenses/LICENSE-2.0
125685  *
125686  * Unless required by applicable law or agreed to in writing, software
125687  * distributed under the License is distributed on an "AS IS" BASIS,
125688  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
125689  * See the License for the specific language governing permissions and
125690  * limitations under the License.
125691  */
125692 module.exports = {
125693     plugins: [
125694         "accelerometer",
125695         "deviceSettings",
125696         "geoView",
125697         "platformEvents",
125698         "widgetConfig",
125699         "messaging",
125700         "push",
125701         "phone",
125702         "build"
125703     ]
125704 };
125705
125706 });
125707 define('ripple/platform/webworks.handset/2.0.0/spec', function (require, exports, module) {
125708 /*
125709  *  Copyright 2011 Research In Motion Limited.
125710  *
125711  * Licensed under the Apache License, Version 2.0 (the "License");
125712  * you may not use this file except in compliance with the License.
125713  * You may obtain a copy of the License at
125714  *
125715  * http://www.apache.org/licenses/LICENSE-2.0
125716  *
125717  * Unless required by applicable law or agreed to in writing, software
125718  * distributed under the License is distributed on an "AS IS" BASIS,
125719  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
125720  * See the License for the specific language governing permissions and
125721  * limitations under the License.
125722  */
125723 module.exports = {
125724
125725     id: "webworks.handset",
125726     version: "2.0.0",
125727     name: "WebWorks",
125728
125729     persistencePrefix: "rim-handset-",
125730
125731     ui: require('ripple/platform/webworks.handset/2.0.0/spec/ui'),
125732     device: require('ripple/platform/webworks.handset/2.0.0/spec/device'),
125733     config: require('ripple/platform/webworks.core/2.0.0/spec/config'),
125734     events: require('ripple/platform/webworks.handset/2.0.0/spec/events'),
125735
125736     initialize: function () {},
125737
125738     objects: {
125739         XMLHttpRequest: {
125740             path: "webworks.handset/2.0.0/XMLHttpRequest"
125741         },
125742         Coordinates: {
125743             path: "w3c/1.0/Coordinates"
125744         },
125745         Position: {
125746             path: "w3c/1.0/Position"
125747         },
125748         PositionError: {
125749             path: "w3c/1.0/PositionError"
125750         },
125751         navigator: {
125752             path: "w3c/1.0/navigator",
125753             children: {
125754                 geolocation: {
125755                     path: "w3c/1.0/geolocation"
125756                 }
125757             }
125758         },
125759         blackberry: {
125760             path: "webworks.handset/2.0.0/client/blackberry",
125761             children: {
125762                 pim: {
125763                     path: "webworks.handset/2.0.0/client/pim",
125764                     feature: "blackberry.pim.category|blackberry.pim.Task|blackberry.pim.Recurrence|blackberry.pim.Reminder|blackberry.pim.Appointment|blackberry.pim.Address|blackberry.pim.Attendee|blackberry.pim.Memo|blackberry.pim.Contact",
125765                     children: {
125766                         category: {
125767                             path: "webworks.handset/2.0.0/client/category",
125768                             feature: "blackberry.pim.category"
125769                         },
125770                         Task: {
125771                             path: "webworks.handset/2.0.0/client/Task",
125772                             feature: "blackberry.pim.Task"
125773                         },
125774                         Recurrence: {
125775                             path: "webworks.handset/2.0.0/client/Recurrence",
125776                             feature: "blackberry.pim.Recurrence"
125777                         },
125778                         Reminder: {
125779                             path: "webworks.handset/2.0.0/client/Reminder",
125780                             feature: "blackberry.pim.Reminder"
125781                         },
125782                         Appointment: {
125783                             path: "webworks.handset/2.0.0/client/Appointment",
125784                             feature: "blackberry.pim.Appointment"
125785                         },
125786                         Address: {
125787                             path: "webworks.handset/2.0.0/client/Address",
125788                             feature: "blackberry.pim.Address"
125789                         },
125790                         Attendee: {
125791                             path: "webworks.handset/2.0.0/client/Attendee",
125792                             feature: "blackberry.pim.Attendee"
125793                         },
125794                         Memo: {
125795                             path: "webworks.handset/2.0.0/client/Memo",
125796                             feature: "blackberry.pim.Memo"
125797                         },
125798                         Contact: {
125799                             path: "webworks.handset/2.0.0/client/Contact",
125800                             feature: "blackberry.pim.Contact"
125801                         }
125802                     }
125803                 },
125804                 phone: {
125805                     children: {
125806                         Phone: {
125807                             path: "webworks.handset/2.0.0/client/Phone",
125808                             feature: "blackberry.phone.Phone"
125809                         },
125810                         PhoneLogs: {
125811                             path: "webworks.handset/2.0.0/client/PhoneLogs",
125812                             feature: "blackberry.phone.PhoneLogs|blackberry.phone.Find",
125813                             children: {
125814                                 CallLog: {
125815                                     path: "webworks.handset/2.0.0/client/CallLog"
125816                                 }
125817                             }
125818                         },
125819                         Find: {
125820                             children: {
125821                                 FilterExpression: {
125822                                     path: "webworks.handset/2.0.0/client/FilterExpression",
125823                                     feature: "blackberry.phone.Find"
125824                                 }
125825                             }
125826                         }
125827                     }
125828                 },
125829                 message: {
125830                     path: "webworks.handset/2.0.0/client/messaging",
125831                     feature: "blackberry.message.sms|blackberry.message",
125832                     children: {
125833                         sms: {
125834                             path: "webworks.handset/2.0.0/client/sms",
125835                             feature: "blackberry.message.sms"
125836                         },
125837                         Message: {
125838                             path: "webworks.handset/2.0.0/client/Message",
125839                             feature: "blackberry.message"
125840                         }
125841                     }
125842                 },
125843                 transport: {
125844                     path: "webworks.core/2.0.0/client/transport"
125845                 },
125846                 events: {
125847                     path: "webworks.core/2.0.0/client/events"
125848                 },
125849                 app: {
125850                     path: "webworks.handset/2.0.0/client/app",
125851                     feature: "blackberry.app",
125852                     children: {
125853                         event: {
125854                             path: "webworks.handset/2.0.0/client/appEvent",
125855                             feature: "blackberry.app.event"
125856                         }
125857                     }
125858                 },
125859                 invoke: {
125860                     path: "webworks.handset/2.0.0/client/invoke",
125861                     feature: "blackberry.invoke",
125862                     children: {
125863                         AddressBookArguments: {
125864                             path: "webworks.handset/2.0.0/client/AddressBookArguments",
125865                             feature: "blackberry.invoke.AddressBookArguments"
125866                         },
125867                         BrowserArguments: {
125868                             path: "webworks.handset/2.0.0/client/BrowserArguments",
125869                             feature: "blackberry.invoke.BrowserArguments"
125870                         },
125871                         CameraArguments: {
125872                             path: "webworks.handset/2.0.0/client/CameraArguments",
125873                             feature: "blackberry.invoke.CameraArguments"
125874                         },
125875                         CalendarArguments: {
125876                             path: "webworks.handset/2.0.0/client/CalendarArguments",
125877                             feature: "blackberry.invoke.CalendarArguments"
125878                         },
125879                         JavaArguments: {
125880                             path: "webworks.handset/2.0.0/client/JavaArguments",
125881                             feature: "blackberry.invoke.JavaArguments"
125882                         },
125883                         MapsArguments: {
125884                             path: "webworks.handset/2.0.0/client/MapsArguments",
125885                             feature: "blackberry.invoke.MapsArguments"
125886                         },
125887                         MemoArguments: {
125888                             path: "webworks.handset/2.0.0/client/MemoArguments",
125889                             feature: "blackberry.invoke.MemoArguments"
125890                         },
125891                         MessageArguments: {
125892                             path: "webworks.handset/2.0.0/client/MessageArguments",
125893                             feature: "blackberry.invoke.MessageArguments"
125894                         },
125895                         PhoneArguments: {
125896                             path: "webworks.handset/2.0.0/client/PhoneArguments",
125897                             feature: "blackberry.invoke.PhoneArguments"
125898                         },
125899                         SearchArguments: {
125900                             path: "webworks.handset/2.0.0/client/SearchArguments",
125901                             feature: "blackberry.invoke.SearchArguments"
125902                         },
125903                         TaskArguments: {
125904                             path: "webworks.handset/2.0.0/client/TaskArguments",
125905                             feature: "blackberry.invoke.TaskArguments"
125906                         }
125907                     }
125908                 },
125909                 identity: {
125910                     path: "webworks.handset/2.0.0/client/identity",
125911                     feature: "blackberry.identity",
125912                     children: {
125913                         Transport: {
125914                             path: "webworks.handset/2.0.0/client/identity/Transport",
125915                             feature: "blackberry.identity"
125916                         },
125917                         Service: {
125918                             path: "webworks.handset/2.0.0/client/identity/Service",
125919                             feature: "blackberry.identity"
125920                         },
125921                         phone: {
125922                             path: "webworks.handset/2.0.0/client/identity/phone",
125923                             feature: "blackberry.identity.phone"
125924                         }
125925                     }
125926                 },
125927                 system: {
125928                     path: "webworks.handset/2.0.0/client/system",
125929                     feature: "blackberry.system",
125930                     children: {
125931                         event: {
125932                             path: "webworks.handset/2.0.0/client/systemEvent",
125933                             feature: "blackberry.system.event"
125934                         }
125935                     }
125936                 },
125937                 ui: {
125938                     children: {
125939                         dialog: {
125940                             path: "webworks.core/2.0.0/client/dialog",
125941                             feature: "blackberry.ui.dialog"
125942                         },
125943                         menu: {
125944                             path: "webworks.handset/2.0.0/client/menu",
125945                             children: {
125946                                 MenuItem: {
125947                                     path: "webworks.handset/2.0.0/client/MenuItem"
125948                                 }
125949                             }
125950                         }
125951                     }
125952                 },
125953                 utils: {
125954                     path: "webworks.core/2.0.0/client/utils",
125955                     feature: "blackberry.utils"
125956                 },
125957                 find: {
125958                     feature: "blackberry.find",
125959                     children: {
125960                         FilterExpression: {
125961                             path: "webworks.handset/2.0.0/client/FilterExpression",
125962                             feature: "blackberry.find"
125963                         }
125964                     }
125965                 },
125966                 push: {
125967                     path: "webworks.handset/2.0.0/client/push",
125968                     feature: "blackberry.push"
125969                 },
125970                 audio: {
125971                     path: "webworks.handset/2.0.0/client/audio",
125972                     feature: "blackberry.audio",
125973                     children: {
125974                         Player: {
125975                             path: "webworks.handset/2.0.0/client/AudioPlayer",
125976                             feature: "blackberry.audio.Player"
125977                         }
125978                     }
125979                 },
125980                 io: {
125981                     children: {
125982                         dir: {
125983                             path: "webworks.handset/2.0.0/client/io/dir",
125984                             feature: "blackberry.io.dir"
125985                         },
125986                         file: {
125987                             path: "webworks.core/2.0.0/client/io/file",
125988                             feature: "blackberry.io.file"
125989                         }
125990                     }
125991                 }
125992             }
125993         }
125994     }
125995 };
125996
125997 });
125998 define('ripple/platform/webworks.tablet/2.0.0/XMLHttpRequest', function (require, exports, module) {
125999 /*
126000  *  Copyright 2011 Research In Motion Limited.
126001  *
126002  * Licensed under the Apache License, Version 2.0 (the "License");
126003  * you may not use this file except in compliance with the License.
126004  * You may obtain a copy of the License at
126005  *
126006  * http://www.apache.org/licenses/LICENSE-2.0
126007  *
126008  * Unless required by applicable law or agreed to in writing, software
126009  * distributed under the License is distributed on an "AS IS" BASIS,
126010  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
126011  * See the License for the specific language governing permissions and
126012  * limitations under the License.
126013  */
126014
126015 var xhr = require("ripple/platform/webworks.core/2.0.0/XMLHttpRequest");
126016 module.exports = xhr.create("ripple/platform/webworks.tablet/2.0.0/server");
126017
126018 });
126019 define('ripple/platform/webworks.tablet/2.0.0/client/BrowserArguments', function (require, exports, module) {
126020 /*
126021  *  Copyright 2011 Research In Motion Limited.
126022  *
126023  * Licensed under the Apache License, Version 2.0 (the "License");
126024  * you may not use this file except in compliance with the License.
126025  * You may obtain a copy of the License at
126026  *
126027  * http://www.apache.org/licenses/LICENSE-2.0
126028  *
126029  * Unless required by applicable law or agreed to in writing, software
126030  * distributed under the License is distributed on an "AS IS" BASIS,
126031  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
126032  * See the License for the specific language governing permissions and
126033  * limitations under the License.
126034  */
126035 //blackberry.invoke.BrowserArguments ( url : String ,  [transport : blackberry.identity.Transport ] )
126036 module.exports = function (url, transport) {
126037     return {
126038         url: url
126039     };
126040 };
126041
126042 });
126043 define('ripple/platform/webworks.tablet/2.0.0/client/CameraArguments', function (require, exports, module) {
126044 /*
126045  *  Copyright 2011 Research In Motion Limited.
126046  *
126047  * Licensed under the Apache License, Version 2.0 (the "License");
126048  * you may not use this file except in compliance with the License.
126049  * You may obtain a copy of the License at
126050  *
126051  * http://www.apache.org/licenses/LICENSE-2.0
126052  *
126053  * Unless required by applicable law or agreed to in writing, software
126054  * distributed under the License is distributed on an "AS IS" BASIS,
126055  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
126056  * See the License for the specific language governing permissions and
126057  * limitations under the License.
126058  */
126059 //blackberry.invoke.CameraArguments ( )
126060 var _self = function () {
126061     return {
126062         //readwrite  property  Number   view
126063         view: 0
126064     };
126065 };
126066
126067 //const Number  VIEW_CAMERA  = 0
126068 _self.__defineGetter__("VIEW_CAMERA", function () {
126069     return 0;
126070 });
126071 //const Number  VIEW_RECORDER  = 1
126072 _self.__defineGetter__("VIEW_RECORDER", function () {
126073     return 1;
126074 });
126075
126076 module.exports = _self;
126077
126078 });
126079 define('ripple/platform/webworks.tablet/2.0.0/client/app', function (require, exports, module) {
126080 /*
126081  *  Copyright 2011 Research In Motion Limited.
126082  *
126083  * Licensed under the Apache License, Version 2.0 (the "License");
126084  * you may not use this file except in compliance with the License.
126085  * You may obtain a copy of the License at
126086  *
126087  * http://www.apache.org/licenses/LICENSE-2.0
126088  *
126089  * Unless required by applicable law or agreed to in writing, software
126090  * distributed under the License is distributed on an "AS IS" BASIS,
126091  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
126092  * See the License for the specific language governing permissions and
126093  * limitations under the License.
126094  */
126095 var transport = require('ripple/platform/webworks.core/2.0.0/client/transport'),
126096     _uri = "blackberry/app/",
126097     _self;
126098
126099 _self = {
126100     exit: function () {
126101         transport.call(_uri + "exit", {async: true});
126102     }
126103 };
126104
126105 _self.__defineGetter__("author", function () {
126106     return transport.call(_uri + "author");
126107 });
126108
126109 _self.__defineGetter__("authorEmail", function () {
126110     return transport.call(_uri + "authorEmail");
126111 });
126112
126113 _self.__defineGetter__("authorURL", function () {
126114     return transport.call(_uri + "authorURL");
126115 });
126116
126117 _self.__defineGetter__("copyright", function () {
126118     return transport.call(_uri + "copyright");
126119 });
126120
126121 _self.__defineGetter__("description", function () {
126122     return transport.call(_uri + "description");
126123 });
126124
126125 _self.__defineGetter__("id", function () {
126126     return transport.call(_uri + "id");
126127 });
126128
126129 _self.__defineGetter__("license", function () {
126130     return transport.call(_uri + "license");
126131 });
126132
126133 _self.__defineGetter__("licenseURL", function () {
126134     return transport.call(_uri + "licenseURL");
126135 });
126136
126137 _self.__defineGetter__("name", function () {
126138     return transport.call(_uri + "name");
126139 });
126140
126141 _self.__defineGetter__("version", function () {
126142     return transport.call(_uri + "version");
126143 });
126144
126145 module.exports = _self;
126146
126147 });
126148 define('ripple/platform/webworks.tablet/2.0.0/client/appEvent', function (require, exports, module) {
126149 /*
126150  *  Copyright 2011 Research In Motion Limited.
126151  *
126152  * Licensed under the Apache License, Version 2.0 (the "License");
126153  * you may not use this file except in compliance with the License.
126154  * You may obtain a copy of the License at
126155  *
126156  * http://www.apache.org/licenses/LICENSE-2.0
126157  *
126158  * Unless required by applicable law or agreed to in writing, software
126159  * distributed under the License is distributed on an "AS IS" BASIS,
126160  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
126161  * See the License for the specific language governing permissions and
126162  * limitations under the License.
126163  */
126164 var transport = require('ripple/platform/webworks.core/2.0.0/client/transport'),
126165     _callbacks = {},
126166     _self;
126167
126168 function _poll(evt, handler) {
126169     _callbacks[evt] = handler;
126170
126171     transport.poll("blackberry/app/event/" + evt, {}, function () {
126172         var func = _callbacks[evt];
126173
126174         if (func) {
126175             func();
126176         }
126177
126178         return !!func;
126179     });
126180 }
126181
126182 _self = {
126183     onBackground: function (handler) {
126184         _poll("onBackground", handler);
126185     },
126186
126187     onForeground: function (handler) {
126188         _poll("onForeground", handler);
126189     },
126190
126191     onSwipeDown: function (handler) {
126192         _poll("onSwipeDown", handler);
126193     },
126194
126195     onSwipeStart: function (handler) {
126196         _poll("onSwipeStart", handler);
126197     }
126198 };
126199
126200 module.exports = _self;
126201
126202 });
126203 define('ripple/platform/webworks.tablet/2.0.0/client/identity', function (require, exports, module) {
126204 /*
126205  *  Copyright 2011 Research In Motion Limited.
126206  *
126207  * Licensed under the Apache License, Version 2.0 (the "License");
126208  * you may not use this file except in compliance with the License.
126209  * You may obtain a copy of the License at
126210  *
126211  * http://www.apache.org/licenses/LICENSE-2.0
126212  *
126213  * Unless required by applicable law or agreed to in writing, software
126214  * distributed under the License is distributed on an "AS IS" BASIS,
126215  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
126216  * See the License for the specific language governing permissions and
126217  * limitations under the License.
126218  */
126219 var transport = require('ripple/platform/webworks.core/2.0.0/client/transport'),
126220     _uri = "blackberry/identity/",
126221     _self = {};
126222
126223 _self.__defineGetter__("PIN", function () {
126224     return transport.call(_uri + "PIN");
126225 });
126226
126227 module.exports = _self;
126228
126229 });
126230 define('ripple/platform/webworks.tablet/2.0.0/client/invoke', function (require, exports, module) {
126231 /*\r
126232  *  Copyright 2011 Research In Motion Limited.\r
126233  *\r
126234  * Licensed under the Apache License, Version 2.0 (the "License");\r
126235  * you may not use this file except in compliance with the License.\r
126236  * You may obtain a copy of the License at\r
126237  *\r
126238  * http://www.apache.org/licenses/LICENSE-2.0\r
126239  *\r
126240  * Unless required by applicable law or agreed to in writing, software\r
126241  * distributed under the License is distributed on an "AS IS" BASIS,\r
126242  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
126243  * See the License for the specific language governing permissions and\r
126244  * limitations under the License.\r
126245  */\r
126246 var _uri = "blackberry/invoke/invoke",\r
126247     APP_TYPE = "appType",\r
126248     APP_URL_CAMERA = "camera://",\r
126249     APP_URL_CAMERA_VIDEO = "camera://video",\r
126250     APP_URL_MAP = "map://",\r
126251     APP_URL_MUSIC = "music://",\r
126252     APP_URL_PHOTOS = "photos://",\r
126253     APP_URL_VIDEOS = "videos://",\r
126254     APP_URL_APPWORLD = "appworld://",\r
126255     APP_URL_UPDATE = "update://",\r
126256     APP_TYPE_ERROR = "appType not supported",\r
126257     APP_BROWSER_ERROR = "Protocol specified in the url is not supported.",\r
126258     transport = require('ripple/platform/webworks.core/2.0.0/client/transport'),\r
126259     _self;\r
126260 \r
126261 _self = {\r
126262     invoke: function (appType, args) {\r
126263         var get = {};\r
126264 \r
126265         switch (appType) {\r
126266 \r
126267         //Camera\r
126268         case 4:\r
126269             if (!args || args.view === 1) {\r
126270                 get.appType = APP_URL_CAMERA_VIDEO;\r
126271             } else {\r
126272                 get.appType = APP_URL_CAMERA;\r
126273             }\r
126274             break;\r
126275 \r
126276         //Maps\r
126277         case 5:\r
126278             get.appType = APP_URL_MAP;\r
126279             break;\r
126280 \r
126281         //Browser\r
126282         case 11:\r
126283 \r
126284             if (!args) {\r
126285                 get.appType = "http://";\r
126286             }\r
126287             else {\r
126288                 get.appType = args.url.split("://");\r
126289 \r
126290                 if (get.appType.length === 1) {\r
126291                     get.appType = "http://" + get.appType[0];\r
126292                 }\r
126293                 else if (get.appType.length === 2) {\r
126294                     if (get.appType[0].indexOf("http") !== 0) {\r
126295                         throw APP_BROWSER_ERROR;\r
126296                     }\r
126297                     else {\r
126298                         get.appType = args.url;\r
126299                     }\r
126300                 }\r
126301             }\r
126302             break;\r
126303 \r
126304         //Music\r
126305         case 13:\r
126306             get.appType = APP_URL_MUSIC;\r
126307             break;\r
126308 \r
126309         //Photos\r
126310         case 14:\r
126311             get.appType = APP_URL_PHOTOS;\r
126312             break;\r
126313 \r
126314         //Videos\r
126315         case 15:\r
126316             get.appType = APP_URL_VIDEOS;\r
126317             break;\r
126318 \r
126319         //AppWorld\r
126320         case 16:\r
126321             get.appType = APP_URL_APPWORLD;\r
126322             break;\r
126323 \r
126324         //Update\r
126325         case 17:\r
126326             get.appType = APP_URL_UPDATE;\r
126327             break;\r
126328 \r
126329         default:\r
126330             throw APP_TYPE_ERROR;\r
126331         }\r
126332 \r
126333         transport.call(_uri, {\r
126334             get: get,\r
126335             async: true\r
126336         });\r
126337     }\r
126338 };\r
126339 \r
126340 _self.__defineGetter__("APP_CAMERA", function () {\r
126341     return 4;\r
126342 });\r
126343 _self.__defineGetter__("APP_MAPS", function () {\r
126344     return 5;\r
126345 });\r
126346 _self.__defineGetter__("APP_BROWSER", function () {\r
126347     return 11;\r
126348 });\r
126349 _self.__defineGetter__("APP_MUSIC", function () {\r
126350     return 13;\r
126351 });\r
126352 _self.__defineGetter__("APP_PHOTOS", function () {\r
126353     return 14;\r
126354 });\r
126355 _self.__defineGetter__("APP_VIDEOS", function () {\r
126356     return 15;\r
126357 });\r
126358 _self.__defineGetter__("APP_APPWORLD", function () {\r
126359     return 16;\r
126360 });\r
126361 \r
126362 module.exports = _self;\r
126363
126364 });
126365 define('ripple/platform/webworks.tablet/2.0.0/client/io/dir', function (require, exports, module) {
126366 /*
126367  * Copyright 2011 Research In Motion Limited.
126368  *
126369  * Licensed under the Apache License, Version 2.0 (the "License");
126370  * you may not use this file except in compliance with the License.
126371  * You may obtain a copy of the License at
126372  *
126373  *     http://www.apache.org/licenses/LICENSE-2.0
126374  *
126375  * Unless required by applicable law or agreed to in writing, software
126376  * distributed under the License is distributed on an "AS IS" BASIS,
126377  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
126378  * See the License for the specific language governing permissions and
126379  * limitations under the License.
126380  */
126381 var dir = require('ripple/platform/webworks.core/2.0.0/client/io/dir'),
126382     utils = require('ripple/utils'),
126383     _self = {};
126384
126385 utils.mixin({
126386     appDirs: {
126387         "app": {
126388             "storage" : {
126389                 "path" : "file:///accounts/1000/appdata/emulatedapp/data"
126390             }
126391         },
126392         "shared": {
126393             "bookmarks": {
126394                 "path" : "file:///accounts/1000/appdata/emulatedapp/shared/bookmarks"
126395             },
126396             "books": {
126397                 "path" : "file:///accounts/1000/appdata/emulatedapp/shared/books"
126398             },
126399             "camera": {
126400                 "path" : "file:///accounts/1000/appdata/emulatedapp/shared/camera"
126401             },
126402             "documents": {
126403                 "path" : "file:///accounts/1000/appdata/emulatedapp/shared/documents"
126404             },
126405             "downloads": {
126406                 "path" : "file:///accounts/1000/appdata/emulatedapp/shared/downloads"
126407             },
126408             "misc": {
126409                 "path" : "file:///accounts/1000/appdata/emulatedapp/shared/misc"
126410             },
126411             "music": {
126412                 "path" : "file:///accounts/1000/appdata/emulatedapp/shared/music"
126413             },
126414             "photos": {
126415                 "path" : "file:///accounts/1000/appdata/emulatedapp/shared/photos"
126416             },
126417             "print": {
126418                 "path" : "file:///accounts/1000/appdata/emulatedapp/shared/print"
126419             },
126420             "videos": {
126421                 "path" : "file:///accounts/1000/appdata/emulatedapp/shared/videos"
126422             },
126423             "voice": {
126424                 "path" : "file:///accounts/1000/appdata/emulatedapp/shared/voice"
126425             }
126426         }
126427     }
126428 }, _self);
126429
126430 utils.mixin(dir, _self);
126431
126432 module.exports = _self;
126433
126434 });
126435 define('ripple/platform/webworks.tablet/2.0.0/client/system', function (require, exports, module) {
126436 /*
126437  *  Copyright 2011 Research In Motion Limited.
126438  *
126439  * Licensed under the Apache License, Version 2.0 (the "License");
126440  * you may not use this file except in compliance with the License.
126441  * You may obtain a copy of the License at
126442  *
126443  * http://www.apache.org/licenses/LICENSE-2.0
126444  *
126445  * Unless required by applicable law or agreed to in writing, software
126446  * distributed under the License is distributed on an "AS IS" BASIS,
126447  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
126448  * See the License for the specific language governing permissions and
126449  * limitations under the License.
126450  */
126451 var utils = require('ripple/utils'),
126452     transport = require('ripple/platform/webworks.core/2.0.0/client/transport'),
126453     system = require('ripple/platform/webworks.core/2.0.0/client/system'),
126454     _uri = "blackberry/system/";
126455
126456 system.__defineGetter__("scriptApiVersion", function () {
126457     return transport.call(_uri + "softwareVersion");
126458 });
126459
126460
126461 module.exports = system;
126462
126463 });
126464 define('ripple/platform/webworks.tablet/2.0.0/client/systemEvent', function (require, exports, module) {
126465 /*
126466  *  Copyright 2011 Research In Motion Limited.
126467  *
126468  * Licensed under the Apache License, Version 2.0 (the "License");
126469  * you may not use this file except in compliance with the License.
126470  * You may obtain a copy of the License at
126471  *
126472  * http://www.apache.org/licenses/LICENSE-2.0
126473  *
126474  * Unless required by applicable law or agreed to in writing, software
126475  * distributed under the License is distributed on an "AS IS" BASIS,
126476  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
126477  * See the License for the specific language governing permissions and
126478  * limitations under the License.
126479  */
126480 var transport = require('ripple/platform/webworks.core/2.0.0/client/transport'),
126481     api = "blackberry/system/event/";
126482
126483 function _poll(evt, handler) {
126484     transport.poll(api + evt, {}, function (data, response) {
126485         if (handler) {
126486             handler(data);
126487         }
126488         return !!handler;
126489     });
126490 }
126491
126492 module.exports = {
126493     deviceBatteryLevelChange: function (handler) {
126494         _poll("deviceBatteryLevelChange", handler);
126495     },
126496     deviceBatteryStateChange: function (handler) {
126497         _poll("deviceBatteryStateChange", handler);
126498     }
126499 };
126500
126501 });
126502 define('ripple/platform/webworks.tablet/2.0.0/server/app', function (require, exports, module) {
126503 /*
126504  *  Copyright 2011 Research In Motion Limited.
126505  *
126506  * Licensed under the Apache License, Version 2.0 (the "License");
126507  * you may not use this file except in compliance with the License.
126508  * You may obtain a copy of the License at
126509  *
126510  * http://www.apache.org/licenses/LICENSE-2.0
126511  *
126512  * Unless required by applicable law or agreed to in writing, software
126513  * distributed under the License is distributed on an "AS IS" BASIS,
126514  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
126515  * See the License for the specific language governing permissions and
126516  * limitations under the License.
126517  */
126518 var event = require('ripple/event'),
126519     app = require('ripple/app'),
126520     _self;
126521
126522 _self = {
126523     event: require('ripple/platform/webworks.tablet/2.0.0/server/appEvent'),
126524
126525     exit: function () {
126526         event.trigger("AppExit");
126527         return {code: 1};
126528     },
126529
126530     author: function () {
126531         return {code: 1, data: app.getInfo().author};
126532     },
126533
126534     authorEmail: function () {
126535         return {code: 1, data: app.getInfo().authorEmail};
126536     },
126537
126538     authorURL: function () {
126539         return {code: 1, data: app.getInfo().authorURL};
126540     },
126541
126542     copyright: function () {
126543         return {code: 1, data: app.getInfo().copyright};
126544     },
126545
126546     description: function () {
126547         return {code: 1, data: app.getInfo().description};
126548     },
126549
126550     id: function () {
126551         return {code: 1, data: app.getInfo().id};
126552     },
126553
126554     license: function () {
126555         return {code: 1, data: app.getInfo().license};
126556     },
126557
126558     licenseURL: function () {
126559         return {code: 1, data: app.getInfo().licenseURL};
126560     },
126561
126562     name: function () {
126563         return {code: 1, data: app.getInfo().name};
126564     },
126565
126566     version: function () {
126567         return {code: 1, data: app.getInfo().version};
126568     }
126569 };
126570
126571 module.exports = _self;
126572
126573 });
126574 define('ripple/platform/webworks.tablet/2.0.0/server/appEvent', function (require, exports, module) {
126575 /*
126576  *  Copyright 2011 Research In Motion Limited.
126577  *
126578  * Licensed under the Apache License, Version 2.0 (the "License");
126579  * you may not use this file except in compliance with the License.
126580  * You may obtain a copy of the License at
126581  *
126582  * http://www.apache.org/licenses/LICENSE-2.0
126583  *
126584  * Unless required by applicable law or agreed to in writing, software
126585  * distributed under the License is distributed on an "AS IS" BASIS,
126586  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
126587  * See the License for the specific language governing permissions and
126588  * limitations under the License.
126589  */
126590 var event = require('ripple/event'),
126591     notifications = require('ripple/notifications'),
126592     _bg,
126593     _fg,
126594     _swipeDown,
126595     _swipeStart,
126596     _exit;
126597
126598 event.on("AppExit", function () {
126599     var baton = _exit;
126600     _exit = null;
126601     notifications.openNotification("normal", "blackberry.app.exit() as called, in the real world your app will exit, here... you get this notification");
126602     return baton && baton.pass({code: 1});
126603 });
126604
126605 event.on("AppRequestBackground", function () {
126606     var baton = _bg;
126607     _bg = null;
126608     return baton && baton.pass({code: 1});
126609 });
126610
126611 event.on("AppRequestForeground", function () {
126612     var baton = _fg;
126613     _fg = null;
126614     return baton && baton.pass({code: 1});
126615 });
126616
126617 event.on("AppSwipeDown", function () {
126618     var baton = _swipeDown;
126619     _swipeDown = null;
126620     return baton && baton.pass({code: 1});
126621 });
126622
126623 event.on("AppSwipeStart", function () {
126624     var baton = _swipeStart;
126625     _swipeStart = null;
126626     return baton && baton.pass({code: 1});
126627 });
126628
126629 module.exports = {
126630     onBackground: function (get, post, baton) {
126631         baton.take();
126632         _bg = baton;
126633         return {code: 1};
126634     },
126635
126636     onForeground: function (get, post, baton) {
126637         baton.take();
126638         _fg = baton;
126639         return {code: 1};
126640     },
126641
126642     onSwipeDown: function (get, post, baton) {
126643         baton.take();
126644         _swipeDown = baton;
126645         return {code: 1};
126646     },
126647
126648     onSwipeStart: function (get, post, baton) {
126649         baton.take();
126650         _swipeStart = baton;
126651         return {code: 1};
126652     }
126653 };
126654
126655 });
126656 define('ripple/platform/webworks.tablet/2.0.0/server/identity', function (require, exports, module) {
126657 /*
126658  *  Copyright 2011 Research In Motion Limited.
126659  *
126660  * Licensed under the Apache License, Version 2.0 (the "License");
126661  * you may not use this file except in compliance with the License.
126662  * You may obtain a copy of the License at
126663  *
126664  * http://www.apache.org/licenses/LICENSE-2.0
126665  *
126666  * Unless required by applicable law or agreed to in writing, software
126667  * distributed under the License is distributed on an "AS IS" BASIS,
126668  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
126669  * See the License for the specific language governing permissions and
126670  * limitations under the License.
126671  */
126672 var deviceSettings = require('ripple/deviceSettings');
126673
126674 module.exports = {
126675     PIN: function () {
126676         return {code: 1, data: deviceSettings.retrieve("identity.PIN")};
126677     }
126678 };
126679
126680 });
126681 define('ripple/platform/webworks.tablet/2.0.0/server/invoke', function (require, exports, module) {
126682 /*
126683  *  Copyright 2011 Research In Motion Limited.
126684  *
126685  * Licensed under the Apache License, Version 2.0 (the "License");
126686  * you may not use this file except in compliance with the License.
126687  * You may obtain a copy of the License at
126688  *
126689  * http://www.apache.org/licenses/LICENSE-2.0
126690  *
126691  * Unless required by applicable law or agreed to in writing, software
126692  * distributed under the License is distributed on an "AS IS" BASIS,
126693  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
126694  * See the License for the specific language governing permissions and
126695  * limitations under the License.
126696  */
126697 var notifications = require('ripple/notifications'),
126698     constants = require('ripple/constants'),
126699     type = "normal",
126700     name = {
126701         "camera://": "Camera",
126702         "camera://video": "Video Camera",
126703         "map://": "Maps",
126704         "http://": "Browser",
126705         "music://": "Music",
126706         "photos://": "Photos",
126707         "videos://": "Videos",
126708         "appworld://": "App World",
126709         "update://": "Update"
126710     };
126711
126712 module.exports = {
126713     invoke: function (opts) {
126714         var app = name[opts.appType];
126715         if (app === undefined && opts.appType && opts.appType.match(/^http/i)) {
126716             app = "Browser";
126717         }
126718
126719         notifications.openNotification(type,
126720            "Requested to launch: " + app + " application.");
126721         return {code: 1};
126722     }
126723 };
126724
126725 });
126726 define('ripple/platform/webworks.tablet/2.0.0/server/systemEvent', function (require, exports, module) {
126727 /*
126728  *  Copyright 2011 Research In Motion Limited.
126729  *
126730  * Licensed under the Apache License, Version 2.0 (the "License");
126731  * you may not use this file except in compliance with the License.
126732  * You may obtain a copy of the License at
126733  *
126734  * http://www.apache.org/licenses/LICENSE-2.0
126735  *
126736  * Unless required by applicable law or agreed to in writing, software
126737  * distributed under the License is distributed on an "AS IS" BASIS,
126738  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
126739  * See the License for the specific language governing permissions and
126740  * limitations under the License.
126741  */
126742 var event = require('ripple/event'),
126743     _onBatteryStateChange,
126744     _onBatteryLevelChange,
126745     _states = {
126746         UNKNOWN: 0,
126747         FULL: 1,
126748         CHARGING: 2,
126749         UNPLUGGED: 3
126750     },
126751     _battery = {
126752         state: _states.UNKNOWN,
126753         charging: null,
126754         level: null
126755     };
126756
126757 function _getState() {
126758     return _battery.level === 100 ? _states.FULL :
126759            _battery.charging ? _states.CHARGING : _states.UNPLUGGED;
126760 }
126761
126762 function _pass(baton, data) {
126763     if (baton) {
126764         baton.pass({code: 1, data: data});
126765     }
126766 }
126767
126768 event.on("DeviceBatteryStateChanged", function (charging) {
126769     _battery.charging = charging;
126770     _battery.state = _getState();
126771     _pass(_onBatteryStateChange, _battery.state);
126772 });
126773
126774 event.on("DeviceBatteryLevelChanged", function (level) {
126775     level = parseInt(level, 10);
126776
126777     _battery.level = level;
126778     _pass(_onBatteryLevelChange, level);
126779
126780     if (level === 100) {
126781         _battery.state = _getState();
126782         _pass(_onBatteryStateChange, _battery.state);
126783     }
126784 });
126785
126786 module.exports = {
126787     deviceBatteryLevelChange: function (get, post, baton) {
126788         baton.take();
126789         _onBatteryLevelChange = baton;
126790     },
126791     deviceBatteryStateChange: function (get, post, baton) {
126792         baton.take();
126793         _onBatteryStateChange = baton;
126794     }
126795 };
126796
126797 });
126798 define('ripple/platform/webworks.tablet/2.0.0/server', function (require, exports, module) {
126799 /*
126800  *  Copyright 2011 Research In Motion Limited.
126801  *
126802  * Licensed under the Apache License, Version 2.0 (the "License");
126803  * you may not use this file except in compliance with the License.
126804  * You may obtain a copy of the License at
126805  *
126806  * http://www.apache.org/licenses/LICENSE-2.0
126807  *
126808  * Unless required by applicable law or agreed to in writing, software
126809  * distributed under the License is distributed on an "AS IS" BASIS,
126810  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
126811  * See the License for the specific language governing permissions and
126812  * limitations under the License.
126813  */
126814 var utils = require('ripple/utils'),
126815     platform = "ripple/platform/webworks.tablet/2.0.0/server/",
126816     core = "ripple/platform/webworks.core/2.0.0/server/",
126817     systemEvent = require(platform + 'systemEvent'),
126818     system = {};
126819
126820 // ugh, thanks to the spec...
126821 system.event = systemEvent;
126822 utils.mixin(require(core + "system"), system);
126823
126824 module.exports = {
126825     blackberry: {
126826         identity: require(platform + "identity"),
126827         app: require(platform + "app"),
126828         invoke: require(platform + "invoke"),
126829         system: system,
126830         ui: {
126831             dialog: require(core + "dialog")
126832         },
126833         io: {
126834             dir: require(core + "io/dir"),
126835             file: require(core + "io/file")
126836         }
126837     }
126838 };
126839
126840 });
126841 define('ripple/platform/webworks.tablet/2.0.0/spec/device', function (require, exports, module) {
126842 /*
126843  *  Copyright 2011 Research In Motion Limited.
126844  *
126845  * Licensed under the Apache License, Version 2.0 (the "License");
126846  * you may not use this file except in compliance with the License.
126847  * You may obtain a copy of the License at
126848  *
126849  * http://www.apache.org/licenses/LICENSE-2.0
126850  *
126851  * Unless required by applicable law or agreed to in writing, software
126852  * distributed under the License is distributed on an "AS IS" BASIS,
126853  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
126854  * See the License for the specific language governing permissions and
126855  * limitations under the License.
126856  */
126857 var event = require('ripple/event');
126858
126859 module.exports = {
126860     "transports": {
126861         "TCPCellular": {
126862             "name": "Cellular TCP",
126863             "control": {
126864                 "type": "checkbox",
126865                 "value": true
126866             }
126867         },
126868         "WAP": {
126869             "name": "WAP",
126870             "control": {
126871                 "type": "checkbox",
126872                 "value": false
126873             }
126874         },
126875         "WAP2": {
126876             "name": "WAP 2.0",
126877             "control": {
126878                 "type": "checkbox",
126879                 "value": false
126880             }
126881         },
126882         "MDS": {
126883             "name": "MDS",
126884             "control": {
126885                 "type": "checkbox",
126886                 "value": true
126887             }
126888         },
126889         "BISB": {
126890             "name": "BIS B",
126891             "control": {
126892                 "type": "checkbox",
126893                 "value": true
126894             }
126895         },
126896         "Unite": {
126897             "name": "Unite!",
126898             "control": {
126899                 "type": "checkbox",
126900                 "value": false
126901             }
126902         },
126903         "TCPWifi": {
126904             "name": "Wifi TCP",
126905             "control": {
126906                 "type": "checkbox",
126907                 "value": true
126908             }
126909         }
126910     },
126911     "identity": {
126912         "PIN": {
126913             "name": "PIN",
126914             "control": {
126915                 "type": "text",
126916                 "value": "43A8C489"
126917             }
126918         }
126919     },
126920     "battery": {
126921         "state": {
126922             "name": "Handset is Charging",
126923             "control": {
126924                 "type": "checkbox",
126925                 "value": true
126926             },
126927             "callback": function (setting) {
126928                 event.trigger("DeviceBatteryStateChanged", [setting]);
126929             }
126930         },
126931         "level":  {
126932             "name": "Charge Level (% remaining)",
126933             "control": {
126934                 "type": "select",
126935                 "value": 100
126936             },
126937             "options": (function () {
126938                 var i,
126939                     optionList = {};
126940
126941                 for (i = 0; i <= 100; i++) {
126942                     optionList[i] = i;
126943                 }
126944
126945                 return optionList;
126946             }()),
126947             "callback": function (setting) {
126948                 event.trigger("DeviceBatteryLevelChanged", [setting]);
126949             }
126950         }
126951     },
126952     "system": {
126953         "isMassStorageActive": {
126954             "name": "Mass Storage Is Connected",
126955             "control": {
126956                 "type": "checkbox",
126957                 "value": true
126958             }
126959         },
126960         "hasDataCoverage": {
126961             "name": "Has Data Coverage",
126962             "control": {
126963                 "type": "checkbox",
126964                 "value": true
126965             },
126966             "callback": function (setting) {
126967                 event.trigger("CoverageChange");
126968                 require('ripple/bus').send("network", setting);
126969             }
126970         },
126971         "lag": {
126972             "name": "Lag the network",
126973             "control": {
126974                 type: "checkbox",
126975                 value: false
126976             },
126977             "callback": function (setting) {
126978                 require('ripple/bus').send("lag", setting);
126979             }
126980         },
126981         "network": {
126982             "name": "Data Network",
126983             "control": {
126984                 "type": "select",
126985                 "value": "3GPP"
126986             },
126987             "options": {
126988                 "3GPP" : "3GPP",
126989                 "CDMA": "CDMA",
126990                 "iDEN": "iDEN",
126991                 "Wi-Fi": "Wi-Fi"
126992             },
126993             "callback": function (setting) {
126994                 event.trigger("CoverageChange");
126995             }
126996         }
126997     }
126998 };
126999
127000 });
127001 define('ripple/platform/webworks.tablet/2.0.0/spec/events', function (require, exports, module) {
127002 /*
127003  *  Copyright 2011 Research In Motion Limited.
127004  *
127005  * Licensed under the Apache License, Version 2.0 (the "License");
127006  * you may not use this file except in compliance with the License.
127007  * You may obtain a copy of the License at
127008  *
127009  * http://www.apache.org/licenses/LICENSE-2.0
127010  *
127011  * Unless required by applicable law or agreed to in writing, software
127012  * distributed under the License is distributed on an "AS IS" BASIS,
127013  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
127014  * See the License for the specific language governing permissions and
127015  * limitations under the License.
127016  */
127017 var _self,
127018     utils = require('ripple/utils'),
127019     event = require('ripple/event'),
127020     events = require('ripple/platform/webworks.core/2.0.0/spec/events');
127021
127022 _self = {
127023     "app.event.onSwipeDown": {
127024         callback: function () {
127025             event.trigger("AppSwipeDown");
127026         }
127027     },
127028     "app.event.onSwipeStart": {
127029         callback: function () {
127030             event.trigger("AppSwipeStart");
127031         }
127032     }
127033 };
127034
127035 utils.mixin(events, _self);
127036
127037 module.exports = _self;
127038
127039 });
127040 define('ripple/platform/webworks.tablet/2.0.0/spec/ui', function (require, exports, module) {
127041 /*
127042  *  Copyright 2011 Research In Motion Limited.
127043  *
127044  * Licensed under the Apache License, Version 2.0 (the "License");
127045  * you may not use this file except in compliance with the License.
127046  * You may obtain a copy of the License at
127047  *
127048  * http://www.apache.org/licenses/LICENSE-2.0
127049  *
127050  * Unless required by applicable law or agreed to in writing, software
127051  * distributed under the License is distributed on an "AS IS" BASIS,
127052  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
127053  * See the License for the specific language governing permissions and
127054  * limitations under the License.
127055  */
127056 module.exports = {
127057     plugins: [
127058         "accelerometer",
127059         "deviceSettings",
127060         "geoView",
127061         "platformEvents",
127062         "widgetConfig",
127063         "build"
127064     ]
127065 };
127066
127067 });
127068 define('ripple/platform/webworks.tablet/2.0.0/spec', function (require, exports, module) {
127069 /*
127070  *  Copyright 2011 Research In Motion Limited.
127071  *
127072  * Licensed under the Apache License, Version 2.0 (the "License");
127073  * you may not use this file except in compliance with the License.
127074  * You may obtain a copy of the License at
127075  *
127076  * http://www.apache.org/licenses/LICENSE-2.0
127077  *
127078  * Unless required by applicable law or agreed to in writing, software
127079  * distributed under the License is distributed on an "AS IS" BASIS,
127080  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
127081  * See the License for the specific language governing permissions and
127082  * limitations under the License.
127083  */
127084 module.exports = {
127085
127086     id: "webworks.tablet",
127087     version: "2.0.0",
127088     name: "WebWorks-TabletOS",
127089
127090     persistencePrefix: "rim-tablet-",
127091
127092     ui: require('ripple/platform/webworks.tablet/2.0.0/spec/ui'),
127093     device: require('ripple/platform/webworks.tablet/2.0.0/spec/device'),
127094     config: require('ripple/platform/webworks.core/2.0.0/spec/config'),
127095     events: require('ripple/platform/webworks.tablet/2.0.0/spec/events'),
127096
127097     initialize: function () {},
127098
127099     objects: {
127100         XMLHttpRequest: {
127101             path: "webworks.tablet/2.0.0/XMLHttpRequest"
127102         },
127103         Coordinates: {
127104             path: "w3c/1.0/Coordinates"
127105         },
127106         Position: {
127107             path: "w3c/1.0/Position"
127108         },
127109         PositionError: {
127110             path: "w3c/1.0/PositionError"
127111         },
127112         navigator: {
127113             path: "w3c/1.0/navigator",
127114             children: {
127115                 geolocation: {
127116                     path: "w3c/1.0/geolocation"
127117                 }
127118             }
127119         },
127120         blackberry: {
127121             children: {
127122                 transport: {
127123                     path: "webworks.core/2.0.0/client/transport"
127124                 },
127125                 events: {
127126                     path: "webworks.core/2.0.0/client/events"
127127                 },
127128                 app: {
127129                     path: "webworks.tablet/2.0.0/client/app",
127130                     feature: "blackberry.app",
127131                     children: {
127132                         event: {
127133                             path: "webworks.tablet/2.0.0/client/appEvent",
127134                             feature: "blackberry.app.event"
127135                         }
127136                     }
127137                 },
127138                 invoke: {
127139                     path: "webworks.tablet/2.0.0/client/invoke",
127140                     feature: "blackberry.invoke",
127141                     children: {
127142                         BrowserArguments: {
127143                             path: "webworks.tablet/2.0.0/client/BrowserArguments",
127144                             feature: "blackberry.invoke.BrowserArguments"
127145                         },
127146                         CameraArguments: {
127147                             path: "webworks.tablet/2.0.0/client/CameraArguments",
127148                             feature: "blackberry.invoke.CameraArguments"
127149                         }
127150                     }
127151                 },
127152                 identity: {
127153                     path: "webworks.tablet/2.0.0/client/identity",
127154                     feature: "blackberry.identity"
127155                 },
127156                 system: {
127157                     path: "webworks.tablet/2.0.0/client/system",
127158                     children: {
127159                         event: {
127160                             path: "webworks.tablet/2.0.0/client/systemEvent"
127161                         }
127162                     }
127163                 },
127164                 ui: {
127165                     children: {
127166                         dialog: {
127167                             path: "webworks.core/2.0.0/client/dialog",
127168                             feature: "blackberry.ui.dialog"
127169                         }
127170                     }
127171                 },
127172                 utils: {
127173                     path: "webworks.core/2.0.0/client/utils",
127174                     feature: "blackberry.utils"
127175                 },
127176                 io: {
127177                     children: {
127178                         dir: {
127179                             path: "webworks.tablet/2.0.0/client/io/dir",
127180                             feature: "blackberry.io.dir"
127181                         },
127182                         file: {
127183                             path: "webworks.core/2.0.0/client/io/file",
127184                             feature: "blackberry.io.file"
127185                         }
127186                     }
127187                 }
127188             }
127189         }
127190     }
127191 };
127192
127193 });
127194 define('ripple/platform', function (require, exports, module) {
127195 /*
127196  *  Copyright 2011 Research In Motion Limited.
127197  *
127198  * Licensed under the Apache License, Version 2.0 (the "License");
127199  * you may not use this file except in compliance with the License.
127200  * You may obtain a copy of the License at
127201  *
127202  * http://www.apache.org/licenses/LICENSE-2.0
127203  *
127204  * Unless required by applicable law or agreed to in writing, software
127205  * distributed under the License is distributed on an "AS IS" BASIS,
127206  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
127207  * See the License for the specific language governing permissions and
127208  * limitations under the License.
127209  */
127210 var _current,
127211     db = require('ripple/db'),
127212     utils = require('ripple/utils'),
127213     _console = require('ripple/console'),
127214     app = require('ripple/app'),
127215     event = require('ripple/event'),
127216     spec = require('ripple/platform/spec'),
127217     _self;
127218
127219 function _getRequestedPlatform() {
127220     var requestedPlatform = null,
127221         enableRippleArg = utils.queryString().enableripple,
127222         platform;
127223
127224     if (enableRippleArg) {
127225         enableRippleArg = enableRippleArg.split('-');
127226         platform = spec.get(enableRippleArg[0], enableRippleArg[1]);
127227         if (platform) {
127228             requestedPlatform = { name: platform.id, version: platform.version };
127229         }
127230     }
127231
127232     return requestedPlatform;
127233 }
127234
127235 function _validatePlatform(platform, defaultPlatform) {
127236     if (!platform ||
127237         !spec[platform.name] ||
127238         !spec[platform.name][platform.version] ||
127239         (spec[platform.name][platform.version] && !spec[platform.name][platform.version].objects)) {
127240         return defaultPlatform;
127241     }
127242     return platform;
127243 }
127244
127245 function _getPlatform() {
127246     return require('ripple/platform/' + _current.name + "/" + _current.version + "/spec");
127247 }
127248
127249 _self = {
127250     initialize: function () {
127251         var firstAvailablePlatform = utils.map(this.getList(), function (platform) {
127252             return utils.map(platform, function (details, version) {
127253                 return {name: details.id, version: version};
127254             })[0];
127255         })[0];
127256
127257         _current = _getRequestedPlatform() || db.retrieveObject("api-key") || firstAvailablePlatform;
127258         _current = _validatePlatform(_current, firstAvailablePlatform);
127259         db.saveObject("api-key", _current);
127260
127261         _console.prefix = _current.name;
127262     },
127263
127264     getList: function () {
127265         var platformList = {};
127266         utils.forEach(spec, function (platform, platformKey) {
127267             utils.forEach(platform, function (version, versionKey) {
127268                 platformList[platformKey] = platformList[platformKey] || {};
127269                 platformList[platformKey][versionKey] = {
127270                     "id": version.id,
127271                     "name": version.name,
127272                     "type": version.type,
127273                     "text": require('ripple/platform/' + platformKey + "/" + versionKey + "/spec").version
127274                 };
127275             });
127276         });
127277
127278         return platformList;
127279     },
127280
127281     getPersistencePrefix: function (id) {
127282         return _getPlatform().persistencePrefix + (id || app.getInfo().id) + "-";
127283     },
127284
127285     current: function () {
127286         return _getPlatform();
127287     },
127288
127289     changeEnvironment: function (platform, deviceId, callback) {
127290         var save = jWorkflow.order(function (prev, baton) {
127291                 baton.take();
127292                 db.saveObject("api-key", platform, null, baton.pass);
127293             }).andThen(function (prev, baton) {
127294                 baton.take();
127295                 db.save("device-key", deviceId, null, baton.pass);
127296             }).andThen(function (prev, baton) {
127297                 //remove the persisted value for the layout
127298                 baton.take();
127299                 db.save("layout", null, null, baton.pass);
127300             }).andThen(function () {
127301                 event.trigger("PlatformChangedEvent", [], true);
127302                 _console.prefix = null;
127303                 _console.log("Emulator :: loading platform " + platform.name);
127304             });
127305
127306         save.start(callback);
127307     }
127308 };
127309
127310 module.exports = _self;
127311
127312 });
127313 define('ripple/resizer', function (require, exports, module) {
127314 /*
127315  *  Copyright 2011 Research In Motion Limited.
127316  *
127317  * Licensed under the Apache License, Version 2.0 (the "License");
127318  * you may not use this file except in compliance with the License.
127319  * You may obtain a copy of the License at
127320  *
127321  * http://www.apache.org/licenses/LICENSE-2.0
127322  *
127323  * Unless required by applicable law or agreed to in writing, software
127324  * distributed under the License is distributed on an "AS IS" BASIS,
127325  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
127326  * See the License for the specific language governing permissions and
127327  * limitations under the License.
127328  */
127329 var db = require('ripple/db'),
127330     exception = require('ripple/exception'),
127331     utils = require('ripple/utils'),
127332     devices = require('ripple/devices'),
127333     constants = require('ripple/constants'),
127334     event = require('ripple/event'),
127335     _win,
127336     _doc,
127337     _self;
127338
127339 function _validateLayoutType(layoutType) {
127340     return (layoutType === "landscape" || layoutType === "portrait");
127341 }
127342
127343 function _validateOrientation(orientation) {
127344     return (orientation === "landscape" || orientation === "portrait");
127345 }
127346
127347 function _getContainers() {
127348     return {
127349         device: {
127350             div: document.getElementById("device-container"),
127351             containerClass: document.getElementById("device-container").getAttribute("class") || ""
127352         },
127353         viewport: {
127354             div: document.getElementById("viewport-container"),
127355             containerClass: document.getElementById("viewport-container").getAttribute("class") || ""
127356         },
127357         "menu-button": {
127358             div: document.getElementById(constants.COMMON.MENU_BUTTON),
127359             containerClass: document.getElementById(constants.COMMON.MENU_BUTTON).getAttribute("class") || ""
127360         },
127361         "back-button": {
127362             div: document.getElementById(constants.COMMON.BACK_BUTTON),
127363             containerClass: document.getElementById(constants.COMMON.BACK_BUTTON).getAttribute("class") || ""
127364         }
127365     };
127366 }
127367
127368 function _setContainers(containers, device, orientation) {
127369     var suffix = {
127370             portrait:  "-wrapper" + (device.skin ? "-" + device.skin : ""),
127371             landscape: "-wrapper-landscape" + (device.skin ? "-" + device.skin : "")
127372         };
127373
127374     utils.forEach(containers, function (container, key) {
127375         container.div.setAttribute("class", container.containerClass.replace(/\s.*$/, "") + " " + key + suffix[orientation]);
127376     });
127377 }
127378
127379 function _getDimensions(device, orientation) {
127380     return {
127381         deviceWidth: orientation === "portrait" ? device.screen.width : device.screen.height,
127382         deviceHeight: orientation === "portrait" ? device.screen.height : device.screen.width,
127383         paddingLeft: device.viewPort[orientation].paddingLeft,
127384         paddingTop: device.viewPort[orientation].paddingTop,
127385         viewPort: {
127386             width: device.viewPort[orientation].width,
127387             height: device.viewPort[orientation].height
127388         }
127389     };
127390 }
127391
127392 function _formatSkin(containers, dimensions) {
127393     var scaleFactor = dimensions.deviceWidth / dimensions.viewPort.width,
127394     scaleString = "scale(" + scaleFactor + ")";
127395
127396     containers.device.div.style.width = (dimensions.deviceWidth + 4) + "px";
127397     containers.device.div.style.height = (dimensions.deviceHeight + 4) + "px";
127398     containers.viewport.div.style.width = dimensions.viewPort.width + "px";
127399     containers.viewport.div.style.height = dimensions.viewPort.height + "px";
127400     containers.viewport.div.style.padding = "0";
127401
127402     jQuery('#viewport-container').css('-webkit-transform', scaleString);
127403     jQuery('#viewport-container').css('-webkit-transform-origin', 'left top');
127404 }
127405
127406 function _setOrientation(layout) {
127407     _win.orientation = window.orientation = layout === "portrait" ? 0 : 90;
127408 }
127409
127410 function _upDateHWKeyPanelPosition(orientation, scaleFactor) {
127411     var left = 0;
127412
127413     if (orientation === 'portrait') {
127414         if (db.retrieve("layout") === "portrait") {
127415             left = 350 + $('#device-layout').width()*scaleFactor;
127416         } else {
127417             left = 470 + $('#device-layout').height()*scaleFactor;
127418         }
127419     } else {
127420         if (db.retrieve("layout") === "portrait") {
127421             left = 490 + $('#device-layout').height()*scaleFactor;
127422         } else {
127423             left = 350 + $('#device-layout').width()*scaleFactor;
127424         }
127425     }
127426
127427     $("#hwkeys-panel").css("top", "40px");
127428     $("#hwkeys-panel").css("left", left+"px");
127429 }
127430
127431 function _getTransformString(orientation, scaleFactor) {
127432     var transformString = "",
127433     offset;
127434
127435     if (orientation === "landscape") {
127436         if (db.retrieve("layout") === "portrait") {
127437             offset = devices.getCurrentDevice().screen.height * scaleFactor + 170;
127438             transformString = "translate("+ offset + "px, 0px) rotate(90deg) scale("+ scaleFactor +")";
127439         } else {
127440             transformString = "translate(0px,0px) rotate(0deg) scale("+ scaleFactor +")";
127441         }
127442     } else {
127443         if (db.retrieve("layout") === "portrait") {
127444             transformString = "translate(0px,0px) rotate(0deg) scale("+ scaleFactor +")";
127445         } else {
127446             offset = devices.getCurrentDevice().screen.width * scaleFactor + 150;
127447             transformString = "translate("+ offset + "px, 0px) rotate(90deg) scale("+ scaleFactor +")";
127448         }
127449     }
127450
127451     return transformString;
127452 }
127453
127454
127455 _self = {
127456     init: function (win, doc) {
127457         _win = win;
127458         _doc = doc;
127459
127460         var layout = db.retrieve("layout") || "portrait";
127461
127462         _setOrientation(layout);
127463
127464         _win.onorientationchange = undefined;
127465     },
127466     // TODO: redo/refactor this in general, seems bloated, also devices REQUIRE viewport schemas which they shouldnt
127467     resize: function (device) {
127468         var layout = db.retrieve("layout"),
127469             orientation = "portrait",
127470             containers, dimensions;
127471
127472         if (layout && layout === "landscape" && device.viewPort.landscape) {
127473             orientation = "landscape";
127474         }
127475
127476         containers = _getContainers();
127477         _setContainers(containers, device, orientation);
127478
127479         dimensions = _getDimensions(device, orientation);
127480         if (!device.skin) {
127481             _formatSkin(containers, dimensions);
127482         }
127483
127484         event.trigger("ScreenChangeDimensions", [dimensions.viewPort.width, dimensions.viewPort.height]);
127485     },
127486
127487     changeLayoutType: function (layoutType) {
127488         var orientation = db.retrieve("deviceOrientation") || "portrait";
127489         if (!_validateLayoutType(layoutType)) {
127490             exception.raise(exception.types.LayoutType, "unknown layout type requested!");
127491         }
127492
127493         db.save("layout", layoutType);
127494         _self.resize(devices.getCurrentDevice());
127495         _self.rotateDevice(orientation);
127496
127497         if (!_win) return;
127498         _setOrientation(layoutType);
127499     },
127500
127501     scaleDevice: function (scaleFactor) {
127502         var orientation = db.retrieve("deviceOrientation") || "portrait",
127503         transformString = _getTransformString(orientation, scaleFactor);
127504         _upDateHWKeyPanelPosition(orientation, scaleFactor);
127505         db.save("deviceScaleFactor", scaleFactor);
127506         jQuery('#device-layout').css('-webkit-transform-origin', '0% 0%');
127507         jQuery('#device-layout').css('-webkit-transform',  transformString);
127508     },
127509
127510     rotateDevice: function (orientation) {
127511         if (!_validateOrientation(orientation)) {
127512             exception.raise(exception.types.OrientationType, "unknown orientation type requested!");
127513         }
127514
127515         db.save("deviceOrientation", orientation);
127516         jQuery('#device-layout').css('-webkit-transform-origin', '0% 0%');
127517         jQuery('#device-layout').css('-webkit-transform',
127518                 _getTransformString(orientation, db.retrieve("deviceScaleFactor")));
127519         _upDateHWKeyPanelPosition(orientation, db.retrieve("deviceScaleFactor"))
127520         if (!_win) return;
127521         if (_win.onorientationchange) {
127522             _win.onorientationchange();
127523         }
127524
127525         var evt = _doc.createEvent("Event");
127526         evt.initEvent("orientationchange", true, true);
127527         _win.dispatchEvent(evt);
127528     }
127529 };
127530
127531 module.exports = _self;
127532
127533 });
127534 define('ripple/sensorSettings', function (require, exports, module) {
127535 /*
127536  *  Copyright 2012 Intel Corporation.
127537  *
127538  * Licensed under the Apache License, Version 2.0 (the "License");
127539  * you may not use this file except in compliance with the License.
127540  * You may obtain a copy of the License at
127541  *
127542  * http://www.apache.org/licenses/LICENSE-2.0
127543  *
127544  * Unless required by applicable law or agreed to in writing, software
127545  * distributed under the License is distributed on an "AS IS" BASIS,
127546  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
127547  * See the License for the specific language governing permissions and
127548  * limitations under the License.
127549  */
127550 var _PERSISTENCE_KEY = "sensorsettings",
127551     db = require('ripple/db'),
127552     platform = require('ripple/platform'),
127553     _currentSensorSettings = {},
127554     _self;
127555
127556 function _default(key) {
127557     var keys = key.split("."),
127558         defaults = platform.current().sensor;
127559
127560     if (keys.length === 1)
127561         return defaults[key];
127562
127563     return keys.length === 2 &&
127564            defaults[keys[0]] &&
127565            defaults[keys[0]][keys[1]] &&
127566            defaults[keys[0]][keys[1]].control ?
127567            defaults[keys[0]][keys[1]].control.value : undefined;
127568 }
127569
127570 _self = {
127571     initialize: function () {
127572         _currentSensorSettings = db.retrieveObject(_PERSISTENCE_KEY) || {};
127573     },
127574     register: function (key, obj) {
127575         _currentSensorSettings[key] = obj;
127576     },
127577
127578     persist: function (key, obj) {
127579         if (key) {
127580             _currentSensorSettings[key] = obj;
127581         }
127582
127583         db.saveObject(_PERSISTENCE_KEY, _currentSensorSettings);
127584     },
127585
127586     retrieve: function (key) {
127587         return _currentSensorSettings.hasOwnProperty(key) ?
127588                _currentSensorSettings[key] : _default(key);
127589     },
127590
127591     retrieveAsInt: function (key) {
127592         return parseInt(_self.retrieve(key), 10);
127593     },
127594
127595     retrieveAsBoolean: function (key) {
127596         return !!_self.retrieve(key);
127597     }
127598 };
127599
127600 module.exports = _self;
127601
127602 });
127603 define('ripple/touchEventEmulator', function (require, exports, module) {
127604 /*
127605  *  Copyright 2011 Research In Motion Limited.
127606  *
127607  * Licensed under the Apache License, Version 2.0 (the "License");
127608  * you may not use this file except in compliance with the License.
127609  * You may obtain a copy of the License at
127610  *
127611  * http://www.apache.org/licenses/LICENSE-2.0
127612  *
127613  * Unless required by applicable law or agreed to in writing, software
127614  * distributed under the License is distributed on an "AS IS" BASIS,
127615  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
127616  * See the License for the specific language governing permissions and
127617  * limitations under the License.
127618  */
127619 var emulatorBridge = require('ripple/emulatorBridge'),
127620     utils = require('ripple/utils'),
127621     _isMouseDown, self;
127622
127623 // NOTE: missing view, detail, touches, targetTouches, scale and rotation
127624 function _initTouchEvent(type, canBubble, cancelable, eventData) {
127625     var touchEvent = emulatorBridge.document().createEvent("Event");
127626     touchEvent.initEvent(type, canBubble, cancelable);
127627     utils.mixin(eventData, touchEvent);
127628     return touchEvent;
127629 }
127630
127631 function _raiseTouchEvent(mouseEvent) {
127632     var type = "",
127633         simulatedEvent,
127634         touchObj,
127635         eventData;
127636
127637     switch (mouseEvent.type) {
127638     case "mousedown":
127639         type = "touchstart";
127640         _isMouseDown = true;
127641         break;
127642     case "mousemove":
127643         if (!_isMouseDown) {
127644             return;
127645         }
127646         type = "touchmove";
127647         break;
127648     case "mouseup":
127649         type = "touchend";
127650         _isMouseDown = false;
127651         break;
127652     default:
127653         return;
127654     }
127655
127656     touchObj = {
127657         clientX: mouseEvent.pageX,
127658         clientY: mouseEvent.pageY,
127659         identifier: "",
127660         pageX: mouseEvent.pageX,
127661         pageY: mouseEvent.pageY,
127662         screenX: mouseEvent.pageX,
127663         screenY: mouseEvent.pageY,
127664         target: mouseEvent.target
127665     };
127666
127667     eventData = {
127668         altKey: mouseEvent.altKey,
127669         ctrlKey: mouseEvent.ctrlKey,
127670         shiftKey: mouseEvent.shiftKey,
127671         metaKey: mouseEvent.metaKey,
127672         changedTouches: [touchObj],
127673         targetTouches: [touchObj],
127674         touches: [touchObj]
127675     };
127676
127677     utils.mixin(touchObj, eventData);
127678
127679     simulatedEvent = _initTouchEvent(type, true, true, eventData);
127680
127681     mouseEvent.target.dispatchEvent(simulatedEvent);
127682
127683     if (typeof mouseEvent.target["on" + type] === "function") {
127684         mouseEvent.target["on" + type].apply(mouseEvent.target, [simulatedEvent]);
127685     }
127686 }
127687
127688 function _marshalEvents(win, doc) {
127689     utils.forEach(["mousedown", "mousemove", "mouseup"],
127690         function (event) {
127691             doc.addEventListener(event, _raiseTouchEvent, true);
127692         });
127693
127694     //win.Node.prototype.ontouchstart = null;
127695     //win.Node.prototype.ontouchend = null;
127696     //win.Node.prototype.ontouchmove = null;
127697 }
127698
127699 self = module.exports = {
127700     mask: function (win, doc) {
127701         _marshalEvents(win, doc);
127702     }
127703 };
127704
127705 });
127706 define('ripple/ui/plugins/HWKeys', function (require, exports, module) {
127707 /*
127708  *  Copyright 2012 Intel Corporation
127709  *
127710  * Licensed under the Apache License, Version 2.0 (the "License");
127711  * you may not use this file except in compliance with the License.
127712  * You may obtain a copy of the License at
127713  *
127714  * http://www.apache.org/licenses/LICENSE-2.0
127715  *
127716  * Unless required by applicable law or agreed to in writing, software
127717  * distributed under the License is distributed on an "AS IS" BASIS,
127718  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
127719  * See the License for the specific language governing permissions and
127720  * limitations under the License.
127721  */
127722
127723 var db = require('ripple/db'),
127724     event = require('ripple/event');
127725
127726
127727 function initHWKey() {
127728     var left = 0,
127729         orientation = db.retrieve('deviceOrientation'),
127730         scaleFactor = db.retrieve('deviceScaleFactor');
127731
127732     if (orientation === 'portrait') {
127733         if (db.retrieve("layout") === "portrait") {
127734             left = 350 + $('#device-layout').width()*scaleFactor;
127735         } else {
127736             left = 470 + $('#device-layout').height()*scaleFactor;
127737         }
127738     } else {
127739         if (db.retrieve("layout") === "portrait") {
127740             left = 490 + $('#device-layout').height()*scaleFactor;
127741         } else {
127742             left = 350 + $('#device-layout').width()*scaleFactor;
127743         }
127744     }
127745
127746     $("#hwkeys-panel").css("top", "40px");
127747     $("#hwkeys-panel").css("left", left+"px");
127748     $("#hwkeys-panel").draggable({ cursor: 'move', containment: [0, 52, 1480, 800]});
127749
127750     jQuery("#hwkey-menu-btn").bind("click", function () {
127751         event.trigger("tizenhwkeyEvent", ["menu"], true);
127752     });
127753     jQuery("#hwkey-back-btn").bind("click", function () {
127754         event.trigger("tizenhwkeyEvent", ["back"], true);
127755     });
127756 }
127757
127758 module.exports = {
127759     initialize: function () {
127760         initHWKey();
127761     }
127762 };
127763
127764 });
127765 define('ripple/ui/plugins/about-dialog', function (require, exports, module) {
127766 /*
127767  *  Copyright 2011 Research In Motion Limited.
127768  *
127769  * Licensed under the Apache License, Version 2.0 (the "License");
127770  * you may not use this file except in compliance with the License.
127771  * You may obtain a copy of the License at
127772  *
127773  * http://www.apache.org/licenses/LICENSE-2.0
127774  *
127775  * Unless required by applicable law or agreed to in writing, software
127776  * distributed under the License is distributed on an "AS IS" BASIS,
127777  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
127778  * See the License for the specific language governing permissions and
127779  * limitations under the License.
127780  */
127781 var bus = require('ripple/bus');
127782
127783 module.exports = {
127784     initialize: function () {
127785         $("#about-dialog").dialog({
127786             resizable: false,
127787             draggable: false,
127788             modal: true,
127789             autoOpen: false,
127790             position: 'center',
127791             minWidth: '464',
127792             minHeight: '262'
127793         });
127794     },
127795     show: function () {
127796         //TODO: Restore this line once framework issue is resolved
127797         //var port =  window.stagewebview ? stagewebview.serverPort : "9900";
127798         var port = "9910";
127799
127800         bus.send("version", null, function (resp) {
127801             $("#about-dialog-ripple-ui-version").html("(v" + resp + ")");
127802         });
127803
127804         bus.ajax(
127805             "GET",
127806             "http://127.0.0.1:" + port + "/ripple/about",
127807             null,
127808             function (resp) {
127809                 $("#about-dialog-ripple-build-deploy-version").html("(v" + resp.data.version + ")");
127810             },
127811             function (error) {
127812                 var version = error.data;
127813                 
127814                 if (error.code === 0 || error.code === 404) {
127815                     version = "The service is not running";
127816                 }
127817                 $("#about-dialog-ripple-build-deploy-version").html("(" + version + ")");
127818             }
127819         );
127820
127821         $("#about-dialog").dialog("open");
127822     }
127823 };
127824
127825 });
127826 define('ripple/ui/plugins/accelerometer', function (require, exports, module) {
127827 /*
127828  * Copyright (c) 2010 Epic Train Hack
127829  * Copyright (c) 2011 Research In Motion Limited
127830  * Contributors: Wolfram Kriesing, Dan Silivestru, Brent Lintner
127831  *
127832  * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
127833  *
127834  * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
127835  *
127836  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
127837  */
127838 var ui = require('ripple/ui'),
127839     goodVibrations = require('ripple/ui/plugins/goodVibrations'),
127840     accelerometer = require('ripple/accelerometer'),
127841     event = require('ripple/event'),
127842     Rotation = require('ripple/platform/w3c/1.0/Rotation'),
127843     Acceleration = require('ripple/platform/w3c/1.0/Acceleration'),
127844     _mouseDown,
127845     _shiftKeyDown,
127846     _offsets = {
127847         x: 0,
127848         y: 0,
127849         z: -9.81,
127850     },
127851     _oldX,
127852     _oldY,
127853     _oldAlphaX,
127854     _shape =
127855         //
127856         // The front side
127857         //
127858         // x, y, z      x, y, z         x, y, z
127859         // for some strange reason for y -100 is top, 100 is bottom
127860         "-30,30,10,     30,30,10,       30,60,10,       100,100,100,-1,0;" + // top left, top right, bottom right - of the right triangle
127861         "-30,30,10,     30,60,10,       -30,60,10,      100,100,100,-1,0;" + // top left, right bottom, left bottom - of the left triangle
127862         // front side "the phone display"
127863         "-20,-50,11,    20,-50,11,      20,20,11,       100,100,100,-1,0;" +
127864         "-20,-50,11,    20,20,11,       -20,20,11,      100,100,100,-1,0;" +
127865         // below the display
127866         "-30,30,10,     30,20,10,       30,30,10,       0,0,0,-1,0;" +
127867         "-30,30,10,     -30,20,10,      30,20,10,       0,0,0,-1,0;" +
127868         // above the display
127869         "-30,-60,10,    30,-60,10,      30,-50,10,      0,0,0,-1,0;" +
127870         "-30,-60,10,    30,-50,10,      -30,-50,10,     0,0,0,-1,0;" +
127871         // left of the display
127872         "-30,-50,10,    -20,-50,10,     -20,20,10,      0,0,0,-1,0;" +
127873         "-30,-50,10,    -20,20,10,      -30,20,10,      0,0,0,-1,0;" +
127874         // right of the display
127875         "20,-50,10,     30,-50,10,      30,20,10,       0,0,0,-1,0;" +
127876         "20,-50,10,     30,20,10,       20,20,10,       0,0,0,-1,0;" +
127877
127878
127879         // back side, opposite side to the above one
127880         "-30,-60,-10,   30,60,-10,      30,-60,-10,     0,0,0,-1,0;" +
127881         "-30,-60,-10,   -30,60,-10,     30,60,-10,      0,00,-1,0;" +
127882         // right side
127883         "30,-60,-10,    30,60,-10,      30,60,10,       50,50,80,-1,0;" +
127884         "30,-60,-10,    30,60,10,       30,-60,10,      50,50,80,-1,0;" +
127885         // left side
127886         "-30,-60,-10,   -30,60,10,      -30,60,-10,     50,50,80,-1,0;" +
127887         "-30,-60,-10,   -30,-60,10,     -30,60,10,      50,50,80,-1,0;" +
127888
127889         // top
127890         "30,-60,-10,    -30,-60,10, -30,-60,-10,    50,80,50,-1,0;" +
127891         "30,-60,-10,    30,-60,10,      -30,-60,10, 50,80,50,-1,0;" +
127892         // bottom
127893         "30,60,-10, -30,60,-10,     -30,60,10,      80,50,50,-1,0;" +
127894         "30,60,-10, -30,60,10,      30,60,10,       80,50,50,-1,0";
127895
127896 function _shakeDevice() {
127897     window.setTimeout(goodVibrations.shakeDevice(8), 1);
127898     accelerometer.shake();
127899 }
127900
127901 function _updateAccelerometerPanel(motion) {
127902     jQuery("#accelerometer-x").html(Math.round(motion.accelerationIncludingGravity.x * 100) / 100);
127903     jQuery("#accelerometer-y").html(Math.round(motion.accelerationIncludingGravity.y * 100) / 100);
127904     jQuery("#accelerometer-z").html(Math.round(motion.accelerationIncludingGravity.z * 100) / 100);
127905     jQuery("#accelerometer-alpha").html(Math.round(motion.orientation.alpha));
127906     jQuery("#accelerometer-beta").html(Math.round(motion.orientation.beta));
127907     jQuery("#accelerometer-gamma").html(Math.round(motion.orientation.gamma));
127908 }
127909
127910 function _updateCanvas(a, b, g) {
127911     ThreeDee.loadMesh(_shape);
127912     g = g || 0;
127913     ThreeDee.rotate(0, g, 0);
127914     ThreeDee.rotate(b, 0, a);
127915     ThreeDee.backface();
127916     ThreeDee.shade();
127917     ThreeDee.zSort();
127918     Draw.initialize(document.querySelector("#accelerometer-canvas"));
127919     Draw.clear(0, 0, 480, 300);
127920     Draw.drawScene(ThreeDee.getTranslation(), 3);
127921 }
127922
127923 function _createCanvas() {
127924     var node = document.querySelector("#accelerometer-canvas"),
127925         x = 0, y = 0, z = -9.81,
127926         alpha = 0, beta = 0, gamma = 0,
127927         cosX, sinX, cosY, sinY,
127928         deltaAlpha = 360;
127929
127930     ThreeDee.setCenter(150, 100);
127931     ThreeDee.setLight(-300, -300, 800);
127932
127933     node.addEventListener("mousemove", function (e) {
127934         if (!_mouseDown)
127935             return;
127936
127937         if (!_shiftKeyDown) {
127938             _offsets.x = (_offsets.x + _oldX - e.offsetX) % 360;
127939             _offsets.y = (_offsets.y + _oldY - e.offsetY) % 360;
127940
127941             alpha = alpha || 0;
127942
127943             // enforce gamma in [-90,90] as per w3c spec
127944             gamma = -_offsets.x;
127945             if (gamma < -90) {
127946                 gamma = -90;
127947             }
127948             if (gamma > 90) {
127949                 gamma = 90;
127950             }
127951
127952             // enforce beta in [-180,180] as per w3c spec
127953             beta = -_offsets.y % 360;
127954             if (beta < -180) {
127955                 beta += 360;
127956             }
127957             else if (beta >= 180) {
127958                 beta -= 360;
127959             }
127960
127961             cosX = Math.cos((gamma) * (Math.PI / 180));
127962             sinX = Math.sin((gamma) * (Math.PI / 180));
127963             cosY = Math.cos((beta) * (Math.PI / 180));
127964             sinY = Math.sin((beta) * (Math.PI / 180));
127965             x = 9.81 * cosY * sinX;
127966             y = -9.81 * sinY;
127967             z = -9.81 * cosY * cosX;
127968
127969         }
127970         else {
127971             deltaAlpha = (deltaAlpha - (_oldAlphaX - e.offsetX) * 2.5) % 360;
127972             alpha = (360 - deltaAlpha) % 360;
127973         }
127974
127975         _oldX = e.offsetX;
127976         _oldY = e.offsetY;
127977         _oldAlphaX = e.offsetX;
127978
127979         _updateCanvas(deltaAlpha, -beta, gamma);
127980         accelerometer.setInfo({
127981             x: x,
127982             y: y,
127983             z: z,
127984             alpha: alpha,
127985             beta: beta,
127986             gamma: gamma
127987         });
127988
127989     });
127990
127991     node.addEventListener("mousedown", function (e) {
127992         _oldX = e.offsetX;
127993         _oldY = e.offsetY;
127994         if (_shiftKeyDown) {
127995             _oldAlphaX = _oldX;
127996         }
127997         _mouseDown = true;
127998     });
127999
128000     node.addEventListener("mouseup", function (e) {
128001         _mouseDown = false;
128002     });
128003
128004     node.addEventListener("dblclick", function (e) {   
128005         x = 0;
128006         y = 0;
128007         z = -9.81;
128008         alpha = 0;
128009         beta = 0;
128010         gamma = 0;
128011         deltaAlpha = 360;
128012         _resetAccelerometer();
128013     });
128014
128015     document.addEventListener("mouseup", function (e) {
128016         //Catch mouseup events that fire when outside canvas bounds
128017         _mouseDown = false;
128018     });
128019
128020     document.addEventListener("keydown", function (e) {
128021         if (e.keyCode === 16) { // Shift Key            
128022             _shiftKeyDown = true;
128023         }
128024     });
128025
128026     document.addEventListener("keyup", function (e) {
128027         if (e.keyCode === 16) { // Shift Key
128028             _shiftKeyDown = false;
128029         }
128030     });    
128031 }
128032
128033 function _resetAccelerometer() {    
128034     _updateCanvas(0, 0);
128035     _oldX = 0;
128036     _oldY = 0;
128037     _oldAlphaX = 0;
128038     _offsets = {
128039         x: 0,
128040         y: 0,
128041         z: -9.81,
128042     };
128043     accelerometer.setInfo({
128044         acceleration: new Acceleration(0, 0, 0),
128045         accelerationIncludingGravity: new Acceleration(0, 0, -9.81),
128046         rotationRate: new Rotation(0, 0, 0),
128047         orientation: new Rotation(0, 0, 0),
128048         timestamp: new Date().getTime()
128049     });
128050 }
128051
128052 module.exports = {
128053     panel: {
128054         domId: "accelerometer-container",
128055         collapsed: true,
128056         pane: "left",
128057         titleName: "Accelerometer",
128058         display: true
128059     },
128060     initialize: function () {
128061         _createCanvas();
128062         
128063         _resetAccelerometer();
128064
128065         _updateAccelerometerPanel(accelerometer.getInfo());
128066
128067         jQuery("#accelerometer-shake").click(_shakeDevice);
128068
128069         event.on("AccelerometerInfoChangedEvent", _updateAccelerometerPanel, this);
128070     }
128071 };
128072
128073 });
128074 define('ripple/ui/plugins/application', function (require, exports, module) {
128075 /*
128076  *  Copyright 2012 Intel Corporation.
128077  *
128078  * Licensed under the Apache License, Version 2.0 (the "License");
128079  * you may not use this file except in compliance with the License.
128080  * You may obtain a copy of the License at
128081  *
128082  * http://www.apache.org/licenses/LICENSE-2.0
128083  *
128084  * Unless required by applicable law or agreed to in writing, software
128085  * distributed under the License is distributed on an "AS IS" BASIS,
128086  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
128087  * See the License for the specific language governing permissions and
128088  * limitations under the License.
128089  */
128090
128091 var event = require('ripple/event'),
128092     utils = require('ripple/utils'),
128093     db = require('ripple/db'),
128094     DB_APPLICATION_KEY = "tizen1-db-application",
128095     _data = {
128096         appList : {},
128097         installedAppList: {}
128098     },
128099     _appInstalledTemplate,
128100     _apps = {
128101         "http://tizen.org/viewer": {
128102             id: "http://tizen.org/viewer",
128103             name: "Tizen viewer",
128104             iconPath: "001.png",
128105             version: "1.9",
128106             show: true,
128107             categories: ["media"],
128108             size: 5120,
128109             packageId: "TEST_APP_ID",
128110             sharedURI: "/usr/local/share/viewer",
128111             operation: "http://tizen.org/appcontrol/operation/view",
128112             appControl: {
128113                 uri: "http://tizen.org/appcontrol/uri/view",
128114                 mime: "image/*",
128115                 category: "media",
128116                 data: ""
128117             },
128118             type: "AUTHOR_ROOT",
128119             value: []
128120         },
128121         "http://tizen.org/player": {
128122             id: "http://tizen.org/player",
128123             name: "Tizen player",
128124             iconPath: "002.png",
128125             version: "2.0",
128126             show: true,
128127             categories: ["media"],
128128             size: 2048,
128129             packageId: "TEST_APP_ID",
128130             sharedURI: "/usr/local/share/player",
128131             operation: "http://tizen.org/appcontrol/operation/play",
128132             appControl: {
128133                 uri: "http://tizen.org/appcontrol/uri/play",
128134                 mime: "video/*",
128135                 category: "media",
128136                 data: ""
128137             },
128138             type: "AUTHOR_SIGNER",
128139             value: []
128140         },
128141         "http://tizen.org/dummy": {
128142             id: "http://tizen.org/dummy",
128143             name: "Tizen dummy",
128144             iconPath: "dummy.png",
128145             version: "1.7",
128146             show: true,
128147             categories: ["media"],
128148             size: 3094,
128149             packageId: "EXAMPLE_ID",
128150             sharedURI: "/usr/local/share/dummy",
128151             operation: "http://tizen.org/appcontrol/operation/dummy",
128152             appControl: {
128153                 uri: "http://tizen.org/appcontrol/uri/dummy",
128154                 mime: "video/*",
128155                 category: "media",
128156                 data: ""
128157             },
128158             type: "AUTHOR_SIGNER",
128159             value: []
128160         },
128161         "http://tizen.org/dialer": {
128162             id: "http://tizen.org/dialer",
128163             name: "Tizen dialer",
128164             iconPath: "002.png",
128165             version: "2.1",
128166             show: true,
128167             categories: ["dialer"],
128168             size: 2048,
128169             packageId: "SAMPLE_ID",
128170             sharedURI: "/usr/local/share/dialer",
128171             operation: "http://tizen.org/appcontrol/operation/call",
128172             appControl: {
128173                 uri: "http://tizen.org/appcontrol/uri/call",
128174                 mime: "application/xml",
128175                 category: "dialer",
128176                 data: ""
128177             },
128178             type: "AUTHOR_ROOT",
128179             value: []
128180         },
128181         "http://tizen.org/sender": {
128182             id: "http://tizen.org/sender",
128183             name: "Tizen sender",
128184             iconPath: "005.png",
128185             version: "2.2",
128186             show: true,
128187             categories: ["message"],
128188             size: 2048,
128189             packageId: "SAMPLE_ID",
128190             sharedURI: "/usr/local/share/sender",
128191             operation: "http://tizen.org/appcontrol/operation/send_text",
128192             appControl: {
128193                 uri: "http://tizen.org/appcontrol/uri/send_text",
128194                 mime: "text/plain",
128195                 category: "message",
128196                 data: ""
128197             },
128198             type: "AUTHOR_ROOT",
128199             value: []
128200         },
128201         "api1pack00.WebAPITizenPackageTests": {
128202             id: "api1pack00.WebAPITizenPackageTests",
128203             name: "Tizen test app",
128204             iconPath: "001.png",
128205             version: "2.2",
128206             show: true,
128207             categories: ["message"],
128208             size: 2048,
128209             packageId: "api1pack00",
128210             sharedURI: "/usr/local/share/apiuri",
128211             operation: "http://tizen.org/appcontrol/operation/test",
128212             appControl: {
128213                 uri: "http://tizen.org/appcontrol/uri/test",
128214                 mime: "text/plain",
128215                 category: "message",
128216                 data: ""
128217             },
128218             type: "AUTHOR_ROOT",
128219             value: []
128220         },
128221         "testpack00.autoWebapiTizenPackageTestApplication": {
128222             id: "testpack00.autoWebapiTizenPackageTestApplication",
128223             name: "Tizen test app 2",
128224             iconPath: "002.png",
128225             version: "3.0",
128226             show: true,
128227             categories: ["message"],
128228             size: 2048,
128229             packageId: "testpack00",
128230             sharedURI: "/usr/local/share/apiuri2",
128231             operation: "http://tizen.org/appcontrol/operation/test2",
128232             appControl: {
128233                 uri: "http://tizen.org/appcontrol/uri/test2",
128234                 mime: "text/plain",
128235                 category: "message",
128236                 data: ""
128237             },
128238             type: "AUTHOR_ROOT",
128239             value: []
128240         }
128241     },
128242     _installedAppList = {
128243         "http://tizen.org/dialer": {
128244             id: "http://tizen.org/dialer",
128245             name: "Tizen dialer",
128246             iconPath: "002.png",
128247             version: "2.1",
128248             show: true,
128249             categories: ["dialer"],
128250             installDate: new Date(),
128251             size: 2048,
128252             packageId: "SAMPLE_ID",
128253             sharedURI: "/usr/local/share/dialer",
128254             operation: "http://tizen.org/appcontrol/operation/call",
128255             appControl: {
128256                 uri: "http://tizen.org/appcontrol/uri/call",
128257                 mime: "application/xml",
128258                 category: "dialer",
128259                 data: ""
128260             },
128261             type: "AUTHOR_ROOT",
128262             value: []
128263         },
128264         "http://tizen.org/sender": {
128265             id: "http://tizen.org/sender",
128266             name: "Tizen sender",
128267             iconPath: "005.png",
128268             version: "2.2",
128269             show: true,
128270             categories: ["message"],
128271             installDate: new Date(),
128272             size: 2048,
128273             packageId: "SAMPLE_ID",
128274             sharedURI: "/usr/local/share/sender",
128275             operation: "http://tizen.org/appcontrol/operation/send_text",
128276             appControl: {
128277                 uri: "http://tizen.org/appcontrol/uri/send_text",
128278                 mime: "text/plain",
128279                 category: "message",
128280                 data: ""
128281             },
128282             type: "AUTHOR_ROOT",
128283             value: []
128284         },
128285         "api1pack00.WebAPITizenPackageTests": {
128286             id: "api1pack00.WebAPITizenPackageTests",
128287             name: "Tizen test app",
128288             iconPath: "001.png",
128289             version: "2.2",
128290             show: true,
128291             categories: ["message"],
128292             installDate: new Date(),
128293             size: 2048,
128294             packageId: "api1pack00",
128295             sharedURI: "/usr/local/share/apiuri",
128296             operation: "http://tizen.org/appcontrol/operation/test",
128297             appControl: {
128298                 uri: "http://tizen.org/appcontrol/uri/test",
128299                 mime: "text/plain",
128300                 category: "message",
128301                 data: ""
128302             },
128303             type: "AUTHOR_ROOT",
128304             value: []
128305         },
128306         "testpack00.autoWebapiTizenPackageTestApplication": {
128307             id: "testpack00.autoWebapiTizenPackageTestApplication",
128308             name: "Tizen test app 2",
128309             iconPath: "002.png",
128310             version: "3.0",
128311             show: true,
128312             categories: ["message"],
128313             installDate: new Date(),
128314             size: 2048,
128315             packageId: "testpack00",
128316             sharedURI: "/usr/local/share/apiuri2",
128317             operation: "http://tizen.org/appcontrol/operation/test2",
128318             appControl: {
128319                 uri: "http://tizen.org/appcontrol/uri/test2",
128320                 mime: "text/plain",
128321                 category: "message",
128322                 data: ""
128323             },
128324             type: "AUTHOR_ROOT",
128325             value: []
128326         }
128327     };
128328
128329 function _get() {
128330     _data = db.retrieveObject(DB_APPLICATION_KEY);
128331     if (_data === undefined) {
128332         _data = {
128333             appList : _apps,
128334             installedAppList: _installedAppList
128335         };
128336         _save();
128337     }
128338 }
128339
128340 function _save() {
128341     db.saveObject(DB_APPLICATION_KEY, _data);
128342 }
128343
128344 function _loadInstalledAppList() {
128345     var html = "";
128346     jQuery("#application-installed-box").empty();
128347     utils.forEach(_data.installedAppList, function (item) {
128348         html += _appInstalledTemplate.replace(/#Name/g, item.name)
128349             .replace(/#ID/g, item.id)
128350             .replace(/#IconPath/, item.iconPath)
128351             .replace(/#Version/, item.version)
128352             .replace(/#Show/, item.show)
128353             .replace(/#Categories/, item.categories.join("<br>"))
128354             .replace(/#InstallDate/, item.installDate)
128355             .replace(/#Size/, item.size)
128356             .replace(/#PackageID/, item.packageId)
128357             .replace(/#SharedURI/, item.sharedURI)
128358             .replace(/#Operation/, item.operation)
128359             .replace(/#URI/, item.appControl.uri)
128360             .replace(/#MIME/, item.appControl.mime)
128361             .replace(/#category/, item.appControl.category)
128362             .replace(/#Data/, item.appControl.data);
128363     });
128364     jQuery("#application-installed-box").accordion("destroy");
128365     jQuery("#application-installed-box").html(html).accordion({
128366         active : false,
128367         collapsible : true,
128368         autoHeight : false
128369     });
128370 }
128371
128372 function _displayInfo(text) {
128373     var html = "<b>" + text + "</b>";
128374     document.getElementById("application-error").innerHTML = html;
128375 }
128376
128377 function _programChanged(status, id) {
128378     event.trigger("programChanged", [status, id]);
128379 }
128380
128381 function updateApp(id, updateFlag) {
128382     var item = _data.appList[id];
128383     if (!item) {
128384         return;
128385     }
128386     _data.installedAppList[id] = {
128387         id: item.id,
128388         name: item.name,
128389         iconPath: item.iconPath,
128390         version: item.version,
128391         show: item.show,
128392         categories: item.categories,
128393         installDate: new Date(),
128394         size: item.size,
128395         packageId: item.packageId,
128396         operation: item.operation,
128397         appControl: {
128398             uri: item.appControl.uri,
128399             mime: item.appControl.mime,
128400             category: item.appControl.category,
128401             data: item.appControl.data
128402         },
128403         type: item.type,
128404         value: item.value
128405     };
128406     _save();
128407     if (updateFlag) {
128408         _programChanged("updated", id);
128409     } else {
128410         _programChanged("installed", id);
128411     }
128412     _loadInstalledAppList();
128413 }
128414
128415 function removeApp(id) {
128416     delete _data.installedAppList[id];
128417     _save();
128418     _programChanged("uninstalled", id);
128419     _loadInstalledAppList();
128420 }
128421
128422 event.on("appServiceReplied", function () {
128423     _displayInfo("The application has been launched successfully");
128424 });
128425
128426 event.on("install-apps", function (ids) {
128427     utils.forEach(ids, function (id) {
128428         updateApp(id, false);
128429     });
128430 });
128431
128432 event.on("update-apps", function (ids) {
128433     utils.forEach(ids, function (id) {
128434         updateApp(id, true);
128435     });
128436 });
128437
128438 event.on("remove-apps", function (ids) {
128439     utils.forEach(ids, function (id) {
128440         removeApp(id);
128441     });
128442 });
128443
128444 module.exports = {
128445     initialize: function () {
128446         _appInstalledTemplate = jQuery("#application-installed-template").html();
128447         _get();
128448         _loadInstalledAppList();
128449     }
128450 };
128451
128452 });
128453 define('ripple/ui/plugins/audioPlayer', function (require, exports, module) {
128454 /*
128455  *  Copyright 2011 Research In Motion Limited.
128456  *
128457  * Licensed under the Apache License, Version 2.0 (the "License");
128458  * you may not use this file except in compliance with the License.
128459  * You may obtain a copy of the License at
128460  *
128461  * http://www.apache.org/licenses/LICENSE-2.0
128462  *
128463  * Unless required by applicable law or agreed to in writing, software
128464  * distributed under the License is distributed on an "AS IS" BASIS,
128465  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
128466  * See the License for the specific language governing permissions and
128467  * limitations under the License.
128468  */
128469 var event = require('ripple/event'),
128470     constants = require('ripple/constants'),
128471     audioObj = document.getElementById("multimedia-audio"),
128472     audioProgress = document.getElementById(constants.COMMON.MULTIMEDIA_AUDIO_PROGRESS_ID);
128473
128474 module.exports = {
128475     initialize: function () {
128476         var audioObj = document.getElementById("multimedia-audio"),
128477             audioProgress = document.getElementById(constants.COMMON.MULTIMEDIA_AUDIO_PROGRESS_ID);
128478
128479         if (audioObj) {
128480             event.on("MultimediaVolumeChanged", function (volume) {
128481                 audioObj.volume = parseFloat(volume / 10);
128482             });
128483
128484             audioObj.addEventListener("timeupdate", function () {
128485                 var s = parseInt(audioObj.currentTime % 60, 10),
128486                     m = parseInt((audioObj.currentTime / 60) % 60, 10);
128487
128488                 audioProgress.innerText = ((m > 9) ? m  : "0" + m) + ':' + ((s > 9) ? s  : "0" + s);
128489             }, false);
128490
128491             event.on("MultimediaAudioStateChanged", function (state) {
128492                 document.getElementById(constants.COMMON.MULTIMEDIA_AUDIO_STATE_FIELD_ID).innerText = state;
128493                 document.getElementById(constants.COMMON.MULTIMEDIA_AUDIO_FILE_FIELD_ID).innerText = audioObj.getAttribute("src");
128494             });
128495         }
128496     }
128497 };
128498
128499 });
128500 define('ripple/ui/plugins/build', function (require, exports, module) {
128501 /*
128502  *  Copyright 2011 Research In Motion Limited.
128503  *
128504  * Licensed under the Apache License, Version 2.0 (the "License");
128505  * you may not use this file except in compliance with the License.
128506  * You may obtain a copy of the License at
128507  *
128508  * http://www.apache.org/licenses/LICENSE-2.0
128509  *
128510  * Unless required by applicable law or agreed to in writing, software
128511  * distributed under the License is distributed on an "AS IS" BASIS,
128512  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
128513  * See the License for the specific language governing permissions and
128514  * limitations under the License.
128515  */
128516 var tooltip = require('ripple/ui/plugins/tooltip'),
128517     settings = require('ripple/ui/plugins/settings-dialog'),
128518     bus = require('ripple/bus');
128519
128520 function handleBuild() {
128521     var node = $(this),
128522         action = node.attr('id').split("-")[2];
128523
128524     if (node.hasClass("not-ready")) {
128525         return;
128526     }
128527
128528     if (!settings.can(action)) {
128529         settings.show(action);
128530     }
128531     else {
128532         settings.perform(action);
128533     }
128534 }
128535
128536 function areServicesRunning(success, fail) {
128537     bus.ajax(
128538         "GET",
128539         "http://127.0.0.1:9910/ripple/about",
128540         null,
128541         function () {
128542             success();
128543         },
128544         function (error) {
128545             fail();
128546         }
128547     );
128548 }
128549
128550 function manageServices(action, callBack) {
128551     bus.send("services", action, function () {
128552         if (typeof callBack === "function") {
128553             callBack();
128554         }
128555     });
128556 }
128557
128558 module.exports = {
128559     panel: {
128560         domId: "build-container",
128561         collapsed: true,
128562         pane: "right"
128563     },
128564
128565     initialize: function () {
128566         $("#options-menu-build").click(handleBuild);
128567         $("#options-menu-sign").click(handleBuild);
128568         $("#options-menu-launch").click(handleBuild);
128569
128570         $('#options-menu-start-service').click(function () {
128571             manageServices("start", function (result) {
128572                 $('#options-menu-services-stop').show();
128573                 $('#options-menu-services-start').hide();
128574             });
128575         });
128576
128577         $('#options-menu-stop-service').click(function () {
128578             manageServices("stop", function (result) {
128579                 $('#options-menu-services-stop').hide();
128580                 $('#options-menu-services-start').show();
128581             });
128582         });
128583
128584         $("#options-menu-settings").click(function () {
128585             settings.show(); 
128586         });
128587
128588         if (settings.value("remoteInspector")) {
128589             $("#options-menu-build-warning").show();
128590             tooltip.create("#options-menu-build-warning", "Remote Web Inspector should be disabled when packaging for App World release");
128591         }
128592
128593         areServicesRunning(
128594             function () {
128595                 $('#options-menu-services-stop').show();
128596                 $('#options-menu-services-start').hide();
128597             }, 
128598             function () {
128599                 $('#options-menu-services-stop').hide();
128600                 $('#options-menu-services-start').show();
128601             }
128602         );
128603     }
128604 };
128605
128606 });
128607 define('ripple/ui/plugins/call', function (require, exports, module) {
128608 /*
128609  *  Copyright 2012 Intel Corporation
128610  *
128611  * Licensed under the Apache License, Version 2.0 (the "License");
128612  * you may not use this file except in compliance with the License.
128613  * You may obtain a copy of the License at
128614  *
128615  * http://www.apache.org/licenses/LICENSE-2.0
128616  *
128617  * Unless required by applicable law or agreed to in writing, software
128618  * distributed under the License is distributed on an "AS IS" BASIS,
128619  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
128620  * See the License for the specific language governing permissions and
128621  * limitations under the License.
128622  */
128623 var event = require('ripple/event'),
128624     utils = require('ripple/utils'),
128625     db = require('ripple/db'),
128626     _exception = {
128627         "unknown":           "Unknown",
128628         "network":           "Network",
128629         "unreachable":       "Unreachable",
128630         "no-answer":         "No Answer",
128631         "bad-number":        "Bad Number",
128632         "number-not-in-use": "Number Not In Use",
128633         "media":             "Media",
128634         "no-sim":            "No Sim Card",
128635         "account-down":      "Account Down",
128636         "credit-down":       "Credit Down",
128637         "barred":            "Barred",
128638         "network-busy":      "Network Busy",
128639         "network-down":      "Network Down"
128640     },
128641     _status = {
128642         IDLE:       0,
128643         DIALED:     1,
128644         PLACED:     2,
128645         INPROGRESS: 3,
128646     },
128647     _statusInfo = [
128648         "Waiting...;Waiting",                                   // IDLE
128649         "Calling... ;Incomming call from simulator",               // DIALED
128650         "Incomming call from ;Calling simulator",                // PLACED
128651         "In conversation with ;In conversation with simulator"   // INPROGRESS
128652     ],
128653     _data = {
128654         status: _status.IDLE,
128655         isInException: false,
128656         isAutoAccept: false,
128657         autoAcceptTimerId: null,
128658         conversationStartTime: null
128659     },
128660     _contactMap = {
128661         "861012345678": "Guest"
128662     },
128663     _CONTACT_KEY = "tizen1-contact",
128664     _RECORDING_KEY = "tizen1-call-recording",
128665     _RECORDING_PATH = "music/",
128666     _record = {},
128667     _conversationSeconds = 0,
128668     _conversationTimer,
128669     _callingEffectTimer;
128670
128671 function _initContacts() {
128672     var data = db.retrieveObject(_CONTACT_KEY),
128673         contactsSelect = document.getElementById("call-local-phone-number"),
128674         displayName = null, number = null, index = 0, i;
128675         
128676     contactsSelect.innerHTML = "";
128677
128678     utils.forEach(data, function (addrBook) {
128679         utils.forEach(addrBook._contacts, function (contact) {
128680             if (contact.name && contact.name && contact.phoneNumbers &&
128681                 contact.phoneNumbers.length > 0) {
128682                 displayName = contact.name.firstName + ' ' + contact.name.lastName;
128683                 number = contact.phoneNumbers[0].number;
128684                 _contactMap[number] = displayName;
128685
128686                 contactsSelect.appendChild(utils.createElement("option", {
128687                     "innerText": displayName + ':' + number,
128688                     "value": index
128689                 }));
128690                 index++;
128691             }
128692         });
128693     });
128694
128695     if (displayName === null && number === null) {
128696         for (i in _contactMap) {
128697             displayName = _contactMap[i];
128698             number = i;
128699             contactsSelect.appendChild(utils.createElement("option", {
128700                 "innerText": displayName + ':' + number,
128701                 "value": index
128702             }));
128703         }
128704     }
128705 }
128706
128707 function _initEventWatchers() {
128708     event.on("DialerLaunched", function (remoteParty) {
128709         var localContact = document.getElementById("call-local-phone-number");
128710
128711         if (_data.status !== _status.IDLE) {
128712             return;
128713         }
128714
128715         localContact.appendChild(utils.createElement("option", {
128716             "innerText": remoteParty.displayName,
128717             "value": remoteParty.remoteParty,
128718             "selected": "selected"
128719         }));
128720         _localCall();
128721     });
128722 }
128723
128724 function _initExceptionTypes() {
128725     utils.forEach(_exception, function (value, key) {
128726         document.getElementById("call-exception-type").appendChild(utils.createElement("option", {
128727             "innerText": value,
128728             "value": key
128729         }));
128730     });
128731 }
128732
128733 function _initRecord() {
128734     var localPartString = jQuery("#call-local-phone-number option:selected").text() || "",
128735         localPartStringList = localPartString.split(":"),
128736         displayName;
128737
128738     if (localPartStringList.length > 1) {
128739         displayName = localPartStringList[0];
128740     }
128741     else {
128742         displayName = localPartString;
128743     }
128744
128745     _record = {};
128746     _record.serviceId = (new Date()).getTime() || 0;
128747     _record.callParticipants = [{
128748         id: localPartString + ':' + displayName,
128749         displayName: displayName,
128750         contactRef: null
128751     }];
128752     _record.forwardedFrom = null;
128753     _record.startTime = new Date();
128754     _record.recording = [];
128755 }
128756
128757
128758 function updateConvTime() {
128759     var timeObj = new Date(1970, 0, 1),
128760     timeString;
128761
128762     timeObj.setSeconds(_conversationSeconds);
128763     timeString = timeObj.toTimeString().substr(0, 8);
128764     jQuery("#ConvTimeString").text(timeString);
128765     jQuery("#ConvTimeString2").text(timeString);
128766     _conversationSeconds = _conversationSeconds + 1;
128767 }
128768
128769
128770 function CallingEffect() {
128771     var color = jQuery("#callingString").css('color');
128772     if (color === "rgb(255, 255, 255)") {
128773         jQuery("#callingString").css('color', "black");
128774         jQuery("#callingString2").css('color', "black");
128775     }
128776     else {
128777         jQuery("#callingString").css('color', "white");
128778         jQuery("#callingString2").css('color', "white");
128779     }
128780 }
128781
128782
128783 function _transferStatus() {
128784     var statusStringList = _statusInfo[_data.status].split(";"),
128785         localPartString = jQuery("#call-local-phone-number option:selected").text() || "",
128786         localPartStringList = localPartString.split(":"),
128787         localNumber = localPartStringList[0],
128788         localName = _contactMap[localNumber] || localNumber;
128789     jQuery("#status-text").show();
128790     jQuery("#remote-status-text").show();
128791     jQuery("#call-status").show();
128792     jQuery("#remote-call-status").show();
128793     jQuery("#remotePartyName").html(localName);
128794     jQuery("#call-local-call").show();
128795     window.clearInterval(_callingEffectTimer);
128796
128797     switch (_data.status) {
128798     case _status.DIALED:      // local call
128799         jQuery("#call-remote-text").html("Accept");
128800         jQuery("#end-remote-text").html("Reject");
128801         jQuery("#call-status").html("<span style='font-size: 22px;'>" + localName + "</span><br>" + 
128802                         "<span id='callingString' style='font-size: 14px;'>&nbsp;" + statusStringList[0] + 
128803                         "</span><br><br><br><button id='call-local-end-d' class='ui-corner-all' style='padding:2px;" +
128804                         " border-width:1px; background-color:red; color:white; font-size:14px; font-weight:bold; width:100%;'>End call</button>");
128805         jQuery("#call-local-end-d").bind("click", _localEnd);
128806         jQuery("#remote-call-status").html("<span style='font-size: 20px;'>Simulator Bot</span><br>" + 
128807                         "<span id='callingString2' style='font-size: 12px;'>&nbsp;Incoming call...</span>" +
128808                         "<br><br><br><button id='call-remote-decline-d' class='ui-corner-all' style='padding:2px;" +
128809                         " border-width:1px; background-color:red; color:white; font-size:14px; font-weight:bold; width:48%;'>Decline</button>&nbsp;&nbsp;" +
128810                         "<button id='call-remote-answer-d' class='ui-corner-all' style='padding:2px; border-width:1px; background-color:green; color:white; font-size:14px; font-weight:bold; width:48%;'>Answer</button>");
128811         jQuery("#call-remote-answer-d").bind("click", _remoteCall);
128812         jQuery("#call-remote-decline-d").bind("click", _remoteEnd);
128813         _callingEffectTimer = window.setInterval(CallingEffect, 800);
128814         break;
128815     case _status.PLACED:      // Remote Call
128816         jQuery("#call-local-text").html("Accept");
128817         jQuery("#end-local-text").html("Reject");
128818         jQuery("#call-status").html(statusStringList[0] + localName);
128819         jQuery("#remote-call-status").html(statusStringList[1]);
128820         jQuery("#remote-call-status").html("<span style='font-size: 22px;'>Simulator Bot</span><br>" + 
128821                         "<span id='callingString' style='font-size: 14px;'>&nbsp;Calling..." + 
128822                         "</span><br><br><br><button id='call-remote-end-d' class='ui-corner-all' style='padding:2px;" +
128823                         " border-width:1px; background-color:red; color:white; font-size:14px; font-weight:bold; width:100%;'>End call</button>");
128824         jQuery("#call-remote-end-d").bind("click", _remoteEnd);
128825         jQuery("#call-status").html("<span style='font-size: 22px;'>" + localName + "</span><br>" + 
128826                         "<span id='callingString2' style='font-size: 14px;'>&nbsp;Incoming call...</span>" +
128827                         "<br><br><br><button id='call-local-decline-d' class='ui-corner-all' style='padding:2px;" +
128828                         " border-width:1px; background-color:red; color:white; font-size:14px; font-weight:bold; width:48%;'>Decline</button>&nbsp;&nbsp;" +
128829                         "<button id='call-local-answer-d' class='ui-corner-all' style='padding:2px; border-width:1px;" +
128830                         " background-color:green; color:white; font-size:14px; font-weight:bold; width:48%;'>Answer</button>");
128831         jQuery("#call-local-answer-d").bind("click", _localCall);
128832         jQuery("#call-local-decline-d").bind("click", _localEnd);
128833         _callingEffectTimer = window.setInterval(CallingEffect, 800);
128834         break;
128835     case _status.INPROGRESS:
128836         jQuery("#call-status").html("<span style='font-size: 22px;'>" + localName + "</span><br>" + 
128837                         "<span id='ConvTimeString' style='font-size: 14px;'>" + "00:00:00" + 
128838                         "</span><br><br><br><button id='call-local-end-d-c' class='ui-corner-all' style='padding:2px;" +
128839                         " border-width:1px; background-color:red; color:white; font-size:14px; font-weight:bold; width:100%;'>End call</button>");
128840         jQuery("#remote-call-status").html("<span style='font-size: 22px;'>Simulator Robot</span><br>" + 
128841                         "<span id='ConvTimeString2' style='font-size: 14px;'>" + "00:00:00" + 
128842                         "</span><br><br><br><button id='call-remote-end-d-c' class='ui-corner-all' style='padding:2px;" +
128843                         " border-width:1px; background-color:red; color:white; font-size:14px; font-weight:bold; width:100%;'>End call</button>");
128844         jQuery("#call-local-end-d-c").bind("click", _localEnd);
128845         jQuery("#call-remote-end-d-c").bind("click", _remoteEnd);
128846         _conversationTimer = window.setInterval(updateConvTime, 1000);
128847         jQuery("#call-remote-text").html("Call");
128848         jQuery("#end-remote-text").html("End");
128849         jQuery("#call-local-text").html("Call");
128850         jQuery("#end-local-text").html("End");
128851         break;
128852     default:
128853         jQuery("#call-status").html(statusStringList[0]);
128854         jQuery("#call-status").html("default");
128855         jQuery("#remote-call-status").html(statusStringList[1]);
128856         jQuery("#remote-call-status").html("default");
128857         jQuery("#call-remote-text").html("Call");
128858         jQuery("#end-remote-text").html("End");
128859         jQuery("#call-local-text").html("Call");
128860         jQuery("#end-local-text").html("End");
128861         return;
128862     }
128863 }
128864
128865 function _startCall() {
128866     _data.conversationStartTime = new Date();
128867     event.trigger("CallInProgress", [true]);
128868     _data.status = _status.INPROGRESS;
128869     //_transferStatus();
128870 }
128871
128872 function _endCall(callEndReason) {
128873     if (_data.autoAcceptTimerId) {
128874         var path = _RECORDING_PATH + _record.serviceId + ".mp3";
128875
128876         _record.recording.push(path);
128877         db.saveObject(_RECORDING_KEY, path);
128878
128879         clearTimeout(_data.autoAcceptTimerId);
128880         _data.autoAcceptTimerId = null;
128881     }
128882
128883     _record.duration = _data.conversationStartTime ? ((new Date()) - _data.conversationStartTime) : 0;
128884     _data.conversationStartTime = null;
128885     
128886     _record.endReason = callEndReason;
128887
128888     if (_data.status === _status.PLACED) {
128889         _record.direction = "missed-new";
128890     }
128891
128892     event.trigger("CallRecorded", [_record]);
128893     event.trigger("CallInProgress", [false]);
128894
128895     _data.status = _status.IDLE;
128896     _transferStatus();
128897     _record = {};
128898
128899     _conversationSeconds = 0;
128900     window.clearInterval(_conversationTimer);
128901     jQuery("#call-status").hide();
128902     jQuery("#remote-call-status").hide();
128903
128904     jQuery("#status-text").hide();
128905     jQuery("#remote-status-text").hide();
128906 }
128907
128908 function _localCall() {
128909     if (_data.isInException) {
128910         return;
128911     }
128912
128913     switch (_data.status) {
128914     case _status.IDLE:    //local call
128915         _data.status = _status.DIALED;
128916         _initRecord();
128917         _record.direction = "dialed";
128918         break;
128919     case _status.PLACED:
128920         _data.status = _status.INPROGRESS;
128921         _record.direction = "received";
128922         if (_data.autoAcceptTimerId) {
128923             clearTimeout(_data.autoAcceptTimerId);
128924             _data.autoAcceptTimerId = null;
128925         }
128926         _startCall();
128927         break;
128928     default:
128929         return;
128930     }
128931
128932     _transferStatus();
128933
128934     if (_data.isInException) {
128935         _endCall(document.getElementById("call-exception-type").value);
128936     }
128937 }
128938
128939 function _localEnd() {
128940     switch (_data.status) {
128941     case _status.DIALED:     // Local Cancel
128942     case _status.INPROGRESS: // Local End
128943         _endCall("local");
128944         break;
128945     case _status.PLACED:
128946         _record.direction = "missed-new";
128947         _endCall("local");
128948         break;
128949     default:
128950         return;
128951     }
128952 }
128953
128954 function _remoteCall() {
128955     if (_data.isInException) {
128956         return;
128957     }
128958
128959     switch (_data.status) {
128960     case _status.IDLE:      // Remote Call
128961         _data.status = _status.PLACED; 
128962         _initRecord();
128963         if (_data.isAutoAccept) {
128964             _data.autoAcceptTimerId = setTimeout(_localCall, 2000);
128965         }
128966         break;
128967     case _status.DIALED:    // Remote Answer
128968         _startCall();
128969         break;
128970     default:
128971         return;
128972     }
128973
128974     _transferStatus();
128975
128976     if (_data.isInException) {
128977         _endCall(document.getElementById("call-exception-type").value);
128978     }
128979 }
128980
128981 function _remoteEnd() {
128982     switch (_data.status) {
128983     case _status.DIALED:     // Remote Reject
128984         _endCall("rejected");
128985         break;
128986     case _status.INPROGRESS: // Remote End
128987         _endCall("remote");
128988         break;
128989     case _status.PLACED:    // Remote Cancel
128990         _record.direction = "missed-new";
128991         _endCall("remote");
128992         break;
128993     default:
128994         return;
128995     }
128996 }
128997
128998 function _leaveMessage() {
128999     if (!this.checked && _data.autoAcceptTimerId) {
129000         clearTimeout(_data.autoAcceptTimerId);
129001         _data.autoAcceptTimerId = null;
129002     }
129003     _data.isAutoAccept = this.checked;
129004 }
129005
129006 function _exceptionStatus() {
129007     _data.isInException = this.checked;
129008     if (_data.isInException && (_data.status !== _status.IDLE)) {
129009         if (_data.status === _status.RECEIVED) {   // Remote Cancel
129010             _record.direction = "missed-new";
129011             _record.duration = 0;
129012         }
129013         _endCall(document.getElementById("call-exception-type").value);
129014     }
129015 }
129016
129017
129018 function _updateRemotePartyName() {
129019     jQuery("#remotePartyName").text(jQuery("#call-local-phone-number option:selected").text());
129020 }
129021
129022
129023 module.exports = {
129024     panel: {
129025         domId: "call-container",
129026         collapsed: true,
129027         pane: "left",
129028         titleName: "Call",
129029         display: true
129030     },
129031     initialize: function () {
129032         jQuery("#call-local-call").bind("click", _localCall);
129033         jQuery("#call-local-end").bind("click", _localEnd);
129034         jQuery("#call-remote-call").bind("click", _remoteCall);
129035         jQuery("#call-remote-end").bind("click", _remoteEnd);
129036         jQuery("#recording-status").bind("click", _leaveMessage);
129037         jQuery("#call-exception-status").bind("click", _exceptionStatus);
129038         jQuery("#call-exception-type").bind("click", null);
129039
129040         _initEventWatchers();
129041         _initContacts();
129042         jQuery("#remotePartyName").text(jQuery("#call-local-phone-number option:selected").text());
129043         jQuery("#call-local-phone-number").bind("change", _updateRemotePartyName);
129044         _initExceptionTypes();
129045     }
129046 };
129047
129048 });
129049 define('ripple/ui/plugins/camera', function (require, exports, module) {
129050 /*
129051  *  Copyright 2011 Research In Motion Limited.
129052  *
129053  * Licensed under the Apache License, Version 2.0 (the "License");
129054  * you may not use this file except in compliance with the License.
129055  * You may obtain a copy of the License at
129056  *
129057  * http://www.apache.org/licenses/LICENSE-2.0
129058  *
129059  * Unless required by applicable law or agreed to in writing, software
129060  * distributed under the License is distributed on an "AS IS" BASIS,
129061  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
129062  * See the License for the specific language governing permissions and
129063  * limitations under the License.
129064  */
129065
129066 var ui = require('ripple/ui'),
129067     event = require('ripple/event'),
129068     video = document.getElementById('camera-video'),
129069     upload = document.getElementById('picture-upload'),
129070     select = document.getElementById('select-file'),
129071     take = document.getElementById('take-file'),
129072     pic = document.getElementById("camera-image");
129073
129074
129075 select.addEventListener('click', function () {
129076     upload.click();
129077 });
129078
129079 upload.addEventListener('change', function () {
129080     pic.src = window.webkitURL.createObjectURL(upload.files[0]);
129081     take.style.display = "inline";
129082 });
129083
129084 take.addEventListener('click', function () {
129085     console.log("captured-image: " + pic.src);
129086     event.trigger('captured-image', [pic.src, upload.files[0]]);
129087     module.exports.hide();
129088 });
129089
129090 module.exports = {
129091     show: function () {
129092         ui.showOverlay("camera-window");
129093         if (pic.src) {
129094             take.style.display = "inline";
129095         }
129096         else {
129097             take.style.display = "none";
129098         }
129099     },
129100     hide: function () {
129101         ui.hideOverlay("camera-window");
129102     }
129103 };
129104
129105 });
129106 define('ripple/ui/plugins/communication', function (require, exports, module) {
129107 /*
129108  *  Copyright 2011 Research In Motion Limited.
129109  *
129110  * Licensed under the Apache License, Version 2.0 (the "License");
129111  * you may not use this file except in compliance with the License.
129112  * You may obtain a copy of the License at
129113  *
129114  * http://www.apache.org/licenses/LICENSE-2.0
129115  *
129116  * Unless required by applicable law or agreed to in writing, software
129117  * distributed under the License is distributed on an "AS IS" BASIS,
129118  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
129119  * See the License for the specific language governing permissions and
129120  * limitations under the License.
129121  */
129122
129123 var ui = require('ripple/ui'),
129124     event = require('ripple/event'),
129125     deviceSettings = require('ripple/deviceSettings'),
129126     db = require('ripple/db'),
129127     utils = require('ripple/utils'),
129128     _messageType = {
129129         sms: "SMS",
129130         mms: "MMS",
129131         email: "E-mail"
129132     },
129133     _attachments = [],
129134 /*
129135     _exception = {
129136         "":                  "Connection Issue",
129137         "unknown":           "Unknown",
129138         "network":           "Network",
129139         "unreachable":       "Unreachable",
129140         "no-answer":         "No Answer",
129141         "bad-number":        "Bad Number",
129142         "number-not-in-use": "Number Not In Use",
129143         "media":             "Media",
129144         "no-sim":            "No Sim Card",
129145         "account-down":      "Account Down",
129146         "credit-down":       "Credit Down",
129147         "barred":            "Barred",
129148         "network-busy":      "Network Busy",
129149         "network-down":      "Network Down"
129150     },
129151 */
129152     _status = {
129153         IDLE:       0,
129154         DIALED:     1,
129155         INPROGRESS: 2,
129156     },
129157     _data = {
129158         status: _status.IDLE,
129159 //        isInException: false,
129160         conversationStartTime: null
129161     },
129162     _contactNameArr = [],
129163     _contactNumArr = [],
129164     _CONTACT_KEY = "tizen1-contact",
129165     _record = {},
129166     _conversationSeconds = 0,
129167     _conversationTimer,
129168     _msgTimer,
129169     _audioPlayersStatus = [];
129170
129171 function _showMsg() {
129172     var messageName = jQuery("#communication-senderName").val(),
129173         messageContent = jQuery("#communication-messageContent").val(),
129174         disMsgName = jQuery(".communication-messageContainer tr:first-child td"),
129175         disMsgContent = jQuery(".communication-messageContainer tr:nth-child(2) td textarea");
129176
129177     ui.showOverlay("communication-window");
129178
129179     disMsgName.text(messageName ? messageName : "Unknown name");
129180     disMsgContent.val(messageContent ? messageContent : "");
129181
129182     jQuery("#communication-viewport").css("height", jQuery("#viewport-container").css("height"))
129183                                      .show("slide", {direction: "up"}, "fast");
129184     jQuery(".communication-callContainer").hide();
129185     jQuery(".communication-messageContainer").show();
129186 }
129187
129188 function _msgEventInitialize() {
129189     jQuery("#communication-messageRadioStatus").hide();
129190     jQuery("#communication-sendMessage").unbind("click").click(function () {
129191         var messageItem,
129192             number = jQuery("#communication-senderName").val(),
129193             text = jQuery("#communication-messageContent").val(),
129194             type = jQuery("#communication-msgType").val(),
129195             message = {
129196                 type: type,
129197                 body: text,
129198                 from: number,
129199                 time: new Date(),
129200                 attachments: _attachments
129201             };
129202
129203         if (deviceSettings.retrieve("CELLULAR_NETWORK.status") === false &&
129204             (type === 'sms' || type === 'mms')) {
129205             jQuery("#communication-messageRadioStatus").html('cellular radio is off<br \>Turn it on from Network Management Panel.');
129206             jQuery("#communication-messageRadioStatus").show();
129207             setTimeout(function () {
129208                 jQuery("#communication-messageRadioStatus").hide();
129209             }, 3000);
129210             return;
129211         }
129212         if (deviceSettings.retrieve("WIFI_NETWORK.status") === false &&
129213             type === 'email') {
129214             jQuery("#communication-messageRadioStatus").html('wifi radio is off<br \>Turn it on from Network Management Panel.');
129215             jQuery("#communication-messageRadioStatus").show();
129216             setTimeout(function () {
129217                 jQuery("#communication-messageRadioStatus").hide();
129218             }, 3000);
129219             return;
129220         }
129221
129222         event.trigger("MessageReceived", [message]);
129223         _attachments = [];
129224         event.trigger("CommWinShow", [true]);
129225         _showMsg();
129226
129227         jQuery(".communication-messageContainer textarea").attr("disabled", "disabled");
129228         jQuery("#communication-messageOut td:nth-child(3)").text(jQuery("#communication-messageContent").val());
129229         messageItem = jQuery("#communication-messageOut").html();
129230         jQuery("#communication-messageDisplay").append(messageItem);
129231
129232         clearTimeout(_msgTimer);
129233         _msgTimer = setTimeout(function () {
129234             if (_data.status === _status.IDLE) {
129235                 ui.hideOverlay("communication-window");
129236                 event.trigger("CommWinShow", [false]);
129237             } else {
129238                 _showCall();
129239             }
129240         }, 5000);
129241     });
129242
129243     jQuery("#communication-clearMessage").unbind("click").click(function () {
129244             jQuery("#communication-messageDisplay").empty();
129245         });
129246
129247     event.on("LayoutChanged", function () {
129248         jQuery("#communication-viewport").css("height", jQuery("#viewport-container").css("height"));
129249
129250     });
129251     event.on("OutsideMessageReceived", function (message) {
129252         var i = 0,
129253             recipients = [],
129254             recipientsStatus = {},
129255             messageItem;
129256
129257         recipientsStatus.id = message.id;
129258         recipientsStatus.msg = message.msg;
129259         for (i in message.to) {
129260             recipientsStatus[message.to[i]] = true;
129261             recipients.push(message.to[i]);
129262         }
129263         for (i in message.cc) {
129264             recipientsStatus[message.cc[i]] = true;
129265             recipients.push(message.cc[i]);
129266         }
129267         for (i in message.bcc) {
129268             recipientsStatus[message.bcc[i]] = true;
129269             recipients.push(message.bcc[i]);
129270         }
129271
129272         event.trigger("MessageSent", [recipientsStatus]);
129273         jQuery("#communication-messageIn td:nth-child(1)").text(message.body);
129274         messageItem = jQuery("#communication-messageIn").html();
129275         jQuery("#communication-messageDisplay").append(messageItem);
129276     });
129277
129278     jQuery("#communication-ok").unbind("click").click(function () {
129279         if (_data.status === _status.IDLE) {
129280             ui.hideOverlay("communication-window");
129281             event.trigger("CommWinShow", [false]);
129282         } else {
129283             _showCall();
129284         }
129285         clearTimeout(_msgTimer);
129286     });
129287 }
129288
129289 function _msgInitialize() {
129290     _msgEventInitialize();
129291
129292     utils.forEach(_messageType, function (msgTypeText, msgType) {
129293         var typeNode = utils.createElement("option", {
129294                 "innerText": msgTypeText,
129295                 "value": msgType
129296             });
129297
129298         jQuery("#communication-msgType").append(typeNode);
129299     });
129300 }
129301
129302 function pauseAllAudioPlayer() {
129303     var audios = $("#document").contents().find("audio"),
129304         index;
129305     for (var index = 0; index < audios.length; index++) {
129306         if (audios[index].paused) {
129307             _audioPlayersStatus[index] = 0;
129308         }
129309         else {
129310             _audioPlayersStatus[index] = 1;
129311             audios[index].pause();
129312         }
129313     }
129314 }
129315
129316 function playAllAudioPlayer() {
129317     var audios = $("#document").contents().find("audio"),
129318         index;
129319     for (var index = 0; index < audios.length; index++) {
129320         if (_audioPlayersStatus[index] === 1) {
129321             audios[index].play();
129322         }
129323     }
129324     _audioPlayersStatus = [];
129325 }
129326
129327 function _showCall() {
129328     var callName = jQuery("#communication-callerName").val(),
129329         callNum = jQuery("#communication-callNum").val(),
129330         disCallName = jQuery(".communication-callContainer tr:first-child td"),
129331         disCallNum = jQuery(".communication-callContainer tr:nth-child(2) td");
129332
129333     ui.showOverlay("communication-window");
129334     event.trigger("CommWinShow", [true]);
129335
129336     disCallName.text(callName ? callName : "Unknown Name");
129337     disCallNum.text(callNum ? callNum : "Unknown Number");
129338
129339     jQuery("#communication-viewport").css("height", jQuery("#viewport-container").css("height"))
129340                                      .show("slide", {direction: "up"}, "fast");
129341     jQuery(".communication-callContainer").show();
129342     jQuery(".communication-messageContainer").hide();
129343     pauseAllAudioPlayer();
129344 }
129345
129346 function _initRecord() {
129347     var callerName = jQuery("#communication-callerName").val(),
129348         callerNum = jQuery("#communication-callNum").val(),
129349         displayName = callerName ? callerName : "Unknown",
129350         displayNum = callerNum ? callerNum : "Unknown";
129351
129352     _record = {};
129353     _record.type = "TEL";
129354     if ($("#is-videoCall").prop("checked") === true) {
129355         _record.features = ["CALL", "VIDEOCALL"];
129356     } else {
129357         _record.features = ["CALL", "VOICECALL"];
129358     }
129359     _record.remoteParties = [{
129360         remoteParty: displayNum,
129361         personId: displayName,
129362     }];
129363     _record.startTime = new Date();
129364 }
129365
129366 function _endCall(callEndReason) {
129367     _record.duration = _data.conversationStartTime ? _conversationSeconds : 0;
129368
129369     _data.conversationStartTime = null;
129370
129371     switch (callEndReason) {
129372     case 'rejected':
129373         _record.direction = "REJECTED";
129374         break;
129375     case 'remote':
129376         _record.direction = "RECEIVED";
129377         break;
129378     case 'local':
129379         _record.direction = "MISSEDNEW";
129380         break; 
129381     }
129382
129383     event.trigger("CallRecorded", [_record]);
129384     event.trigger("CallInProgress", [false]);
129385
129386     _data.status = _status.IDLE;
129387     _record = {};
129388
129389     _conversationSeconds = 0;
129390     window.clearInterval(_conversationTimer);
129391     ui.hideOverlay("communication-window");
129392     event.trigger("CommWinShow", [false]);
129393     playAllAudioPlayer();
129394 }
129395
129396 function _callEventInitialize() {
129397     jQuery("#communication-cellularStatus").hide();
129398     jQuery("#communication-callStart").unbind('click').click(
129399         function () {
129400             if (deviceSettings.retrieve("CELLULAR_NETWORK.status") === false) {
129401                 jQuery("#communication-cellularStatus").show();
129402                 setTimeout(function () {
129403                     jQuery("#communication-cellularStatus").hide();
129404                 }, 3000);
129405
129406                 return;
129407             }
129408             if (_data.status === _status.IDLE) {
129409                 _data.status = _status.DIALED;
129410                 _initRecord();
129411                 _showCall();
129412                 jQuery("#callSettings tr:last-child td").text("Calliing...");
129413                 jQuery("#communication-callStart > span").text("End Call");
129414                 jQuery("#callSettings input").attr("disabled", "disabled");
129415             } else {
129416                 _endCall("local");
129417
129418                 jQuery("#callSettings tr:last-child td").text("");
129419                 jQuery("#communication-callStart > span").text("Call");
129420                 jQuery(".communication-callContainer tr:nth-child(3)").show();
129421                 jQuery(".communication-callContainer tr:last-child").hide();
129422                 jQuery("#callSettings input").removeAttr("disabled");
129423             }
129424
129425         }
129426     );
129427
129428     event.on("ApplicationLoad", function () {
129429         switch (_data.status) {
129430         case _status.INPROGRESS:
129431             jQuery("#communication-callStart").click();
129432             break;
129433         case _status.DIALED:
129434             jQuery("#communication-ignore").click();
129435             break;
129436         default:
129437             break;
129438         }
129439     });
129440
129441     jQuery("#communication-ignore").unbind('click').click(function () {
129442         _endCall("rejected");
129443
129444         jQuery("#callSettings tr:last-child td").text("");
129445         jQuery("#communication-callStart > span").text("Call");
129446         jQuery("#communication-callStart").removeData();
129447         jQuery("#callSettings input").removeAttr("disabled");
129448     });
129449
129450     jQuery("#communication-answer").unbind('click').click(function () {
129451         _data.conversationStartTime = new Date();
129452         event.trigger("CallInProgress", [true]);
129453         _data.status = _status.INPROGRESS;
129454
129455         _conversationTimer = setInterval(function () {
129456             var timeObj = new Date(1970, 0, 1),
129457                 timeString;
129458
129459             timeObj.setSeconds(_conversationSeconds);
129460             timeString = timeObj.toTimeString().substr(0, 8);
129461             jQuery("#callSettings tr:last-child td").text(timeString);
129462             _conversationSeconds = _conversationSeconds + 1;
129463         }, 1000);
129464
129465         jQuery(".communication-callContainer tr:nth-child(3)").hide();
129466         jQuery(".communication-callContainer tr:last-child").show();
129467     });
129468
129469     jQuery("#communication-end").unbind('click').click(function () {
129470         _endCall("remote");
129471
129472         jQuery("#callSettings tr:last-child td").text("");
129473         jQuery("#communication-callStart > span").text("Call");
129474         jQuery("#communication-callStart").removeData();
129475         jQuery(".communication-callContainer tr:nth-child(3)").show();
129476         jQuery(".communication-callContainer tr:last-child").hide();
129477         jQuery("#callSettings input").removeAttr("disabled");
129478     });
129479 /*
129480     jQuery("#communication-callEndReason").unbind("change").change(function () {
129481         if (!jQuery("#communication-callEndReason").val()) {
129482             _data.isInException = false;
129483         } else {
129484             _data.isInException = true;
129485             if (_data.isInException && (_data.status !== _status.IDLE)) {
129486                 _endCall(jQuery("#communication-callEndReason").val());
129487             }
129488         }
129489
129490         jQuery("#callSettings tr:last-child td").text("");
129491         jQuery("#communication-callStart > span").text("Call");
129492         jQuery("#communication-callStart").removeData();
129493         jQuery(".communication-callContainer tr:nth-child(3)").show();
129494         jQuery(".communication-callContainer tr:last-child").hide();
129495         jQuery("#callSettings input").removeAttr("disabled");
129496     });
129497 */
129498 }
129499
129500 function _contactInitialize() {
129501     var data = db.retrieveObject(_CONTACT_KEY),
129502         displayName = null, number = null, index = 0;
129503
129504     _contactNameArr = [];
129505     _contactNumArr = [];
129506
129507     utils.forEach(data, function (addrBook) {
129508         utils.forEach(addrBook._contacts, function (contact) {
129509             if (contact.name && contact.name && contact.phoneNumbers && contact.phoneNumbers.length > 0) {
129510                 displayName = contact.name.firstName + ' ' + contact.name.lastName;
129511                 number = contact.phoneNumbers[0].number;
129512                 _contactNameArr.push(displayName);
129513                 _contactNumArr[displayName] = number;
129514                 index++;
129515             }
129516         });
129517     });
129518
129519     jQuery("#communication-callerName").autocomplete({
129520         source: _contactNameArr,
129521         select: function (event, ui) {
129522             jQuery("#communication-callNum").val(_contactNumArr[ui.item.value]);
129523         }
129524     });
129525     jQuery("#communication-senderName").autocomplete({
129526         source: _contactNameArr
129527     });
129528 }
129529
129530 function _callInitialize() {
129531     _callEventInitialize();
129532
129533     _contactInitialize();
129534 /*
129535     utils.forEach(_exception, function (value, key) {
129536         var typeNode = utils.createElement("option", {
129537                 "innerText": value,
129538                 "value": key
129539             });
129540
129541         jQuery("#communication-callEndReason").append(typeNode);
129542     });
129543 */
129544 }
129545
129546 function _pushEventInitialize() {
129547     function register(appService) {
129548         appService.registrationId = Math.uuid(null, 16);
129549
129550         window.setTimeout(function () {
129551             var appLabel;
129552
129553             if ($("#communication-push-" + appService.appId).length !== 0) {
129554                 $("#" + appService.appId).click();
129555                 $("#communication-push-status-" + appService.appId).html("||");
129556                 $("#communication-push-status-" + appService.appId).css("color", "#ff0000");
129557
129558                 return;
129559             }
129560
129561             if (!$("#communication-push-app > tbody").html()) {
129562                 $("#communication-push-header").show();
129563                 $("#communication-push-submit").removeAttr("disabled");
129564             }
129565
129566             appLabel = appService.appControl.uri || appService.appId;
129567
129568             $("#communication-push-app").append(
129569                 "<tr id='communication-push-" + appService.appId + "'>" +
129570                 "<td style='width: 90%'><input type='radio' name='communication-push-list' id='" +
129571                 appService.appId + "' style='margin: 5px' checked='checked' />" +
129572                 "<label for='" + appService.appId + "'>" + appLabel + "</label></td>" +
129573                 "<td id='communication-push-status-" + appService.appId + "'>||</td>" +
129574                 "</tr>");
129575
129576             $("label[for='" + appService.appId + "']").css({
129577                 "display": "inline-block",
129578                 "width": "220px",
129579                 "white-space": "nowrap",
129580                 "overflow": "hidden",
129581                 "text-overflow": "ellipsis"
129582             });
129583
129584             $("#communication-push-status-" + appService.appId).css({
129585                 "width": "10%",
129586                 "color": "#ff0000",
129587                 "text-align": "center",
129588                 "font-weight": "bold",
129589                 "font-size": "14px"
129590             });
129591
129592             $("#communication-push-app tr:even").css("background-color", "white");
129593             $("#communication-push-app tr:odd").css("background-color", "whitesmoke");
129594         }, 1);
129595     }
129596
129597     function unregister(appId) {
129598         if ($("#communication-push-" + appId).length === 0)
129599             return;
129600
129601         $("tr[id='communication-push-" + appId + "']").remove();
129602
129603         if (!$("#communication-push-app > tbody").html()) {
129604             $("#communication-push-header").hide();
129605             $("#communication-push-submit").attr("disabled", "disabled");
129606
129607             return;
129608         }
129609
129610         if ($("input[name='communication-push-list']:checked").length === 0) {
129611             $("#communication-push-app input:first").click();
129612         }
129613
129614         $("#communication-push-app tr:even").css("background-color", "white");
129615         $("#communication-push-app tr:odd").css("background-color", "whitesmoke");
129616     }
129617
129618     function connect(appId) {
129619         $("#communication-push-status-" + appId).html("<=>");
129620         $("#communication-push-status-" + appId).css("color", "#32cd32");
129621     }
129622
129623     function disconnect(appId) {
129624         $("#communication-push-status-" + appId).html("||");
129625         $("#communication-push-status-" + appId).css("color", "#ff0000");
129626     }
129627
129628     event.on("PushRequest", function (command, cmdData) {
129629         switch (command) {
129630         case "REGISTER":
129631             register(cmdData);
129632             break;
129633
129634         case "UNREGISTER":
129635             unregister(cmdData);
129636             break;
129637
129638         case "CONNECT":
129639             connect(cmdData);
129640             break;
129641
129642         case "DISCONNECT":
129643             disconnect(cmdData);
129644             break;
129645         }
129646     });
129647 }
129648
129649 function _pushElementInitialize() {
129650     $("#communication-push-submit").attr("disabled", "disabled");
129651     $("#communication-push-submit").unbind('click').click(function () {
129652         var appId, pushMessage;
129653
129654         appId = $("#communication-push-app :checked").attr("id");
129655         if (!appId)
129656             return;
129657
129658         pushMessage = {
129659             appData:      $("#communication-push-data").val(),
129660             alertMessage: $("#communication-push-msg").val(),
129661             date:         new Date()
129662         };
129663
129664         if (!pushMessage.appData || !pushMessage.alertMessage)
129665             return;
129666
129667         event.trigger("PushNotified", [appId, pushMessage]);
129668     });
129669
129670     $("#communication-push-clear").unbind('click').click(function () {
129671         $("#communication-push-msg").val("");
129672         $("#communication-push-data").val("");
129673     });
129674 }
129675
129676 function _pushInitialize() {
129677     _pushEventInitialize();
129678     _pushElementInitialize();
129679 }
129680
129681 module.exports = {
129682     panel: {
129683         domId: "communication-container",
129684         collapsed: true,
129685         pane: "left",
129686         titleName: "Communications",
129687         display: true
129688     },
129689     initialize: function () {
129690         jQuery("#communication-select").tabs();
129691         _callInitialize();
129692         _msgInitialize();
129693         _pushInitialize();
129694     }
129695 };
129696
129697 });
129698 define('ripple/ui/plugins/configWindow', function (require, exports, module) {
129699 /*
129700  *  Copyright 2011 Research In Motion Limited.
129701  *
129702  * Licensed under the Apache License, Version 2.0 (the "License");
129703  * you may not use this file except in compliance with the License.
129704  * You may obtain a copy of the License at
129705  *
129706  * http://www.apache.org/licenses/LICENSE-2.0
129707  *
129708  * Unless required by applicable law or agreed to in writing, software
129709  * distributed under the License is distributed on an "AS IS" BASIS,
129710  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
129711  * See the License for the specific language governing permissions and
129712  * limitations under the License.
129713  */
129714 var utils = require('ripple/utils'),
129715     event = require('ripple/event'),
129716     db = require('ripple/db'),
129717     tooltip = require('ripple/ui/plugins/tooltip'),
129718     platform = require('ripple/platform'),
129719     items = [{name: "DEVICE", id: "device-conf-panel"},
129720              {name: "SYSTEM SETTINGS", id: "system-settings-conf-panel"},
129721              {name: "NETWORK", id: "network-conf-panel"}
129722             ],
129723     _KEY = "tizen-configuration-window-setting",
129724     _PERSISTENCE_KEY = "devicesettings",
129725     _DEVICESETTING_SAVE_KEY = "tizen-configuration-window-device-setting",
129726     _DB_APPLICATION_KEY = "tizen1-db-application",
129727     _DB_APPLICATION_SAVE_KEY = "tizen-configuration-window-application-key";
129728
129729 function reload() {
129730     window.tinyHipposReload = true;
129731     location.reload();
129732 }
129733
129734 function _hideConfigWindow() {
129735     $("#configure-window-popup").hide("slide", {direction: "up"}, "slow");
129736     $("#overlayBackground").hide("fade", "slow");
129737 }
129738
129739
129740 function checkResolutionValue(val) {
129741     var ret = false;
129742     if (val >= 200 && val <= 2000) {
129743         ret = true;
129744     }
129745     return ret;
129746 }
129747
129748 function _showConfigWindow() {
129749     var position_x;
129750     $("#item_container").empty();
129751     items.forEach(function (item) {
129752         $("#item_container").append('<div class="configuration-window-item">' + item.name + '</div>');
129753         $("#" + item.id).hide();
129754     });
129755
129756     $("#content_container").show();
129757     $("#" + items[0].id).show("fast");
129758     
129759     $(".configuration-window-item:eq(0)").css("background-color", "#003399");
129760     $(".configuration-window-item:eq(0)").css("color", "#ffffff");
129761
129762     $(".configuration-window-item").unbind('click');
129763     $(".configuration-window-item").bind("click", function () {
129764         $(".configuration-window-item").css("background-color", "#eeeeee");
129765         $(".configuration-window-item").css("color", "#333333");
129766        
129767         $(this).css("background-color", "#003399");
129768         $(this).css("color", "#ffffff");
129769
129770         items.forEach(function (item) {
129771             $("#" + item.id).hide();
129772         });
129773         $("#" + items[$(this).index()].id).show("fast");
129774     });
129775
129776     if ($("#configure-window-popup").is(":visible")) {
129777         $("#configure-window-popup").hide("slide", {direction: "up"}, "slow");
129778         $("#overlayBackground").hide("fade", "slow");
129779         return;
129780     }
129781
129782     position_x = (($(window).width() - 800) / 2)  < 0 ? 0 : ($(window).width() - 800) / 2;
129783     $("#configure-window-popup").css("top", 80);
129784     $("#configure-window-popup").css("left", position_x);
129785
129786     position_x = (($(window).width() - 400) / 2)  < 0 ? 0 : ($(window).width() - 400) / 2;
129787     $("#configure-window-done-popup").css("top", 80);
129788     $("#configure-window-done-popup").css("left", position_x);
129789
129790     $("#overlayBackground").css("width", $(window).width());
129791     $("#overlayBackground").css("height", $(window).height());
129792     $("#overlayBackground").show("fade", "slow");
129793     $("#configure-window-popup").show("slide", {direction: "up"}, "slow");
129794
129795     $("#configuration-window-done-btn").unbind('click');
129796     $("#configuration-window-done-btn").bind("click", function () {
129797         var platformId, version, device, type, width, height;
129798
129799         // device & resolution setting
129800         platformId = jQuery("#platform-select").val();
129801         version = jQuery("#version-select").val();
129802         device = jQuery("#device-select").val();
129803         width = jQuery("#resolution-custom-width").val();
129804         height = jQuery("#resolution-custom-height").val();
129805         type = jQuery('input:radio[name="resolution-type"]:checked').val();
129806
129807         if (type === "custom") {
129808             device = "custom";
129809             if (!checkResolutionValue(width) || !checkResolutionValue(height)) {
129810                 return;
129811             }
129812         }
129813
129814         platform.changeEnvironment({
129815             "name": platformId,
129816             "version": version
129817         }, device, null);
129818
129819         _hideConfigWindow();
129820         setTimeout(reload, 500);
129821     });
129822
129823     $("#configuration-window-close-btn").unbind('click');
129824     $("#configuration-window-close-btn").bind("click", function () {
129825         if ($("#configure-window-popup").is(":visible")) {
129826             _hideConfigWindow();
129827             return;
129828         }
129829     });
129830     tooltip.create("#configuration-window-save-btn", "Save Configuration");
129831     $("#configuration-window-save-btn").unbind('click');
129832     $("#configuration-window-save-btn").bind("click", function () {
129833         var _type, _device, _custom_width = 0, _custom_height = 0, programs, deviceInfo, _settings;
129834
129835         deviceInfo = db.retrieveObject(_PERSISTENCE_KEY);
129836         db.saveObject(_DEVICESETTING_SAVE_KEY, deviceInfo);
129837
129838         _device = jQuery("#device-select").val();
129839         _type = jQuery('input:radio[name="resolution-type"]:checked').val();
129840         if (_type === "custom") {
129841             _device = "custom";
129842             _custom_width = jQuery("#resolution-custom-width").val();
129843             _custom_height = jQuery("#resolution-custom-height").val();
129844         }
129845         _settings = {
129846             platformId : jQuery("#platform-select").val(),
129847             version : jQuery("#version-select").val(),
129848             device : _device,
129849             type : _type,
129850             custom_width : _custom_width,
129851             custom_height : _custom_height
129852         };
129853         db.saveObject(_KEY, _settings);
129854         programs = db.retrieveObject(_DB_APPLICATION_KEY);
129855         db.saveObject(_DB_APPLICATION_SAVE_KEY, programs);
129856
129857     });
129858     tooltip.create("#configuration-window-load-btn", "Load Configuration");
129859     $("#configuration-window-load-btn").unbind('click');
129860     $("#configuration-window-load-btn").bind("click", function () {
129861         var platformList,
129862             programs,
129863             deviceInfo,
129864             _settings,
129865             versionSelect = document.getElementById("version-select");
129866         if (db.retrieveObject(_DEVICESETTING_SAVE_KEY) === undefined) {
129867             //Never saving data exist
129868             return;
129869         }
129870         //reload system & network setting
129871         deviceInfo = db.retrieveObject(_DEVICESETTING_SAVE_KEY);
129872         db.saveObject("devicesettings", deviceInfo);
129873         jQuery("#devicesettings-content-container").empty();
129874         jQuery("#networksettings-content-container").empty();
129875         require('ripple/deviceSettings').initialize();
129876         require('ripple/ui/plugins/deviceSettings').terminate();
129877         require('ripple/ui/plugins/deviceSettings').initialize();
129878
129879         //reload device setting
129880         jQuery(versionSelect).empty();
129881         _settings = db.retrieveObject(_KEY);
129882         jQuery("#platform-select").val(_settings.platformId);
129883         jQuery("#device-select").val(_settings.device);
129884         if (_settings.type === "custom") {
129885             $('input:radio[name="resolution-type"][value="custom"]').click();
129886             jQuery("#resolution-custom-width").val(parseInt(_settings.custom_width, 10));
129887             jQuery("#resolution-custom-height").val(parseInt(_settings.custom_height, 10));
129888         } else {
129889             $('input:radio[name="resolution-type"][value="predefined"]').click();
129890         }
129891
129892         platformList = platform.getList();
129893         utils.forEach(platformList, function (platform) {
129894             utils.forEach(platform, function (version, versionNumber) {
129895                 if (_settings.platformId === version.id) {
129896                     versionSelect.appendChild(utils.createElement("option", {
129897                         "innerText": versionNumber,
129898                         "value":  versionNumber
129899                     }));
129900                 }
129901             });
129902         });
129903         jQuery("#version-select").val(_settings.version);
129904     });
129905
129906     $(window).bind('resize', function () {
129907         var position_x = 0;
129908         $("#configure-window-popup").css("top", 80);
129909         position_x = (($(window).width() - 800) / 2)  < 0 ? 0 : ($(window).width() - 800) / 2;
129910         $("#configure-window-popup").css("left", position_x);
129911
129912         $("#configure-window-done-popup").css("top", 180);
129913         position_x = (($(window).width() - 400) / 2)  < 0 ? 0 : ($(window).width() - 400) / 2;
129914         $("#configure-window-done-popup").css("left", position_x);
129915
129916         $("#overlayBackground").css("width", $(window).width());
129917         $("#overlayBackground").css("height", $(window).height());
129918     });
129919 }
129920
129921 module.exports = {
129922     initialize: function () {
129923         if (platform.current().id === "cordova") {
129924             items.splice(1, 1);
129925         }
129926         $("#options-button-config-window").bind("click", function ()  {
129927             _showConfigWindow();
129928         });
129929     }
129930 };
129931
129932 });
129933 define('ripple/ui/plugins/deviceSettings', function (require, exports, module) {
129934 /*
129935  *  Copyright 2011 Research In Motion Limited.
129936  *
129937  * Licensed under the Apache License, Version 2.0 (the "License");
129938  * you may not use this file except in compliance with the License.
129939  * You may obtain a copy of the License at
129940  *
129941  * http://www.apache.org/licenses/LICENSE-2.0
129942  *
129943  * Unless required by applicable law or agreed to in writing, software
129944  * distributed under the License is distributed on an "AS IS" BASIS,
129945  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
129946  * See the License for the specific language governing permissions and
129947  * limitations under the License.
129948  */
129949 var event = require('ripple/event'),
129950     constants = require('ripple/constants'),
129951     deviceSettings = require('ripple/deviceSettings'),
129952     utils = require('ripple/utils'),
129953     exception = require('ripple/exception'),
129954     platform = require('ripple/platform'),
129955     db = require('ripple/db'),
129956     _CONST = {
129957         "CONTENT_CONTAINER_ID": "devicesettings-content-container",
129958         "UKNOWN_CONTROL_MESSAGE": "Unknown device control type"
129959     },
129960     _contentContainer,
129961     _network_contentContainer,
129962     DBNETWORKSETTING_KEY = "tizen2-preFlightModeNetworksetting",
129963     _CONTAINER_ID = _CONST.CONTENT_CONTAINER_ID;
129964
129965 function _retrieveDeviceInfo(key) {
129966     var layout, rtn, deviceInfo = require('ripple/devices').getCurrentDevice();
129967
129968     switch (key) {
129969     case "Device.model":
129970         return deviceInfo.model;
129971     case "Device.version":
129972         return deviceInfo.firmware;
129973     case "Device.vendor":
129974         return deviceInfo.manufacturer;
129975     case "DISPLAY.resolutionHeight":
129976         return deviceInfo.screen.height;
129977     case "DISPLAY.resolutionWidth":
129978         return deviceInfo.screen.width;
129979     case "DISPLAY.pixelAspectRatio":
129980         return (deviceInfo.screen.width / deviceInfo.screen.height).toFixed(2);
129981
129982     case "DISPLAY.physicalWidth":
129983         return Number((deviceInfo.screen.width / deviceInfo.ppi).toFixed(2));
129984     case "DISPLAY.physicalHeight":
129985         return Number((deviceInfo.screen.height / deviceInfo.ppi).toFixed(2));
129986     case "DISPLAY.dpiY":
129987     case "DISPLAY.dotsPerInchHeight":
129988         return deviceInfo.ppi;
129989     case "DISPLAY.dpiX":
129990     case "DISPLAY.dotsPerInchWidth":
129991         return deviceInfo.ppi;
129992     case "OperatingSystem.version":
129993         return deviceInfo.osVersion;
129994     case "OperatingSystem.name":
129995         return deviceInfo.osName;
129996     case "OperatingSystem.vendor":
129997         return deviceInfo.manufacturer;
129998     case "DEVICE_ORIENTATION.status":
129999         layout = db.retrieve("layout");
130000         if (layout === null || layout === undefined) {
130001             layout = deviceInfo.defaultOrientation || "portrait";
130002         }
130003         if (layout === "portrait") {
130004             return "PORTRAIT_PRIMARY";
130005         } else {
130006             return "LANDSCAPE_PRIMARY";
130007         }
130008         break;
130009     case "WIFI_NETWORK.status":
130010     case "CELLULAR_NETWORK.status":
130011         rtn = deviceSettings.retrieve(key);
130012         if (rtn === true) {
130013             return "ON";
130014         } else {
130015             return "OFF";
130016         }
130017         break;
130018     case "CPU.load":
130019         rtn = deviceSettings.retrieve(key);
130020         if (rtn > 1) {
130021             rtn = 1;
130022             deviceSettings.persist(key, rtn);
130023         }
130024         if (rtn < 0) {
130025             rtn = 0;
130026             deviceSettings.persist(key, rtn);
130027         }
130028         return rtn;
130029     case "DISPLAY.brightness":
130030         rtn = deviceSettings.retrieve(key);
130031         if (rtn > 1) {
130032             rtn = 1;
130033             deviceSettings.persist("DISPLAY.brightness", rtn);
130034         }
130035         if (rtn < 0) {
130036             rtn = 0;
130037             deviceSettings.persist("DISPLAY.brightness", rtn);
130038         }
130039         return rtn;
130040     case "BUILD.manufacturer":
130041         return deviceInfo.manufacturer;
130042     default:
130043         return deviceSettings.retrieve(key);
130044     }
130045 }
130046
130047 function _retrieveSettingName(type) {
130048
130049     switch (type) {
130050     case "CellularHardware":
130051         return "Cellular Hardware";
130052     case "CellularNetwork":
130053         return "Cellular Network";
130054     case "MemoryUnit":
130055         return "Memory Unit";
130056     case "OperatingSystem":
130057         return "Operating System";
130058     case "WebRuntime":
130059         return "Web Runtime";
130060     case "WiFiHardware":
130061         return "WiFi Hardware";
130062     case "WiFiNetwork":
130063         return "WiFi Network";
130064     default:
130065         return type;
130066     }
130067 }
130068
130069 function _appendSettingNode(labelNode, inputNode, label) {
130070     var frag = document.createDocumentFragment(),
130071         rowNode = frag.appendChild(utils.createElement("tr")),
130072         tempTdNode;
130073
130074     rowNode.appendChild(utils.createElement("td"))
130075            .appendChild(labelNode);
130076
130077     tempTdNode = rowNode.appendChild(utils.createElement("td"));
130078
130079     if (label) {
130080         tempTdNode.appendChild(label);
130081     }
130082
130083     tempTdNode.appendChild(inputNode);
130084
130085     return frag;
130086 }
130087
130088 function _getCurrentSetting(setting, settingType, key) {
130089     var ret, savedSetting, fullKey;
130090     fullKey = settingType + "." + key;
130091     savedSetting = _retrieveDeviceInfo(fullKey);
130092     if (fullKey === "WIFI_NETWORK.status" || fullKey === "CELLULAR_NETWORK.status") {
130093         if (savedSetting === "ON") {
130094             savedSetting = true;
130095         } else {
130096             savedSetting = false;
130097         }
130098     }
130099     ret = (savedSetting || savedSetting === false || savedSetting === "" || savedSetting === 0) ? savedSetting : setting.control.value;
130100     return ret;
130101 }
130102
130103 function _buildDOMNode(setting, settingType, key) {
130104     var settingsNode, tagName, jNode,
130105         fullKey = settingType + "." + key,
130106         savedSetting = _retrieveDeviceInfo(fullKey),
130107         // TODO: move this into Utils (isSet method)
130108         currentSetting,
130109         domNode,
130110         domNodeLabel = null;
130111
130112     if (fullKey === "WIFI_NETWORK.status" || fullKey === "CELLULAR_NETWORK.status") {
130113         if (savedSetting === "ON") {
130114             savedSetting = true;
130115         } else {
130116             savedSetting = false;
130117         }
130118     }
130119     currentSetting = (savedSetting || savedSetting === false || savedSetting === "" || savedSetting === 0) ? savedSetting : setting.control.value;
130120
130121     switch (setting.control.type) {
130122     case "text":
130123     case "number":
130124     case "range":
130125     case "checkbox":
130126         tagName = "input";
130127         break;
130128     case "textarea":
130129         tagName = "textarea";
130130         break;
130131     case "select":
130132         tagName = "select";
130133         break;
130134     case "label":
130135         tagName = "label";
130136         break;
130137     default:
130138         exception.raise(exception.types.Application, _CONST.UKNOWN_CONTROL_MESSAGE);
130139     }
130140
130141     settingsNode = utils.createElement(tagName, setting.control.type === "select" ? null : setting.control);
130142     settingsNode.setAttribute("id", "device-settings-" + settingType + "-" + key);
130143
130144     // TODO: this should really be part of utils.createControl? add element of type "range" with label?
130145     if (setting.control.type === "range") {
130146         domNodeLabel = utils.createElement("label", {
130147             "class": constants.UI.LEFT_RANGE_LABEL_CLASS
130148         });
130149     }
130150
130151     domNode = _appendSettingNode(utils.createElement("span", {"innerText": setting.name, "class": "configure-window-text-label"}), settingsNode, domNodeLabel);
130152
130153     jNode = jQuery(settingsNode);
130154     if (tagName !== "label") {
130155         jNode.addClass(constants.UI.JQUERY_UI_INPUT_CLASSES);
130156     }
130157
130158     switch (setting.control.type) {
130159     case "checkbox":
130160         jNode.bind("click", function () {
130161             var checked = this.checked ? true : false;
130162             deviceSettings.persist(fullKey, checked);
130163             if (typeof setting.callback === "function") {
130164                 setting.callback(checked);
130165             }
130166         });
130167
130168         if (currentSetting === true) {
130169             jNode.attr("checked", "checked");
130170         }
130171
130172         break;
130173
130174     case "text":
130175     case "textarea":
130176     case "number":
130177         jNode.val(currentSetting);
130178         utils.bindAutoSaveEvent(jNode, function () {
130179             if (setting.control.type === "number") {
130180                 deviceSettings.persist(fullKey, Number(jNode.val()));
130181             } else {
130182                 deviceSettings.persist(fullKey, jNode.val());
130183             }
130184
130185             if (typeof setting.callback === "function") {
130186                 setting.callback(jNode.val());
130187             }
130188         });
130189         break;
130190
130191     case "label":
130192         jNode.text(currentSetting);
130193         break;
130194
130195     case "select":
130196     case "range":
130197         if (setting.control.type === "select") {
130198             utils.forEach(setting.options,  function (value, option) {
130199                 jNode.append(utils.createElement("option", {
130200                     "value": option,
130201                     "innerText": value
130202                 }));
130203             });
130204         }
130205         else {
130206             if (domNodeLabel) {
130207                 domNodeLabel.innerText = currentSetting;
130208             }
130209         }
130210
130211         jNode.val(currentSetting)
130212              .bind("change", function () {
130213                 if (setting.control.type === "range" && domNodeLabel) {
130214                     domNodeLabel.innerText = jQuery(this).val();
130215                 }
130216                 deviceSettings.persist(fullKey, jQuery(this).val());
130217
130218                 if (typeof setting.callback === "function") {
130219                     setting.callback(jQuery(this).val(), currentSetting);
130220                 }
130221             }
130222         );
130223     }
130224
130225     // TODO: Brent, do in DeviceSettings on load instead?
130226     if (currentSetting !== setting.control.value) {
130227         deviceSettings.register(fullKey, currentSetting);
130228     }
130229
130230     return domNode;
130231 }
130232
130233 function displayBrightnessCB(value) {
130234     if (value > 1) value = 1;
130235     if (value < 0) value = 0;
130236     if (document.getElementById("device-settings-DISPLAY-brightness").value === value) {
130237         return;
130238     }
130239     deviceSettings.persist("DISPLAY.brightness", Number(value));
130240     document.getElementById("device-settings-DISPLAY-brightness").value = value;
130241 }
130242
130243 function cpuLoadCB(value) {
130244     if (value > 1) value = 1;
130245     if (value < 0) value = 0;
130246     if (document.getElementById("device-settings-CPU-load").value === value) {
130247         return;
130248     }
130249     deviceSettings.persist("CPU.load", Number(value));
130250     document.getElementById("device-settings-CPU-load").value = value;
130251 }
130252
130253 function availCapacityCB(value) {
130254     var capacity = deviceSettings.retrieve("STORAGE.capacity");
130255     if (Number(value) > Number(capacity)) value = capacity;
130256     if (Number(value) < 0) value = 0;
130257     deviceSettings.persist("STORAGE.availableCapacity", Number(value));
130258     document.getElementById("device-settings-STORAGE-availableCapacity").value = Number(value);
130259 }
130260
130261 function wiFiNetworkStatusCB(value) {
130262     document.getElementById("device-settings-WIFI_NETWORK-status").checked = value;
130263 }
130264
130265 function flightModeChangedCB(value) {
130266     var networkSettings = {};
130267     if (value === true) {
130268         networkSettings['wifiSetting'] = deviceSettings.retrieve("WIFI_NETWORK.status");
130269         networkSettings['cellularSetting'] = deviceSettings.retrieve("CELLULAR_NETWORK.status");
130270         //networkSettings['bluetoothSetting'] = deviceSettings.retrieve("CELLULAR_NETWORK.status");
130271         //networkSettings['nfcSetting'] = deviceSettings.retrieve("CELLULAR_NETWORK.status");
130272         db.saveObject(DBNETWORKSETTING_KEY, networkSettings);
130273
130274         deviceSettings.persist("CELLULAR_NETWORK.status", false);
130275         deviceSettings.persist("WIFI_NETWORK.status", false);
130276         event.trigger("nfc-power-setting", [false]);
130277         event.trigger("bt-power-setting", [false]);
130278
130279         document.getElementById("device-settings-WIFI_NETWORK-status").checked = false;
130280         document.getElementById("device-settings-CELLULAR_NETWORK-status").checked = false;
130281         $("#device-settings-CELLULAR_NETWORK-status").parent().append("<span id='config_flight_mode_notice' style='color:#555555;'>  (Disabled for Flight Mode)</span>");
130282         document.getElementById("device-settings-CELLULAR_NETWORK-status").disabled = true;
130283
130284     } else {
130285         networkSettings = db.retrieveObject(DBNETWORKSETTING_KEY)||{"wifiSetting": true, "cellularSetting": true};
130286         deviceSettings.persist("WIFI_NETWORK.status", networkSettings['wifiSetting']);
130287         deviceSettings.persist("CELLULAR_NETWORK.status", networkSettings['cellularSetting']);
130288         document.getElementById("device-settings-WIFI_NETWORK-status").checked = networkSettings['wifiSetting'];
130289         document.getElementById("device-settings-CELLULAR_NETWORK-status").checked = networkSettings['cellularSetting'];
130290         $("#config_flight_mode_notice").remove();
130291         document.getElementById("device-settings-CELLULAR_NETWORK-status").disabled = false;
130292     }
130293 }
130294
130295 function cellularNetworkStatusCB(value) {
130296     document.getElementById("device-settings-CELLULAR_NETWORK-status").checked = value;
130297 }
130298
130299 function layoutCB(value) {
130300     if (value === 'portrait') {
130301         deviceSettings.register("DEVICE_ORIENTATION.status", "PORTRAIT_PRIMARY");
130302         document.getElementById("device-settings-DEVICE_ORIENTATION-status").innerText = "PORTRAIT_PRIMARY";
130303     } else {
130304         deviceSettings.register("DEVICE_ORIENTATION.status", "LANDSCAPE_PRIMARY");
130305         document.getElementById("device-settings-DEVICE_ORIENTATION-status").innerText = "LANDSCAPE_PRIMARY";
130306     }
130307 }
130308
130309 // goes through current platforms device settings
130310 // adds nodes to panel and binds respective events
130311 // talks to DeviceSettings for persistence
130312 module.exports = {
130313     initialize: function () {
130314         var settings, value;
130315         _contentContainer = document.getElementById(_CONTAINER_ID);
130316         _network_contentContainer = document.getElementById("networksettings-content-container");
130317
130318         settings = platform.current().device;
130319         utils.forEach(settings, function (settingSection, settingType) {
130320
130321             var currentTableNode, currentTableNode2, settingNameNode, settingName = _retrieveSettingName(settingType);
130322
130323             settingNameNode = utils.createElement("h3", { "innerText": settingName });
130324             settingNameNode.setAttribute("class", "configure-window-session-title");
130325
130326             if (settingType === 'NETWORK' || settingType === 'WIFI_NETWORK' || settingType === 'CELLULAR_NETWORK' || settingType === 'SIM') {
130327                 _network_contentContainer.appendChild(settingNameNode);
130328                 currentTableNode2 = utils.createElement("table", {
130329                     "class": constants.UI.PANEL_TABLE_CLASS
130330                 });
130331                 currentTableNode2.setAttribute("class", "configure-window-panel-table");
130332                 _network_contentContainer.appendChild(currentTableNode2);
130333             }
130334             else {
130335                 _contentContainer.appendChild(settingNameNode);
130336                 currentTableNode = utils.createElement("table", {
130337                     "class": constants.UI.PANEL_TABLE_CLASS
130338                 });
130339                 currentTableNode.setAttribute("class", "configure-window-panel-table");
130340                 _contentContainer.appendChild(currentTableNode);
130341             }
130342
130343             utils.forEach(settingSection, function (setting, key) {
130344                 if (settingType === 'NETWORK' || settingType === 'WIFI_NETWORK' || settingType === 'CELLULAR_NETWORK' || settingType === 'SIM') {
130345                     currentTableNode2.appendChild(_buildDOMNode(setting, settingType, key));
130346                 }
130347                 else {
130348                     currentTableNode.appendChild(_buildDOMNode(setting, settingType, key));
130349                 }
130350                 value = _getCurrentSetting(setting, settingType, key);
130351                 if (setting.callback) {
130352                     setting.callback(value);
130353                 }
130354             });
130355         });
130356
130357         if (deviceSettings.retrieve("CELLULAR_NETWORK.isFlightMode") === true) {
130358             $("#device-settings-CELLULAR_NETWORK-status").parent().append("<span id='config_flight_mode_notice' style='color:#555555;'>  (Disabled for Flight Mode)</span>");
130359             document.getElementById("device-settings-CELLULAR_NETWORK-status").disabled = true;
130360         }
130361
130362         event.on("DisplayBrightnessChanged", displayBrightnessCB);
130363         event.on("DisplayBrightnessChangedByPower", displayBrightnessCB);
130364         event.on("CpuLoadChanged", cpuLoadCB);
130365         event.on("AvailCapacityChanged", availCapacityCB);
130366         event.on("CpuLoadChangedByPower", cpuLoadCB);
130367         event.on("FlightModeChanged", flightModeChangedCB);
130368         event.on("WiFiNetworkStatusChanged", wiFiNetworkStatusCB);
130369         event.on("CellularNetworkStatusChanged", cellularNetworkStatusCB);
130370         event.on("LayoutChanged", layoutCB);
130371     },
130372     terminate: function () {
130373         event.deleteEventHandler("DisplayBrightnessChanged", displayBrightnessCB);
130374         event.deleteEventHandler("DisplayBrightnessChangedByPower", displayBrightnessCB);
130375         event.deleteEventHandler("CpuLoadChanged", cpuLoadCB);
130376         event.deleteEventHandler("AvailCapacityChanged", availCapacityCB);
130377         event.deleteEventHandler("FlightModeChanged", flightModeChangedCB);
130378         event.deleteEventHandler("CpuLoadChangedByPower", cpuLoadCB);
130379         event.deleteEventHandler("WiFiNetworkStatusChanged", wiFiNetworkStatusCB);
130380         event.deleteEventHandler("CellularNetworkStatusChanged", cellularNetworkStatusCB);
130381         event.deleteEventHandler("LayoutChanged", layoutCB);
130382     }
130383 };
130384
130385 });
130386 define('ripple/ui/plugins/devices', function (require, exports, module) {
130387 /*
130388  *  Copyright 2011 Research In Motion Limited.
130389  *
130390  * Licensed under the Apache License, Version 2.0 (the "License");
130391  * you may not use this file except in compliance with the License.
130392  * You may obtain a copy of the License at
130393  *
130394  * http://www.apache.org/licenses/LICENSE-2.0
130395  *
130396  * Unless required by applicable law or agreed to in writing, software
130397  * distributed under the License is distributed on an "AS IS" BASIS,
130398  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
130399  * See the License for the specific language governing permissions and
130400  * limitations under the License.
130401  */
130402 var constants = require('ripple/constants'),
130403     db = require('ripple/db'),
130404     resizer = require('ripple/resizer');
130405
130406 function _getTextZooming(zooming) {
130407     return zooming + '%';
130408 }
130409
130410 module.exports = {
130411     panel: {
130412         domId: "devices-container",
130413         collapsed: true,
130414         pane: "left",
130415         titleName: "Orientation and Zooming",
130416         display: true
130417     },
130418
130419     initialize: function () {
130420         var zooming = document.getElementById(constants.ENCAPSULATOR.ZOOMING);
130421         function updateZoomingValues() {
130422             var zoomingText, scaleFactor;
130423
130424             zoomingText = _getTextZooming(zooming.value);
130425             jQuery('#screen-zooming-label').html(zoomingText);
130426
130427             // Zooming device skin
130428             scaleFactor = zooming.value / 100;
130429             resizer.scaleDevice(scaleFactor);
130430         }
130431
130432         function initializeValues() {
130433             var zoomingValue =  db.retrieve(constants.ENCAPSULATOR.ZOOMING);
130434
130435             if (!zoomingValue) {
130436                 zoomingValue = 100;
130437             }
130438             jQuery("#" + constants.ENCAPSULATOR.ZOOMING).val(zoomingValue);
130439             updateZoomingValues();
130440         }
130441
130442         jQuery("#" + constants.ENCAPSULATOR.ZOOMING).bind("change", function () {
130443             updateZoomingValues();
130444             db.save(constants.ENCAPSULATOR.ZOOMING, zooming.value);
130445         });
130446
130447         initializeValues();
130448     }
130449 };
130450
130451
130452 });
130453 define('ripple/ui/plugins/download', function (require, exports, module) {
130454 /*
130455  *  Copyright 2012 Intel Corporation.
130456  *
130457  * Licensed under the Apache License, Version 2.0 (the "License");
130458  * you may not use this file except in compliance with the License.
130459  * You may obtain a copy of the License at
130460  *
130461  * http://www.apache.org/licenses/LICENSE-2.0
130462  *
130463  * Unless required by applicable law or agreed to in writing, software
130464  * distributed under the License is distributed on an "AS IS" BASIS,
130465  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
130466  * See the License for the specific language governing permissions and
130467  * limitations under the License.
130468  */
130469
130470 var db = require('ripple/db'),
130471     event = require('ripple/event'),
130472     utils = require('ripple/utils'),
130473     _data = {
130474         DB_DOWNLOAD_KEY : "tizen1-db-download",
130475         resources : []
130476     },
130477     _cleanInputs, intervalId,
130478     _downloads;
130479
130480 function _get() {
130481     _downloads = [
130482         {id: "0001", url : "http://tizen.org/small_file.zip", size : "5", speed : "1.0", estimatedTime : "5", MIMEType : "application/zip"},
130483         {id: "0002", url : "http://tizen.org/big_file.zip", size : "20", speed : "1.0", estimatedTime : "20", MIMEType : "application/zip"},
130484         {id: "0003", url : "http://download.tizen.org/tct/2_1/webapi-tizen-download-test-image-hq.png", size : "3937596", speed : "1968798", estimatedTime : "2", MIMEType : "image/png"},
130485         {id: "0004", url : "http://download.tizen.org/tct/2_1/webapi-tizen-download-test-image-lq.png", size : "589", speed : "589", estimatedTime : "1", MIMEType : "image/png"}
130486     ];
130487     _data.resources = db.retrieveObject(_data.DB_DOWNLOAD_KEY) || _downloads;
130488     if (db.retrieveObject(_data.DB_DOWNLOAD_KEY) && db.retrieveObject(_data.DB_DOWNLOAD_KEY).length === 0) {
130489         _data.resources = _downloads;
130490     } else {
130491         _data.resources = db.retrieveObject(_data.DB_DOWNLOAD_KEY) || _downloads;
130492     }
130493     _save();
130494 }
130495
130496 function _save() {
130497     db.saveObject(_data.DB_DOWNLOAD_KEY, _data.resources);
130498     event.trigger('downloadResourceChanged');
130499 }
130500
130501 function checkURL(url) {
130502     var rg = new RegExp("((^http)|(^https)|(^ftp)):\/\/()+");
130503     return rg.test(url);
130504 }
130505
130506 function loadResources() {
130507     var installed = document.getElementById("download-resource"), node, i;
130508     installed.innerHTML = "";
130509     for (i in _data.resources) {
130510         node = utils.createElement("option", {
130511             "innerText": _data.resources[i].url,
130512             "value": _data.resources[i].id
130513         });
130514         installed.appendChild(node);
130515     }
130516     _cleanInputs();
130517 }
130518
130519 function _displayInfo(text) {
130520     var info = document.getElementById("download-error");
130521     info.innerHTML = text;
130522     if (intervalId) {
130523         clearTimeout(intervalId);
130524     }
130525     intervalId = setTimeout(clearDisplayInfo, 5000);
130526 }
130527
130528 function clearDisplayInfo() {
130529     document.getElementById('download-error').innerHTML = '';
130530 }
130531
130532 function _cleanInputs() {
130533     document.getElementById("download-url").value = "";
130534     document.getElementById("download-size").value = "";
130535     document.getElementById("download-speed").value = "";
130536     document.getElementById("download-time").innerText = "0";
130537     document.getElementById("download-MIMEType").value = "";
130538 }
130539
130540 function checkProperties(optionType, url, size, speed, time, MIMEType) {
130541     var back = true;
130542     if (url === "" || size === "" ||  speed === "" || time === "" || MIMEType === "") {
130543         _displayInfo(optionType + " failed, empty input.");
130544         back = false;
130545     }
130546     if (!checkURL(url)) {
130547         _displayInfo(optionType + " failed, 'URL' is invalid.");
130548         back = false;
130549     }
130550     if (size <= 0 ||  speed <= 0) {
130551         _displayInfo(optionType + " failed, invalid input.");
130552         back = false;
130553     }
130554     return back;
130555 }
130556
130557 function showUpdateNotification() {
130558     var url     = document.getElementById("download-url").value,
130559         size    = document.getElementById("download-size").value,
130560         speed   = document.getElementById("download-speed").value,
130561         MIMEType = document.getElementById("download-MIMEType").value,
130562         isValid = true;
130563     if (url === "" || size === "" ||  speed === "" || MIMEType === "" || !checkURL(url) || size <= 0 ||  speed <= 0) {
130564         isValid = false;
130565     }
130566     if (isValid) {
130567         _displayInfo("Resource changed, please Add or Update the content.");
130568     }
130569 }
130570
130571 function _adding() {
130572     var id, time, url, size, speed, MIMEType, object, i, isValid;
130573     url     = document.getElementById("download-url").value;
130574     size    = document.getElementById("download-size").value;
130575     speed   = document.getElementById("download-speed").value;
130576     MIMEType = document.getElementById("download-MIMEType").value;
130577     time    = size / speed;
130578     id      = Math.uuid(null, 16);
130579
130580     isValid = checkProperties("Add", url, size, speed, time, MIMEType);
130581     if (!isValid)
130582         return;
130583     if (_data.resources.length !== 0) {
130584         for (i in _data.resources) {
130585             if (url === _data.resources[i].url) {
130586                 _displayInfo("Add failed, the download resource is already available.");
130587                 return;
130588             }
130589         }
130590     }
130591     document.getElementById("download-time").innerText = Math.round(time * 100) / 100;
130592     object = {'id': id, 'url': url, 'size': size, 'speed': speed, 'estimatedTime': time, MIMEType: MIMEType};
130593     _data.resources.push(object);
130594     _save();
130595     loadResources();
130596 }
130597
130598 function _update() {
130599     var id, time, url, size, speed, MIMEType, i, isExist = false, isValid;
130600
130601     id    = document.getElementById("download-resource").value;
130602     url   = document.getElementById("download-url").value;
130603     size  = document.getElementById("download-size").value;
130604     speed = document.getElementById("download-speed").value;
130605     MIMEType = document.getElementById("download-MIMEType").value;
130606     time  = size / speed;
130607
130608     if (_data.resources.length === 0) {
130609         _displayInfo("Update failed, there is no download resource now.");
130610         return;
130611     }
130612     isValid = checkProperties("Update", url, size, speed, time, MIMEType);
130613     if (!isValid)
130614         return;
130615     for (i in _data.resources) {
130616         if (_data.resources[i].url === url) {
130617             isExist = true;
130618             _data.resources[i] = {id: id, url : url, size : size, speed : speed, estimatedTime: time, MIMEType: MIMEType};
130619             loadResources();
130620             _save();
130621             break;
130622         }
130623     }
130624     if (!isExist)
130625         _displayInfo("Update failed, the download resource doesn't exist.");
130626 }
130627
130628 function _delete() {
130629     var i, id;
130630     id = document.getElementById("download-resource").value;
130631     if (id) {
130632         for (i in _data.resources) {
130633             if (_data.resources[i].id === id) {
130634                 _data.resources.splice(i, 1);
130635                 _save();
130636                 loadResources();
130637             }
130638         }
130639     }
130640 }
130641
130642 function _showAppDetail(id) {
130643     var i;
130644     for (i in _data.resources) {
130645         if (id === _data.resources[i].id) {
130646             document.getElementById("download-time").innerText = Math.round(_data.resources[i].estimatedTime * 100) / 100;
130647             jQuery("#download-url").val(_data.resources[i].url);
130648             jQuery("#download-size").val(_data.resources[i].size);
130649             jQuery("#download-speed").val(_data.resources[i].speed);
130650             jQuery("#download-MIMEType").val(_data.resources[i].MIMEType);
130651         }
130652     }
130653 }
130654
130655 function _changeAppData() {
130656     var id = jQuery("#download-resource").val();
130657     _showAppDetail(id);
130658 }
130659 function changeValue() {
130660     var size  = document.getElementById("download-size").value,
130661         speed = document.getElementById("download-speed").value;
130662     if (size > 0 && speed > 0) {
130663         document.getElementById("download-time").innerText = Math.round(size / speed * 100) / 100;
130664     } else {
130665         document.getElementById("download-time").innerText  = "";
130666     }
130667 }
130668 function checkInputValue(input) {
130669     if (input.value === "" || input.value <= 0) {
130670         input.style['border-color'] = 'red';
130671         _displayInfo("Invalided value.");
130672     } else {
130673         if (input.style['border-color']) {
130674             input.style.removeProperty('border-color');
130675         }
130676         changeValue();
130677         //showUpdateNotification();
130678     }
130679 }
130680 module.exports = {
130681     panel: {
130682         domId: "download-container",
130683         collapsed: true,
130684         pane: "left",
130685         titleName: "Download",
130686         display: true
130687     },
130688     initialize: function () {
130689         _get();
130690         loadResources();
130691
130692         document.getElementById("download-add").addEventListener("click", _adding, false);
130693         document.getElementById("download-update").addEventListener("click", _update, false);
130694         document.getElementById("download-delete").addEventListener("click", _delete, false);
130695
130696         jQuery("#download-resource").bind("focus change", function () {
130697             var url = document.getElementById("download-url"),
130698                 size = document.getElementById("download-size"),
130699                 speed = document.getElementById("download-speed"),
130700                 MIMEType = document.getElementById("download-MIMEType");
130701             if (url.style['border-color']) {
130702                 url.style.removeProperty('border-color');
130703             }
130704             if (MIMEType.style['border-color']) {
130705                 MIMEType.style.removeProperty('border-color');
130706             }
130707             if (size.value > 0 && size.style['border-color']) {
130708                 size.style.removeProperty('border-color');
130709             }
130710             if (speed.value > 0 && speed.style['border-color']) {
130711                 speed.style.removeProperty('border-color');
130712             }
130713             _changeAppData();
130714         });
130715         jQuery("#download-speed").bind("blur", function () {
130716             changeValue();
130717         });
130718         jQuery("#download-size").bind("blur", function () {
130719             changeValue();
130720         });
130721         jQuery("#download-speed").bind("change", function () {
130722             checkInputValue(this);
130723         });
130724         jQuery("#download-size").bind("change", function () {
130725             checkInputValue(this);
130726         });
130727         jQuery("#download-speed").bind("change", function () {
130728             checkInputValue(this);
130729         });
130730         jQuery("#download-url").bind("change", function () {
130731             if (this.style['border-color']) {
130732                 this.style.removeProperty('border-color');
130733             }
130734             if (this.value && checkURL(this.value)) {
130735                 //showUpdateNotification();
130736             } else  {
130737                 _displayInfo("Invalided URL.");
130738                 this.style['border-color'] = 'red';
130739             }
130740         });
130741     }
130742 };
130743
130744 });
130745 define('ripple/ui/plugins/eulaCheck', function (require, exports, module) {
130746 /*
130747  *  Copyright 2011 Research In Motion Limited.
130748  *
130749  * Licensed under the Apache License, Version 2.0 (the "License");
130750  * you may not use this file except in compliance with the License.
130751  * You may obtain a copy of the License at
130752  *
130753  * http://www.apache.org/licenses/LICENSE-2.0
130754  *
130755  * Unless required by applicable law or agreed to in writing, software
130756  * distributed under the License is distributed on an "AS IS" BASIS,
130757  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
130758  * See the License for the specific language governing permissions and
130759  * limitations under the License.
130760  */
130761 var utils = require('ripple/utils'),
130762     bus = require('ripple/bus');
130763
130764 function _initializeEulaCheck() {
130765     var width = jQuery(document).width(),
130766         p = (width / 2) - 277;
130767
130768
130769     $(".eula-window").show();
130770     $(".eula-dialog").show().css({left: p + "px"});
130771
130772     $("#eula-accept").click(function () {
130773         bus.send("acceptEula", null, function (result) {
130774             $(".eula-window").hide();
130775             $(".eula-dialog").hide();
130776         });
130777     });
130778
130779     $("#eula-decline").click(function () {
130780         bus.send("disable", null, null);
130781     });
130782 }
130783
130784 module.exports = {
130785     initialize: function () {
130786         //HACK: there has to be a better way!!!
130787         if ($("#extension-url").val().match(/geelfhphabnejjhdalkjhgipohgpdnoc/)) {
130788             // do nothing, extension was installed from the Chrome Store
130789             return;
130790         }
130791
130792         bus.send("checkEula", null, function (response) {
130793             console.log("eula response: ", response);
130794             if (response === false) {
130795                 _initializeEulaCheck();
130796             }
130797         });
130798     }
130799 };
130800
130801 });
130802 define('ripple/ui/plugins/exec-dialog', function (require, exports, module) {
130803 /*
130804  *  Copyright 2011 Research In Motion Limited.
130805  *
130806  * Licensed under the Apache License, Version 2.0 (the "License");
130807  * you may not use this file except in compliance with the License.
130808  * You may obtain a copy of the License at
130809  *
130810  * http://www.apache.org/licenses/LICENSE-2.0
130811  *
130812  * Unless required by applicable law or agreed to in writing, software
130813  * distributed under the License is distributed on an "AS IS" BASIS,
130814  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
130815  * See the License for the specific language governing permissions and
130816  * limitations under the License.
130817  */
130818
130819 function exec(func) {
130820     return function () {
130821         var val = $("#exec-response").val();
130822
130823         //TODO: handle multiple args
130824         func.apply(null, val ? [JSON.parse(val)] : []);
130825         $("#exec-dialog").dialog("close");
130826     };
130827 }
130828
130829 module.exports = {
130830     initialize: function () {
130831         $("#exec-dialog").dialog({
130832             autoOpen: false,
130833             modal: true,
130834             title: "I Haz Cheeseburger?!?!",
130835             width: 500,
130836             position: 'center'
130837         }).hide();
130838
130839         $("#exec-success").button();
130840         $("#exec-fail").button();
130841     },
130842
130843     show: function (service, action, success, fail) {
130844         console.log(service);
130845         console.log(action);
130846         $("#exec-service").text(service);
130847         $("#exec-action").text(action);
130848         $("#exec-dialog").dialog("open");
130849         $("#exec-success").unbind().bind('click', exec(success));
130850         $("#exec-fail").unbind().bind('click', exec(fail));
130851     }
130852 };
130853
130854 });
130855 define('ripple/ui/plugins/fileSystem', function (require, exports, module) {
130856 /*
130857  *  Copyright 2011 Research In Motion Limited.
130858  *
130859  * Licensed under the Apache License, Version 2.0 (the "License");
130860  * you may not use this file except in compliance with the License.
130861  * You may obtain a copy of the License at
130862  *
130863  * http://www.apache.org/licenses/LICENSE-2.0
130864  *
130865  * Unless required by applicable law or agreed to in writing, software
130866  * distributed under the License is distributed on an "AS IS" BASIS,
130867  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
130868  * See the License for the specific language governing permissions and
130869  * limitations under the License.
130870  */
130871 var utils = require('ripple/utils'),
130872     constants = require('ripple/constants'),
130873     fileSystem = require('ripple/fileSystem'),
130874     fileSystemPaths = fileSystem.getFileSystemPaths();
130875
130876 module.exports = {
130877     panel: {
130878         domId: "filsystem-container",
130879         collapsed: true,
130880         pane: "left"
130881     },
130882     initialize: function () {
130883         var fileSystemPaths = fileSystem.getFileSystemPaths();
130884
130885         utils.forEach(fileSystemPaths, function (value, key) {
130886             utils.bindAutoSaveEvent(jQuery(constants.FILESYSTEM.INPUT_PREFIX_ID + key).val(value.uri), function () {
130887                 value.uri = jQuery(constants.FILESYSTEM.INPUT_PREFIX_ID + key).val();
130888                 fileSystem.updateFileSystemPaths(fileSystemPaths);
130889             });
130890         });
130891     }
130892 };
130893
130894 });
130895 define('ripple/ui/plugins/firstRunCheck', function (require, exports, module) {
130896 /*
130897  *  Copyright 2011 Research In Motion Limited.
130898  *
130899  * Licensed under the Apache License, Version 2.0 (the "License");
130900  * you may not use this file except in compliance with the License.
130901  * You may obtain a copy of the License at
130902  *
130903  * http://www.apache.org/licenses/LICENSE-2.0
130904  *
130905  * Unless required by applicable law or agreed to in writing, software
130906  * distributed under the License is distributed on an "AS IS" BASIS,
130907  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
130908  * See the License for the specific language governing permissions and
130909  * limitations under the License.
130910  */
130911 var utils = require('ripple/utils'),
130912     _platform = require('ripple/platform'),
130913     db = require('ripple/db');
130914
130915 function _handleFirstRunResponse(platform, version) {
130916     var device = jQuery("#device-select").val(),
130917         api = {
130918             name: platform.id,
130919             version: version
130920         };
130921
130922
130923     _platform.changeEnvironment(api, device, function () {
130924         window.tinyHipposReload = true;
130925         location.reload();
130926     });
130927 }
130928
130929 function _addPlatformButton(platform, version) {
130930     var section = jQuery(".platform-select-buttons"),
130931         buttonID = "platform-" + platform.id,
130932         button = utils.createElement("button", {
130933             "id": buttonID,
130934             "class": "ui-button ui-widget ui-state-default ui-corner-all ui-button-text-only"
130935         });
130936
130937     button.appendChild(utils.createElement("span", {
130938         "class": "ui-button-text",
130939         "innertext" : platform.name
130940     }));
130941
130942     section.append(button);
130943
130944     document.getElementById(buttonID).addEventListener("click", function () {
130945         _handleFirstRunResponse(platform, version);
130946     });
130947 }
130948
130949 function _initializeFirstRunCheck() {
130950     var savedPlatform = db.retrieveObject("api-key"),
130951         firstRunOverlayNode, firstRunOptionsNode,
130952         width, p;
130953
130954     if (!savedPlatform) {
130955         width = jQuery(document).width();
130956         p = (width / 2) - 277;
130957
130958         firstRunOverlayNode = jQuery(".first-run-window").css({display: 'block'});
130959         firstRunOptionsNode = jQuery(".platform-select-dialog").css({display: 'block', left: p + "px"});
130960
130961         utils.forEach(_platform.getList(), function (platform) {
130962             utils.forEach(platform, function (details, version) {
130963                 _addPlatformButton(details, version);
130964             });
130965         });
130966     }
130967 }
130968
130969 module.exports = {
130970     initialize: function () {
130971         if (utils.map(_platform.getList(), function (platform) {
130972             return platform;
130973         }).length > 1) {
130974             _initializeFirstRunCheck();
130975         }
130976     }
130977 };
130978
130979 });
130980 define('ripple/ui/plugins/geoDB', function (require, exports, module) {
130981 /*
130982  *  Copyright 2012 Intel Corporation.
130983  *
130984  * Licensed under the Apache License, Version 2.0 (the "License");
130985  * you may not use this file except in compliance with the License.
130986  * You may obtain a copy of the License at
130987  *
130988  * http://www.apache.org/licenses/LICENSE-2.0
130989  *
130990  * Unless required by applicable law or agreed to in writing, software
130991  * distributed under the License is distributed on an "AS IS" BASIS,
130992  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
130993  * See the License for the specific language governing permissions and
130994  * limitations under the License.
130995  */
130996
130997 var db = require('ripple/db'),
130998     utils = require('ripple/utils'),
130999     lbs = require('ripple/platform/tizen/2.0/lbs_utils'),
131000     _GEO_OBJECTS = "tizen1.0-geocode-objects",
131001     _geoList, _currentGeo, _saveID, _showGeoDetail;
131002
131003 function _getGeo() {
131004     var geoList = [],
131005         data = db.retrieveObject(_GEO_OBJECTS);
131006
131007     utils.forEach(data, function (geo) {
131008         geoList.push(geo);
131009     });
131010     return geoList;
131011 }
131012
131013 function _saveGeo() {
131014     db.saveObject(_GEO_OBJECTS, _geoList);
131015 }
131016
131017 function GeoEntry(addr, coord) {
131018     var _self;
131019     _self = {
131020         address : addr || null,
131021         coordinate : coord || null
131022     };
131023     return _self;
131024 }
131025
131026 function _updateGeoDBSelect() {
131027     var geoDBSelect = document.getElementById("geo-select"),
131028         geoNode, i;
131029
131030     geoDBSelect.innerHTML = "";
131031     for (i = 0; i < _geoList.length; i++) {
131032         geoNode = utils.createElement("option", {
131033             "innerText": "(" + _geoList[i].coordinate.latitude + ", " + _geoList[i].coordinate.longitude + ")",
131034             "value": i
131035         });
131036         if (_currentGeo === Number(geoNode.value)) {
131037             geoNode.selected = true;
131038             _showGeoDetail(_geoList[_currentGeo].coordinate, _geoList[_currentGeo].address);
131039         }
131040         geoDBSelect.appendChild(geoNode);
131041     }
131042 }
131043
131044 function _showGeoDetail(coord, addr) {
131045     jQuery("#geoDB-latitude").val(coord.latitude);
131046     jQuery("#geoDB-longitude").val(coord.longitude);
131047     jQuery("#geoDB-altitude").val(coord.altitude);
131048     jQuery("#geoDB-accuracy").val(coord.accuracy);
131049     jQuery("#geoDB-altitudeAccuracy").val(coord.altitudeAccuracy);
131050     jQuery("#geoDB-heading").val(coord.heading);
131051     jQuery("#geoDB-speed").val(coord.speed);
131052
131053     jQuery("#geoDB-country").val(addr.country);
131054     jQuery("#geoDB-region").val(addr.region);
131055     jQuery("#geoDB-county").val(addr.county);
131056     jQuery("#geoDB-city").val(addr.city);
131057     jQuery("#geoDB-street").val(addr.street);
131058     jQuery("#geoDB-streetNumber").val(addr.streetNumber);
131059     jQuery("#geoDB-premises").val(addr.premises);
131060     jQuery("#geoDB-additionalInformation").val(addr.additionalInformation);
131061     jQuery("#geoDB-postalCode").val(addr.postalCode);
131062 }
131063
131064 function _changeGeoData() {
131065     var id = Number(jQuery("#geo-select").val());
131066     _currentGeo = id;
131067     _showGeoDetail(_geoList[id].coordinate, _geoList[id].address);
131068 }
131069
131070 function _triggerReadOnly(on) {
131071     if (on === true) {
131072         jQuery("#geoDB-table input").attr("readonly", "readonly");
131073         jQuery("#geoDB-add").show();
131074         jQuery("#geoDB-modify").show();
131075         jQuery("#geoDB-delete").show();
131076         jQuery("#geo-select").removeAttr("disabled");
131077         jQuery("#geoDB-save").hide();
131078         jQuery("#geoDB-cancel").hide();
131079     } else {
131080         jQuery("#geoDB-table input").removeAttr("readonly");
131081         jQuery("#geoDB-add").hide();
131082         jQuery("#geoDB-modify").hide();
131083         jQuery("#geoDB-delete").hide();
131084         jQuery("#geo-select").attr("disabled", "disabled");
131085         jQuery("#geoDB-save").show();
131086         jQuery("#geoDB-cancel").show();
131087     }
131088 }
131089
131090 function _addGeoData() {
131091     _triggerReadOnly(false);
131092     jQuery("#geoDB-table input").val("");
131093     _saveID = _geoList.length;
131094     jQuery("#geo-select").val("");
131095 }
131096 function _modifyGeoData() {
131097     _triggerReadOnly(false);
131098     _saveID = _currentGeo;
131099 }
131100 function _deleteGeoData() {
131101     _geoList.splice(_currentGeo, 1);
131102     _saveGeo();
131103     _currentGeo = 0;
131104     _updateGeoDBSelect();
131105 }
131106 function _saveGeoData() {
131107     var entry;
131108     entry = new GeoEntry(new lbs.StructuredAddress({
131109         country: jQuery("#geoDB-country").val(),
131110         region: jQuery("#geoDB-region").val(),
131111         county: jQuery("#geoDB-county").val(),
131112         city: jQuery("#geoDB-city").val(),
131113         street: jQuery("#geoDB-street").val(),
131114         streetNumber: jQuery("#geoDB-streetNumber").val(),
131115         premises: jQuery("#geoDB-premises").val(),
131116         additionalInformation: jQuery("#geoDB-additionalInformation").val(),
131117         postalCode: jQuery("#geoDB-postalCode").val()
131118     }),
131119         new lbs.GeoCoordinates({
131120         latitude: parseFloat(jQuery("#geoDB-latitude").val()),
131121         longitude: parseFloat(jQuery("#geoDB-longitude").val()),
131122         altitude: parseFloat(jQuery("#geoDB-altitude").val()),
131123         accuracy: parseFloat(jQuery("#geoDB-accuracy").val()),
131124         altitudeAccuracy: parseFloat(jQuery("#geoDB-altitudeAccuracy").val()),
131125         heading: parseFloat(jQuery("#geoDB-heading").val()),
131126         speed: parseFloat(jQuery("#geoDB-speed").val())
131127     }));
131128     if (_saveID === _geoList.length)
131129         _geoList.push(entry);
131130     else
131131         _geoList[_saveID] = entry;
131132     
131133     _saveGeo();
131134     _currentGeo = _saveID;
131135     _updateGeoDBSelect();
131136     _triggerReadOnly(true);
131137 }
131138
131139 function _cancelGeoData() {
131140     _triggerReadOnly(true);
131141     _updateGeoDBSelect();
131142 }
131143
131144 module.exports = {
131145     panel: {
131146         domId: "geoDB-container",
131147         collapsed: true,
131148         pane: "right"
131149     },
131150
131151     initialize: function () {
131152         _currentGeo = 0; // set _geoList[0] as default value
131153         _geoList = _getGeo();
131154         _updateGeoDBSelect();
131155         _triggerReadOnly(true);
131156
131157         jQuery("#geo-select").bind("change", function () {
131158             _changeGeoData();
131159         });
131160         jQuery("#geoDB-add").bind("click", function () {
131161             _addGeoData();
131162         });
131163         jQuery("#geoDB-modify").bind("click", function () {
131164             _modifyGeoData();
131165         });
131166         jQuery("#geoDB-delete").bind("click", function () {
131167             _deleteGeoData();
131168         });
131169         jQuery("#geoDB-save").bind("click", function () {
131170             _saveGeoData();
131171         });
131172         jQuery("#geoDB-cancel").bind("click", function () {
131173             _cancelGeoData();
131174         });
131175     }
131176 };
131177
131178 });
131179 define('ripple/ui/plugins/geoView', function (require, exports, module) {
131180 /*
131181  *  Copyright 2011 Research In Motion Limited.
131182  *
131183  * Licensed under the Apache License, Version 2.0 (the "License");
131184  * you may not use this file except in compliance with the License.
131185  * You may obtain a copy of the License at
131186  *
131187  * http://www.apache.org/licenses/LICENSE-2.0
131188  *
131189  * Unless required by applicable law or agreed to in writing, software
131190  * distributed under the License is distributed on an "AS IS" BASIS,
131191  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
131192  * See the License for the specific language governing permissions and
131193  * limitations under the License.
131194  */
131195 var constants = require('ripple/constants'),
131196     geo = require('ripple/geo'),
131197     db = require('ripple/db'),
131198     event = require('ripple/event'),
131199     utils = require('ripple/utils'),
131200     platform = require('ripple/platform'),
131201     markers,
131202     _gpsMapZoomLevel,
131203     _routePoints = [],
131204     _routes = [],
131205     _routeMarkers,
131206     _lineLayer,
131207     _drawLineTimeout,
131208     _playFrequency = 0,
131209     _originalNavigator = window.navigator,
131210     _locationSharing = false;
131211     _playState = {'play': false, 'replay': false};
131212
131213 function _initTimeZone() {
131214     var allTZ, dbTZ, node = jQuery("#time-locale-select"),
131215         timezone = require('ripple/platform/tizen/2.0/timezone_info'),
131216         alarms, time;
131217
131218     function triggerAlarm() {
131219         time = new Date();
131220         alarms = db.retrieveObject("tizen1.0-db-alarms");
131221         if (alarms !== null) {
131222             utils.forEach(alarms, function (obj) {
131223                 if (obj.id !== undefined) {
131224                     event.trigger("CheckAlarm", [obj.id]);
131225                 }
131226             });
131227         }
131228     }
131229     window.setInterval(triggerAlarm, 1000);
131230
131231     allTZ = timezone.getAllTimezone();
131232     utils.forEach(allTZ, function (tz) {
131233         node.append(utils.createElement("option", {
131234             "value": tz,
131235             "innerHTML": tz + " - " + timezone.getTimezoneAbbr(tz) + "(" + timezone.getTimezoneDiff(tz) + ")"
131236         }));
131237     });
131238     dbTZ = db.retrieve("tizen-timezone");
131239     if (timezone.isValidTimezone(dbTZ)) {
131240         node.val(dbTZ);
131241     } else {
131242         db.save("tizen-timezone", node.val());
131243     }
131244     node.bind("change", function () {
131245         db.save("tizen-timezone", node.val());
131246     });
131247 }
131248
131249 function _updateGpsMap() {
131250     var positionInfo = geo.getPositionInfo(),
131251         mapContainer = document.getElementById(constants.GEO.OPTIONS.MAP_CONTAINER);
131252
131253     if (mapContainer && jQuery(mapContainer).is(':visible')) {
131254         geo.map.setCenter(new OpenLayers.LonLat(positionInfo.longitude, positionInfo.latitude).transform(
131255             new OpenLayers.Projection("EPSG:4326"), new OpenLayers.Projection("EPSG:900913")), _gpsMapZoomLevel, true);
131256     }
131257
131258     if (_lineLayer) {
131259         geo.map.removeLayer(_lineLayer);
131260         geo.map.addLayer(_lineLayer);
131261     }
131262 }
131263
131264 function _updateGpsMapZoom(goUp) {
131265     if (goUp && _gpsMapZoomLevel < constants.GEO.MAP_ZOOM_MAX) {
131266         _gpsMapZoomLevel++;
131267     }
131268     else if (!goUp && _gpsMapZoomLevel > constants.GEO.MAP_ZOOM_MIN) {
131269         _gpsMapZoomLevel--;
131270     }
131271
131272     _updateGpsMap();
131273     db.save(constants.GEO.MAP_ZOOM_KEY, _gpsMapZoomLevel);
131274 }
131275
131276 function _getTextHeading(heading) {
131277     if (heading >= 337.5 || (heading >= 0 && heading <= 22.5)) {
131278         return 'N';
131279     }
131280
131281     if (heading >= 22.5 && heading <= 67.5) {
131282         return 'NE';
131283     }
131284
131285     if (heading >= 67.5 && heading <= 112.5) {
131286         return 'E';
131287     }
131288     if (heading >= 112.5 && heading <= 157.5) {
131289         return 'SE';
131290     }
131291
131292     if (heading >= 157.5 && heading <= 202.5) {
131293         return 'S';
131294     }
131295
131296     if (heading >= 202.5 && heading <= 247.5) {
131297         return 'SW';
131298     }
131299
131300     if (heading >= 247.5 && heading <= 292.5) {
131301         return 'W';
131302     }
131303
131304     if (heading >= 292.5 && heading <= 337.5) {
131305         return 'NW';
131306     }
131307 }
131308
131309 function _updateRoutes() {
131310     var i, j, k, lon_step, lat_step;
131311     _routes = [];
131312
131313     for (i = 0; i < _routePoints.length - 1; i++) {
131314         lon_step = (_routePoints[i + 1].lonlat.lon - _routePoints[i].lonlat.lon) / 50;
131315         lat_step = (_routePoints[i + 1].lonlat.lat - _routePoints[i].lonlat.lat) / 50;
131316
131317         _routes.push(new OpenLayers.LonLat(_routePoints[i].lonlat.lon, _routePoints[i].lonlat.lat));
131318         for (j = 1, k = _routes.length; j < 50; j++, k++) {
131319             _routes.push(new OpenLayers.LonLat(_routes[k - 1].lon + lon_step, _routes[k - 1].lat + lat_step));
131320         }
131321     }
131322     _routes.push(new OpenLayers.LonLat(
131323         _routePoints[_routePoints.length - 1].lonlat.lon,
131324         _routePoints[_routePoints.length - 1].lonlat.lat)
131325     );
131326 }
131327
131328 function _drawLine(array) {
131329     var GEO_OPTIONS = constants.GEO.OPTIONS,
131330         latitude = document.getElementById(GEO_OPTIONS.LATITUDE),
131331         longitude = document.getElementById(GEO_OPTIONS.LONGITUDE),
131332         lonlat = new OpenLayers.LonLat(array[0].lon, array[0].lat).transform(
131333             new OpenLayers.Projection("EPSG:900913"),
131334             new OpenLayers.Projection("EPSG:4326")
131335         ),
131336         points = new Array(
131337             new OpenLayers.Geometry.Point(array[0].lon, array[0].lat),
131338             new OpenLayers.Geometry.Point(array[1].lon, array[1].lat)
131339         ),
131340         line = new OpenLayers.Geometry.LineString(points),
131341         style = {
131342             strokeColor: '#0000ff',
131343             strokeOpacity: 1,
131344             strokeWidth: 3
131345         },
131346         lineFeature = new OpenLayers.Feature.Vector(line, null, style);
131347
131348     if (!_lineLayer) {
131349         _lineLayer = new OpenLayers.Layer.Vector("Line Layer");
131350         geo.map.addLayer(_lineLayer);
131351     }
131352
131353     _lineLayer.addFeatures([lineFeature]);
131354     longitude.value = lonlat.lon;
131355     latitude.value = lonlat.lat;
131356
131357     if (_playFrequency % 10 === 0) {
131358         geo.map.panTo(new OpenLayers.LonLat(array[0].lon, array[0].lat), _gpsMapZoomLevel);
131359     }
131360     _playFrequency++;
131361 }
131362
131363 function clearRoute() {
131364     if (!_playState.play) {
131365         _routePoints.forEach(function (item) {
131366             _routeMarkers.removeMarker(item.marker);
131367         });
131368         _routePoints = [];
131369         _routes = [];
131370         _lineLayer.removeFeatures(_lineLayer.features);
131371     }
131372 }
131373
131374 function setRoute() {
131375     var clickHandler = new OpenLayers.Handler.Click(
131376         this,
131377         {
131378             click: function (e) {
131379                 if (geo.map.calculateBounds(null, 1) === null) {
131380                     geo.map.zoomTo(geo.map.zoom);
131381                 }
131382                 var location = geo.map.getLonLatFromViewPortPx(e.xy),
131383                     size = new OpenLayers.Size(21, 25),
131384                     offset = new OpenLayers.Pixel(-(size.w / 2), -size.h),
131385                     icon = new OpenLayers.Icon('images/map_marker.png', size, offset),
131386                     marker = new OpenLayers.Marker(new OpenLayers.LonLat(location.lon, location.lat), icon);
131387
131388                 geo.map.addLayer(_routeMarkers);
131389                 _routeMarkers.addMarker(marker);
131390                 _routePoints.push({
131391                     lonlat : location,
131392                     marker : marker
131393                 });
131394             }
131395         },
131396         {double: true}
131397     );
131398     clickHandler.dblclick = function () {
131399         _updateRoutes();
131400         this.deactivate();
131401     };
131402
131403     if (!_playState.play) {
131404         clickHandler.setMap(geo.map);
131405         clickHandler.activate();
131406     }
131407 }
131408
131409 function playRoute() {
131410     var speed = document.getElementById("play-route-speed"),
131411         getPlaySpeed = function () {
131412             return 20 / speed.value * 1000 / 50;
131413         },
131414         draw = function () {
131415             if (_routes.length <= 1) {
131416                 window.clearTimeout(_drawLineTimeout);
131417                 geo.map.panTo(new OpenLayers.LonLat(
131418                     _routePoints[_routePoints.length - 1].lonlat.lon,
131419                     _routePoints[_routePoints.length - 1].lonlat.lat),
131420                     _gpsMapZoomLevel);
131421                 _playState.play = false;
131422                 _playState.replay = true;
131423                 document.getElementById('play-btn-icon').src = "images/play.png";
131424             } else {
131425                 _drawLine(_routes);
131426                 _routes.splice(0, 1);
131427                 _drawLineTimeout = window.setTimeout(draw, getPlaySpeed());
131428             }
131429         };
131430
131431     if (!_playState.play && _routes.length !== 0) {
131432         if (_lineLayer && _playState.replay) {
131433             _lineLayer.removeFeatures(_lineLayer.features);
131434             _updateRoutes();
131435         }
131436         draw();
131437         _playState.play = true;
131438         document.getElementById('play-btn-icon').src = "images/pause.png";
131439     } else if (_playState.play) {
131440         window.clearTimeout(_drawLineTimeout);
131441         _playState.play = false;
131442         _playState.replay = false;
131443         document.getElementById('play-btn-icon').src = "images/play.png";
131444     }
131445 }
131446
131447 function skipTo(position) {
131448     if (_routes.length !== 0) {
131449         var index = (position === 'start' ? 0 : _routePoints.length - 1);
131450         window.clearTimeout(_drawLineTimeout);
131451         _lineLayer.removeFeatures(_lineLayer.features);
131452         geo.map.panTo(new OpenLayers.LonLat(_routePoints[index].lonlat.lon, _routePoints[index].lonlat.lat), _gpsMapZoomLevel);
131453         _routes = [];
131454         _updateRoutes();
131455         _playFrequency = 0;
131456         _playState.play = false;
131457         _playState.replay = false;
131458         document.getElementById('play-btn-icon').src = "images/play.png";
131459     }
131460 }
131461
131462 module.exports = {
131463     panel: {
131464         domId: "gps-container",
131465         collapsed: true,
131466         pane: "left",
131467         titleName: "Geolocation",
131468         display: true
131469     },
131470     initialize: function () {
131471         var GEO_OPTIONS = constants.GEO.OPTIONS,
131472             positionInfo = geo.getPositionInfo(),
131473             positionEvent = "PositionInfoUpdatedEvent",
131474             latitude = document.getElementById(GEO_OPTIONS.LATITUDE),
131475             longitude = document.getElementById(GEO_OPTIONS.LONGITUDE),
131476             altitude = document.getElementById(GEO_OPTIONS.ALTITUDE),
131477             accuracy = document.getElementById(GEO_OPTIONS.ACCURACY),
131478             altitudeAccuracy = document.getElementById(GEO_OPTIONS.ALTITUDE_ACCURACY),
131479             heading = document.getElementById(GEO_OPTIONS.HEADING),
131480             speed = document.getElementById(GEO_OPTIONS.SPEED),
131481             cellID = document.getElementById(GEO_OPTIONS.CELL_ID),
131482             delay = document.getElementById(GEO_OPTIONS.DELAY),
131483             delayLabel = document.getElementById(GEO_OPTIONS.DELAY_LABEL),
131484             headingLabel = document.getElementById(GEO_OPTIONS.HEADING_LABEL),
131485             headingMapLabel = document.getElementById(GEO_OPTIONS.HEADING_MAP_LABEL),
131486             timeout = document.getElementById(GEO_OPTIONS.TIMEOUT),
131487             gpxMultiplier = document.getElementById(GEO_OPTIONS.GPXMULTIPLIER),
131488             gpxReplayStatus = document.getElementById(GEO_OPTIONS.GPXREPLAYSTATUS),
131489             gpxGo = $(document.getElementById(GEO_OPTIONS.GPXGO)).find("span")[0],
131490             mapContainer = document.getElementById(GEO_OPTIONS.MAP_CONTAINER),
131491             map = null,
131492             track = [],
131493             _replayingGpxFile = false,
131494             _haltGpxReplay = false;
131495
131496         function updateGeo() {
131497             if (parseFloat(latitude.value) > 90)
131498                 latitude.value = 90;
131499             else if (parseFloat(latitude.value) < -90)
131500                 latitude.value = -90;
131501
131502             if (parseFloat(longitude.value) > 180)
131503                 longitude.value = 180;
131504             else if (parseFloat(longitude.value) < -180)
131505                 longitude.value = -180;
131506
131507             geo.updatePositionInfo({
131508                 latitude: parseFloat(latitude.value),
131509                 longitude: parseFloat(longitude.value),
131510                 altitude: parseInt(altitude.value, 10),
131511                 accuracy: parseInt(accuracy.value, 10),
131512                 altitudeAccuracy: parseInt(altitudeAccuracy.value, 10),
131513                 heading: heading.value ? parseFloat(heading.value) : 0, // HACK: see techdebt http://www.pivotaltracker.com/story/show/5478847
131514                 speed: speed.value ? parseInt(speed.value, 10) : 0, // HACK: see techdebt http://www.pivotaltracker.com/story/show/5478847
131515                 cellID: cellID.value,
131516                 timeStamp: new Date()
131517             },
131518             delay.value,
131519             timeout.checked);
131520         }
131521
131522         function updateHeadingValues() {
131523             var headingDeg = parseFloat(heading.value),
131524                 headingText = _getTextHeading(parseFloat(heading.value));
131525
131526             headingLabel.innerText = headingText;
131527             headingMapLabel.innerHTML = headingText + "</br>" + headingDeg + "&deg;";
131528         }
131529
131530         function updateValsFromMap() {
131531             var center = geo.map.getCenter().transform(
131532                 new OpenLayers.Projection("EPSG:900913"),
131533                 new OpenLayers.Projection("EPSG:4326"));
131534             longitude.value = center.lon;
131535             latitude.value = center.lat;
131536             updateGeo();
131537         }
131538
131539         function initializeValues() {
131540             latitude.value =          positionInfo.latitude;
131541             longitude.value =         positionInfo.longitude;
131542             altitude.value =          positionInfo.altitude;
131543             accuracy.value =          positionInfo.accuracy;
131544             altitudeAccuracy.value =  positionInfo.altitudeAccuracy;
131545             cellID.value =            positionInfo.cellID;
131546             delay.value = document.getElementById(GEO_OPTIONS.DELAY_LABEL).innerText = geo.delay || 0;
131547             if (geo.timeout) {
131548                 timeout.checked = true;
131549             }
131550             updateHeadingValues();
131551         }
131552
131553         function initMap() {
131554             var marker, clickHandler;
131555             // override image location so we don't have to include image assets
131556             OpenLayers.ImgPath = 'http://openlayers.org/api/img/';
131557
131558             // init map
131559             geo.map = new OpenLayers.Map(mapContainer, { controls: [] });
131560
131561             // add controls and OSM map layer
131562             geo.map.addLayer(new OpenLayers.Layer.OSM());
131563             geo.map.addControl(new OpenLayers.Control.Navigation());
131564
131565             // override behaviour of click to pan and double click to zoom in
131566             clickHandler = new OpenLayers.Handler.Click(
131567                 this,
131568                 {
131569                     click: function (e) {
131570                         if (geo.map.calculateBounds(null, 1) === null) {
131571                             geo.map.zoomTo(geo.map.zoom);
131572                         }
131573                         var location = geo.map.getLonLatFromViewPortPx(e.xy);
131574                         geo.map.panTo(new OpenLayers.LonLat(location.lon, location.lat), _gpsMapZoomLevel);
131575                     },
131576
131577                     dblclick: function () {
131578                         _updateGpsMapZoom(true);
131579                     }
131580                 },
131581                 {double: true}
131582             );
131583
131584             // add click handler to map
131585             clickHandler.setMap(geo.map);
131586             clickHandler.activate();
131587
131588             // update long and lat when map is panned
131589             geo.map.events.register("moveend", map, function () {
131590                 updateValsFromMap();
131591             });
131592             geo.map.events.register("zoomend", map, function (obj) {
131593                 if ((obj.object.zoom > _gpsMapZoomLevel && _gpsMapZoomLevel < constants.GEO.MAP_ZOOM_MAX) ||
131594                     (obj.object.zoom < _gpsMapZoomLevel && _gpsMapZoomLevel > constants.GEO.MAP_ZOOM_MIN)) {
131595                     _gpsMapZoomLevel = obj.object.zoom;
131596                 }
131597             });
131598
131599             markers = new OpenLayers.Layer.Markers("markers");
131600             _routeMarkers = new OpenLayers.Layer.Markers("markers");
131601             geo.map.addLayer(markers);
131602
131603             event.on("ApplicationState", function (obj) {
131604                 if (obj && obj[0].id === 'gps-container' && obj.hasClass('ui-box-open')) {
131605                     _updateGpsMap();
131606
131607                     // Update the position if user accept location sharing
131608                     if (_locationSharing === false) {
131609                         _originalNavigator.geolocation.getCurrentPosition(function(geoPosition) {
131610                             geo.map.panTo(new OpenLayers.LonLat(geoPosition.coords.longitude, geoPosition.coords.latitude).transform(
131611                                 new OpenLayers.Projection("EPSG:4326"), new OpenLayers.Projection("EPSG:900913")), _gpsMapZoomLevel);
131612                             _locationSharing = true;
131613                         });
131614                     }
131615
131616                     // Simulator is loaded with geo panel folded, now it's the first time it's unfolded
131617                     if (!marker) {
131618                         // Only when the geo panel is unfolded, getCenter() will go well
131619                         marker = new OpenLayers.Marker(geo.map.getCenter(),
131620                             new OpenLayers.Icon("images/arrow.png", new OpenLayers.Size(22, 30), new OpenLayers.Pixel(-11, -15)));
131621                         markers.addMarker(marker);
131622
131623                         navigator.geolocation.getCurrentPosition(function (geoPosition) {
131624                             geo.map.panTo(new OpenLayers.LonLat(geoPosition.coords.longitude, geoPosition.coords.latitude).transform(
131625                                 new OpenLayers.Projection("EPSG:4326"), new OpenLayers.Projection("EPSG:900913")), _gpsMapZoomLevel);
131626                         });
131627                     }
131628                 }
131629             });
131630             _updateGpsMap();
131631
131632             // Simulator is loaded with geo panel unfolded
131633             if (mapContainer && jQuery(mapContainer).is(':visible')) {
131634                 marker = new OpenLayers.Marker(geo.map.getCenter(),
131635                     new OpenLayers.Icon("images/arrow.png", new OpenLayers.Size(22, 30), new OpenLayers.Pixel(-11, -15)));
131636                 markers.addMarker(marker);
131637
131638                 navigator.geolocation.getCurrentPosition(function (geoPosition) {
131639                     geo.map.panTo(new OpenLayers.LonLat(geoPosition.coords.longitude, geoPosition.coords.latitude).transform(
131640                         new OpenLayers.Projection("EPSG:4326"), new OpenLayers.Projection("EPSG:900913")), _gpsMapZoomLevel);
131641                     _locationSharing = true;
131642                 });
131643             }
131644
131645             geo.map.events.register("move", map, function () {
131646                 markers.clearMarkers();
131647                 marker = new OpenLayers.Marker(geo.map.getCenter(),
131648                         new OpenLayers.Icon("images/arrow.png", new OpenLayers.Size(22, 30), new OpenLayers.Pixel(-11, -15)));
131649                 markers.addMarker(marker);
131650             });
131651         }
131652
131653         function loadGpxFile(win, fail, args) {
131654             var reader = new FileReader(),
131655                 file = args[0],
131656                 _xml,
131657                 t,
131658                 att,
131659                 lastAtt,
131660                 _ele,
131661                 _timestamp,
131662                 _lastTimestamp,
131663                 _useTimestamp = new Date().getTime(),
131664                 _tempTimestamp,
131665                 _tempPosition,
131666                 _lastPosition,
131667                 _useLastTimestamp,
131668                 _heading = 0,
131669                 _speed = 0,
131670                 _dist = 0,
131671                 navUtils = new utils.navHelper();
131672
131673             reader.onload = function (e) {
131674                 _xml = e.target.result;
131675                 t = $(_xml).find('trkpt');
131676
131677                 track = [];
131678
131679                 utils.forEach(t, function (p, i) {
131680                     if (!isNaN(i)) {
131681                         att = t[i].attributes;
131682                         lastAtt = t[i - 1] ? t[i - 1].attributes : {};
131683                         _ele = $(t[i]).find("ele")[0];
131684                         _timestamp = $(t[i]).find("time")[0];
131685                         _lastTimestamp = $(t[i - 1]).find("time")[0];
131686
131687                         if (_timestamp) {
131688                             //files recorded with endomondo and others have timestamps, this is not a route plan but a record of a track
131689                             _useTimestamp = new Date(_timestamp.innerText).getTime();
131690                         }
131691
131692                         if (t[i - 1]) {
131693                             _dist = navUtils.getDistance(att["lat"].value, att["lon"].value, lastAtt["lat"].value, lastAtt["lon"].value);
131694
131695                             if (_lastTimestamp) {
131696                                 _useLastTimestamp = new Date(_lastTimestamp.innerText).getTime();
131697                             }
131698                             else {
131699                                 //routes from YOURS come in as tracks (rather than routes under the GPX schema), but with no timestamps.  This is a route.
131700                                 _useLastTimestamp = _useTimestamp;
131701                                 _useTimestamp += Math.round(_dist / 22.2222 * 1000);  //80km/h in m/s
131702                             }
131703
131704                             _heading = navUtils.getHeading(lastAtt["lat"].value, lastAtt["lon"].value, att["lat"].value, att["lon"].value);
131705                             _speed = (_dist / ((_useTimestamp - _useLastTimestamp) / 1000)).toFixed(2);
131706
131707                             if (!_lastTimestamp) {
131708                                 //on YOURS routes, make sure we have at least one update a second
131709                                 _tempTimestamp = _useLastTimestamp;
131710
131711                                 while (_useTimestamp - _tempTimestamp > 1000) {
131712                                     _tempTimestamp += 1000;
131713                                     _lastPosition = track[track.length - 1].coords;
131714                                     _tempPosition = navUtils.simulateTravel(_lastPosition.latitude, _lastPosition.longitude, _heading, _speed);
131715                                     track.push({
131716                                         coords: {
131717                                             latitude: _tempPosition.latitude,
131718                                             longitude: _tempPosition.longitude,
131719                                             altitude: _ele ? _ele.innerText : 0,
131720                                             accuracy: 150,
131721                                             altitudeAccuracy: 80,
131722                                             heading: _heading,
131723                                             speed: _speed
131724                                         },
131725                                         timestamp: _tempTimestamp
131726                                     });
131727                                 }
131728                             }
131729                         }
131730
131731                         track.push({
131732                             coords: {
131733                                 latitude: att["lat"].value,
131734                                 longitude: att["lon"].value,
131735                                 altitude: _ele ? _ele.innerText : 0,
131736                                 accuracy: 150,
131737                                 altitudeAccuracy: 80,
131738                                 heading: _heading,
131739                                 speed: _speed
131740                             },
131741                             timestamp: _useTimestamp
131742                         });
131743                     }
131744                 });
131745             };
131746             reader.onerror = function (e) {
131747                 fail(e);
131748             };
131749             reader.readAsText(file.target.files[0], "UTF-8");
131750         }
131751
131752         function replayGpxTrack() {
131753             if (_replayingGpxFile) {
131754                 _haltGpxReplay = true;
131755                 gpxGo.innerText = constants.GEO.GPXGO_LABELS.GO;
131756             }
131757             else {
131758                 if (track.length > 0) {
131759                     _haltGpxReplay = false;
131760                     gpxGo.innerText = constants.GEO.GPXGO_LABELS.STOP;
131761
131762                     latitude.value = track[0].coords.latitude;
131763                     longitude.value = track[0].coords.longitude;
131764                     altitude.value = track[0].coords.altitude;
131765                     accuracy.value = track[0].coords.accuracy;
131766                     altitudeAccuracy.value = track[0].coords.altitudeAccuracy;
131767                     heading.value = track[0].coords.heading;
131768                     speed.value = track[0].coords.speed;
131769
131770                     updateGeo();
131771                     updateHeadingValues();
131772                     _triggerEvent();
131773
131774                     moveNextGpxTrack(1);
131775                 }
131776             }
131777         }
131778
131779         function moveNextGpxTrack(i)
131780         {
131781             if (_haltGpxReplay) {
131782                 _replayingGpxFile = false;
131783                 _haltGpxReplay = false;
131784                 console.log("Ripple :: User interrupted replay of GPX file (Aye Captain, answers All Stop.)");
131785             }
131786             else {
131787                 _replayingGpxFile = true;
131788                 var _timeMultiplier = !isNaN(gpxMultiplier.value) ? gpxMultiplier.value : 1,
131789                 _step = 0,
131790                 _interval = 0;
131791
131792                 while (_interval < 250) {
131793                     _step++;
131794                     if ((i + _step) >= track.length) { break; }
131795                     _interval = (track[i + _step].timestamp - track[i].timestamp) / _timeMultiplier;
131796                 }
131797
131798                 gpxReplayStatus.textContent = (_interval / 1000).toFixed(2) + "s (" + (_interval / 1000 * _timeMultiplier).toFixed(2) + "s realtime), " + (i + 1) + " of " + track.length + " (stepping " + _step + " at " + _timeMultiplier + "x)";
131799
131800                 setTimeout(function () {
131801                     latitude.value = track[i].coords.latitude;
131802                     longitude.value = track[i].coords.longitude;
131803                     altitude.value = track[i].coords.altitude;
131804                     accuracy.value = track[i].coords.accuracy;
131805                     altitudeAccuracy.value = track[i].coords.altitudeAccuracy;
131806                     heading.value = track[i].coords.heading;
131807                     speed.value = track[i].coords.speed;
131808
131809                     updateGeo();
131810                     updateHeadingValues();
131811                     _triggerEvent();
131812
131813                     if (track[i + _step]) {
131814                         moveNextGpxTrack(i + _step);
131815                     }
131816                     else {
131817                         if (i < track.length - 1) {
131818                             moveNextGpxTrack(track.length - 1);
131819                         }
131820                         else {
131821                             _replayingGpxFile = false;
131822                             gpxGo.innerText = constants.GEO.GPXGO_LABELS.GO;
131823                             console.log("Ripple :: Finished replaying GPX file (Arriving at our destination, assuming standard orbit Captain.)");
131824                         }
131825                     }
131826                 }, _interval);
131827             }
131828         }
131829
131830         // HACK: see techdebt http://www.pivotaltracker.com/story/show/5478847 (double HACK!!!)
131831         if (platform.current().id === 'phonegap' ||
131832             platform.current().id === 'webworks' ||
131833             platform.current().id === 'cordova') {
131834             // make the fields visible
131835             jQuery("#geo-cellid-container").hide();
131836             jQuery("#geo-heading-container").show();
131837             jQuery("#geo-speed-container").show();
131838         }
131839         else {
131840             jQuery("#geo-cellid-container").show();
131841             jQuery("#geo-heading-container").hide();
131842             jQuery("#geo-speed-container").hide();
131843         }
131844
131845         _gpsMapZoomLevel = db.retrieve(constants.GEO.MAP_ZOOM_KEY) || 14;
131846
131847         jQuery("#geo-map-zoom-decrease").bind("click", function () {
131848             _updateGpsMapZoom(false);
131849         });
131850
131851         jQuery("#geo-map-zoom-increase").bind("click", function () {
131852             _updateGpsMapZoom(true);
131853         });
131854
131855         utils.bindAutoSaveEvent(jQuery("#" + GEO_OPTIONS.LATITUDE), updateGeo);
131856         utils.bindAutoSaveEvent(jQuery("#" + GEO_OPTIONS.LONGITUDE), updateGeo);
131857         utils.bindAutoSaveEvent(jQuery("#" + GEO_OPTIONS.ALTITUDE), updateGeo);
131858         utils.bindAutoSaveEvent(jQuery("#" + GEO_OPTIONS.ACCURACY), updateGeo);
131859         utils.bindAutoSaveEvent(jQuery("#" + GEO_OPTIONS.ALTITUDE_ACCURACY), updateGeo);
131860         utils.bindAutoSaveEvent(jQuery("#" + GEO_OPTIONS.CELL_ID), updateGeo);
131861
131862         jQuery("#play-route-speed-label").html(jQuery("#play-route-speed").val() + 'x');
131863         jQuery("#play-route-speed").bind("change", function () {
131864             jQuery("#play-route-speed-label").html(jQuery("#play-route-speed").val() + 'x');
131865         });
131866         jQuery("#clear-route-btn").bind("click", function () {
131867             clearRoute();
131868         });
131869         jQuery("#set-route-btn").bind("click", function () {
131870             setRoute();
131871         });
131872         jQuery("#play-route-btn").bind("click", function () {
131873             playRoute();
131874         });
131875         jQuery("#back-route-btn").bind("click", function () {
131876             skipTo("start");
131877         });
131878         jQuery("#forward-route-btn").bind("click", function () {
131879             skipTo("end");
131880         });
131881
131882         jQuery("#" + GEO_OPTIONS.DELAY).bind("change", function () {
131883             updateGeo();
131884             delayLabel.innerText = delay.value;
131885         });
131886         jQuery("#" + GEO_OPTIONS.TIMEOUT).bind("click", function () {
131887             updateGeo();
131888         });
131889         jQuery("#" + GEO_OPTIONS.GPXFILE).bind("change", function (a) {
131890             loadGpxFile(null, null, [a]);
131891         });
131892         jQuery("#" + GEO_OPTIONS.GPXGO).bind("click", function () {
131893             replayGpxTrack();
131894         });
131895
131896         // HACK: see techdebt http://www.pivotaltracker.com/story/show/5478847 (double HACK!!!)
131897         if (platform.current().id === 'phonegap' || platform.current().id === 'webworks' || platform.current().id === 'cordova') {
131898             jQuery("#" + GEO_OPTIONS.HEADING).bind("change", function () {
131899                 updateGeo();
131900                 updateHeadingValues();
131901             });
131902
131903             utils.bindAutoSaveEvent(jQuery("#" + GEO_OPTIONS.SPEED), updateGeo);
131904             heading.value =       positionInfo.heading;
131905             speed.value =         positionInfo.speed;
131906         }
131907
131908         initMap();
131909         if (navigator.onLine === false) {
131910             jQuery("#disable_geo_panel").show();
131911         }
131912         jQuery(window).bind("online", function () {
131913             jQuery("#disable_geo_panel").hide();
131914             console.log("ONLINE");
131915         });
131916         jQuery(window).bind("offline", function () {
131917             jQuery("#disable_geo_panel").show();
131918             console.log("OFFLINE");
131919         });
131920
131921         initializeValues();
131922         _initTimeZone();
131923
131924         event.on(positionEvent, function () {
131925             _updateGpsMap();
131926         });
131927
131928         _triggerEvent();
131929
131930         function _triggerEvent() {
131931             event.trigger(positionEvent, [{
131932                 latitude: latitude.value,
131933                 longitude: longitude.value,
131934                 altitude: altitude.value,
131935                 accuracy: accuracy.value,
131936                 altitudeAccuracy: altitudeAccuracy.value,
131937                 heading: heading ? heading.value : 0, // HACK: see techdebt http://www.pivotaltracker.com/story/show/5478847
131938                 speed: speed ? speed.value : 0, // HACK: see techdebt http://www.pivotaltracker.com/story/show/5478847
131939                 cellID: cellID.value,
131940                 timeStamp: new Date()
131941             }]);
131942         }
131943     }
131944 };
131945
131946 });
131947 define('ripple/ui/plugins/goodVibrations', function (require, exports, module) {
131948 /*
131949  *  Copyright 2011 Research In Motion Limited.
131950  *
131951  * Licensed under the Apache License, Version 2.0 (the "License");
131952  * you may not use this file except in compliance with the License.
131953  * You may obtain a copy of the License at
131954  *
131955  * http://www.apache.org/licenses/LICENSE-2.0
131956  *
131957  * Unless required by applicable law or agreed to in writing, software
131958  * distributed under the License is distributed on an "AS IS" BASIS,
131959  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
131960  * See the License for the specific language governing permissions and
131961  * limitations under the License.
131962  */
131963 var constants = require('ripple/constants');
131964
131965 module.exports = {
131966     vibrateDevice: function (milliseconds) {
131967         var node = jQuery("#" + constants.COMMON.DEVICE_CONTAINER),
131968             x, times;
131969
131970         times = Math.floor(milliseconds / 100);
131971
131972         for (x = 1; x <= times; x++) {
131973             node.animate({ left: -10 }, 5)
131974             .animate({ left: 0 }, 1)
131975             .animate({ left: 10 }, 5)
131976             .animate({ left: 0 }, 1);
131977
131978             node.animate({ top: -10 }, 5)
131979             .animate({ top: 0 }, 1)
131980             .animate({ top: 10 }, 5)
131981             .animate({ top: 0 }, 1);
131982         }
131983     },
131984     shakeDevice: function (times) {
131985         var node = jQuery("#" + constants.COMMON.DEVICE_CONTAINER),
131986             x;
131987
131988         for (x = 1; x <= times; x++) {
131989             node.animate({ left: -25 }, 50)
131990             .animate({ left: 0 }, 30)
131991             .animate({ left: 25 }, 50)
131992             .animate({ left: 0 }, 30);
131993         }
131994     }
131995 };
131996
131997 });
131998 define('ripple/ui/plugins/information', function (require, exports, module) {
131999 /*
132000  *  Copyright 2011 Research In Motion Limited.
132001  *
132002  * Licensed under the Apache License, Version 2.0 (the "License");
132003  * you may not use this file except in compliance with the License.
132004  * You may obtain a copy of the License at
132005  *
132006  * http://www.apache.org/licenses/LICENSE-2.0
132007  *
132008  * Unless required by applicable law or agreed to in writing, software
132009  * distributed under the License is distributed on an "AS IS" BASIS,
132010  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
132011  * See the License for the specific language governing permissions and
132012  * limitations under the License.
132013  */
132014 var constants = require('ripple/constants'),
132015     devices = require('ripple/devices'),
132016     event = require('ripple/event'),
132017     platform = require('ripple/platform'),
132018     utils = require('ripple/utils'),
132019     app = require('ripple/app'),
132020     tooltip = require('ripple/ui/plugins/tooltip'),
132021     db = require('ripple/db');
132022
132023 function _updateInformationView() {
132024     var infoPane = document.getElementById(constants.COMMON.INFO_SECTION),
132025         infoList = [],
132026         device = devices.getCurrentDevice(),
132027         tempString = "",
132028         widgetInfo = app.getInfo(),
132029         layout = db.retrieve("layout") || "portrait",
132030         _systemSettings = db.retrieveObject("tizen2-systemsetting") || {"HOME_SCREEN": "", "LOCK_SCREEN": "", "INCOMING_CALL": "", "NOTIFICATION_EMAIL": ""};
132031
132032     //TODO: refactor this stuff to grab info from API, do this in a loop rather then hardcoded. Better DOM injection approach. This is legacy code
132033
132034     infoList.push('<section id=\"information-banner\" style=\"display:none\"><img id=\"information-banner-icon\" width=\"16px\" height=\"16px\"/> <span id=\"information-banner-count\"></span></section>');
132035
132036     if (widgetInfo.icon) {
132037         infoList.push('<section style="position: absolute; left: 260px;"  class="information-widgeticon"><img class="ui-corner-all" width="64" src="' + utils.appLocation() + widgetInfo.icon + '" alt="widget icon"/></section>');
132038     }
132039     if (widgetInfo.name) {
132040         infoList.push("<section><div id=\"systemSummaryAppNameContainer\" style=\"width:240px; height:20px; overflow:hidden; white-space: nowrap; text-overflow: ellipsis;\" ><label class=\"ui-text-label\">App Name: </label><span class=\"text-is-selectable\">" + widgetInfo.name + "</span></div></section>");
132041         //Update Title
132042         document.title = "Web Simulator - " + widgetInfo.name;
132043     }
132044
132045     infoList.push('<table class="tf_panel-table" style="border-spacing: 0px;">');
132046    
132047     if (widgetInfo.version) {
132048         infoList.push('<section class="information-widgetversion"><label class=\"ui-text-label\">Version: </label><span class="text-is-selectable">' + widgetInfo.version + '</span></section>');
132049     }
132050     infoList.push("<section><label class=\"ui-text-label\">Platform: </label><span class=\"text-is-selectable\">" + platform.current().name + "</span></section>");
132051     infoList.push("<section><label class=\"ui-text-label\">Device: </label><span class=\"text-is-selectable\">" + device.name + "</span></section>");
132052     infoList.push("<section><label class=\"ui-text-label\">OS: </label><span class=\"text-is-selectable\">" + device.osName + " " + device.osVersion + "</span></section>");
132053     infoList.push("<section><label class=\"ui-text-label\">Manufacturer: </label><span class=\"text-is-selectable\">" + device.manufacturer + "</span></section>");
132054     infoList.push("<section><label class=\"ui-text-label\">Screen: </label><span class=\"text-is-selectable\">" + device.screen.width + "x" + device.screen.height + "</span></section>");
132055     infoList.push("<section><label class=\"ui-text-label\">Viewport: </label><span class=\"text-is-selectable\">" + device.viewPort[layout].width.toFixed(0) + "x" + device.viewPort[layout].height.toFixed(0) + "</span></section>");
132056     infoList.push("<section><label class=\"ui-text-label\">Density: </label><span class=\"text-is-selectable\">" + device.ppi + " PPI</span></section>");
132057     infoList.push("<section><label class=\"ui-text-label\" style=\"float:left; padding-top: 0px; \">User Agent: </label>" +
132058                     "<div class=\"text-is-selectable\" style=\"padding-left: 80px\">" + device.userAgent + "</div></section>");
132059
132060     if (device.notes) {
132061         utils.forEach(device.notes, function (note) {
132062             tempString += "<li class=\"text-is-selectable\">" + note + "</li>";
132063         });
132064         infoList.push("<section><div style=\"clear:both;\"></div><label class=\"ui-text-label\">Notes: </label><ul>" + tempString + "</ul></section>");
132065     }
132066
132067     infoList.push("<section><div style=\"clear:both;\"></div><div id=\"systemSummaryHomeScreenContainer\" style=\"width:320px; height:20px; overflow:hidden; white-space: nowrap; text-overflow: ellipsis;\" ><label class=\"ui-text-label\">Home Screen Image: </label><span>" + _systemSettings["HOME_SCREEN"] + "</span></div></section>");
132068     infoList.push("<section><div style=\"clear:both;\"></div><div id=\"systemSummaryLockScreenContainer\" style=\"width:320px; height:20px; overflow:hidden; white-space: nowrap; text-overflow: ellipsis;\" ><label class=\"ui-text-label\">Lock Screen Image: </label><span>" + _systemSettings["LOCK_SCREEN"] + "</span></div></section>");
132069     infoList.push("<section><div style=\"clear:both;\"></div><div id=\"systemSummaryInComingCallContainer\" style=\"width:320px; height:20px; overflow:hidden; white-space: nowrap; text-overflow: ellipsis;\" ><label class=\"ui-text-label\">Incoming Call Number: </label><span>" + _systemSettings["INCOMING_CALL"] + "</span></div></section>");
132070     infoList.push("<section><div style=\"clear:both;\"></div><div id=\"systemSummaryNotiEMailContainer\" style=\"width:320px; height:20px; overflow:hidden; white-space: nowrap; text-overflow: ellipsis;\" ><label class=\"ui-text-label\">Notification Email: </label><span>" + _systemSettings["NOTIFICATION_EMAIL"] + "</span></div></section>");
132071     infoList.push("<section><div style=\"clear:both;\"></div><div id=\"NFCExclusiveModeContainer\" style=\"width:320px; height:20px; overflow:hidden; white-space: nowrap; text-overflow: ellipsis;\" ><label class=\"ui-text-label\">NFC Exclusive Mode: </label><span id=\"NFCExclusiveModeValue\">false</span></div></section>");
132072     infoPane.innerHTML = infoList.join("");
132073
132074     // Make tooltip if it needed
132075     if ((jQuery("#systemSummaryAppNameContainer").children("label").width() + jQuery("#systemSummaryAppNameContainer").children("span").width()) > 240) {
132076         tooltip.create("#systemSummaryAppNameContainer", jQuery("#systemSummaryAppNameContainer").children("span").text());
132077     }
132078     if ((jQuery("#systemSummaryHomeScreenContainer").children("label").width() + jQuery("#systemSummaryHomeScreenContainer").children("span").width()) > 320) {
132079         tooltip.create("#systemSummaryHomeScreenContainer", jQuery("#systemSummaryHomeScreenContainer").children("span").text());
132080     }
132081     if ((jQuery("#systemSummaryLockScreenContainer").children("label").width() + jQuery("#systemSummaryLockScreenContainer").children("span").width()) > 320) {
132082         tooltip.create("#systemSummaryLockScreenContainer", jQuery("#systemSummaryLockScreenContainer").children("span").text());
132083     }
132084     if ((jQuery("#systemSummaryInComingCallContainer").children("label").width() + jQuery("#systemSummaryInComingCallContainer").children("span").width()) > 320) {
132085         tooltip.create("#systemSummaryInComingCallContainer", jQuery("#systemSummaryInComingCallContainer").children("span").text());
132086     }
132087     if ((jQuery("#systemSummaryNotiEMailContainer").children("label").width() + jQuery("#systemSummaryNotiEMailContainer").children("span").width()) > 320) {
132088         tooltip.create("#systemSummaryNotiEMailContainer", jQuery("#systemSummaryNotiEMailContainer").children("span").text());
132089     }
132090 }
132091
132092 function _updateBanner(icon, count) {
132093     var bannerSection = document.getElementById("information-banner"),
132094         iconImg  = document.getElementById("information-banner-icon"),
132095         countSpan = document.getElementById("information-banner-count");
132096
132097     if (icon && (count === undefined || count !== 0)) {
132098         count = count || "";
132099         jQuery("#" + constants.COMMON.INFO_SECTION).show();
132100         jQuery(bannerSection).fadeToggle(1000);
132101         jQuery(bannerSection).fadeIn(1000);
132102     }
132103     else {
132104         jQuery(bannerSection).fadeOut(1000);
132105     }
132106
132107     iconImg.src = utils.appLocation() + icon;
132108     if (icon.indexOf("http") === 0) {
132109         iconImg.src = icon;
132110     }
132111
132112     countSpan.innerHTML = count > 99 ? "99+" : count;
132113 }
132114
132115 module.exports = {
132116     panel: {
132117         domId: "information-container",
132118         collapsed: false,
132119         pane: "left",
132120         titleName: "System Summary",
132121         display: true
132122     },
132123     initialize: function () {
132124         event.on("BannerUpdated", function (icon, count) {
132125             _updateBanner(icon, count);
132126         });
132127
132128         event.on("PlatformChangedEvent", function () {
132129             _updateInformationView();
132130         });
132131
132132         event.on("WidgetInformationUpdated", function () {
132133             _updateInformationView();
132134         });
132135         
132136         event.on("SystemSettingChanged", function () {
132137             _updateInformationView();
132138         });
132139
132140         event.on("ScreenChangeDimensions", function() {
132141             _updateInformationView();
132142         });
132143         _updateInformationView();
132144     }
132145 };
132146
132147 });
132148 define('ripple/ui/plugins/invoke', function (require, exports, module) {
132149 /*
132150  *  Copyright 2011 Research In Motion Limited.
132151  *
132152  * Licensed under the Apache License, Version 2.0 (the "License");
132153  * you may not use this file except in compliance with the License.
132154  * You may obtain a copy of the License at
132155  *
132156  * http://www.apache.org/licenses/LICENSE-2.0
132157  *
132158  * Unless required by applicable law or agreed to in writing, software
132159  * distributed under the License is distributed on an "AS IS" BASIS,
132160  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
132161  * See the License for the specific language governing permissions and
132162  * limitations under the License.
132163  */
132164 var constants = require('ripple/constants'),
132165     event = require('ripple/event');
132166
132167 module.exports = {
132168     panel: {
132169         domId: "invoke-container",
132170         collapsed: true,
132171         pane: "left"
132172     },
132173     initialize: function () {
132174         document.getElementById("invoke-send")
132175             .addEventListener("click", function () {
132176                 var invokeInfo = {};
132177
132178                 invokeInfo.uri = document.getElementById("invoke-uri-text").value;
132179                 invokeInfo.source = document.getElementById("invoke-source-text").value;
132180                 invokeInfo.target = document.getElementById("invoke-target-text").value;
132181                 invokeInfo.action = document.getElementById("invoke-action-text").value;
132182                 invokeInfo.type = document.getElementById("invoke-mime-type-text").value;
132183                 invokeInfo.extension = document.getElementById("invoke-extension-text").value;
132184                 invokeInfo.data = document.getElementById("invoke-data-text").value;
132185                 if (invokeInfo.data) {
132186                     invokeInfo.data = window.btoa(invokeInfo.data);
132187                 }
132188
132189                 event.trigger("AppInvoke", [invokeInfo]);
132190             }, false);
132191     }
132192 };
132193
132194 });
132195 define('ripple/ui/plugins/layout', function (require, exports, module) {
132196 /*
132197  *  Copyright 2011 Research In Motion Limited.
132198  *
132199  * Licensed under the Apache License, Version 2.0 (the "License");
132200  * you may not use this file except in compliance with the License.
132201  * You may obtain a copy of the License at
132202  *
132203  * http://www.apache.org/licenses/LICENSE-2.0
132204  *
132205  * Unless required by applicable law or agreed to in writing, software
132206  * distributed under the License is distributed on an "AS IS" BASIS,
132207  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
132208  * See the License for the specific language governing permissions and
132209  * limitations under the License.
132210  */
132211 var constants = require('ripple/constants'),
132212     db = require('ripple/db'),
132213     resizer = require('ripple/resizer'),
132214     devices = require('ripple/devices'),
132215     event = require('ripple/event');
132216
132217 function _initializeLayout(prev, baton) {
132218     var layout = db.retrieve("layout"),
132219         orientation = db.retrieve("deviceOrientation") || "portrait",
132220         layoutLandscape = document.getElementById(constants.COMMON.ORIENTATION_SELECT_LANDSCAPE_ID),
132221         layoutPortrait = document.getElementById(constants.COMMON.ORIENTATION_SELECT_PORTRAIT_ID),
132222         currentDevice = devices.getCurrentDevice(),
132223         defaultOrientation =  currentDevice ? currentDevice.defaultOrientation : null,
132224         layoutTypeChanged = false;
132225
132226     jQuery("#" + constants.COMMON.ORIENTATION_SELECT_LANDSCAPE_ID).bind("click", function () {
132227         layoutLandscape.setAttribute("class", "layout-selected");
132228         layoutPortrait.setAttribute("class", "layout-not-selected");
132229         resizer.rotateDevice("landscape");
132230         event.trigger("OrientationChanged", ["landscape"], true);
132231     });
132232
132233     jQuery("#" + constants.COMMON.ORIENTATION_SELECT_PORTRAIT_ID).bind("click", function () {
132234         layoutLandscape.setAttribute("class", "layout-not-selected");
132235         layoutPortrait.setAttribute("class", "layout-selected");
132236         resizer.rotateDevice("portrait");
132237         event.trigger("OrientationChanged", ["portrait"], true);
132238     });
132239
132240     jQuery("#" + constants.COMMON.MENU_BUTTON).bind("click", function () {
132241         event.trigger("HardwareKey", [1]);
132242     });
132243
132244     jQuery("#" + constants.COMMON.BACK_BUTTON).bind("click", function () {
132245         event.trigger("HardwareKey", [0]);
132246     });
132247
132248     if (!layout) {
132249         layout = defaultOrientation || "portrait";
132250         layoutTypeChanged = true;
132251         resizer.changeLayoutType(layout);
132252     }
132253
132254     //Hide the orientation buttons that we don't need for this device
132255     if (!currentDevice.viewPort.landscape) {
132256         layoutLandscape.setAttribute("style", "display:none");
132257     }
132258
132259     if (!currentDevice.viewPort.portrait) {
132260         layoutPortrait.setAttribute("style", "display:none");
132261     }
132262
132263     if (layout && layout === "portrait") {
132264         layoutLandscape.setAttribute("class", "layout-not-selected");
132265         layoutPortrait.setAttribute("class", "layout-selected");
132266     }
132267     else if (layout && layout === "landscape") {
132268         layoutLandscape.setAttribute("class", "layout-selected");
132269         layoutPortrait.setAttribute("class", "layout-not-selected");
132270     }
132271
132272     if (!layoutTypeChanged) {
132273         resizer.resize(currentDevice);
132274     }
132275
132276     if (orientation === "portrait") {
132277         layoutLandscape.setAttribute("class", "layout-not-selected");
132278         layoutPortrait.setAttribute("class", "layout-selected");
132279     } else {
132280         layoutLandscape.setAttribute("class", "layout-selected");
132281         layoutPortrait.setAttribute("class", "layout-not-selected");
132282     }
132283     resizer.rotateDevice(orientation);
132284 }
132285
132286 module.exports = {
132287     initialize: _initializeLayout
132288 };
132289
132290 });
132291 define('ripple/ui/plugins/messaging', function (require, exports, module) {
132292 /*
132293  *  Copyright 2011 Research In Motion Limited.
132294  *
132295  * Licensed under the Apache License, Version 2.0 (the "License");
132296  * you may not use this file except in compliance with the License.
132297  * You may obtain a copy of the License at
132298  *
132299  * http://www.apache.org/licenses/LICENSE-2.0
132300  *
132301  * Unless required by applicable law or agreed to in writing, software
132302  * distributed under the License is distributed on an "AS IS" BASIS,
132303  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
132304  * See the License for the specific language governing permissions and
132305  * limitations under the License.
132306  */
132307 var event = require('ripple/event'),
132308     utils = require('ripple/utils'),
132309     _type = {
132310         sms: "SMS",
132311         mms: "MMS",
132312         email: "E-mail"
132313     },
132314     _filename_suffix = 0,
132315     _attachments = [];
132316
132317 function _getAttachmentFileName() {
132318     return "attach" + _filename_suffix + ".txt";
132319 }
132320
132321 module.exports = {
132322     panel: {
132323         domId: "messaging-container",
132324         collapsed: true,
132325         pane: "left",
132326         titleName: "Messaging",
132327         display: true
132328     },
132329     initialize: function () {
132330         document.getElementById("messaging-send")
132331             .addEventListener("click", function () {
132332                 var number = document.getElementById("messaging-sms-number").value,
132333                     text = document.getElementById("messaging-text").value,
132334                     type = document.getElementById("messaging-type").value,
132335                     message = {
132336                         type: type,
132337                         body: text,
132338                         from: number,
132339                         time: new Date(),
132340                         attachments: _attachments
132341                     };
132342
132343                 event.trigger("MessageReceived", [message]);
132344                 
132345                 _attachments = [];
132346 /* TODO: add back when attachment is finished
132347                 document.getElementById("messaging-attachments").innerHTML = "";
132348 */
132349                 _filename_suffix = 0;
132350             }, false);
132351
132352 /* TODO: add back when attachment is finished
132353         document.getElementById("messaging-attach")
132354             .addEventListener("click", function () {
132355                 var attachedFile, attachedFileCheckbox, attachedFileName;
132356                 if (_filename_suffix > 0)
132357                     return;
132358                 _attachments.push({filename: _getAttachmentFileName(), content: document.getElementById("messaging-attachment-content").value});
132359
132360                 attachedFile = document.getElementById("messaging-attachments").insertRow(0);
132361                 attachedFileName = attachedFile.insertCell(0);
132362                 attachedFileCheckbox = attachedFile.insertCell(1);
132363                 attachedFileName.innerHTML = _attachments[_filename_suffix].filename;
132364 //                attachedFileCheckbox.innerHTML = '<input type="checkbox" value="' + _filename_suffix + '">';
132365
132366                 document.getElementById("messaging-attachment-content").value = "";
132367                 _filename_suffix++;
132368             }, false);
132369
132370         document.getElementById("messaging-detach")
132371             .addEventListener("click", function () {
132372                 _attachments = [];
132373                 document.getElementById("messaging-attachments").innerHTML = "";
132374                 _filename_suffix = 0;
132375             }, false);
132376 */
132377         event.on("OutsideMessageReceived", function (message) {
132378             var numRecipients = 0,
132379                 i = 0,
132380                 recipients = [],
132381                 recipientsStatus = {},
132382                 strRecipients = document.getElementById("messaging-recipients").value;
132383
132384             recipientsStatus.id = message.id;
132385             recipientsStatus.msg = message.msg;
132386             for (i in message.to) {
132387                 recipientsStatus[message.to[i]] = true;
132388                 recipients.push(message.to[i]);
132389             }
132390             for (i in message.cc) {
132391                 recipientsStatus[message.cc[i]] = true;
132392                 recipients.push(message.cc[i]);
132393             }
132394             for (i in message.bcc) {
132395                 recipientsStatus[message.bcc[i]] = true;
132396                 recipients.push(message.bcc[i]);
132397             }
132398             numRecipients = recipients.length;
132399             strRecipients = recipients.join(",");
132400             event.trigger("MessageSent", [recipientsStatus]);
132401             document.getElementById("messaging-received").innerHTML = "" + numRecipients + " recipient(s)" + " delivered";
132402             document.getElementById("messaging-recipients").value = strRecipients;
132403             document.getElementById("received-message-box").value = message.body;
132404         });
132405         
132406         document.getElementById("messaging-clear")
132407             .addEventListener("click", function () {
132408                 document.getElementById("received-message-box").value = "";
132409                 document.getElementById("messaging-received").innerHTML = "";
132410             }, false);
132411         
132412         utils.forEach(_type, function (msgTypeText, msgType) {
132413             var typeNode = utils.createElement("option", {
132414                     "innerText": msgTypeText,
132415                     "value": msgType
132416                 });
132417
132418             document.getElementById("messaging-type").appendChild(typeNode);
132419         });
132420     }
132421 };
132422
132423 });
132424 define('ripple/ui/plugins/multimedia', function (require, exports, module) {
132425 /*
132426  *  Copyright 2011 Research In Motion Limited.
132427  *
132428  * Licensed under the Apache License, Version 2.0 (the "License");
132429  * you may not use this file except in compliance with the License.
132430  * You may obtain a copy of the License at
132431  *
132432  * http://www.apache.org/licenses/LICENSE-2.0
132433  *
132434  * Unless required by applicable law or agreed to in writing, software
132435  * distributed under the License is distributed on an "AS IS" BASIS,
132436  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
132437  * See the License for the specific language governing permissions and
132438  * limitations under the License.
132439  */
132440 var constants = require('ripple/constants'),
132441     event = require('ripple/event'),
132442     volumeField = document.getElementById(constants.COMMON.MULTIMEDIA_VOLUME_FIELD_ID),
132443     volume = document.getElementById(constants.COMMON.MULTIMEDIA_VOLUME_SLIDER_ID);
132444
132445 module.exports = {
132446     panel: {
132447         domId: "multimedia-container",
132448         collapsed: true,
132449         pane: "left"
132450     },
132451     initialize: function () {
132452         var volumeField = document.getElementById(constants.COMMON.MULTIMEDIA_VOLUME_FIELD_ID),
132453             volume = document.getElementById(constants.COMMON.MULTIMEDIA_VOLUME_SLIDER_ID);
132454
132455         event.on("MultimediaVolumeChanged", function (volume) {
132456             volumeField.innerText = volume > 9 ? volume : "0" + volume;
132457             if (volume.value !== volume) {
132458                 volume.value = volume;
132459             }
132460         });
132461
132462         volume.addEventListener('change', function () {
132463             event.trigger("MultimediaVolumeChanged", [this.value], true);
132464         }, false);
132465
132466         event.on("MultimediaAudioStateChanged", function updateIsAudioPlaying(state) {
132467             document.getElementById(constants.COMMON.MULTIMEDIA_AUDIO_PLAYING_FIELD_ID).innerHTML = state === constants.MULTIMEDIA.AUDIO_STATES.PLAYING;
132468         });
132469     }
132470 };
132471
132472 });
132473 define('ripple/ui/plugins/network', function (require, exports, module) {
132474 /*
132475  *  Copyright 2012 Intel Corporation
132476  *
132477  * Licensed under the Apache License, Version 2.0 (the "License");
132478  * you may not use this file except in compliance with the License.
132479  * You may obtain a copy of the License at
132480  *
132481  * http://www.apache.org/licenses/LICENSE-2.0
132482  *
132483  * Unless required by applicable law or agreed to in writing, software
132484  * distributed under the License is distributed on an "AS IS" BASIS,
132485  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
132486  * See the License for the specific language governing permissions and
132487  * limitations under the License.
132488  */
132489
132490 var db = require('ripple/db'),
132491     utils = require('ripple/utils'),
132492     event = require('ripple/event'),
132493     deviceSettings = require('ripple/deviceSettings'),
132494     btdevices = require('ripple/platform/tizen/2.0/spec/btdevices'),
132495     _NFC_TAG = "tizen1.0-nfc-tag",
132496     _NFC_PEER = "tizen1.0-nfc-peer",
132497     _NFC_OUTPUT_MESSAGE = "tizen1.0-nfc-output-message",
132498     _powered = false,
132499     _isConnected = false,
132500     _tagNDEF = {
132501         type: "GENERIC_TARGET",
132502         isSupportedNDEF: true,
132503         ndefSize: 3,
132504         ndefs: [{
132505             recordCount: 2,
132506             records: [{
132507                 tnf: 1,
132508                 type: "TypeA",
132509                 id: "ID001",
132510                 payload: "This is 1st payload"
132511             }, {
132512                 tnf: 1,
132513                 type: "TypeA",
132514                 id: "ID002",
132515                 payload: "This is 2nd payload"
132516             }]
132517         },
132518         {
132519             recordCount: 2,
132520             records: [{
132521                 tnf: 1,
132522                 type: "TypeA",
132523                 id: "ID003",
132524                 payload: "This is 1st payload"
132525             }, {
132526                 tnf: 1,
132527                 type: "TypeA",
132528                 id: "ID004",
132529                 payload: "This is 2nd payload"
132530             }]
132531         },
132532         {
132533             recordCount: 2,
132534             records: [{
132535                 tnf: 1,
132536                 type: "TypeA",
132537                 id: "ID005",
132538                 payload: "This is 1st payload"
132539             }, {
132540                 tnf: 1,
132541                 type: "TypeA",
132542                 id: "ID006",
132543                 payload: "This is 2nd payload"
132544             }]
132545         }]
132546     },
132547     _tagRaw = {
132548         type: "GENERIC_TARGET",
132549         isSupportedNDEF: false,
132550         rawData : ""
132551     },
132552     _peerNDEF = {
132553         ndef: {
132554             recordCount: 2,
132555             records: [{
132556                 tnf: 1,
132557                 type: "TypeA",
132558                 id: "ID001",
132559                 payload: "This is 1st payload"
132560             }, {
132561                 tnf: 1,
132562                 type: "TypeA",
132563                 id: "ID002",
132564                 payload: "This is 2nd payload"
132565             }]
132566         }
132567     },
132568     btNodes,
132569     _btDeviceTemplate = "",
132570     _btSimulatedDevs = {};
132571
132572 function elementEnableDisableSetting(prop) {
132573     jQuery("#nfc-attach-msg").text("\xa0");
132574     jQuery("#nfc-peer-send-msg").text("\xa0");
132575     if (prop && prop.power !== undefined && prop.power !== null) {
132576         if (!prop.power) {
132577             $("#nfc-type").removeAttr("disabled");
132578         }
132579     }
132580     if (prop && prop.connectedState !== undefined && prop.connectedState !== null) {
132581         if (prop.connectedState) {
132582             $("#nfc-type").attr("disabled", "disabled");
132583             $("#nfc-tag-type-text").text($("#nfc-tag-type option:selected").text());
132584             $("#nfc-tag-type").hide();
132585             $("#nfc-tag-type-text").show();
132586             $("#nfc-tag-NDEF-support-text").text($("#nfc-tag-NDEF-support option:selected").text());
132587             $("#nfc-tag-NDEF-support").hide();
132588             $("#nfc-tag-NDEF-support-text").show();
132589             $("#nfc-raw-data").attr("disabled", "disabled");
132590         } else {
132591             $("#nfc-type").removeAttr("disabled");
132592             $("#nfc-tag-type").show();
132593             $("#nfc-tag-type-text").hide();
132594             $("#nfc-tag-NDEF-support").show();
132595             $("#nfc-tag-NDEF-support-text").hide();
132596             $("#nfc-raw-data").removeAttr("disabled");
132597         }
132598     }
132599 }
132600
132601 function _initializeElements() {
132602     jQuery(function () {
132603         var stop = false,
132604         wifiRadio = $("#wifi-radio"),
132605         isSupportNDEF, type;
132606
132607         // initialize main menus
132608         wifiRadio.buttonset();
132609
132610         $("#cellular-radio").buttonset();
132611         $("#nfc-radio").buttonset();
132612         $("#bluetooth-radio").buttonset();
132613         $("#bearer-radio").buttonset();
132614
132615         $("#wifi-radio1").prop('checked', false);
132616         $("#wifi-radio2").prop('checked', false);
132617         if (deviceSettings.retrieve("WIFI_NETWORK.status") === true) {
132618             $("#wifi-radio1").prop('checked', true);
132619             $("#wifi-radio1-label").css({'color': '#000000'});
132620             $("#wifi-radio2-label").css({'color': '#bbbbbb'});
132621         }
132622         else {
132623             $("#wifi-radio2").prop('checked', true);
132624             $("#wifi-radio1-label").css({'color': '#bbbbbb'});
132625             $("#wifi-radio2-label").css({'color': '#222222'});
132626         }
132627         $("#wifi-radio1").button("refresh");
132628         $("#wifi-radio2").button("refresh");
132629
132630         $("#cellular-radio1").prop('checked', false);
132631         $("#cellular-radio2").prop('checked', false);
132632         if (deviceSettings.retrieve("CELLULAR_NETWORK.status") === true) {
132633             $("#cellular-radio1").prop('checked', true);
132634             $("#cellular-radio1-label").css({'color': '#000000'});
132635             $("#cellular-radio2-label").css({'color': '#bbbbbb'});
132636         }
132637         else {
132638             $("#cellular-radio2").prop('checked', true);
132639             $("#cellular-radio1-label").css({'color': '#bbbbbb'});
132640             $("#cellular-radio2-label").css({'color': '#222222'});
132641         }
132642
132643         if (deviceSettings.retrieve("CELLULAR_NETWORK.isFlightMode") === true) {
132644             $("#cellular-radio1").prop('disabled', true);
132645             $("#cellular-radio2").prop('disabled', true);
132646             $("#panel_flight_mode_notice").show();
132647         }
132648         else {
132649             $("#cellular-radio1").prop('disabled', false);
132650             $("#cellular-radio2").prop('disabled', false);
132651             $("#panel_flight_mode_notice").hide();
132652         }
132653
132654         $("#cellular-radio1").button("refresh");
132655         $("#cellular-radio2").button("refresh");
132656
132657         $("#bearer-radio2").prop('checked', true);
132658         $("#bearer-radio2").button("refresh");
132659
132660         $("#wifi-radio1").click(function () {
132661             $("#wifi-radio1-label").css({'color': '#000000'});
132662             $("#wifi-radio2-label").css({'color': '#bbbbbb'});
132663             deviceSettings.persist("WIFI_NETWORK.status", true);
132664             event.trigger("WiFiNetworkStatusChanged", [true]);
132665         });
132666
132667         $("#wifi-radio2").click(function () {
132668             $("#wifi-radio1-label").css({'color': '#bbbbbb'});
132669             $("#wifi-radio2-label").css({'color': '#222222'});
132670             deviceSettings.persist("WIFI_NETWORK.status", false);
132671             event.trigger("WiFiNetworkStatusChanged", [false]);
132672         });
132673
132674         $("#cellular-radio1").click(function () {
132675             $("#cellular-radio1-label").css({'color': '#000000'});
132676             $("#cellular-radio2-label").css({'color': '#bbbbbb'});
132677             deviceSettings.persist("CELLULAR_NETWORK.status", true);
132678             event.trigger("CellularNetworkStatusChanged", [true]);
132679         });
132680
132681         $("#cellular-radio2").click(function () {
132682             $("#cellular-radio1-label").css({'color': '#bbbbbb'});
132683             $("#cellular-radio2-label").css({'color': '#222222'});
132684             deviceSettings.persist("CELLULAR_NETWORK.status", false);
132685             event.trigger("CellularNetworkStatusChanged", [false]);
132686         });
132687
132688         $("#nfc-radio1-label").css({'color': '#bbbbbb'});
132689         $("#nfc-radio2-label").css({'color': '#222222'});
132690
132691         $("#bluetooth-radio1-label").css({'color': '#bbbbbb'});
132692         $("#bluetooth-radio2-label").css({'color': '#222222'});
132693
132694         $("#bearer-radio1-label").css({'color': '#bbbbbb'});
132695         $("#bearer-radio2-label").css({'color': '#222222'});
132696
132697         $("#nfc-radio1").click(function () {
132698             $("#nfc-radio2-label").css({'color': '#bbbbbb'});
132699             $("#nfc-radio1-label").css({'color': '#222222'});
132700             $("#nfc-main-container").show();
132701         });
132702
132703         $("#nfc-radio2").click(function () {
132704             $("#nfc-radio1-label").css({'color': '#bbbbbb'});
132705             $("#nfc-radio2-label").css({'color': '#222222'});
132706             $("#nfc-main-container").hide();
132707         });
132708
132709         $("#bluetooth-radio1").click(function () {
132710             $("#bluetooth-radio2-label").css({'color': '#bbbbbb'});
132711             $("#bluetooth-radio1-label").css({'color': '#222222'});
132712             $("#bluetooth-main-container").show();
132713         });
132714
132715         $("#bluetooth-radio2").click(function () {
132716             $("#bluetooth-radio1-label").css({'color': '#bbbbbb'});
132717             $("#bluetooth-radio2-label").css({'color': '#222222'});
132718             $("#bluetooth-main-container").hide();
132719         });
132720
132721         $("#bearer-radio1").click(function () {
132722             $("#bearer-radio2-label").css({'color': '#bbbbbb'});
132723             $("#bearer-radio1-label").css({'color': '#222222'});
132724             $("#bearer-main-container").show();
132725         });
132726
132727         $("#bearer-radio2").click(function () {
132728             $("#bearer-radio1-label").css({'color': '#bbbbbb'});
132729             $("#bearer-radio2-label").css({'color': '#222222'});
132730             $("#bearer-main-container").hide();
132731         });
132732
132733         // initialize nfc
132734         jQuery("nfc-tag-ndef-container h3").click(function (event) {
132735             if (stop) {
132736                 event.stopImmediatePropagation();
132737                 event.preventDefault();
132738                 stop = false;
132739             }
132740         });
132741         jQuery("#nfc-tag-ndef-container").accordion("destroy").accordion({
132742             header: "> div > h3",
132743             autoHeight: false
132744         });
132745         jQuery("nfc-nfcpeer h3").click(function (event) {
132746             if (stop) {
132747                 event.stopImmediatePropagation();
132748                 event.preventDefault();
132749                 stop = false;
132750             }
132751         });
132752         jQuery("#nfc-nfcpeer").accordion("destroy").accordion({
132753             header: "> div > h3",
132754             autoHeight: false
132755         });
132756         jQuery("#nfc-tag-NDEF-support").bind("change", function () {
132757             isSupportNDEF = jQuery("#nfc-tag-NDEF-support").val();
132758             if (isSupportNDEF === "Yes") {
132759                 jQuery("#nfc-tag-ndef-container").fadeIn();
132760                 jQuery("#nfc-tag-raw-container").hide();
132761             } else {
132762                 jQuery("#nfc-tag-ndef-container").hide();
132763                 jQuery("#nfc-tag-raw-container").fadeIn();
132764             }
132765         });
132766         jQuery("#nfc-type").bind("change", function () {
132767             type = jQuery("#nfc-type").val();
132768             if (type === "Tag") {
132769                 jQuery("#nfc-nfctag").fadeIn();
132770                 jQuery("#nfc-nfcpeer").hide();
132771             } else {
132772                 jQuery("#nfc-nfctag").hide();
132773                 jQuery("#nfc-nfcpeer").fadeIn();
132774             }
132775             elementEnableDisableSetting();
132776         });
132777         jQuery("#nfc-power").bind("change", function () {
132778             var status;
132779             status = jQuery("#nfc-power").val() === "On" ? true : false;
132780             if (status)
132781                 jQuery("#nfc").show();
132782             event.trigger("nfc-power-setting", [status]);
132783         });
132784         jQuery("#nfc-attach").bind("click", function () {
132785             var type, isAttached;
132786             isAttached = jQuery("#nfc-attach").children().text() === "Attach" ? true : false;
132787             jQuery("#nfc-attach-msg").text("\xa0");
132788
132789             if (!_powered && isAttached) {
132790                 jQuery("#nfc-attach-msg").text("Power:Off, attach won't work");
132791                 return;
132792             }
132793             type = jQuery("#nfc-type").val();
132794             event.trigger("nfc-attach-setting", [type, isAttached]);
132795         });
132796         jQuery("#nfc-peer-send").bind("click", function () {
132797             jQuery("#nfc-peer-send-msg").text("\xa0");
132798             if (!_isConnected) {
132799                 jQuery("#nfc-peer-send-msg").text("Disconnected. Send won't work");
132800                 return;
132801             }
132802             db.saveObject(_NFC_PEER, _peerNDEF);
132803             event.trigger("nfc-peer-sending-ndef", []);
132804         });
132805
132806         // Initialize network bearer selection
132807         $("#bearer-cellular-radio1").prop('checked', true);
132808         $("#bearer-unknown-radio2").prop('checked', true);
132809         $("#bearer-cellular-radio1").button("refresh");
132810         $("#bearer-unknown-radio2").button("refresh");
132811
132812         $("#bearer-cellular-radio2").click(function () {
132813             $("#bearer-cellular button").click();
132814         });
132815
132816         $("#bearer-unknown-radio2").click(function () {
132817             $("#bearer-unknown button").click();
132818         });
132819     });
132820 }
132821
132822 function _btRender() {
132823     var devicesHTML, btHtmlContent = "";
132824
132825     utils.forEach(_btSimulatedDevs, function (item) {
132826         var uuidsHTML = "", firstService = null;
132827
132828         utils.forEach(item.services, function (s, index) {
132829             if (!firstService) {
132830                 firstService = s;
132831             }
132832             uuidsHTML += '<option value="' + index + '">' + s.name + '</option>';
132833         });
132834
132835         devicesHTML = _btDeviceTemplate.replace(/#name/g, item.name)
132836         .replace(/#address/g, item.address)
132837         .replace(/#class-major/, item.deviceClass.majorName)
132838         .replace(/#class-minor/, item.deviceClass.minorName)
132839         .replace(/#class-service/, item.deviceClass.servicesName.join(","))
132840         .replace(/#bonded/, "No")
132841         .replace(/#trusted/, item.isTrusted ? "Yes" : "No")
132842         .replace(/#connected/, "No")
132843         .replace(/#uuids/, uuidsHTML)
132844         .replace(/#service-uuid/, firstService.uuid)
132845         .replace(/#service-protocol/, firstService.protocol)
132846         .replace(/#service-state/, firstService.state || "CLOSED")
132847         .replace(/#id/g, item.address.replace(/:/g, ""));
132848
132849         btHtmlContent += devicesHTML;
132850     });
132851
132852     $("#network-bt-box").accordion("destroy");
132853     $("#network-bt-box").html(btHtmlContent).accordion({
132854         active : false,
132855         collapsible : true,
132856         autoHeight : false
132857     });
132858 }
132859
132860 function _btRemove(index) {
132861     delete _btSimulatedDevs[index];
132862     db.saveObject("bt-simulated-devices", _btSimulatedDevs);
132863     event.trigger("bt-simulated-devices-changed", []);
132864     _btRender();
132865 }
132866
132867 function _bearerRelease(type, idBearer, evNetworkDisconnected) {
132868     if ($("#bearer-row-" + idBearer).length > 0) {
132869         $("tr[id='bearer-row-" + idBearer + "']").remove();
132870     }
132871
132872     event.trigger(evNetworkDisconnected);
132873
132874     $("#bearer-" + type + " tr:even").css("background-color", "white");
132875     $("#bearer-" + type + " tr:odd").css("background-color", "whitesmoke");
132876 }
132877
132878 module.exports = {
132879     panel: {
132880         domId: "network-container",
132881         collapsed: true,
132882         pane: "left",
132883         titleName: "Network Management",
132884         display: true
132885     },
132886     initialize: function () {
132887         _initializeElements();
132888
132889         // Events for nfc module
132890         event.on("nfc-power-changed", function (status) {
132891             _powered = status;
132892             if (_powered === true) {
132893                 $("#nfc-power").val("On");
132894             } else {
132895                 $("#nfc-power").val("Off");
132896             }
132897             elementEnableDisableSetting({power: status});
132898         });
132899         event.on("nfc-connectedState-changed", function (state) {
132900             var i, type, isSupportedNDEF, str, bytes = [];
132901             _isConnected = state;
132902             elementEnableDisableSetting({connectedState: state});
132903             type = jQuery("#nfc-type").val();
132904             if (state) {
132905                 jQuery("#nfc-attach").children().text("Detach");
132906                 jQuery("#nfc-tag-connection").text("Connected");
132907                 jQuery("#nfc-peer-connection").text("Connected");
132908                 if (type === "Tag") {
132909                     isSupportedNDEF = jQuery("#nfc-tag-NDEF-support").val() === "Yes" ? true : false;
132910                     if (isSupportedNDEF) {
132911                         _tagNDEF.type = jQuery("#nfc-tag-type").val();
132912                         db.saveObject(_NFC_TAG, _tagNDEF);
132913                     } else {
132914                         _tagRaw.type = jQuery("#nfc-tag-type").val();
132915                         str = jQuery("#nfc-raw-data").val();
132916                         for (i = 0; i < str.length; i++) {
132917                             bytes.push(str.charCodeAt(i));
132918                         }
132919                         _tagRaw.rawData = bytes;
132920                         db.saveObject(_NFC_TAG, _tagRaw);
132921                     }
132922                     event.trigger("nfc-tag-send", [true]);
132923                 } else {
132924                     event.trigger("nfc-peer-send", [true]);
132925                 }
132926             } else {
132927                 jQuery("#nfc-attach").children().text("Attach");
132928                 jQuery("#nfc-tag-connection").text("Disconnected");
132929                 jQuery("#nfc-peer-connection").text("Disconnected");
132930                 jQuery("#nfc-output").text("");
132931                 jQuery("#nfc-output-table").hide();
132932                 if (type === "Tag") {
132933                     event.trigger("nfc-tag-send", [false]);
132934                 } else {
132935                     event.trigger("nfc-peer-send", [false]);
132936                 }
132937             }
132938         });
132939         event.on("nfc-output-msg", function () {
132940             var msg;
132941             msg = db.retrieve(_NFC_OUTPUT_MESSAGE);
132942             jQuery("#nfc-output").text(msg);
132943             jQuery("#nfc-output-table").show();
132944         });
132945
132946         // Events for bluetooth module
132947         event.on("bluetoothPowerState", function (state) {
132948             if (state) {
132949                 $("#bluetooth-radio1").click();
132950             } else {
132951                 $("#bluetooth-radio2").click();
132952             }
132953         });
132954         event.on("bt-adapter-name-changed", function (name) {
132955             $("#bt-adapter-name").text(name);
132956         });
132957         event.on("bt-adapter-power-changed", function (state) {
132958             if (state) {
132959                 $("#bt-adapter-power").text("On");
132960             } else {
132961                 $("#bt-adapter-power").text("Off");
132962             }
132963         });
132964         event.on("bt-adapter-visible-changed", function (state) {
132965             if (state) {
132966                 $("#bt-adapter-visible").text("On");
132967             } else {
132968                 $("#bt-adapter-visible").text("Off");
132969             }
132970         });
132971         event.on("bt-device-bonded-changed", function (addr, isBonded) {
132972             var str = "No";
132973             if (isBonded) {
132974                 str = "Yes";
132975             }
132976             jQuery("#bonded-" + addr.replace(/:/g, "")).html(str);
132977         });
132978         event.on("bt-device-connected-changed", function (addr, isConnected) {
132979             var str = "No";
132980             if (isConnected) {
132981                 str = "Yes";
132982             }
132983             jQuery("#connected-" + addr.replace(/:/g, "")).html(str);
132984         });
132985         event.on("bt-service-state-changed", function (addr, uuid, state) {
132986             var str = "CLOSED";
132987             if (state) {
132988                 str = "OPEN";
132989             }
132990             _btSimulatedDevs[addr].services[uuid].state = str;
132991             jQuery("#service-state-" + addr.replace(/:/g, "")).html(str);
132992         });
132993         event.on("bt-service-write-msg", function (addr, uuid, data) {
132994             var msg = "", uuidNow;
132995             utils.forEach(data, function (char) {
132996                 msg += String.fromCharCode(char);
132997             });
132998             uuidNow = jQuery("#network-bt-uuid-" + addr.replace(/:/g, "")).html();
132999             if (uuidNow === uuid) {
133000                 jQuery("#service-receive-textarea-" + addr.replace(/:/g, "")).html(msg);
133001             }
133002         });
133003
133004         // Event for network bearer selection module
133005         event.on("NetworkRequest", function (networkType, domainName) {
133006             var type = networkType.toLowerCase(), name, idBearer,
133007                 evNetworkOpened       = "NO_" + networkType + "_" + domainName,
133008                 evNetworkDisconnected = "ND_" + networkType + "_" + domainName;
133009
133010             if (!$("#bearer-" + type + "-radio1").prop("checked")) {
133011                 event.trigger(evNetworkOpened, [false]);
133012                 event.trigger(evNetworkDisconnected);
133013
133014                 return;
133015             }
133016
133017             name = domainName.replace(/\./, "");
133018             idBearer = type + '-' + name;
133019
133020             if ($("#bearer-row-" + idBearer).length <= 0) {
133021                 $("#bearer-" + type).append("<tr id='bearer-row-" + idBearer + "'>" +
133022                      "<td>&nbsp<lable class='ui-text-label'>" + domainName + "</label></td>" +
133023                      "<td><button id='bearer-btn-" + idBearer + "'>X</button>&nbsp&nbsp</td>" +
133024                      "</tr>");
133025
133026                 $("#bearer-btn-" + idBearer).click(function () {
133027                     _bearerRelease(type, idBearer, evNetworkDisconnected);
133028                 });
133029
133030                 $("#bearer-" + type + " tr:even").css("background-color", "white");
133031                 $("#bearer-" + type + " tr:odd").css("background-color", "whitesmoke");
133032             }
133033
133034             event.trigger(evNetworkOpened, [true]);
133035         });
133036
133037         event.on("NetworkRelease", function (networkType, domainName) {
133038             var type = networkType.toLowerCase(),
133039                 name = domainName.replace(/\./, ""),
133040                 idBearer = type + '-' + name,
133041                 evNetworkDisconnected = "ND_" + networkType + "_" + domainName;
133042
133043             _bearerRelease(type, idBearer, evNetworkDisconnected);
133044         });
133045
133046         // Update UI for Flight Mode changing
133047         event.on("FlightModeChanged", function (value) {
133048             if (value === true) {
133049                 $("#cellular-radio1").prop('disabled', true);
133050                 $("#cellular-radio2").prop('disabled', true);
133051                 $("#panel_flight_mode_notice").show();
133052             }
133053             else {
133054                 $("#cellular-radio1").prop('disabled', false);
133055                 $("#cellular-radio2").prop('disabled', false);
133056                 $("#panel_flight_mode_notice").hide();
133057             }
133058
133059             $("#cellular-radio1").button("refresh");
133060             $("#cellular-radio2").button("refresh");
133061         });
133062
133063         $("#bt-adapter-name").text(db.retrieveObject("tizen1-db-bluetooth_adapter-name") || "Tizen BT Adapter");
133064         _btDeviceTemplate = $("#network-bt-template").html();
133065         $("#network-bt-box").empty();
133066         btNodes = jQuery("#network-bt-device-select");
133067         btNodes.html("");
133068         utils.forEach(btdevices, function (item, index) {
133069             btNodes.append(utils.createElement("option", {
133070                 "value": index,
133071                 "innerText": item.name
133072             }));
133073         });
133074
133075         jQuery("#network-bt-nearby-btn").click(function () {
133076             var index;
133077             index = jQuery("#network-bt-device-select").val();
133078             if (_btSimulatedDevs[index]) {
133079                 return;
133080             }
133081             _btSimulatedDevs[index] = btdevices[index];
133082             db.saveObject("bt-simulated-devices", _btSimulatedDevs);
133083             event.trigger("bt-simulated-devices-changed", []);
133084             _btRender();
133085         });
133086         $(".network-bt-remove-btn").live("click", function () {
133087             _btRemove(this.id);
133088         });
133089         $(".network-bt-send-btn").live("click", function () {
133090             var msg = jQuery("#service-transfer-textarea-" + this.id.replace(/:/g, "")).val(),
133091             uuid = jQuery("#network-bt-uuid-" + this.id.replace(/:/g, "")).html();
133092             event.trigger("bt-service-rawdata-received", [this.id, uuid, msg]);
133093         });
133094         $(".network-bt-service-select").live("change", function () {
133095             var uuid = this.children[this.selectedIndex].value,
133096             index = this.id,
133097             addr,
133098             service;
133099             addr = index.replace(/:/g, "");
133100             service = _btSimulatedDevs[index].services[uuid];
133101             jQuery("#network-bt-uuid-" + index.replace(/:/g, "")).html(service.uuid);
133102             jQuery("#network-bt-protocol-" + index.replace(/:/g, "")).html(service.protocol);
133103             jQuery("#service-state-" + index.replace(/:/g, "")).html(service.state || "CLOSED");
133104             jQuery("#service-transfer-textarea-" + addr).val("");
133105             jQuery("#service-receive-textarea-" + addr).html("");
133106         });
133107     }
133108 };
133109
133110 });
133111 define('ripple/ui/plugins/nfc', function (require, exports, module) {
133112 /*
133113  *  Copyright 2012 Intel Corporation
133114  *
133115  * Licensed under the Apache License, Version 2.0 (the "License");
133116  * you may not use this file except in compliance with the License.
133117  * You may obtain a copy of the License at
133118  *
133119  * http://www.apache.org/licenses/LICENSE-2.0
133120  *
133121  * Unless required by applicable law or agreed to in writing, software
133122  * distributed under the License is distributed on an "AS IS" BASIS,
133123  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
133124  * See the License for the specific language governing permissions and
133125  * limitations under the License.
133126  */
133127
133128 var db = require('ripple/db'),
133129     event = require('ripple/event'),
133130     _NFC_TAG = "tizen1.0-nfc-tag",
133131     _NFC_PEER = "tizen1.0-nfc-peer",
133132     _NFC_OUTPUT_MESSAGE = "tizen1.0-nfc-output-message",
133133     powered = false,
133134     polling = false,
133135     isConnected = false,
133136     _tagNDEF = {
133137         type: "GENERIC_TARGET",
133138         isSupportedNDEF: true,
133139         ndefSize: 2,
133140         ndefs: [{
133141             recordCount: 2,
133142             records: [{
133143                 tnf: 1,
133144                 type: "TypeA",
133145                 id: "ID001",
133146                 payload: "This is 1st payload"
133147             }, {
133148                 tnf: 1,
133149                 type: "TypeA",
133150                 id: "ID002",
133151                 payload: "This is 2nd payload"
133152             }]
133153         },
133154             {
133155             recordCount: 2,
133156             records: [{
133157                 tnf: 1,
133158                 type: "TypeA",
133159                 id: "ID001",
133160                 payload: "This is 1st payload"
133161             }, {
133162                 tnf: 1,
133163                 type: "TypeA",
133164                 id: "ID002",
133165                 payload: "This is 2nd payload"
133166             }]
133167         }]
133168     },
133169     _tagRaw = {
133170         type: "GENERIC_TARGET",
133171         isSupportedNDEF: false,
133172         rawData : ""
133173     },
133174     _peerNDEF = {
133175         ndef: {
133176             recordCount: 2,
133177             records: [{
133178                 tnf: 1,
133179                 type: "TypeA",
133180                 id: "ID001",
133181                 payload: "This is 1st payload"
133182             }, {
133183                 tnf: 1,
133184                 type: "TypeA",
133185                 id: "ID002",
133186                 payload: "This is 2nd payload"
133187             }]
133188         }
133189     };
133190
133191 function elementEnableDisableSetting(prop) {
133192     jQuery("#nfc-attach-msg").text("\xa0");
133193     jQuery("#nfc-peer-send-msg").text("\xa0");
133194     if (prop && prop.power !== undefined && prop.power !== null) {
133195         if (prop.power) {
133196             $("#nfc-polling").removeAttr("disabled");
133197             $("#nfc-main-container").show();
133198         } else {
133199             $("#nfc-polling").attr("disabled", "disabled");
133200             $("#nfc-type").removeAttr("disabled");
133201             $("#nfc-main-container").hide();
133202         }
133203     }
133204     if (prop && prop.connectedState !== undefined && prop.connectedState !== null) {
133205         if (prop.connectedState) {
133206             $("#nfc-type").attr("disabled", "disabled");
133207             $("#nfc-tag-type-text").text($("#nfc-tag-type option:selected").text());
133208             $("#nfc-tag-type").hide();
133209             $("#nfc-tag-type-text").show();
133210             $("#nfc-tag-NDEF-support-text").text($("#nfc-tag-NDEF-support option:selected").text());
133211             $("#nfc-tag-NDEF-support").hide();
133212             $("#nfc-tag-NDEF-support-text").show();
133213             $("#nfc-raw-data").attr("disabled", "disabled");
133214         } else {
133215             $("#nfc-type").removeAttr("disabled");
133216             $("#nfc-tag-type").show();
133217             $("#nfc-tag-type-text").hide();
133218             $("#nfc-tag-NDEF-support").show();
133219             $("#nfc-tag-NDEF-support-text").hide();
133220             $("#nfc-raw-data").removeAttr("disabled");
133221         }
133222     }
133223 }
133224
133225 function _initializeElements() {
133226
133227     jQuery(function () {
133228         var stop = false,
133229             isSupportNDEF, type;
133230
133231         jQuery("nfc-tag-ndef-container h3").click(function (event) {
133232             if (stop) {
133233                 event.stopImmediatePropagation();
133234                 event.preventDefault();
133235                 stop = false;
133236             }
133237         });
133238         jQuery("#nfc-tag-ndef-container").accordion("destroy").accordion({
133239             header: "> div > h3",
133240             autoHeight: false
133241         });
133242         jQuery("nfc-nfcpeer h3").click(function (event) {
133243             if (stop) {
133244                 event.stopImmediatePropagation();
133245                 event.preventDefault();
133246                 stop = false;
133247             }
133248         });
133249         jQuery("#nfc-nfcpeer").accordion("destroy").accordion({
133250             header: "> div > h3",
133251             autoHeight: false
133252         });
133253         jQuery("#nfc-tag-NDEF-support").bind("change", function () {
133254             isSupportNDEF = jQuery("#nfc-tag-NDEF-support").val();
133255             if (isSupportNDEF === "Yes") {
133256                 jQuery("#nfc-tag-ndef-container").fadeIn();
133257                 jQuery("#nfc-tag-raw-container").hide();
133258             } else {
133259                 jQuery("#nfc-tag-ndef-container").hide();
133260                 jQuery("#nfc-tag-raw-container").fadeIn();
133261             }
133262         });
133263         jQuery("#nfc-type").bind("change", function () {
133264             type = jQuery("#nfc-type").val();
133265             if (type === "Tag") {
133266                 jQuery("#nfc-nfctag").fadeIn();
133267                 jQuery("#nfc-nfcpeer").hide();
133268             } else {
133269                 jQuery("#nfc-nfctag").hide();
133270                 jQuery("#nfc-nfcpeer").fadeIn();
133271             }
133272             elementEnableDisableSetting();
133273         });
133274         jQuery("#nfc-power").bind("change", function () {
133275             var status;
133276             status = jQuery("#nfc-power").val() === "On" ? true : false;
133277             event.trigger("nfc-power-setting", [status]);
133278         });
133279         jQuery("#nfc-polling").bind("change", function () {
133280             var status;
133281             status = jQuery("#nfc-polling").val() === "On" ? true : false;
133282             event.trigger("nfc-polling-setting", [status]);
133283         });
133284         jQuery("#nfc-attach").bind("click", function () {
133285             var type, isAttached;
133286             isAttached = jQuery("#nfc-attach").children().text() === "Attach" ? true : false;
133287             jQuery("#nfc-attach-msg").text("\xa0");
133288
133289             if (!polling && isAttached) {
133290                 jQuery("#nfc-attach-msg").text("Polling:Off, attach won't work");
133291                 return;
133292             }
133293             type = jQuery("#nfc-type").val();
133294             event.trigger("nfc-attach-setting", [type, isAttached]);
133295         });
133296         jQuery("#nfc-peer-send").bind("click", function () {
133297             jQuery("#nfc-peer-send-msg").text("\xa0");
133298             if (!isConnected) {
133299                 jQuery("#nfc-peer-send-msg").text("Disconnected. Send won't work");
133300                 return;
133301             }
133302             db.saveObject(_NFC_PEER, _peerNDEF);
133303             event.trigger("nfc-peer-sending-ndef", []);
133304         });
133305     });
133306 }
133307
133308 module.exports = {
133309     panel: {
133310         domId: "nfc-container",
133311         collapsed: true,
133312         pane: "left",
133313         titleName: "NFC",
133314         display: true
133315     },
133316     initialize: function () {
133317         _initializeElements();
133318         event.on("nfc-power-changed", function (status) {
133319             powered = status;
133320             if (powered === true) {
133321                 $("#nfc-power").val("On");
133322             } else {
133323                 $("#nfc-power").val("Off");
133324             }
133325             elementEnableDisableSetting({power: status});
133326         });
133327         event.on("nfc-polling-changed", function (status) {
133328             polling = status;
133329             if (polling === true) {
133330                 $("#nfc-polling").val("On");
133331             } else {
133332                 $("#nfc-polling").val("Off");
133333             }
133334             elementEnableDisableSetting();
133335         });
133336         event.on("nfc-connectedState-changed", function (state) {
133337             var i, type, isSupportedNDEF, str, bytes = [];
133338             isConnected = state;
133339             elementEnableDisableSetting({connectedState: state});
133340             type = jQuery("#nfc-type").val();
133341             if (state) {
133342                 jQuery("#nfc-attach").children().text("Detach");
133343                 jQuery("#nfc-tag-connection").text("Connected");
133344                 jQuery("#nfc-peer-connection").text("Connected");
133345                 if (type === "Tag") {
133346                     isSupportedNDEF = jQuery("#nfc-tag-NDEF-support").val() === "Yes" ? true : false;
133347                     if (isSupportedNDEF) {
133348                         _tagNDEF.type = jQuery("#nfc-tag-type").val();
133349                         db.saveObject(_NFC_TAG, _tagNDEF);
133350                     } else {
133351                         _tagRaw.type = jQuery("#nfc-tag-type").val();
133352                         str = jQuery("#nfc-raw-data").val();
133353                         for (i = 0; i < str.length; i++) {
133354                             bytes.push(str.charCodeAt(i));
133355                         }
133356                         _tagRaw.rawData = bytes;
133357                         db.saveObject(_NFC_TAG, _tagRaw);
133358                     }
133359                     event.trigger("nfc-tag-send", [true]);
133360                 } else {
133361                     event.trigger("nfc-peer-send", [true]);
133362                 }
133363             } else {
133364                 jQuery("#nfc-attach").children().text("Attach");
133365                 jQuery("#nfc-tag-connection").text("Disconnected");
133366                 jQuery("#nfc-peer-connection").text("Disconnected");
133367                 jQuery("#nfc-output").text("");
133368                 jQuery("#nfc-output-table").hide();
133369                 if (type === "Tag") {
133370                     event.trigger("nfc-tag-send", [false]);
133371                 } else {
133372                     event.trigger("nfc-peer-send", [false]);
133373                 }
133374             }
133375         });
133376         event.on("nfc-output-msg", function () {
133377             var msg;
133378             msg = db.retrieve(_NFC_OUTPUT_MESSAGE);
133379             jQuery("#nfc-output").text(msg);
133380             jQuery("#nfc-output-table").show();
133381         });
133382     }
133383 };
133384
133385
133386 });
133387 define('ripple/ui/plugins/notifications', function (require, exports, module) {
133388 /*
133389  *  Copyright 2011 Research In Motion Limited.
133390  *
133391  * Licensed under the Apache License, Version 2.0 (the "License");
133392  * you may not use this file except in compliance with the License.
133393  * You may obtain a copy of the License at
133394  *
133395  * http://www.apache.org/licenses/LICENSE-2.0
133396  *
133397  * Unless required by applicable law or agreed to in writing, software
133398  * distributed under the License is distributed on an "AS IS" BASIS,
133399  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
133400  * See the License for the specific language governing permissions and
133401  * limitations under the License.
133402  */
133403
133404 var db = require('ripple/db'),
133405     utils = require('ripple/utils'),
133406     event = require('ripple/event'),
133407     _notificationUIStack,
133408     _notificationTemplate = "";
133409
133410 function _remove(id) {
133411     delete _notificationUIStack[id];
133412     db.saveObject("posted-notifications", _notificationUIStack);
133413     event.trigger("refreshNotificationStack", [], true);
133414     _render();
133415 }
133416
133417 function _removeAll() {
133418     _notificationUIStack = {};
133419     db.saveObject("posted-notifications", _notificationUIStack);
133420     event.trigger("refreshNotificationStack", [], true);
133421     $("#notification-box").empty();
133422     $("#notification-box").append('<div style="color:#666666;">(Empty notification.)</div>');
133423     $("#remove-all-notifications-btn").hide();
133424 }
133425
133426 function _render() {
133427     var notificationHTML = "",
133428         htmlContent = "";
133429
133430     utils.forEach(_notificationUIStack, function (item) {
133431         notificationHTML = _notificationTemplate.replace(/#id/g, item.id)
133432             .replace(/#title/g, item.title)
133433             .replace(/#content/, item.content ? item.content : "")
133434             .replace(/#type/, item.type)
133435             .replace(/#statusType/, item.statusType)
133436             .replace(/#postedTime/, item.postedTime)
133437             .replace(/#iconPath/, item.iconPath ? item.iconPath : "")
133438             .replace(/#subIconPath/, item.subIconPath ? item.subIconPath : "")
133439             .replace(/#number/, item.number ? item.number : "")
133440             .replace(/#detailInfo/, item.detailInfo ? item.detailInfo.join() : "")
133441             .replace(/#backgroundImagePath/, item.backgroundImagePath ? item.backgroundImagePath : "")
133442             .replace(/#thumbnails/, item.thumbnails ? item.thumbnails.join() : "")
133443             .replace(/#soundPath/, item.soundPath ? item.soundPath : "")
133444             .replace(/#vibration/, item.vibration !== undefined ? (item.vibration === true ? "true" : "false") : "")
133445             .replace(/#appControl/, item.appControl ? item.appControl : "")
133446             .replace(/#appId/, item.appId ? item.appId : "")
133447             .replace(/#progressType/g, item.progressType ? item.progressType: "")
133448             .replace(/#progressValue/, (item.statusType === "PROGRESS" && item.progressType === "PERCENTAGE" && item.progressValue) ? item.progressValue.toString() + "%" : "")
133449             .replace(/#progressBarValue/, (item.statusType === "PROGRESS" && item.progressType === "PERCENTAGE" && item.progressValue) ? item.progressValue : 0)
133450             .replace(/#progress2Value/, (item.statusType === "PROGRESS" && item.progressType === "BYTE" && item.progressValue) ? item.progressValue.toString() + " byte(s)" : "")
133451             .replace(/#displayBar/g, (item.statusType !== "PROGRESS" || item.progressType !== "PERCENTAGE") ? "none" : "")
133452             .replace(/#display2Bar/g, (item.statusType !== "PROGRESS" || item.progressType !== "BYTE") ? "none" : "");
133453         htmlContent += notificationHTML;
133454     });
133455
133456     $("#notification-box").accordion("destroy");
133457     $("#notification-box").html(htmlContent).accordion({
133458         active : false,
133459         collapsible : true,
133460         autoHeight : false
133461     });
133462
133463     $("#notification-box .progress-bar").each(function (index, item) {
133464         $(item).width(this.id);
133465     });
133466     if (utils.count(_notificationUIStack) !== 0) {
133467         $("#remove-all-notifications-btn").show();
133468     } else {
133469         $("#remove-all-notifications-btn").hide();
133470     }
133471     $("." + "remove-notification-btn").bind("click", function () {
133472         _remove(this.id);
133473     });
133474 }
133475
133476 module.exports = {
133477     panel: {
133478         domId: "notification-container",
133479         collapsed: true,
133480         pane: "left",
133481         titleName: "Notification",
133482         display: true
133483     },
133484     initialize: function () {
133485         _notificationTemplate = $("#notification-template").html();
133486         $("#notification-box").empty();
133487         _notificationUIStack = db.retrieveObject("posted-notifications") || {};
133488         if (utils.count(_notificationUIStack) === 0) {
133489             $("#notification-box").append('<div style="color:#666666;">(Empty notification.)</div>');
133490         }
133491         else
133492             _render();
133493         $("#remove-all-notifications-btn").bind("click", _removeAll);
133494
133495         event.on("refreshNotificationUI", function () {
133496             _notificationUIStack = db.retrieveObject("posted-notifications");
133497             _render();
133498         });
133499     }
133500 };
133501
133502 });
133503 define('ripple/ui/plugins/omnibar', function (require, exports, module) {
133504 /*
133505  *  Copyright 2011 Research In Motion Limited.
133506  *
133507  * Licensed under the Apache License, Version 2.0 (the "License");
133508  * you may not use this file except in compliance with the License.
133509  * You may obtain a copy of the License at
133510  *
133511  * http://www.apache.org/licenses/LICENSE-2.0
133512  *
133513  * Unless required by applicable law or agreed to in writing, software
133514  * distributed under the License is distributed on an "AS IS" BASIS,
133515  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
133516  * See the License for the specific language governing permissions and
133517  * limitations under the License.
133518  */
133519 var emulatorBridge = require('ripple/emulatorBridge'),
133520     db = require('ripple/db'),
133521     constants = require('ripple/constants'),
133522     _event = require('ripple/event'),
133523     tooltip = require('ripple/ui/plugins/tooltip'),
133524     histories = [];
133525
133526 function _omnibar() {
133527     return document.querySelector(".omni-bar input");
133528 }
133529
133530 function _persist(url) {
133531     db.save("current-url", url);
133532 }
133533
133534 function _persistRoot(url) {
133535     db.save("root-url", url);
133536 }
133537
133538 function _currentURL() {
133539     return db.retrieve("current-url") || "about:blank";
133540 }
133541
133542 function _rootURL() {
133543     return db.retrieve("root-url") || "about:blank";
133544 }
133545
133546 function _reload() {
133547     _event.trigger("ApplicationLoad", null);
133548     emulatorBridge.window().location.reload();
133549 }
133550
133551 function _loadApplication() {
133552     var omnibar = _omnibar(),
133553             xhr;
133554     if (omnibar.value.trim() !== "") {
133555         if (_currentURL().match(/^file:/) && omnibar.value.match(/^file:/)) { // Use ajax to know whether that file exists
133556             xhr = new XMLHttpRequest();
133557             xhr.onreadystatechange = function () {
133558                 if (xhr.readyState === 4) {
133559                     if (xhr.responseText !== '') {
133560                         _persist(omnibar.value);
133561                         _persistRoot(omnibar.value);
133562                         emulatorBridge.window().location.assign(omnibar.value);
133563                     } else {
133564                         alert("File doesn't exist!");
133565                         return;
133566                     }
133567                 }
133568             };
133569             xhr.open('GET', omnibar.value, true);
133570             xhr.send(null);
133571         } else {
133572             omnibar.value = omnibar.value.indexOf("://") < 0 ? "http://" + omnibar.value : omnibar.value;
133573             _persist(omnibar.value);
133574             _persistRoot(omnibar.value);
133575             emulatorBridge.window().location.assign(omnibar.value);
133576         }
133577         _addHistory(omnibar.value);
133578     }
133579     _event.trigger("ApplicationLoad", null);
133580 }
133581
133582 function _hideHistory() {
133583     $("#app-launching-history").hide("slide", {direction: "up"}, "fast");
133584     $("#overlayBackground-transparent").hide();
133585 }
133586
133587 function _makeHistoryItems() {
133588     histories = db.retrieveObject(constants.LAUNCHING_HISTORY);
133589     if (histories === undefined) {
133590         histories = [];
133591     }
133592     $("#app-launching-history").empty();
133593     histories.reverse();
133594     histories.forEach(function (item) {
133595         $("#app-launching-history").append('<div class="app-launching-history-item">' + item + '</div>');
133596     });
133597
133598     if (histories.length === 0) {
133599         $("#app-launching-history").append('<div class="app-launching-history-item-empty">History empty</div>');
133600     }
133601
133602     $(".app-launching-history-item").unbind('click');
133603     $(".app-launching-history-item").bind("click", function () {
133604         $(".omni-bar input").val(histories[$(this).index()]);
133605         _loadApplication();
133606         _hideHistory();
133607     });
133608 }
133609
133610
133611 function _showHistory() {
133612     _makeHistoryItems();
133613     $("#app-launching-history").css("width", $(".omni-bar input").width() + 20);
133614     $("#app-launching-history").show("slide", {direction: "up"}, "fast");
133615     $(window).bind('resize', function () {
133616         $("#app-launching-history").css("width", $(".omni-bar input").width() + 20);
133617         $("#overlayBackground-transparent").css("width", $(window).width());
133618         $("#overlayBackground-transparent").css("height", $(window).height());
133619     });
133620
133621     $("#history-background-overlay").show();
133622     $("#overlayBackground-transparent").css("width", $(window).width());
133623     $("#overlayBackground-transparent").css("height", $(window).height());
133624     $("#overlayBackground-transparent").show();
133625     $("#overlayBackground-transparent").unbind('click');
133626     $("#overlayBackground-transparent").bind("click", function () {
133627         _hideHistory();
133628     });
133629 }
133630
133631
133632 function _addHistory(uri) {
133633     var i = 0, thehistories = db.retrieveObject(constants.LAUNCHING_HISTORY);
133634     if (thehistories !== undefined) {
133635         for (i; i < thehistories.length; i++) {
133636             if (uri === thehistories[i]) {
133637                 return;
133638             }
133639         }
133640         if (thehistories.length >= 20) {
133641             thehistories.reverse();
133642             thehistories.pop();
133643             thehistories.reverse();
133644         }
133645     } else {
133646         thehistories = [];
133647     }
133648     thehistories.push(uri);
133649     db.saveObject(constants.LAUNCHING_HISTORY, thehistories);
133650 }
133651
133652 _event.on("FrameHistoryChange", function (url) {
133653     _omnibar().value = url;
133654     _persist(url);
133655     _persistRoot(url);
133656 });
133657
133658 module.exports = {
133659     initialize: function () {
133660         var omnibar = _omnibar(),
133661             position, loc, tmp,
133662             url, filename, matching,
133663             xhr;
133664
133665         jQuery(".logo, .beta, .left, .right, .left-panel-collapse, .right-panel-collapse").css({
133666             "marginTop": "35px"
133667         });
133668
133669         jQuery("#settings-xhr-proxy").parent().parent().hide();
133670
133671         $(".omni-bar").show();
133672
133673         position = document.documentURI.indexOf("?url=");
133674         if (position !== -1) {
133675             url = document.documentURI.substring(position + 5, document.documentURI.length);
133676             if (url.match(/^\.[\.]?/) !== null) {
133677                 loc = document.location;
133678                 filename = loc.pathname.replace(/^.*[\\\/]/, '');
133679                 matching = new RegExp(filename, "g");
133680                 tmp = loc.protocol + "//" + loc.hostname + loc.pathname.replace(matching, "") + url;
133681                 url = tmp;
133682             }
133683             _persist(url);
133684             _persistRoot(url);
133685             require('ripple/widgetConfig').initialize();
133686             require('ripple/ui/plugins/widgetConfig').initialize();
133687         }
133688
133689         omnibar.value = _currentURL();
133690
133691         omnibar.addEventListener("keydown", function (event) {
133692             if (event.keyCode === '13' || event.keyCode === 13 || event.keyCode === '0' || event.keyCode === 0) { // enter or return
133693                 if (omnibar.value.trim() !== "") {
133694                     if (_currentURL().match(/^file:/) && omnibar.value.match(/^file:/)) { // Use ajax to know whether that file exists
133695                         xhr = new XMLHttpRequest();
133696                         xhr.onreadystatechange = function () {
133697                             if (xhr.readyState === 4) {
133698                                 if (xhr.responseText !== '') {
133699                                     _persist(omnibar.value);
133700                                     _persistRoot(omnibar.value);
133701                                     emulatorBridge.window().location.assign(omnibar.value);
133702                                 } else {
133703                                     alert("File doesn't exist!");
133704                                     return;
133705                                 }
133706                             }
133707                         };
133708                         xhr.open('GET', omnibar.value, true);
133709                         xhr.send(null);
133710                     } else {
133711                         //default the protocal if not provided
133712                         omnibar.value = omnibar.value.indexOf("://") < 0 ? "http://" + omnibar.value : omnibar.value;
133713                         _persist(omnibar.value);
133714                         _persistRoot(omnibar.value);
133715                         emulatorBridge.window().location.assign(omnibar.value);
133716                     }
133717                     _event.trigger("ApplicationLoad", null);
133718                     _addHistory(omnibar.value);
133719                 }
133720             }
133721         });
133722
133723         window.addEventListener("keydown", function (event) {
133724             var hasMetaOrAltPressed = (event.metaKey || event.ctrlKey),
133725                 key = parseInt(event.keyCode, 10);
133726
133727             if (key === 82 && hasMetaOrAltPressed) { // cmd/ctrl + r
133728                 event.preventDefault();
133729                 _reload();
133730             }
133731
133732             if (key === 116) { // F5
133733                 event.preventDefault();
133734                 _reload();
133735             }
133736         });
133737
133738         document.getElementById("history-reload").addEventListener("click", _reload);
133739         $("#options-button-history").bind("click", function () {
133740             _showHistory();
133741         });
133742         tooltip.create("#history-reload", "Reload Application");
133743         tooltip.create("#options-button-history", "History");
133744         tooltip.create("#options-button-config-window", "Configuration");
133745         tooltip.create("#options-button-panels", "Panel Settings");
133746         tooltip.create("#options-button-about", "About");
133747     },
133748     currentURL: function () {
133749         return _currentURL();
133750     },
133751     rootURL: function () {
133752         return _rootURL();
133753     }
133754 };
133755
133756 });
133757 define('ripple/ui/plugins/options', function (require, exports, module) {
133758 /*
133759  *  Copyright 2011 Research In Motion Limited.
133760  *
133761  * Licensed under the Apache License, Version 2.0 (the "License");
133762  * you may not use this file except in compliance with the License.
133763  * You may obtain a copy of the License at
133764  *
133765  * http://www.apache.org/licenses/LICENSE-2.0
133766  *
133767  * Unless required by applicable law or agreed to in writing, software
133768  * distributed under the License is distributed on an "AS IS" BASIS,
133769  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
133770  * See the License for the specific language governing permissions and
133771  * limitations under the License.
133772  */
133773 var about = require('ripple/ui/plugins/about-dialog'),
133774     settings = require('ripple/ui/plugins/settings-dialog'),
133775     tooltip = require('ripple/ui/plugins/tooltip'),
133776     hide,
133777     show;
133778
133779 show = function () {
133780     if (settings.value("remoteInspector")) {
133781         $("#options-menu-build-warning").show();
133782         tooltip.create("#options-menu-build-warning", "Remote Web Inspector should be disabled when packaging for App World release");
133783     }
133784     else {
133785         $("#options-menu-build-warning").hide();
133786     }
133787
133788     $("#options-window").show();
133789     $("#options-menu").show();
133790 };
133791
133792 hide = function () {
133793     $("#options-window").hide();
133794     $("#options-menu").effect("fade", {}, 300);
133795 };
133796
133797 module.exports = {
133798     initialize: function () {
133799         $("#options-menu").menu().hide();
133800         $("#options-menu").bind("click", function (event) {
133801             var target = $("#" + event.target.parentElement.id),
133802                 action;
133803
133804             if (target.hasClass("not-ready")) {
133805                 return;
133806             }
133807
133808             switch (target.attr("id")) {
133809             case "options-menu-build":
133810             case "options-menu-launch":
133811             case "options-menu-sign":
133812                 action = target.attr("id").split("-")[2];
133813                 if (!settings.can(action)) {
133814                     settings.show(action);
133815                 }
133816                 else {
133817                     settings.perform(action);
133818                 }
133819                 break;
133820             case "options-menu-about":
133821                 about.show();
133822                 break;
133823             case "options-menu-settings":
133824                 settings.show();
133825                 break;
133826             default:
133827                 break;
133828             }
133829             hide();
133830         });
133831
133832         $("#options-window").click(hide);
133833         
133834         $("#options-button-about").bind("click", function (event) {
133835             about.show();
133836         });
133837         
133838         hide();
133839     }
133840 };
133841
133842 });
133843 define('ripple/ui/plugins/package', function (require, exports, module) {
133844 /*
133845  *  Copyright 2011 Research In Motion Limited.
133846  *
133847  * Licensed under the Apache License, Version 2.0 (the "License");
133848  * you may not use this file except in compliance with the License.
133849  * You may obtain a copy of the License at
133850  *
133851  * http://www.apache.org/licenses/LICENSE-2.0
133852  *
133853  * Unless required by applicable law or agreed to in writing, software
133854  * distributed under the License is distributed on an "AS IS" BASIS,
133855  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
133856  * See the License for the specific language governing permissions and
133857  * limitations under the License.
133858  */
133859
133860 var db = require('ripple/db'),
133861     utils = require('ripple/utils'),
133862     event = require('ripple/event'),
133863     PackageInformation = require('ripple/platform/tizen/2.0/PackageInformation'),
133864     DB_PACKAGE_KEY = "tizen-db-package",
133865     _data = {
133866         packageList: {},
133867         installedList: {}
133868     },
133869     _packages = {
133870         "/opt/usr/media/test.wgt": {id: "TEST_APP_ID", name: "Test Package", iconPath: "test.png", version: "2.1",
133871             totalSize: 9216, dataSize: 124, author: "Tizen.org", description: "This is testing package",
133872             appIds: ["http://tizen.org/viewer", "http://tizen.org/player"]},
133873         "/opt/usr/media/example.wgt": {id: "EXAMPLE_ID", name: "Example Package", iconPath: "example.png", version: "2.3",
133874             totalSize: 10240, dataSize: 384, author: "Tizen.org", description: "This is example package",
133875             appIds: ["http://tizen.org/dummy"]},
133876         "/opt/usr/media/sample.wgt": {id: "SAMPLE_ID", name: "Sample Package", iconPath: "sample.png", version: "1.9",
133877             totalSize: 8264, dataSize: 50, author: "Tizen.org", description: "This is sample package",
133878             appIds: ["http://tizen.org/dialer", "http://tizen.org/sender"]},
133879         "/opt/usr/media/api1pack00.wgt": {
133880             id: "api1pack00", name: "tct-package-tizen-tests",
133881             iconPath: "tizen.png", version: "1.9",
133882             totalSize: 8264, dataSize: 50, author: "TizenDev",
133883             description: "This is a description which is used in tests.",
133884             appIds: ["api1pack00.WebAPITizenPackageTests"]},
133885         "/opt/usr/media/testpack00.wgt": {
133886             id: "testpack00", name: "autoWebapiTizenPackageTestApplication",
133887             iconPath: "tizen.png", version: "5.5.5",
133888             totalSize: 8264, dataSize: 50, author: "TizenDev",
133889             description: "This is a description which is used in tests.",
133890             appIds: ["testpack00.autoWebapiTizenPackageTestApplication"]}
133891     },
133892     _installedList = {
133893         "SAMPLE_ID": { id: "SAMPLE_ID", name: "Sample Package", iconPath: "sample.png", version: "1.9",
133894             totalSize: 8264, dataSize: 50, lastModified: new Date(), author: "Tizen.org", description: "This is sample package",
133895             appIds: ["http://tizen.org/dialer", "http://tizen.org/sender"]
133896         },
133897         "api1pack00": {id: "api1pack00", name: "tct-package-tizen-tests",
133898             iconPath: "tizen.png", version: "1.9",
133899             totalSize: 8264, dataSize: 50, lastModified: new Date(),
133900             author: "TizenDev",
133901             description: "This is a description which is used in tests.",
133902             appIds: ["api1pack00.WebAPITizenPackageTests"]
133903         },
133904         "testpack00": {id: "testpack00", name: "autoWebapiTizenPackageTestApplication",
133905             iconPath: "tizen.png", version: "5.5.5",
133906             totalSize: 8264, dataSize: 50, lastModified: new Date(),
133907             author: "TizenDev",
133908             description: "This is a description which is used in tests.",
133909             appIds: ["testpack00.autoWebapiTizenPackageTestApplication"]
133910         }
133911
133912     },
133913     _packageListTemplate,
133914     _packageInstalledTemplate;
133915
133916 function _get() {
133917     _data = db.retrieveObject(DB_PACKAGE_KEY);
133918     if (_data === undefined) {
133919         _data = {
133920             packageList: _packages,
133921             installedList: _installedList
133922         };
133923         _save();
133924     }
133925     utils.forEach(_data.installedList, function (item) {
133926         item.lastModified = new Date(item.lastModified);
133927     });
133928
133929 }
133930
133931 function _save() {
133932     db.saveObject(DB_PACKAGE_KEY, _data);
133933 }
133934
133935 function loadPackageList() {
133936     var nodes = jQuery("#package-list-select");
133937     nodes.html("");
133938     utils.forEach(_data.packageList, function (item, index) {
133939         nodes.append(utils.createElement("option", {
133940             "value": index,
133941             "innerText": item.name
133942         }));
133943     });
133944     renderPackageListBox($("#package-list-select option:selected").val());
133945 }
133946
133947 function loadInstalledList() {
133948     var html = "";
133949     jQuery("#package-installed-box").empty();
133950     utils.forEach(_data.installedList, function (item) {
133951         html += _packageInstalledTemplate.replace(/#Name/g, item.name)
133952             .replace(/#ID/g, item.id)
133953             .replace(/#IconPath/, item.iconPath)
133954             .replace(/#Version/, item.version)
133955             .replace(/#TotalSize/, item.totalSize)
133956             .replace(/#DataSize/, item.dataSize)
133957             .replace(/#LastModified/, item.lastModified)
133958             .replace(/#Author/, item.author)
133959             .replace(/#Description/, item.description)
133960             .replace(/#APPIDs/, item.appIds.join("<br>"));
133961     });
133962     $("#package-installed-box").accordion("destroy");
133963     $("#package-installed-box").html(html).accordion({
133964         active : false,
133965         collapsible : true,
133966         autoHeight : false
133967     });
133968     $("." + "package-remove-btn").bind("click", function () {
133969         var id = this.id;
133970         utils.forEach(_data.packageList, function (item) {
133971             if (item.id === id) {
133972                 event.trigger("remove-apps", [item.appIds]);
133973             }
133974         });
133975         delete _data.installedList[this.id];
133976         _save();
133977         loadPackageList();
133978         loadInstalledList();
133979         event.trigger("uninstall-package", [this.id]);
133980     });
133981 }
133982
133983 function renderPackageListBox(path) {
133984     var item, html;
133985     jQuery("#package-list-box").empty();
133986     item = _data.packageList[path];
133987     html = _packageListTemplate.replace(/#Path/, path)
133988         .replace(/#ID/, item.id)
133989         .replace(/#Name/, item.name)
133990         .replace(/#IconPath/, item.iconPath)
133991         .replace(/#Version/, item.version)
133992         .replace(/#TotalSize/, item.totalSize)
133993         .replace(/#DataSize/, item.dataSize)
133994         .replace(/#Author/, item.author)
133995         .replace(/#Description/, item.description)
133996         .replace(/#APPList/, item.appIds.join("<br>"));
133997     jQuery("#package-list-box").html(html);
133998     if (_data.installedList[item.id]) {
133999         jQuery("#package-update-btn").show();
134000     } else {
134001         jQuery("#package-install-btn").show();
134002     }
134003 }
134004
134005 function addPackage(path, type) {
134006     var item;
134007     if (!_data.packageList[path]) {
134008         return;
134009     }
134010     item = _data.packageList[path];
134011     _data.installedList[item.id] = new PackageInformation(
134012         item.id, item.name, item.iconPath, item.version,
134013         item.totalSize, item.dataSize, new Date(),
134014         item.author, item.description, item.appIds
134015     );
134016     if (type === "install") {
134017         event.trigger("install-apps", [item.appIds]);
134018     } else {
134019         event.trigger("update-apps", [item.appIds]);
134020     }
134021     _save();
134022 }
134023
134024 module.exports = {
134025     panel: {
134026         domId: "package-container",
134027         collapsed: true,
134028         pane: "left",
134029         titleName: "Packages and Applications",
134030         display: true
134031     },
134032     initialize: function () {
134033         _packageListTemplate = jQuery("#package-list-template").html();
134034         _packageInstalledTemplate = jQuery("#package-installed-template").html();
134035
134036         _get();
134037         loadPackageList();
134038         loadInstalledList();
134039         jQuery("#package-list-select").bind("focus change", function () {
134040             var path = $("#package-list-select option:selected").val();
134041             renderPackageListBox(path);
134042         });
134043         jQuery("#package-install-btn").live("click", function () {
134044             var path = $("#package-list-select option:selected").val();
134045             addPackage(path, "install");
134046             _get();
134047             loadPackageList();
134048             loadInstalledList();
134049             event.trigger("install-packge", [path]);
134050         });
134051         jQuery("#package-update-btn").live("click", function () {
134052             var path = $("#package-list-select option:selected").val();
134053             addPackage(path, "update");
134054             loadPackageList();
134055             loadInstalledList();
134056             event.trigger("update-package", [path]);
134057         });
134058         jQuery("#package-select").tabs();
134059         event.on("installedList-updated", function () {
134060             _get();
134061             loadPackageList();
134062             loadInstalledList();
134063         });
134064     }
134065 };
134066
134067 });
134068 define('ripple/ui/plugins/panelCollapse', function (require, exports, module) {
134069 /*
134070  *  Copyright 2011 Research In Motion Limited.
134071  *
134072  * Licensed under the Apache License, Version 2.0 (the "License");
134073  * you may not use this file except in compliance with the License.
134074  * You may obtain a copy of the License at
134075  *
134076  * http://www.apache.org/licenses/LICENSE-2.0
134077  *
134078  * Unless required by applicable law or agreed to in writing, software
134079  * distributed under the License is distributed on an "AS IS" BASIS,
134080  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
134081  * See the License for the specific language governing permissions and
134082  * limitations under the License.
134083  */
134084 // TODO: could use a bit of refactoring sugar
134085 var db = require('ripple/db'),
134086     constants = require('ripple/constants'),
134087     _LEFT_PANEL_COLLAPSE = ".left-panel-collapse",
134088     _RIGHT_PANEL_COLLAPSE = ".right-panel-collapse",
134089     _LEFT_PANEL = ".left",
134090     _RIGHT_PANEL = ".right",
134091     _SAVE_KEY = "panel-collapsed",
134092     platform = require('ripple/platform'),
134093     devices = require('ripple/devices'),
134094     _leftEngaged, _rightEngaged, _store;
134095
134096
134097 $(function () { 
134098     $(window).resize(function () {
134099         var windowHeight = $(window).height();
134100         jQuery(".PanelCollapseBar").css("top", windowHeight - 56);
134101         jQuery("#left_div").css("height", $(window).height() - 21);
134102         if (_store["left"] === true) {
134103             jQuery("#middle_div").css("width", $(window).width());
134104         } else {
134105             jQuery("#middle_div").css("width", $(window).width());
134106         }
134107     });
134108 });
134109
134110
134111 function _persist() {
134112     db.saveObject(_SAVE_KEY, _store);
134113 }
134114
134115
134116 function updateZoomingValues(value, origin) {
134117     var scaleFactor = value / 100, scaleString;
134118     scaleString = "scale(" + scaleFactor + ")";
134119     jQuery('#device-layout').css('-webkit-transform', scaleString);
134120     if (origin === "center") {
134121         jQuery('#device-layout').css('-webkit-transform-origin', 'center top');
134122     } else {
134123         jQuery('#device-layout').css('-webkit-transform-origin', 'left top');
134124     }
134125 }
134126
134127
134128 function _process(collapseNode, panelNode, side, callback) {
134129     var jNode = collapseNode.children("span"),
134130         jPanelNode = jQuery(panelNode),
134131         properties = {},
134132         collapseProperties = {},
134133         options = {
134134             duration: 600,
134135             complete: callback
134136         },
134137         oldIcon, newIcon,
134138         zoomingValue =  db.retrieve(constants.ENCAPSULATOR.ZOOMING);
134139
134140     if (_store[side] === true) {
134141         _store[side] = false;
134142         
134143         if (side === "left") {
134144             jQuery('#left_div').show("fast");
134145             collapseNode.removeClass("PanelCollapseBarCollapsed");
134146             collapseNode.addClass("PanelCollapseBar");
134147             collapseNode.children().remove();
134148             collapseNode.append('<img src="images/sideCollapseIconLeftSide.png" style="margin-left:330px; margin-top: 6px;"/>');
134149             collapseNode.css("top", $(window).height() - 56);
134150             collapseNode.css("left", 0);
134151             jQuery("#middle_div").css("width", $(window).width());
134152             updateZoomingValues(zoomingValue, "left");
134153         }
134154         oldIcon = (side === "left" ? "ui-icon-arrowthick-1-e" : "ui-icon-arrowthick-1-w");
134155         newIcon = (side === "left" ? "ui-icon-arrowthick-1-w" : "ui-icon-arrowthick-1-e");
134156
134157         properties[side] = "0px";
134158         collapseProperties[side] = "345px";
134159         properties.opacity = "1";
134160
134161         if (jQuery("#device-layout").position().left < 290 ) {
134162             jQuery("#device-layout").animate({left: "350px"}, 200 );
134163         }
134164     } else {
134165         _store[side] = true;
134166         
134167         if (side === "left") {
134168             collapseNode.removeClass("PanelCollapseBar");
134169             collapseNode.addClass("PanelCollapseBarCollapsed");
134170             collapseNode.children().remove();
134171             collapseNode.append('<img src="images/sideCollapseIconRightSide.png" style="position: absolute; margin-left:5px; margin-top:48%;"/>');
134172             collapseNode.css("top", 10);
134173             collapseNode.css("left", 0);
134174             collapseNode.css("margin-left", 0);
134175             jQuery('#left_div').hide("slow");
134176             jQuery("#middle_div").css("width", $(window).width());
134177             updateZoomingValues(zoomingValue, "left");
134178         }
134179
134180         oldIcon = (side === "left" ? "ui-icon-arrowthick-1-w" : "ui-icon-arrowthick-1-e");
134181         newIcon = (side === "left" ? "ui-icon-arrowthick-1-e" : "ui-icon-arrowthick-1-w");
134182
134183         properties[side] = "-340px";
134184         collapseProperties[side] = "5px";
134185         properties.opacity = "0.1";
134186     }
134187
134188     jNode.removeClass(oldIcon).addClass(newIcon);
134189
134190     jPanelNode.animate(properties, options);
134191     _persist();
134192 }
134193
134194 module.exports = {
134195     initialize: function () {
134196         var rightCollapseNode = jQuery(_RIGHT_PANEL_COLLAPSE),
134197             leftCollapseNode = jQuery(_LEFT_PANEL_COLLAPSE),
134198             device = devices.getCurrentDevice(),
134199             zoomingValue =  db.retrieve(constants.ENCAPSULATOR.ZOOMING),
134200             deviceNode = jQuery("#device-layout");
134201            
134202         _store = db.retrieveObject(_SAVE_KEY) || {
134203             left: false,
134204             right: false
134205         };
134206
134207         jQuery("#left_div").css("height", $(window).height() - 21);
134208         jQuery("#middle_div").css("width", $(window).width());
134209
134210         jQuery("#device-container").bind("mousedown", function () {
134211             jQuery("#device-maskmask").show();
134212         });
134213
134214         jQuery("#device-container").bind("mouseup", function () {
134215             jQuery("#device-maskmask").hide();
134216         });
134217
134218         jQuery("#deviceTitleBar").bind("mousedown", function () {
134219             jQuery("#device-maskmask").show();
134220         });
134221
134222         jQuery("#deviceTitleBar").bind("mouseup", function () {
134223             jQuery("#device-maskmask").hide();
134224         });
134225
134226         deviceNode.draggable({ cursor: 'move', handle: "#deviceTitleBar", containment: [0, 52, 1280, 800]});
134227         jQuery("#deviceTitle").text(device.name);
134228         if (_store.left === true) {
134229             jQuery(_LEFT_PANEL).css({
134230                 left: "-340px",
134231                 opacity: "0.1"
134232             });
134233
134234             leftCollapseNode.removeClass("PanelCollapseBar");
134235             leftCollapseNode.addClass("PanelCollapseBarCollapsed");
134236             leftCollapseNode.children().remove();
134237             leftCollapseNode.append('<img src="images/sideCollapseIconRightSide.png" style="position: absolute; margin-left:5px; margin-top:48%;"/>');
134238             leftCollapseNode.css("top", 10);
134239             leftCollapseNode.css("left", 0);
134240             leftCollapseNode.css("margin-left", 0);
134241             jQuery('#left_div').hide();
134242             jQuery("#device-layout").css("left", "21px");
134243             updateZoomingValues(zoomingValue, "left");
134244         } else {
134245             jQuery('#left_div').show("fast");
134246             leftCollapseNode.removeClass("PanelCollapseBarCollapsed");
134247             leftCollapseNode.addClass("PanelCollapseBar");
134248             leftCollapseNode.children().remove();
134249             leftCollapseNode.append('<img src="images/sideCollapseIconLeftSide.png" style="margin-left:330px; margin-top: 6px;"/>');
134250             leftCollapseNode.css("top", $(window).height() - 56);
134251             leftCollapseNode.css("left", 0);
134252             jQuery("#device-layout").css("left", "350px");
134253             updateZoomingValues(zoomingValue, "left");
134254         }   
134255
134256         if (_store.right === true) {
134257             jQuery(_RIGHT_PANEL).css({
134258                 right: "-340px",
134259                 opacity: "0.1"
134260             });
134261
134262             rightCollapseNode.css({
134263                 right: "5px"
134264             }).children("span").removeClass("ui-icon-arrowthick-1-e").addClass("ui-icon-arrowthick-1-w");
134265         }
134266
134267         leftCollapseNode.bind("click", function () {
134268             if (!_leftEngaged) {
134269                 _leftEngaged = true;
134270                 _process(leftCollapseNode, _LEFT_PANEL, "left", function () {
134271                     _leftEngaged = false;
134272                 });
134273             }
134274         });
134275
134276         rightCollapseNode.bind("click", function () {
134277             if (!_rightEngaged) {
134278                 _rightEngaged = true;
134279                 _process(rightCollapseNode, _RIGHT_PANEL, "right", function () {
134280                     _rightEngaged = false;
134281                 });
134282             }
134283         });
134284     }
134285 };
134286
134287 });
134288 define('ripple/ui/plugins/phone', function (require, exports, module) {
134289 /*
134290  *  Copyright 2011 Research In Motion Limited.
134291  *
134292  * Licensed under the Apache License, Version 2.0 (the "License");
134293  * you may not use this file except in compliance with the License.
134294  * You may obtain a copy of the License at
134295  *
134296  * http://www.apache.org/licenses/LICENSE-2.0
134297  *
134298  * Unless required by applicable law or agreed to in writing, software
134299  * distributed under the License is distributed on an "AS IS" BASIS,
134300  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
134301  * See the License for the specific language governing permissions and
134302  * limitations under the License.
134303  */
134304 var utils = require('ripple/utils'),
134305     Phone = require('ripple/platform/webworks.handset/2.0.0/client/Phone'),
134306     CallLog = require('ripple/platform/webworks.handset/2.0.0/client/CallLog'),
134307     event = require('ripple/event'),
134308     _console = require('ripple/console'),
134309     eventSelect = document.getElementById("phone-event-types"),
134310     eventErrorContainer = document.getElementById("phone-event-error-container"),
134311     eventErrorSelect = document.getElementById("phone-event-error-types");
134312
134313 function _firePhoneLogEvents(type, number, error) {
134314     if (type === Phone.CB_CALL_INITIATED ||
134315         type === Phone.CB_CALL_ANSWERED) {
134316         event.trigger("PhoneCallLogAdded", [{
134317             date: new Date(),
134318             number: number,
134319             status: CallLog.STATUS_NORMAL,
134320             type: CallLog.TYPE_RECEIVED_CALL
134321         }], true);
134322     } else if (type === Phone.CB_CALL_ENDED_BYUSER ||
134323                 type === Phone.CB_CALL_FAILED) {
134324         event.trigger("PhoneCallLogAdded", [{
134325             date: new Date(),
134326             number: number,
134327             status: CallLog.STATUS_NORMAL,
134328             type: CallLog.TYPE_PLACED_CALL
134329         }], true);
134330     }
134331 }
134332
134333 function _updateActiveCalls(type, number, error) {
134334     if (type === Phone.CB_CALL_INITIATED ||
134335         type === Phone.CB_CALL_CONNECTED ||
134336         type === Phone.CB_CALL_CONFERENCECALL_ESTABLISHED ||
134337         type === Phone.CB_CALL_DIRECTCONNECT_CONNECTED ||
134338         type === Phone.CB_CALL_ANSWERED) {
134339         event.trigger("PhoneCallInitiated", [{
134340             id: number,
134341             onhold: false,
134342             outgoing: false,
134343             recipient: {
134344                 name: "",
134345                 number: String(number)
134346             }
134347         }], true);
134348     } else if (type === Phone.CB_CALL_ENDED_BYUSER ||
134349                 type === Phone.CB_CALL_FAILED ||
134350                 type === Phone.CB_CALL_DISCONNECTED ||
134351                 type === Phone.CB_CONFERENCECALL_DISCONNECTED ||
134352                 type === Phone.CB_CALL_DIRECTCONNECT_DISCONNECTED) {
134353         event.trigger("PhoneCallEnded", [{
134354             id: number
134355         }], true);
134356     }
134357 }
134358
134359 module.exports = {
134360     panel: {
134361         domId: "phone-container",
134362         collapsed: true,
134363         pane: "right"
134364     },
134365     initialize: function (prev, baton) {
134366         utils.forEach(Phone, function (value, prop) {
134367             if (prop.match(/^CB_/)) {
134368                 eventSelect.appendChild(utils.createElement("option", {
134369                     value: value,
134370                     innerHTML: prop.replace(/^CB_(CALL_)?/, "")
134371                 }));
134372             }
134373
134374             if (prop.match(/^CALL_ERROR_/)) {
134375                 eventErrorSelect.appendChild(utils.createElement("option", {
134376                     value: value,
134377                     innerHTML: prop.replace(/^CALL_ERROR_/, "")
134378                 }));
134379             }
134380         });
134381
134382         document.getElementById("phone-event-types").addEventListener("change", function () {
134383             eventErrorContainer.setAttribute("style", parseInt(eventSelect.value, 10) === Phone.CB_CALL_FAILED ? "" : "display: none");
134384         });
134385
134386         document.getElementById("phone-logs-clear").addEventListener("click", function () {
134387             event.trigger("PhoneCallLogReset");
134388         });
134389
134390         document.getElementById("phone-event-send").addEventListener("click", function () {
134391             var type = parseInt(eventSelect.value, 10),
134392                 error = type === Phone.CB_CALL_FAILED ? eventErrorSelect.value : undefined,
134393                 callId = document.getElementById("phone-call-id").value;
134394
134395             _firePhoneLogEvents(type, callId, error);
134396             _updateActiveCalls(type, callId, error);
134397
134398             event.trigger("PhoneEvent", [type, callId, error]);
134399
134400             _console.log("Fired PhoneEvent (type " + type +  ") CallID: " +
134401                          callId + (error ? (" (error type " + error + ")") : ""));
134402         }, false);
134403     }
134404 };
134405
134406 });
134407 define('ripple/ui/plugins/platform', function (require, exports, module) {
134408 /*
134409  *  Copyright 2011 Research In Motion Limited.
134410  *
134411  * Licensed under the Apache License, Version 2.0 (the "License");
134412  * you may not use this file except in compliance with the License.
134413  * You may obtain a copy of the License at
134414  *
134415  * http://www.apache.org/licenses/LICENSE-2.0
134416  *
134417  * Unless required by applicable law or agreed to in writing, software
134418  * distributed under the License is distributed on an "AS IS" BASIS,
134419  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
134420  * See the License for the specific language governing permissions and
134421  * limitations under the License.
134422  */
134423 var constants = require('ripple/constants'),
134424     utils = require('ripple/utils'),
134425     devices = require('ripple/devices'),
134426     platform = require('ripple/platform'),
134427     db = require('ripple/db');
134428
134429 function _updatePlatformDeviceSelect(platformID, currentDeviceKey) {
134430     var devicesSelect = document.getElementById(constants.COMMON.DEVICE_SELECT_ID),
134431         listOfSortedDevices = devices.getDevicesForPlatform(platformID)
134432                                         .sort(function (a, b) {
134433                                             return (a.screen.width * a.screen.height) < (b.screen.width * b.screen.height) ? -1 : ((a.screen.width * a.screen.height) > (b.screen.width * b.screen.height) ? 1 : 0);
134434                                         });
134435     db.remove("viewport_width");
134436     db.remove("viewport_height");
134437     db.remove("viewportTag");
134438
134439     devicesSelect.innerHTML = "";
134440     listOfSortedDevices.forEach(function (dev) {
134441         var deviceNode = utils.createElement("option", {
134442             "innerText": dev.name,
134443             "value": dev.id
134444         });
134445
134446         if (currentDeviceKey && deviceNode.value === currentDeviceKey) {
134447             deviceNode.selected = true;
134448         }
134449
134450         devicesSelect.appendChild(deviceNode);
134451     });
134452 }
134453
134454 function checkResolutionSize(evt) {
134455         var query_str, id_str, len;
134456         query_str = "#resolution-custom-" + evt.data.msg;
134457         id_str = "custom_" + evt.data.msg;
134458         len = jQuery(query_str).val();
134459         if (len >= 200 && len <= 2000) {
134460                 db.save(id_str, len);
134461         } else {
134462                 jQuery(query_str).val(db.retrieve(id_str));
134463         }
134464 }
134465
134466 module.exports = {
134467     initialize: function () {
134468         var currentPlatform = platform.current().id,
134469             currentVersion = platform.current().version,
134470             platformList = platform.getList(),
134471             platformSelect = document.getElementById(constants.COMMON.PLATFORM_SELECT_ID),
134472             versionSelect = document.getElementById("version-select"),
134473             currentDeviceKey = devices.getCurrentDevice().id,
134474             platformNode, versionNode;
134475
134476         jQuery("#platform-select").bind("change", function () {
134477             var newPlatform = jQuery(this).val(),
134478                 newDevice = jQuery("#device-select").val();
134479
134480             jQuery(versionSelect).children("option").remove();
134481             utils.forEach(platformList, function (platform) {
134482                 utils.forEach(platform, function (version, versionNumber) {
134483                     if (newPlatform === version.id) {
134484                         versionSelect.appendChild(utils.createElement("option", {
134485                             "innerText": version.text,
134486                             "value":  versionNumber
134487                         }));
134488                     }
134489                 });
134490             });
134491             _updatePlatformDeviceSelect(newPlatform, newDevice);
134492
134493         });
134494
134495         jQuery("#device-select").bind("focus", function () {
134496             $('input:radio[name="resolution-type"][value="predefined"]').click();
134497         });
134498         jQuery("#resolution-custom-width").bind("focus", function () {
134499             $('input:radio[name="resolution-type"][value="custom"]').click();
134500         });
134501         jQuery("#resolution-custom-height").bind("focus", function () {
134502             $('input:radio[name="resolution-type"][value="custom"]').click();
134503         });
134504         jQuery("#resolution-custom-width").bind("change", {msg: "width"}, checkResolutionSize);
134505         jQuery("#resolution-custom-height").bind("change", {msg: "height"}, checkResolutionSize);
134506
134507         utils.forEach(platformList, function (platform, platformKey) {
134508             platformNode = utils.createElement("option", {
134509                 "innerText": platformKey,
134510                 "value":  platformKey
134511             });
134512
134513             utils.forEach(platform, function (version, versionNumber) {
134514                 versionNode = utils.createElement("option", {
134515                     "innerText": version.text,
134516                     "value":  versionNumber
134517                 });
134518
134519                 if (currentPlatform && version.id === currentPlatform) {
134520                     if (currentVersion && currentVersion === versionNumber) {
134521                         platformNode.selected = true;
134522                         versionNode.selected = true;
134523                     }
134524                 }
134525                 if (currentPlatform && version.id === currentPlatform) {
134526                     versionSelect.appendChild(versionNode);
134527                 }
134528             });
134529             platformSelect.appendChild(platformNode);
134530         });
134531
134532         _updatePlatformDeviceSelect(currentPlatform, currentDeviceKey);
134533     }
134534 };
134535
134536 });
134537 define('ripple/ui/plugins/platformEvents', function (require, exports, module) {
134538 /*
134539  *  Copyright 2011 Research In Motion Limited.
134540  *
134541  * Licensed under the Apache License, Version 2.0 (the "License");
134542  * you may not use this file except in compliance with the License.
134543  * You may obtain a copy of the License at
134544  *
134545  * http://www.apache.org/licenses/LICENSE-2.0
134546  *
134547  * Unless required by applicable law or agreed to in writing, software
134548  * distributed under the License is distributed on an "AS IS" BASIS,
134549  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
134550  * See the License for the specific language governing permissions and
134551  * limitations under the License.
134552  */
134553 var _console = require('ripple/console'),
134554     platform = require('ripple/platform'),
134555     event = require('ripple/event'),
134556     exception = require('ripple/exception'),
134557     utils = require('ripple/utils');
134558
134559 module.exports = {
134560     panel: {
134561         domId: "platform-events-container",
134562         collapsed: true,
134563         pane: "right",
134564         titleName: "Platform Events",
134565         display: true
134566     },
134567     initialize: function () {
134568         var eventSelect = document.getElementById("platform-events-select"),
134569             spec = platform.current();
134570
134571         if (!spec.events) {
134572             return;
134573         }
134574
134575         utils.forEach(spec.events, function (method, name) {
134576             eventSelect.appendChild(utils.createElement("option", {
134577                 "innerText": name,
134578                 "value": name
134579             }));
134580         });
134581
134582         jQuery("#platform-events-fire").click(function () {
134583             var eventName = document.getElementById("platform-events-select").value,
134584                 args = spec.events[eventName].args ? document.getElementById("platform-events-args").value : null,
134585                 callback = spec.events[eventName].callback;
134586
134587             _console.log("fired event => " + eventName);
134588
134589             try {
134590                 callback(args);
134591             } catch (e) {
134592                 exception.throwMaskedException(e);
134593             }
134594         });
134595
134596         jQuery(eventSelect).change(function () {
134597             var argsSelect = jQuery("#platform-events-args"),
134598                 args = spec.events[this.value].args;
134599
134600             argsSelect.empty();
134601
134602             if (args) {
134603                 utils.forEach(spec.events[this.value].args, function (arg, index) {
134604                     argsSelect.append(utils.createElement("option", {
134605                         innerText: arg,
134606                         value: index
134607                     }));
134608                 });
134609
134610                 argsSelect.show();
134611             } else {
134612                 argsSelect.hide();
134613             }
134614         });
134615     }
134616 };
134617
134618 });
134619 define('ripple/ui/plugins/power', function (require, exports, module) {
134620 /*
134621  *  Copyright 2012 Intel Corporation
134622  *
134623  * Licensed under the Apache License, Version 2.0 (the "License");
134624  * you may not use this file except in compliance with the License.
134625  * You may obtain a copy of the License at
134626  *
134627  * http://www.apache.org/licenses/LICENSE-2.0
134628  *
134629  * Unless required by applicable law or agreed to in writing, software
134630  * distributed under the License is distributed on an "AS IS" BASIS,
134631  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
134632  * See the License for the specific language governing permissions and
134633  * limitations under the License.
134634  */
134635
134636 var db = require('ripple/db'),
134637     event = require('ripple/event'),
134638     constants = require('ripple/constants'),
134639     _volume  = document.getElementById(constants.BATTERY.VOLUME),
134640     _volumeLabel  = document.getElementById(constants.BATTERY.VOLUME + "-label"),
134641     _charging = document.getElementById(constants.BATTERY.CHARGING),
134642     _battery = {
134643         volume: 600,
134644         level:  1.0,
134645         timerId: null,
134646         charge: function (isStart, isCharge, callback) {
134647             var currentVolume,
134648                 checkValue = function () {
134649                     if (_battery.level < 0 || _battery.level > 1.0 || !isStart) {
134650                         clearInterval(_battery.timerId);
134651                         _battery.timerId = null;
134652                         if (_battery.level < 0)
134653                             _battery.level = 0;
134654                         else if (_battery.level > 1.0)
134655                             _battery.level = 1.0;
134656                     }
134657                 };
134658
134659             if (isStart && !_battery.timerId) {
134660                 _battery.timerId = setInterval(function () {
134661                     currentVolume = isCharge ? _battery.level * _battery.volume + 1 : _battery.level * _battery.volume - 1;
134662                     _battery.level = currentVolume / _battery.volume;
134663                     checkValue();
134664                     return callback && callback();
134665                 }, 1000);
134666             }
134667             checkValue();
134668             return callback && callback();
134669         }
134670     };
134671
134672 function _triggerEvent(chargingStatus, chargingTime, dischargingTime, level, type) {
134673     var status = {
134674         charging: chargingStatus,
134675         chargingTime: chargingTime,
134676         dischargingTime: dischargingTime,
134677         level: level,
134678         type: type
134679     };
134680     event.trigger("BatteryEvent", [status]); // for w3c battery api
134681     // for tizen systeminfo api
134682     if (type === "levelchange") {
134683         event.trigger("BatteryLevelChanged", [level]);
134684     }
134685     if (type === "chargingchange") {
134686         event.trigger("BatteryChargingChanged", [status]);
134687     }
134688 }
134689
134690 function _updateLevelIcons() {
134691     var colors = ["black", "black", "black", "black", "black", "black", "#404040", "#606060", "#808080", "#b0b0b0", "#ffffff", "#ffffff", "#ffffff", "#ffffff", "#ffffff", "#ffffff"],
134692         colorIndex = 10 - Math.round(_battery.level * 10),
134693         index;
134694
134695     //map the battery level to the color range
134696     for (index = 0 ; index <= 5 ; index++) {
134697         $("#block" + index).css("backgroundColor", colors[colorIndex]);
134698         colorIndex++;
134699     }
134700 }
134701
134702 function _setVolumeReadOnly(flag) {
134703     if (flag) {
134704         $("#" + constants.BATTERY.VOLUME).hide();
134705         $("#" + constants.BATTERY.VOLUME + "-label").show();
134706     } else {
134707         $("#" + constants.BATTERY.VOLUME).show();
134708         $("#" + constants.BATTERY.VOLUME + "-label").hide();
134709     }
134710 }
134711
134712 function _startDischarging() {
134713     var remainVolume = 0;
134714
134715     if ($("#simulate-low-battery #low-battery-remain-time").val() <= 0) {
134716         $("#simulate-low-battery #low-battery-remain-time").val(0);
134717     }
134718     remainVolume = Number($("#simulate-low-battery #low-battery-remain-time").val());
134719     if ($("#simulate-low-battery #low-battery-start-at").val() > 100) {
134720         $("#simulate-low-battery #low-battery-start-at").val(100);
134721     }
134722     if ($("#simulate-low-battery #low-battery-start-at").val() <= 0) {
134723         $("#simulate-low-battery #low-battery-start-at").val(0);
134724     }
134725     _battery.level = $("#simulate-low-battery #low-battery-start-at").val() / 100.0;
134726     if (_battery.level === 0 || remainVolume === 0) {
134727         $("#simulate-low-battery").dialog("close");
134728         _stopDischarging();
134729         return;
134730     }
134731     _setVolumeReadOnly(true);
134732     if (_charging.checked) {
134733         _charging.checked = false;
134734         _battery.charge(false);
134735     }
134736
134737     _charging.disabled = true;
134738     $("#remaining-time-label").html("Remaining Time to empty (seconds)");
134739     $("#charging-state").html("Plugged in?");
134740
134741     $("#remain-time").show();
134742     _battery.volume = remainVolume / _battery.level;
134743     _volumeLabel.innerText = (_battery.level * 100).toFixed(2);
134744     _battery.charge(true, false, function () {
134745         _volumeLabel.innerText = (_battery.level * 100).toFixed(2);
134746         _volume.value = (_battery.level * 100).toFixed(2);
134747         changeBatteryVolume();
134748         $("#remain-time").html(Math.round(_battery.volume * _battery.level) + " Seconds");
134749         _updateLevelIcons();
134750         if (_battery.level <= 0.0) {
134751             _stopDischarging();
134752         }
134753     });
134754     $("#simulate-low-battery").dialog("close");
134755     $("#simulate-low-battery-btn").hide();
134756     $("#stop-btn").show();
134757     _triggerEvent(false, Infinity, Math.round(_battery.volume * _battery.level), _battery.level, "chargingtimechange");
134758 }
134759
134760 function _stopDischarging() {
134761     _charging.disabled = false;
134762     _battery.level = _volume.value / 100.0;
134763     $("#remain-time").hide();
134764     $("#remain-time").html("");
134765     $("#remaining-time-label").html("Remaining Time (seconds)");
134766     _setVolumeReadOnly(false);
134767     _battery.charge(false);
134768     $("#simulate-low-battery-btn").show();
134769     $("#stop-btn").hide();
134770     _updateLevelIcons();
134771 }
134772
134773 function _setCharging() {
134774     // update the UI parts
134775     if (_charging.checked) {
134776         _battery.volume = 600;
134777         _battery.level = _volume.value / 100;
134778         _setVolumeReadOnly(true);
134779         $("#remain-time").show();
134780         $("#remaining-time-label").html("Remaining Time to fully charged (seconds)");
134781         $("#charging-state").html("Plugged in - charging rate 0.17%/second");
134782         _triggerEvent(true, Math.round(_battery.volume * (1 - _battery.level)), Infinity, _battery.level, "chargingchange");
134783     } else {
134784         _battery.level = _volume.value / 100.0;
134785         _updateLevelIcons();
134786         $("#remain-time").hide();
134787         $("#remain-time").html("");
134788         _setVolumeReadOnly(false);
134789         $("#remaining-time-label").html("Remaining Time (seconds)");
134790         $("#charging-state").html("Plugged in?");
134791         _triggerEvent(false, Infinity, Math.round(_battery.volume * _battery.level), _battery.level, "chargingchange");
134792     }
134793     // if it's unchecked, the timer will stop in this function call, the UI update blow it
134794     _battery.charge(_charging.checked, true, function () {
134795         _volumeLabel.innerText = (_battery.level * 100).toFixed(2);
134796         _volume.value = (_battery.level * 100).toFixed(2);
134797         changeBatteryVolume();
134798         $("#remain-time").html(Math.round(_battery.volume * (1 - _battery.level)) + " Seconds");    //show current remain time
134799         _updateLevelIcons();
134800     });
134801 }
134802
134803 function changeBatteryVolume() {
134804     if (_volume.value < 0)
134805         _volume.value = 0;
134806     else if (_volume.value > 100)
134807         _volume.value = 100;
134808
134809     _battery.level = _volume.value / 100.0;
134810     if (_charging.checked === true) {
134811         _triggerEvent(true, Math.round(_battery.volume * (1 - _battery.level)), Infinity, _battery.level, "levelchange");
134812     } else {
134813         _triggerEvent(false, Infinity, Math.round(_battery.volume * _battery.level), _battery.level, "levelchange");
134814     }
134815     db.save(constants.BATTERY.VOLUME, _volume.value);
134816     _updateLevelIcons();
134817 }
134818
134819 function initBattery() {
134820     $("#" + constants.BATTERY.CHARGING).bind("change", _setCharging);
134821
134822     $("#simulate-low-battery-btn").bind("click", function () {
134823         $("#simulate-low-battery").dialog("open");
134824     });
134825
134826     $("#simulate-low-battery-cancel").bind("click", function () {
134827         $("#low-battery-start-at").val = 20;  //UI initialize
134828         $("#low-battery-remain-time").val = 1200;
134829         $("#simulate-low-battery").dialog("close");
134830     });
134831
134832     $("#simulate-low-battery-start").bind("click", _startDischarging);
134833     $("#stop-btn").bind("click", _stopDischarging);
134834
134835     $("#" + constants.BATTERY.VOLUME).bind("change", function () {
134836         changeBatteryVolume();
134837     });
134838
134839     _charging.checked = false;
134840     _battery.level = db.retrieve(constants.BATTERY.VOLUME) / 100.0;
134841     if (isNaN(_battery.level)) {
134842         _battery.level = 1;
134843     }
134844     _volume.value = (_battery.level * 100).toFixed(2);
134845     _updateLevelIcons();
134846     $("#simulate-low-battery").dialog({
134847         resizable: false,
134848         draggable: true,
134849         modal: true,
134850         autoOpen: false,
134851         position: 'center',
134852         minWidth: '460',
134853         minHeight: '240'
134854     });
134855 }
134856
134857 module.exports = {
134858     panel: {
134859         domId: "power-container",
134860         collapsed: true,
134861         pane: "left",
134862         titleName: "Power Manager",
134863         display: true
134864     },
134865
134866     initialize: function () {
134867         initBattery();
134868     }
134869 };
134870
134871 });
134872 define('ripple/ui/plugins/push', function (require, exports, module) {
134873 /*
134874  *  Copyright 2011 Research In Motion Limited.
134875  *
134876  * Licensed under the Apache License, Version 2.0 (the "License");
134877  * you may not use this file except in compliance with the License.
134878  * You may obtain a copy of the License at
134879  *
134880  * http://www.apache.org/licenses/LICENSE-2.0
134881  *
134882  * Unless required by applicable law or agreed to in writing, software
134883  * distributed under the License is distributed on an "AS IS" BASIS,
134884  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
134885  * See the License for the specific language governing permissions and
134886  * limitations under the License.
134887  */
134888 var constants = require('ripple/constants'),
134889     event = require('ripple/event'),
134890     utils = require('ripple/utils'),
134891     db = require('ripple/db'),
134892     PUSH_OPTIONS = constants.PUSH.OPTIONS;
134893
134894 function _updatePushPanel(ports) {
134895     var portsSelect = document.getElementById("port-select"),
134896         currentPort = portsSelect.value;
134897
134898     portsSelect.innerHTML = "";
134899
134900     ports.forEach(function (port) {
134901         portsSelect.appendChild(utils.createElement("option", {
134902             innerText: port,
134903             value: port,
134904             selected: currentPort === port
134905         }));
134906     });
134907 }
134908
134909 module.exports = {
134910     panel: {
134911         domId: "push-container",
134912         collapsed: true,
134913         pane: "left"
134914     },
134915     initialize: function () {
134916         event.on("PushListenersChanged", function (listeners) {
134917             _updatePushPanel(listeners);
134918             jQuery("#port-select").effect("highlight", {color: "#62B4C8"}, 1000);
134919         });
134920
134921         _updatePushPanel([]);
134922
134923         document.getElementById("push-send")
134924             .addEventListener("click", function () {
134925                 var port = document.getElementById("port-select").value,
134926                     text = document.getElementById(PUSH_OPTIONS.PAYLOAD).value,
134927                     pushData = {
134928                         headerField: ["21f39092"],
134929                         requestURI: "/",
134930                         source: "ripple",
134931                         isChannelEncrypted: false,
134932                         payload: text
134933                     };
134934
134935                 event.trigger("Push", [pushData, port], true);
134936             }, false);
134937
134938         utils.bindAutoSaveEvent(jQuery("#" + PUSH_OPTIONS.PAYLOAD), function () {
134939             db.save(PUSH_OPTIONS.PAYLOAD, document.getElementById(PUSH_OPTIONS.PAYLOAD).value);
134940         });
134941
134942         document.getElementById(PUSH_OPTIONS.PAYLOAD).value = db.retrieve(PUSH_OPTIONS.PAYLOAD) || "My payload data";
134943     }
134944 };
134945
134946 });
134947 define('ripple/ui/plugins/sensorSettings', function (require, exports, module) {
134948 /*
134949  *  Copyright 2012 Intel Corporation.
134950  *
134951  * Licensed under the Apache License, Version 2.0 (the "License");
134952  * you may not use this file except in compliance with the License.
134953  * You may obtain a copy of the License at
134954  *
134955  * http://www.apache.org/licenses/LICENSE-2.0
134956  *
134957  * Unless required by applicable law or agreed to in writing, software
134958  * distributed under the License is distributed on an "AS IS" BASIS,
134959  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
134960  * See the License for the specific language governing permissions and
134961  * limitations under the License.
134962  */
134963
134964 var constants = require('ripple/constants'),
134965     sensorSettings = require('ripple/sensorSettings'),
134966     utils = require('ripple/utils'),
134967     exception = require('ripple/exception'),
134968     platform = require('ripple/platform'),
134969     _CONST = {
134970         "CONTENT_CONTAINER_ID": "sensorsettings-content-container",
134971         "UKNOWN_CONTROL_MESSAGE": "Unknown sensor control type"
134972     },
134973     _contentContainer,
134974     _CONTAINER_ID = _CONST.CONTENT_CONTAINER_ID;
134975
134976 function _appendSettingNode(labelNode, inputNode, label) {
134977     var frag = document.createDocumentFragment(),
134978         rowNode = frag.appendChild(utils.createElement("tr")),
134979         tempTdNode;
134980
134981     rowNode.appendChild(utils.createElement("td"))
134982            .appendChild(labelNode);
134983
134984     tempTdNode = rowNode.appendChild(utils.createElement("td"));
134985
134986     if (label) {
134987         tempTdNode.appendChild(label);
134988     }
134989
134990     tempTdNode.appendChild(inputNode);
134991
134992     return frag;
134993 }
134994
134995 function _buildDOMNode(setting, settingType, key) {
134996     var settingsNode, tagName, jNode,
134997         fullKey = settingType + "." + key,
134998         savedSetting = sensorSettings.retrieve(fullKey),
134999         // TODO: move this into Utils (isSet method)
135000         currentSetting = (savedSetting || savedSetting === false || savedSetting === "" || savedSetting === 0) ? savedSetting : setting.control.value,
135001         domNode,
135002         domNodeLabel = null;
135003
135004     switch (setting.control.type) {
135005     case "text":
135006     case "number":
135007     case "range":
135008     case "checkbox":
135009         tagName = "input";
135010         break;
135011     case "textarea":
135012         tagName = "textarea";
135013         break;
135014     case "select":
135015         tagName = "select";
135016         break;
135017     default:
135018         exception.raise(exception.types.Application, _CONST.UKNOWN_CONTROL_MESSAGE);
135019     }
135020
135021     settingsNode = utils.createElement(tagName, setting.control.type === "select" ? null : setting.control);
135022
135023     // TODO: this should really be part of utils.createControl? add element of type "range" with label?
135024     if (setting.control.type === "range") {
135025         domNodeLabel = utils.createElement("label", {
135026             "class": constants.UI.LEFT_RANGE_LABEL_CLASS
135027         });
135028     }
135029
135030     domNode = _appendSettingNode(utils.createElement("span", {"innerText": setting.name, "class": constants.UI.TEXT_LABEL_CLASS}), settingsNode, domNodeLabel);
135031
135032     jNode = jQuery(settingsNode);
135033     jNode.addClass(constants.UI.JQUERY_UI_INPUT_CLASSES);
135034
135035     switch (setting.control.type) {
135036     case "checkbox":
135037         jNode.bind("click", function () {
135038             var checked = this.checked ? true : false;
135039             sensorSettings.persist(fullKey, checked);
135040             if (typeof setting.callback === "function") {
135041                 setting.callback(checked);
135042             }
135043         });
135044
135045         if (currentSetting === true) {
135046             jNode.attr("checked", "checked");
135047         }
135048
135049         break;
135050
135051     case "text":
135052     case "textarea":
135053     case "number":
135054         jNode.val(currentSetting);
135055         utils.bindAutoSaveEvent(jNode, function () {
135056             sensorSettings.persist(fullKey, jNode.val());
135057             if (typeof setting.callback === "function") {
135058                 setting.callback(jNode.val());
135059             }
135060         });
135061         break;
135062
135063     case "select":
135064     case "range":
135065         if (setting.control.type === "select") {
135066             utils.forEach(setting.options,  function (value, option) {
135067                 jNode.append(utils.createElement("option", {
135068                     "value": option,
135069                     "innerText": value
135070                 }));
135071             });
135072         }
135073         else {
135074             if (domNodeLabel) {
135075                 domNodeLabel.innerText = currentSetting;
135076             }
135077         }
135078
135079         jNode.val(currentSetting)
135080              .bind("change", function () {
135081                 if (setting.control.type === "range" && domNodeLabel) {
135082                     domNodeLabel.innerText = jQuery(this).val();
135083                 }
135084                 sensorSettings.persist(fullKey, jQuery(this).val());
135085
135086                 if (typeof setting.callback === "function") {
135087                     setting.callback(jQuery(this).val());
135088                 }
135089             }
135090         );
135091     }
135092
135093     // TODO: Brent, do in DeviceSettings on load instead?
135094     if (currentSetting !== setting.control.value) {
135095         sensorSettings.register(fullKey, currentSetting);
135096     }
135097
135098     return domNode;
135099 }
135100
135101 // goes through current platforms sensor settings
135102 // adds nodes to panel and binds respective events
135103 // talks to SensorSettings for persistence
135104 module.exports = {
135105     panel: {
135106         domId: "sensors-panel-container",
135107         collapsed: true,
135108         pane: "right",
135109         titleName: "Sensors",
135110         display: true
135111     },
135112     initialize: function () {
135113         var settings;
135114
135115         _contentContainer = document.getElementById(_CONTAINER_ID);
135116
135117         settings = platform.current().sensor;
135118
135119         utils.forEach(settings, function (settingSection, settingType) {
135120
135121             var currentTableNode, flag = false;
135122             
135123             utils.forEach(settingSection, function (setting, key) {
135124                 if (typeof setting === "object") {
135125                     flag = true;
135126                     return;
135127                 }
135128             });
135129
135130             if (flag) {
135131                 _contentContainer.appendChild(utils.createElement("h3", { "innerText": settingType }));
135132             }
135133
135134             currentTableNode = utils.createElement("table", {
135135                 "class": constants.UI.PANEL_TABLE_CLASS
135136             });
135137
135138             _contentContainer.appendChild(currentTableNode);
135139
135140             utils.forEach(settingSection, function (setting, key) {
135141                 if (typeof setting === "object") {
135142                     currentTableNode.appendChild(_buildDOMNode(setting, settingType, key));
135143                 }
135144
135145             });
135146         });
135147     }
135148 };
135149
135150 });
135151 define('ripple/ui/plugins/sensors', function (require, exports, module) {
135152 /*
135153  * Copyright (c) 2010 Epic Train Hack
135154  * Copyright (c) 2011 Research In Motion Limited
135155  * Contributors: Wolfram Kriesing, Dan Silivestru, Brent Lintner
135156  *
135157  * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
135158  *
135159  * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
135160  *
135161  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
135162  */
135163 var event = require('ripple/event'),
135164     accelerometer = require('ripple/accelerometer'),
135165     deviceSettings = require('ripple/deviceSettings'),
135166     Acceleration = require('ripple/platform/w3c/1.0/Acceleration'),
135167     Rotation = require('ripple/platform/w3c/1.0/Rotation'),
135168     sensorSettings = require('ripple/sensorSettings'),
135169     _oldX, _oldY, _oldAlphaX,
135170     _camera, _scene, _renderer, _mesh,
135171     _offsets = {
135172         x: 0,
135173         y: 0,
135174         z: -9.81,
135175     },
135176     _flag, // whether the browser supports webGL
135177     _shape =
135178         //
135179         // The front side
135180         //
135181         // x, y, z      x, y, z         x, y, z
135182         // for some strange reason for y -100 is top, 100 is bottom
135183         "-30,30,10,     30,30,10,       30,60,10,       100,100,100,-1,0;" + // top left, top right, bottom right - of the right triangle
135184         "-30,30,10,     30,60,10,       -30,60,10,      100,100,100,-1,0;" + // top left, right bottom, left bottom - of the left triangle
135185         // front side "the phone display"
135186         "-20,-50,11,    20,-50,11,      20,20,11,       100,100,100,-1,0;" +
135187         "-20,-50,11,    20,20,11,       -20,20,11,      100,100,100,-1,0;" +
135188         // below the display
135189         "-30,30,10,     30,20,10,       30,30,10,       0,0,0,-1,0;" +
135190         "-30,30,10,     -30,20,10,      30,20,10,       0,0,0,-1,0;" +
135191         // above the display
135192         "-30,-60,10,    30,-60,10,      30,-50,10,      0,0,0,-1,0;" +
135193         "-30,-60,10,    30,-50,10,      -30,-50,10,     0,0,0,-1,0;" +
135194         // left of the display
135195         "-30,-50,10,    -20,-50,10,     -20,20,10,      0,0,0,-1,0;" +
135196         "-30,-50,10,    -20,20,10,      -30,20,10,      0,0,0,-1,0;" +
135197         // right of the display
135198         "20,-50,10,     30,-50,10,      30,20,10,       0,0,0,-1,0;" +
135199         "20,-50,10,     30,20,10,       20,20,10,       0,0,0,-1,0;" +
135200
135201
135202         // back side, opposite side to the above one
135203         "-30,-60,-10,   30,60,-10,      30,-60,-10,     0,0,0,-1,0;" +
135204         "-30,-60,-10,   -30,60,-10,     30,60,-10,      0,00,-1,0;" +
135205         // right side
135206         "30,-60,-10,    30,60,-10,      30,60,10,       50,50,80,-1,0;" +
135207         "30,-60,-10,    30,60,10,       30,-60,10,      50,50,80,-1,0;" +
135208         // left side
135209         "-30,-60,-10,   -30,60,10,      -30,60,-10,     50,50,80,-1,0;" +
135210         "-30,-60,-10,   -30,-60,10,     -30,60,10,      50,50,80,-1,0;" +
135211
135212         // top
135213         "30,-60,-10,    -30,-60,10, -30,-60,-10,    50,80,50,-1,0;" +
135214         "30,-60,-10,    30,-60,10,      -30,-60,10, 50,80,50,-1,0;" +
135215         // bottom
135216         "30,60,-10, -30,60,-10,     -30,60,10,      80,50,50,-1,0;" +
135217         "30,60,-10, -30,60,10,      30,60,10,       80,50,50,-1,0";
135218
135219 function _createThreeDModel() {
135220     var node,
135221         shader,
135222         hemiLight,
135223         dirLight,
135224         material,
135225         uniforms,
135226         container,
135227         loader,
135228         directionalLight,
135229         isDiffuseTextureLoaded,
135230         isNormalTextureLoaded,
135231         shiftKeyDown,
135232         mouseDown,
135233         ctrlKeyDown = false;
135234
135235     if (_flag) {
135236         // create a 3D phone model with three.js if webGL is supported
135237         node = document.getElementById("accelerometer-div");
135238         container = document.createElement("div");
135239         $("#accelerometer-div").append(container);
135240
135241         _camera = new THREE.PerspectiveCamera(50, 1.5, 0.1, 100);
135242         _camera.position.set(4.32823, 3.74714, 2.62985);
135243         _scene = new THREE.Scene();
135244         _scene.add(new THREE.AmbientLight(0xffffff));
135245         directionalLight = new THREE.DirectionalLight(0xffffff, 1);
135246         directionalLight.position.set(1, 1, 1).normalize();
135247         _scene.add(directionalLight);
135248         hemiLight = new THREE.HemisphereLight(0xffffff, 0xffffff, 0.6);
135249         hemiLight.color.setHSV(0.6, 0.75, 1);
135250         hemiLight.groundColor.setHSV(0.095, 0.5, 1);
135251         hemiLight.position.set(0, 500, 0);
135252         _scene.add(hemiLight);
135253         dirLight = new THREE.DirectionalLight(0xffffff, 1);
135254         dirLight.color.setHSV(0.1, 0.1, 1);
135255         dirLight.position.set(-1, 1.75, 1);
135256         dirLight.position.multiplyScalar(50);
135257         _scene.add(dirLight);
135258         shader = THREE.ShaderSkin["skin"];
135259         uniforms = THREE.UniformsUtils.clone(shader.uniforms);
135260         uniforms["tNormal"].value = THREE.ImageUtils.loadTexture("images/phoneMap_tNormal.png", {}, function () {
135261             isNormalTextureLoaded = true;
135262             if (isDiffuseTextureLoaded) {
135263                 _renderer.clear();
135264                 _renderer.render(_scene, _camera);
135265             }
135266         });
135267         uniforms["uNormalScale"].value = 0.75;
135268         uniforms["tDiffuse"].value = THREE.ImageUtils.loadTexture("images/phoneMap_tDiffuse.png", {}, function () {
135269             isDiffuseTextureLoaded = true;
135270             if (isNormalTextureLoaded) {
135271                 _renderer.clear();
135272                 _renderer.render(_scene, _camera);
135273             }
135274         });
135275         uniforms["uDiffuseColor"].value.setHex(0xbbbbbb);
135276         uniforms["uSpecularColor"].value.setHex(0x070707);
135277         uniforms["uAmbientColor"].value.setHex(0x111111);
135278         uniforms["uRoughness"].value = 0.185;
135279         uniforms["uSpecularBrightness"].value = 0.8;
135280         material = new THREE.ShaderMaterial({ fragmentShader: shader.fragmentShader, vertexShader: shader.vertexShader, uniforms: uniforms, lights: true });
135281         loader = new THREE.JSONLoader(true);
135282         document.body.appendChild(loader.statusDomElement);
135283
135284         loader.load("phoneModel.js", function (geometry) {
135285             loader.statusDomElement.style.display = "none";
135286             geometry.computeTangents();
135287             _mesh = new THREE.Mesh(geometry, material);
135288             _mesh.position.set(7, 2, -50);
135289             _mesh.scale.set(18, 12, 18);
135290             _scene.add(_mesh);
135291             _renderer.clear();
135292             _renderer.render(_scene, _camera);
135293         });
135294
135295         _renderer = new THREE.WebGLRenderer({antialias: false});
135296         _renderer.setSize(300, 280);
135297         _renderer.setClearColorHex(0xffffff, 1);
135298         _renderer.autoClear = false;
135299
135300         container.appendChild(_renderer.domElement);
135301     } else { // create the model with 3d.js
135302         node = document.querySelector("#accelerometer-canvas");
135303
135304         jQuery("#accelerometer-div").css("display", "none");
135305         jQuery("#accelerometer-canvas").css("display", "block");
135306         ThreeDee.setCenter(150, 100);
135307         ThreeDee.setLight(-300, -300, 800);
135308         _updateCanvas(0, 0);
135309     }
135310
135311     //change accelerometer and phone by moving the mouse and the key "shift"
135312     node.addEventListener("mousemove", function (event) {
135313         var cosX, sinX, cosY, sinY,
135314             alpha = accelerometer.getInfo().orientation.alpha,
135315             beta = accelerometer.getInfo().orientation.beta,
135316             gamma = accelerometer.getInfo().orientation.gamma,
135317             x = accelerometer.getInfo().acceleration.x,
135318             y = accelerometer.getInfo().acceleration.y,
135319             z = accelerometer.getInfo().acceleration.z;
135320
135321         if (!mouseDown) {
135322             return;
135323         }
135324
135325         // if the shift key is pressed down, only the alpha value will be chagned
135326         if (!shiftKeyDown) {
135327             _offsets.x = (_offsets.x + _oldX - event.offsetX) % 360;
135328             _offsets.y = (_offsets.y + _oldY - event.offsetY) % 360;
135329
135330             alpha = alpha || 0;
135331
135332             // enforce gamma in [-90,90] as per w3c spec
135333             gamma = -_offsets.x;
135334             if (gamma < -90) {
135335                 gamma = -90;
135336             }
135337             if (gamma > 90) {
135338                 gamma = 90;
135339             }
135340
135341             // enforce beta in [-180,180] as per w3c spec
135342             beta = -_offsets.y % 360;
135343             if (beta < -180) {
135344                 beta += 360;
135345             }
135346             else if (beta >= 180) {
135347                 beta -= 360;
135348             }
135349
135350             cosX = Math.cos(gamma * (Math.PI / 180));
135351             sinX = Math.sin(gamma * (Math.PI / 180));
135352             cosY = Math.cos(beta * (Math.PI / 180));
135353             sinY = Math.sin(beta * (Math.PI / 180));
135354             x = 9.81 * cosY * sinX;
135355             y = -9.81 * sinY;
135356             z = -9.81 * cosY * cosX;
135357
135358         } else {
135359             alpha = (alpha - (_oldAlphaX - event.offsetX) * 2.5) % 360;
135360         }
135361         _oldX = event.offsetX;
135362         _oldY = event.offsetY;
135363         _oldAlphaX = event.offsetX;
135364         if (_flag)
135365             _updatePhoneModel(alpha, beta, gamma);
135366         else
135367             _updateCanvas(alpha, -beta, gamma);
135368         accelerometer.setInfo({
135369             x: x,
135370             y: y,
135371             z: z,
135372             alpha: alpha,
135373             beta: beta,
135374             gamma: gamma
135375         });
135376     }, false);
135377
135378     node.addEventListener("mousedown", function (e) {
135379         mouseDown = true;
135380         _oldX = e.offsetX;
135381         _oldY = e.offsetY;
135382         if (shiftKeyDown) {
135383             _oldAlphaX = _oldX;
135384         }
135385     });
135386
135387     node.addEventListener("mouseup", function () {
135388         mouseDown = false;
135389     });
135390
135391     document.addEventListener("mouseup", function () {
135392         //Catch mouseup events that fire when outside canvas bounds
135393         mouseDown = false;
135394     });
135395
135396     document.addEventListener("keydown", function (e) {
135397         switch (e.keyCode) {
135398         case 16:                // Shift Key
135399             shiftKeyDown = true;
135400             break;
135401         case 17:                // Ctrl Key
135402             ctrlKeyDown = true;
135403             break;
135404         case 74:                // J Key
135405             if (shiftKeyDown && ctrlKeyDown) { //if shift+ctrl+j keydown in the meantime, console comes up rather than shift key down
135406                 shiftKeyDown = false;
135407                 ctrlKeyDown = false;
135408             }
135409             break;
135410         }
135411     });
135412
135413     document.addEventListener("keyup", function (e) {
135414         if (e.keyCode === 16) { // Shift Key
135415             shiftKeyDown = false;
135416         }
135417     });
135418 }
135419
135420 // update the 3d model created by 3d.js
135421 function _updateCanvas(a, b, g) {
135422     ThreeDee.loadMesh(_shape);
135423     g = g || 0;
135424     ThreeDee.rotate(0, g, 0);
135425     ThreeDee.rotate(b, 0, a);
135426     ThreeDee.backface();
135427     ThreeDee.shade();
135428     ThreeDee.zSort();
135429     Draw.initialize(document.querySelector("#accelerometer-canvas"));
135430     Draw.clear(0, 0, 480, 300);
135431     Draw.drawScene(ThreeDee.getTranslation(), 3);
135432 }
135433
135434 // update the 3d model created by three.js
135435 function _updatePhoneModel(a, b, g) {
135436     _mesh.rotation.x = b / 90 * 1.5;
135437     _mesh.rotation.y = g / 90 * 1.5;
135438     _mesh.rotation.z = a / 90 * 1.5;
135439     _renderer.clear();
135440     _renderer.render(_scene, _camera);
135441 }
135442
135443 function _resetAccelerometer() {
135444     _oldX = 0;
135445     _oldY = 0;
135446     _oldAlphaX = 0;
135447     _offsets = {
135448         x: 0,
135449         y: 0,
135450         z: -9.81
135451     };
135452     if (_flag) {
135453         _mesh.rotation.x = 0;
135454         _mesh.rotation.y = 0;
135455         _mesh.rotation.z = 0;
135456         _renderer.clear();
135457         _renderer.render(_scene, _camera);
135458     } else {
135459         _updateCanvas(0, 0);
135460     }
135461
135462     accelerometer.setInfo({
135463         acceleration: new Acceleration(0, 0, 0),
135464         accelerationIncludingGravity: new Acceleration(0, 0, -9.81),
135465         rotationRate: new Rotation(0, 0, 0),
135466         orientation: new Rotation(0, 0, 0),
135467         timestamp: new Date().getTime()
135468     });
135469     accelerometer.triggerEvent();
135470 }
135471
135472 function _resetMagneticField() {
135473     jQuery("#magnetic-x").val("100");
135474     jQuery("#magnetic-y").val("100");
135475     jQuery("#magnetic-z").val("100");
135476 }
135477
135478 function _resetLightLevel() {
135479     $("#display-state").children().each(function() {
135480         if ($(this).val() === "OFF") {
135481             $(this).attr("selected", "true");
135482             this.selected = true;
135483         }
135484         else {
135485             $(this).attr("selected", "false");
135486             this.selected = false;
135487         }
135488     });
135489 }
135490
135491
135492 // set a typical mode for accelerometer simulation, when the phone drops,
135493 // x will become to be 0, y will become to be -9.81 and z will become to be 0
135494 function _setDrop() {
135495     //duration = 20 * 50 = 1000ms. 20 is ths number of steps and 50 is the duration of steps.
135496     var alpha = Number(accelerometer.getInfo().orientation.alpha),
135497         beta = Number(accelerometer.getInfo().orientation.beta),
135498         gamma = Number(accelerometer.getInfo().orientation.gamma),
135499         cosX, cosY, sinX, sinY, x, y, z,
135500         alphaStep = Math.abs(alpha) / 20,
135501         betaStep = Math.abs(beta - 90) / 20,
135502         gammaStep = Math.abs(gamma) / 20,
135503         counts = 0, dropTimeout,
135504         drop = function () {
135505             if (counts >= 20) {
135506                 window.clearTimeout(dropTimeout);
135507                 // to avoid showing "-0" or "-0.00"
135508                 if (_flag)
135509                     _updatePhoneModel(0, 90, 0);
135510                 else
135511                     _updateCanvas(0, -90, 0);
135512                 accelerometer.setInfo({
135513                     x: 0,
135514                     y: -9.81,
135515                     z: 0,
135516                     alpha: 0,
135517                     beta: 90,
135518                     gamma: 0
135519                 });
135520             } else {
135521                 dropTimeout = setTimeout(drop, 50);
135522                 step();
135523                 counts++;
135524             }
135525         },
135526         step = function () {
135527             var _beta;
135528
135529             alpha = alpha > 0 ? alpha - alphaStep : alpha + alphaStep;
135530             beta = beta > 90 ? beta - betaStep : beta + betaStep;
135531             gamma = gamma > 0 ? gamma - gammaStep : gamma + gammaStep;
135532             _beta = _flag ? beta + betaStep : -(beta + betaStep);
135533             if (_flag)
135534                 _updatePhoneModel(alpha, _beta, gamma);
135535             else
135536                 _updateCanvas(alpha, _beta, gamma);
135537
135538             cosX = Math.cos(gamma * (Math.PI / 180));
135539             sinX = Math.sin(gamma * (Math.PI / 180));
135540             cosY = Math.cos(beta * (Math.PI / 180));
135541             sinY = Math.sin(beta * (Math.PI / 180));
135542             x = 9.81 * cosY * sinX;
135543             y = -9.81 * sinY;
135544             z = -9.81 * cosY * cosX;
135545             accelerometer.setInfo({
135546                 x: x,
135547                 y: y,
135548                 z: z,
135549                 alpha: alpha,
135550                 beta: beta,
135551                 gamma: gamma
135552             });
135553             _offsets.x = -gamma;
135554             _offsets.y = -beta;
135555         };
135556
135557     drop();
135558 }
135559
135560 function _initializeSensorSettings() {
135561     var sensorsInputID = ["accelerometer-alpha", "accelerometer-beta", "accelerometer-gamma", "magnetic-x", "magnetic-y", "magnetic-z"],
135562         magneticEvent = ["MagneticField-xChanged", "MagneticField-yChanged", "MagneticField-zChanged"],
135563          magneticData = ["MagneticField.x", "MagneticField.y", "MagneticField.z"],
135564         oldValue, oldInputX,
135565         inputMouseDown,
135566         triggerFunction,
135567         selectedInputID = null;
135568
135569     triggerFunction = function (val, index) {
135570         var cosX, cosY, sinX, sinY, x, y, z,
135571             alpha = accelerometer.getInfo().orientation.alpha,
135572             beta = accelerometer.getInfo().orientation.beta,
135573             gamma = accelerometer.getInfo().orientation.gamma;
135574
135575         //choose which value to change according to index
135576         switch (index) {
135577         case 0:
135578             alpha = val;
135579             break;
135580         case 1:
135581             beta = val;
135582             break;
135583         case 2:
135584             gamma = val;
135585             break;
135586         default:
135587             sensorSettings.persist(magneticData[index - 3], val);
135588             event.trigger(magneticEvent[index - 3], [val]);
135589         }
135590
135591         //change the phone model and values of other inputs when changing a value of input
135592         if (_flag)
135593             _updatePhoneModel(alpha, beta, gamma);
135594         else
135595             _updateCanvas(alpha, -beta, gamma);
135596         cosX = Math.cos(gamma * (Math.PI / 180));
135597         sinX = Math.sin(gamma * (Math.PI / 180));
135598         cosY = Math.cos(beta * (Math.PI / 180));
135599         sinY = Math.sin(beta * (Math.PI / 180));
135600         x = 9.81 * cosY * sinX;
135601         y = -9.81 * sinY;
135602         z = -9.81 * cosY * cosX;
135603         accelerometer.setInfo({
135604             x: x,
135605             y: y,
135606             z: z,
135607             alpha: alpha,
135608             beta: beta,
135609             gamma: gamma
135610         });
135611         _offsets.x = -gamma;
135612         _offsets.y = -beta;
135613     };
135614
135615     // make the input elements more powful: drag mouse to left to decrease the value and right to increase it;
135616     // also change the value with arrow keys.
135617
135618
135619     sensorsInputID.forEach(function (id, index) {
135620         jQuery("#" + id).mousedown(function (e) {
135621             selectedInputID = id;
135622             oldValue = parseInt(this.value, 10);
135623             oldInputX = e.offsetX;
135624             inputMouseDown = true;
135625         });
135626
135627         jQuery("#" + id).mousemove(function (e) {
135628             if (inputMouseDown && (selectedInputID !== null)) {
135629                 jQuery("#" + selectedInputID).val(parseInt(oldValue + (e.offsetX - oldInputX) / 2, 10));
135630                 if (parseInt(this.value, 10) <= parseInt(jQuery(this).attr("minValue"), 10)) {
135631                     this.value = jQuery(this).attr("minValue");
135632                 }
135633                 if (parseInt(this.value, 10) >= parseInt(jQuery(this).attr("maxValue"), 10)) {
135634                     this.value = jQuery(this).attr("maxValue");
135635                 }
135636                 triggerFunction(this.value, index);
135637             }
135638         });
135639
135640         jQuery("#" + id).mouseup(function () {
135641             selectedInputID = null;
135642             inputMouseDown = false;
135643         });
135644         jQuery(document).mouseup(function () {
135645             selectedInputID = null;
135646             inputMouseDown = false;
135647         });
135648
135649         jQuery("#" + id).click(function () {
135650             this.select();
135651         });
135652
135653         jQuery("#" + id).blur(function () {
135654             if (isNaN(this.value)) {
135655                 this.value = 0;
135656             }
135657             else if (parseInt(this.value, 10) > parseInt(jQuery(this).attr("maxValue"), 10))
135658                 this.value = jQuery(this).attr("maxValue");
135659             else if (parseInt(this.value, 10) < parseInt(jQuery(this).attr("minValue"), 10))
135660                 this.value = jQuery(this).attr("minValue");
135661             else
135662                 this.value = parseInt(this.value, 10);
135663             triggerFunction(this.value, index);
135664         });
135665
135666         jQuery("#" + id).keydown(function (e) {
135667             switch (e.keyCode) {
135668             case 38:
135669                 if (parseInt(this.value, 10) < parseInt(jQuery(this).attr("maxValue"), 10)) {
135670                     this.value = parseInt(this.value, 10) + 1;
135671                     triggerFunction(this.value, index);
135672                 }
135673                 break;
135674             case 40:
135675                 if (parseInt(this.value, 10) > parseInt(jQuery(this).attr("minValue"), 10)) {
135676                     this.value = parseInt(this.value, 10) - 1;
135677                     triggerFunction(this.value, index);
135678                 }
135679                 break;
135680             default:
135681                 return;
135682             }
135683         });
135684     });
135685 }
135686
135687 /*
135688 //initialize light settings
135689 function _initializeLightSettings() {
135690     var displayObj = document.getElementById("display-state"),
135691         DISPLAY_STATE  = require('ripple/constants').POWER_RESOURCE.SCREEN.STATE,
135692         brightness;
135693
135694     displayObj.addEventListener("change", function () {
135695         var state = displayObj.value, value;
135696         value = DISPLAY_STATE[state].VALUE;
135697         deviceSettings.persist("Display.brightness", value);
135698         event.trigger("DisplayBrightnessChanged", [value]);
135699     });
135700
135701     brightness = deviceSettings.retrieve("Display.brightness");
135702     if (brightness ===  DISPLAY_STATE.SCREEN_OFF.MAX) {
135703         displayObj.options[0].selected = true;
135704     } else if (brightness <= DISPLAY_STATE.SCREEN_DIM.MAX) {
135705         displayObj.options[1].selected = true;
135706     } else if (brightness <= DISPLAY_STATE.SCREEN_NORMAL.MAX) {
135707         displayObj.options[2].selected = true;
135708     } else {
135709         displayObj.options[3].selected = true;
135710     }
135711 }
135712 */
135713
135714 module.exports = {
135715     panel: {
135716         domId: "sensors-container",
135717         collapsed: true,
135718         pane: "left",
135719         titleName: "Sensors",
135720         display: true
135721     },
135722     initialize: function () {
135723         var gl,
135724             testCanvas = document.getElementById("accelerometer-canvas");
135725
135726         try { // check whether the browser supports webGL, returns null if not support
135727             gl = testCanvas.getContext("experimental-webgl");
135728             gl.viewport(0, 0, testCanvas.width, testCanvas.height);
135729         } catch (e) {
135730             console.log("unsupport webgl");
135731         }
135732
135733         _flag = gl ? true : false;
135734
135735         accelerometer.init();
135736         _createThreeDModel();
135737         _initializeSensorSettings();
135738         //_initializeLightSettings();
135739
135740         jQuery("#accelerometer-shake").click(function () {
135741             window.setTimeout(require('ripple/ui/plugins/goodVibrations').shakeDevice(8), 1);
135742             accelerometer.shake();
135743         });
135744
135745         jQuery("#sensor-reset-all").click(function () {
135746             _resetAccelerometer();
135747             _resetMagneticField();
135748             _resetLightLevel();
135749         });
135750
135751         jQuery("#accelerometer-drop").click(_setDrop);
135752
135753         event.on("AccelerometerInfoChangedEvent", function (motion) {
135754             jQuery("#accelerometer-x").html(motion.accelerationIncludingGravity.x.toFixed(2));
135755             jQuery("#accelerometer-y").html(motion.accelerationIncludingGravity.y.toFixed(2));
135756             jQuery("#accelerometer-z").html(motion.accelerationIncludingGravity.z.toFixed(2));
135757             jQuery("#accelerometer-alpha").val(Number(motion.orientation.alpha).toFixed(2));
135758             jQuery("#accelerometer-beta").val(Number(motion.orientation.beta).toFixed(2));
135759             jQuery("#accelerometer-gamma").val(Number(motion.orientation.gamma).toFixed(2));
135760         }, this);
135761     }
135762 };
135763
135764 });
135765 define('ripple/ui/plugins/settings-dialog', function (require, exports, module) {
135766 /*
135767  *  Copyright 2011 Research In Motion Limited.
135768  *
135769  * Licensed under the Apache License, Version 2.0 (the "License");
135770  * you may not use this file except in compliance with the License.
135771  * You may obtain a copy of the License at
135772  *
135773  * http://www.apache.org/licenses/LICENSE-2.0
135774  *
135775  * Unless required by applicable law or agreed to in writing, software
135776  * distributed under the License is distributed on an "AS IS" BASIS,
135777  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
135778  * See the License for the specific language governing permissions and
135779  * limitations under the License.
135780  */
135781 var db = require('ripple/db'),
135782     utils = require('ripple/utils'),
135783     platform = require('ripple/platform'),
135784     notifications = require('ripple/notifications'),
135785     tooltip = require('ripple/ui/plugins/tooltip'),
135786     bus = require('ripple/bus'),
135787     required = {
135788         build: {
135789             "webworks.tablet": ["sdk", "projectPath", "outputPath", "projectName"],
135790             "webworks.bb10": ["sdk", "projectPath", "outputPath", "projectName"],
135791             "webworks.handset": ["sdk", "projectPath", "outputPath", "projectName"]
135792         },
135793         sign: {
135794             "webworks.tablet": ["sdk", "projectPath", "outputPath", "projectName", "csk_password", "p12_password", "bundle_number"],
135795             "webworks.bb10": ["sdk", "projectPath", "outputPath", "projectName", "signingPassword", "bundle_number"],
135796             "webworks.handset": ["sdk", "projectPath", "outputPath", "projectName", "signingPassword"]
135797         },
135798         launch: {
135799             "webworks.tablet": ["sdk", "projectPath", "outputPath", "projectName", "device"],
135800             "webworks.bb10": ["sdk", "projectPath", "outputPath", "projectName", "device"],
135801             "webworks.handset": ["sdk", "projectPath", "outputPath", "projectName", "simulator"]
135802         }
135803     },
135804     _settings = {
135805         get: function () {
135806             var settings = db.retrieveObject("build-settings", platform.getPersistencePrefix()) || {};
135807             settings.debug = !!settings["remoteInspector"];
135808
135809             return settings;
135810         },
135811         save: function (settings) {
135812             db.saveObject("build-settings", settings, platform.getPersistencePrefix());
135813         }
135814     },
135815     port = "9910",
135816     host = "http://127.0.0.1:" + port + "/ripple",
135817     progressContainer = jQuery("#options-progress"),
135818     progressInterval,
135819     _passwordFields = [
135820         "signingPassword",
135821         "devicePassword",
135822         "csk_password",
135823         "p12_password"
135824     ],
135825     _checkboxFields = [
135826         "remoteInspector"
135827     ],
135828     _passwords = {},
135829     _self;
135830
135831 function missing(settings, action) {
135832     return required[action][platform.current().id].filter(function (field) {
135833         return !settings.hasOwnProperty(field);
135834     });
135835 }
135836
135837 function _isPasswordField(id) {
135838     var match = typeof id === "string" && new RegExp("^" + id + "$", "i");
135839     return match && utils.some(_passwordFields, function (name) {
135840         return match.test(name);
135841     });
135842 }
135843
135844 function _isCheckboxField(id) {
135845     var match = typeof id === "string" && new RegExp("^" + id + "$", "i");
135846     return match && utils.some(_checkboxFields, function (name) {
135847         return match.test(name);
135848     });
135849 }
135850
135851 function table(action) {
135852     var _table = $("<table class='panel-table'>"),
135853         _row = {
135854             row: function (item, desc, opts) {
135855                 var id = "settings-field-" + item.toLowerCase(),
135856                     input = "",
135857                     save = function () {
135858                         var s = _settings.get(),
135859                             v = $("#" + id).val(),
135860                             val = opts.type === "number" ? parseInt(v, 10) : v;
135861
135862                         if (_isCheckboxField(item)) {
135863                             s[item] = $("#" + id).prop("checked");
135864                         }
135865                         else if (val) {
135866                             (_isPasswordField(item) ? _passwords : s)[item] = val;
135867                         }
135868                         else {
135869                             delete s[item];
135870                         }
135871                         _settings.save(s);
135872
135873                         if (opts.onChanged) {
135874                             opts.onChanged(s[item]);
135875                         }
135876                     },
135877                     row;
135878
135879                 opts = opts || { type: "text" };
135880
135881                 switch (opts.type) {
135882                 case "select":
135883                     input = "<select id='" + id + "' class='ui-state-default ui-corner-all' style='width:100%'/>";
135884                     break;
135885                 case "span":
135886                     input = "<span id = '" + id + "'>" + opts.text + "</span>";
135887                     break;
135888                 default:
135889                     input = "<input id='" + id + "' type='" + opts.type + "' class='ui-state-default ui-corner-all' style='width:90%' />";
135890                     break;
135891                 }
135892
135893                 row = $("<tr>" +
135894                     "<td><label for='" + id + "' class='ui-text-label'>" + desc + "</label></td>" +
135895                     "<td>" + input + "</td>" +
135896                 "</tr>");
135897
135898                 row.appendTo(_table);
135899
135900                 //bind save handlers to the row
135901                 utils.bindAutoSaveEvent(row.find("#" + id).change(save), save);
135902
135903                 return _row;
135904             },
135905             appendTo: function (id) {
135906                 var fs = $("<fieldset class='main'><legend class='cap-text'>" + action + "</legend></fieldset>");
135907
135908                 $(_table).appendTo(fs);
135909                 fs.appendTo($(id));
135910             }
135911         };
135912
135913     return _row;
135914 }
135915
135916 function create() {
135917     var build = table('build'),
135918         sign = table('sign'),
135919         launch = table('launch');
135920
135921     build
135922         .row("sdk", "SDK Path")
135923         .row("projectPath", "Project Root")
135924         .row("projectName", "Archive Name")
135925         .row("outputPath", "Output Folder")
135926         .row("remoteInspector", "Enable Remote Web Inspector", {
135927             type: "checkbox",
135928             onChanged: function (enabled) {
135929                 if (enabled) {
135930                     $("#options-menu-build-warning").show();
135931                     tooltip.create("#options-menu-build-warning", "Remote Web Inspector should be disabled when packaging for App World release");
135932                 }
135933                 else {
135934                     $("#options-menu-build-warning").hide();
135935                 }
135936             }
135937         })
135938         .appendTo("#settings-tabs-build");
135939
135940     switch (platform.current().id) {
135941     case "webworks.handset":
135942         sign.row("signingPassword", "Password", {
135943             type: "password"
135944         });
135945
135946         launch.row("simulator", "Simulator", {
135947             type: "select"
135948         });
135949
135950         launch.row("simulatorstatus", "Simulator", {
135951             type: "span",
135952             text: "Searching for simulators ..."
135953         });
135954         
135955         break;
135956
135957     case "webworks.tablet":
135958         sign.row("csk_password", "CSK Password", {
135959             type: "password"
135960         });
135961         sign.row("p12_password", "P12 Password", {
135962             type: "password"
135963         });
135964         sign.row("bundle_number", "Bundle Number", {
135965             type: "number"
135966         });
135967
135968         launch.row("device", "Playbook IP");
135969         launch.row("devicePassword", "Playbook Password", {
135970             type: "password"
135971         });
135972
135973         break;
135974
135975     case "webworks.bb10":
135976         sign.row("signingPassword", "Signing Password", {
135977             type: "password"
135978         });
135979         sign.row("bundle_number", "Bundle Number", {
135980             type: "number"
135981         });
135982
135983         launch.row("device", "Device IP");
135984         launch.row("devicePassword", "Device Password", {
135985             type: "password"
135986         });
135987
135988         break;
135989     }
135990
135991     sign.appendTo("#settings-tabs-build");
135992     launch.appendTo("#settings-tabs-build");
135993
135994     $("#settings-field-simulator").parent().parent().hide();
135995 }
135996
135997 function populate(settings) {
135998     var fill = function (action, prop) {
135999         var element = $("#settings-field-" + prop.toLowerCase());
136000
136001         if (_isPasswordField(prop)) {
136002             element.val(_passwords[prop]);
136003         }
136004         else if (_isCheckboxField(prop)) {
136005             element.prop("checked", settings[prop]);
136006         }
136007         else {
136008             element.val(settings[prop]);
136009         }
136010     };
136011
136012     fill("build", "sdk");
136013     fill("build", "projectPath");
136014     fill("build", "outputPath");
136015     fill("build", "projectName");
136016     fill("build", "remoteInspector");
136017
136018     fill("sign", "signingPassword");
136019     fill("sign", "csk_password");
136020     fill("sign", "p12_password");
136021     fill("sign", "bundle_number");
136022
136023     fill("launch", "simulator");
136024     fill("launch", "device");
136025     fill("launch", "devicePassword");
136026 }
136027
136028 function url(action) {
136029     var target = "";
136030
136031     switch (platform.current().id) {
136032     case "webworks.bb10":
136033         target = "bb10";
136034         break;
136035     case "webworks.tablet":
136036         target = "tablet";
136037         break;
136038     case "webworks.handset":
136039         target = "smartphone";
136040         break;
136041     }
136042
136043     return host + "/" + action + "/" + target;
136044 }
136045
136046 function enable(action) {
136047     $("#options-menu-" + action).removeClass("not-ready");
136048     if (action === "launch") {
136049         $("#settings-field-simulatorstatus").parent().parent().hide();
136050         $("#settings-field-simulator").parent().parent().show();
136051     }
136052 }
136053
136054 function disable(action) {
136055     $("#options-menu-" + action).addClass("not-ready");
136056     if (action === "launch") {
136057         $("#settings-field-simulatorstatus").parent().parent().show();
136058         $("#settings-field-simulator").parent().parent().hide();
136059     }
136060 }
136061
136062 function getSimulators() {
136063     if (!_settings.get().sdk) {
136064         $("#settings-field-simulatorstatus").text("");
136065         disable("launch");
136066         return;
136067     }
136068
136069     bus.ajax(
136070         "POST",
136071         host + "/simulators",
136072         _settings.get(),
136073         function (resp) {
136074             var sims = resp.data.simulators;
136075
136076             $("#settings-field-simulator").empty();
136077             if (sims.length > 0) {
136078                 $(resp.data.simulators.map(function (sim) {
136079                     return "<option value='" + sim + "'>" + sim + "</option>";
136080                 }).join()).appendTo("#settings-field-simulator");
136081
136082                 enable("launch");
136083             }
136084             else {
136085                 disable("launch");
136086                 $("#settings-field-simulatorstatus").text("No simulators found :(");
136087             }
136088         },
136089         function () {
136090             disable("launch");
136091             $("#settings-field-simulatorstatus").text("Error attempting to get simulators :(");
136092         }
136093     );
136094 }
136095
136096 function _startProgress() {
136097     if (progressInterval) {
136098         window.clearInterval(progressInterval);
136099     }
136100     progressInterval = window.setInterval(function () {
136101         if (progressContainer.html().length === 5) {
136102             progressContainer.html(".");
136103         }
136104         else {
136105             progressContainer.html(progressContainer.html() + ".");
136106         }
136107     }, 250);
136108 }
136109
136110 function _endProgress() {
136111     window.clearInterval(progressInterval);
136112     progressInterval = null;
136113     progressContainer.html("");
136114 }
136115
136116
136117 _self = {
136118     initialize: function () {
136119         $("#settings-dialog").dialog({
136120             autoOpen: false,
136121             modal: true,
136122             width: 700,
136123             title: "Settings",
136124             position: 'center'
136125         }).hide();
136126
136127         $("#settings-tabs").tabs();
136128         $("#settings-action").button();
136129
136130         create();
136131
136132         if (platform.current().id === "webworks.handset") {
136133             enable("build");
136134             enable("sign");
136135             enable("settings");
136136
136137             getSimulators();
136138             $("#settings-field-sdk").change(getSimulators);
136139         }
136140         else if (platform.current().id === "webworks.tablet") {
136141             enable("build");
136142             enable("sign");
136143             enable("launch");
136144             enable("settings");
136145         }
136146         else if (platform.current().id === "webworks.bb10") {
136147             enable("build");
136148             enable("sign");
136149             enable("launch");
136150             enable("settings");
136151         }
136152     },
136153
136154     can: function (action) {
136155         var settings = {};
136156
136157         utils.mixin(_settings.get(), settings);
136158         utils.mixin(_passwords, settings);
136159
136160         return action && missing(settings, action).length === 0;
136161     },
136162
136163     value: function (prop) {
136164         var settings = {};
136165
136166         utils.mixin(_settings.get(), settings);
136167         return settings[prop];
136168     },
136169
136170     show: function (action) {
136171         var settings = {};
136172
136173         utils.mixin(_settings.get(), settings);
136174         utils.mixin(_passwords, settings);
136175
136176         populate(settings);
136177
136178         $("#settings-dialog").dialog("open");
136179         $("#settings-action").button("option", "label", action || "Close")[action ? "show" : "hide"]();
136180
136181         if (action) {
136182             missing(settings, action).forEach(function (field) {
136183                 $("#settings-field-" + field.toLowerCase()).effect("highlight", {color: "red"}, 1500);
136184             });
136185
136186             $("#settings-action").unbind("click").click(function () {
136187                 if (_self.can(action)) {
136188                     _self.perform(action);
136189                     $("#settings-dialog").dialog("close");
136190                 }
136191                 else {
136192                     _self.show(action);
136193                 }
136194             });
136195         }
136196     },
136197
136198     perform: function (action) {
136199         var settings = _settings.get(),
136200             data = {},
136201             poll = function (resp) {
136202                 var notifications = require("ripple/notifications");
136203
136204                 if (resp && resp.code !== 0) {
136205                     notifications.openNotification("error", "Build request failed with message: " + resp.msg);
136206                     _endProgress();
136207                 }
136208                 else {
136209                     if (resp && resp.data.status === "building") {
136210                         setTimeout(function () {
136211                             bus.ajax(
136212                                 "GET",
136213                                 host + "/build_status/" + resp.data.id,
136214                                 null,
136215                                 poll,
136216                                 function (error) {
136217                                     notifications.openNotification("error", "Build request failed with message: " + JSON.stringify(error));
136218                                     _endProgress();
136219                                 }
136220                             );
136221                         }, 500);
136222                     }
136223                     else {
136224                         if (action.match(/sign/)) {
136225                             settings["bundle_number"] = $("#settings-field-bundle_number").val(parseInt($("#settings-field-bundle_number").val(), 10) + 1).val();
136226                             _settings.save(settings);
136227                         }
136228                         notifications.openNotification("normal", "Build succeeded!");
136229                         _endProgress();
136230                     }
136231                 }
136232             };
136233
136234         utils.mixin(settings, data);
136235         utils.mixin(_passwords, data);
136236
136237         bus.ajax(
136238             "POST",
136239             url(action),
136240             data,
136241             function (resp) {
136242                 _startProgress();
136243                 poll(resp);
136244             },
136245             function (error) {
136246                 var message = "Build request failded with message: " + error.data;
136247
136248                 if (error.code === 0 || error.code === 404) {
136249                     message += "<br>This could be due to the Build and Deploy services not running or not being installed";
136250                 }
136251
136252                 notifications.openNotification("error", message);
136253             }
136254         );
136255     }
136256 };
136257
136258 module.exports = _self;
136259
136260 });
136261 define('ripple/ui/plugins/settings-menu', function (require, exports, module) {
136262 /*
136263  *  Copyright 2011 Research In Motion Limited.
136264  *
136265  * Licensed under the Apache License, Version 2.0 (the "License");
136266  * you may not use this file except in compliance with the License.
136267  * You may obtain a copy of the License at
136268  *
136269  * http://www.apache.org/licenses/LICENSE-2.0
136270  *
136271  * Unless required by applicable law or agreed to in writing, software
136272  * distributed under the License is distributed on an "AS IS" BASIS,
136273  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
136274  * See the License for the specific language governing permissions and
136275  * limitations under the License.
136276  */
136277 var utils = require('ripple/utils'),
136278     constants = require('ripple/constants'),
136279     platform = require('ripple/platform'),
136280     db = require('ripple/db'),
136281     _applicationStateId
136282     ;
136283
136284
136285 function reload() {
136286     window.tinyHipposReload = true;
136287     location.reload();
136288 }
136289
136290 function _showSettingMenu() {
136291     var contentTable = "",
136292     settings = [],
136293     _applicationState = [],
136294     _applicationStateTmp = [],
136295     unselectedNum = 0,
136296     i = 0;
136297
136298     if ($("#settings-menu-popup").is(":visible")) {
136299         $("#settings-menu-popup").hide("slide", {direction: "up"}, "slow");
136300         $("#overlayBackground").hide("fade", "slow");
136301         return;
136302     }
136303
136304     _applicationStateId = constants.COMMON.APPLICATION_STATE + platform.current().id;
136305
136306     _applicationStateTmp = db.retrieveObject(_applicationStateId) || [];
136307
136308     utils.forEach(_applicationStateTmp, function (obj) {
136309         if (obj.display)
136310             _applicationState.push(obj);
136311     });
136312
136313     utils.forEach(_applicationStateTmp, function (obj) {
136314         if (!obj.display)
136315             _applicationState.push(obj);
136316     });
136317
136318     $("#settings-menu-content-panel-table").remove();
136319
136320     contentTable = '<table id="settings-menu-content-panel-table" class="settings-menu-content-table">';
136321     utils.forEach(_applicationState, function (obj) {
136322         var checked = obj.display ? 'checked="yes"':"";
136323         contentTable += '<tr><td><input name="panel-display-setting" type="checkbox" class="settings-menu-checkbox "' +
136324                         checked + '></input>' +
136325                         obj.titleName + '</td></tr>\n';
136326     });
136327     contentTable += "</table>";
136328
136329     $("#settings-menu-container-div").append(contentTable);
136330     $("#settings-menu-popup").css("top", 50);
136331     $("#settings-menu-popup").css("left", $(window).width() - 340);
136332
136333     $("#overlayBackground").css("width", $(window).width());
136334     $("#overlayBackground").css("height", $(window).height());
136335     $("#overlayBackground").show("fade", "slow");
136336     $("#settings-menu-popup").show("slide", {direction: "up"}, "slow");
136337
136338     $("#settings-menu-save-btn").unbind('click');
136339     $("#settings-menu-save-btn").bind("click", function (event) {
136340         $("input[name='panel-display-setting']").each(function (i, a) {
136341             settings.push(a.checked);
136342         });
136343
136344         utils.forEach(_applicationState, function (obj) {
136345             if (!settings[i])
136346                 obj.collapsed = true;
136347             obj.display = settings[i];
136348             i++;
136349         }, this);
136350   
136351         db.saveObject(_applicationStateId, _applicationState);
136352         _applicationStateTmp = db.retrieveObject(_applicationStateId) || [];
136353
136354         $("#settings-menu-popup").hide("slide", {direction: "up"}, "slow");
136355         $("#overlayBackground").hide("fade", "slow");
136356         setTimeout(reload, 500);
136357     });
136358
136359     $(".settings-menu-content-table td").unbind('click');
136360     $(".settings-menu-content-table td").bind("click", function (event) {
136361         var checkbox;
136362         if (($(event.target).children().length === 0)) {
136363             return;
136364         } else {
136365             checkbox = $(event.target).children();
136366         }
136367         
136368         if (checkbox.is(':checked')) {
136369             checkbox.prop('checked', false);
136370         }
136371         else
136372             checkbox.prop('checked', true);
136373     });
136374
136375     $("#settings-menu-close-btn").unbind('click');
136376     $("#settings-menu-close-btn").bind("click", function (event) {
136377         if ($("#settings-menu-popup").is(":visible")) {
136378             $("#settings-menu-popup").hide("slide", {direction: "up"}, "slow");
136379             $("#overlayBackground").hide("fade", "slow");
136380             return;
136381         }
136382     });
136383
136384     $(window).bind('resize', function () {
136385         $("#settings-menu-popup").css("top", 50);
136386         $("#settings-menu-popup").css("left", $(window).width() - 340);
136387         $("#overlayBackground").css("width", $(window).width());
136388         $("#overlayBackground").css("height", $(window).height());
136389     });
136390
136391     $(".settings-menu-checkbox").each(function (i, a) {
136392         if (a.checked === false) {
136393             unselectedNum++;
136394         }
136395     });
136396
136397     if (unselectedNum === 0) {
136398         $("#select_unselect_text").text("Unselect All");
136399         $("#panelSettingSelectAll").prop('checked', true);
136400     }
136401
136402     $("#panelSettingSelectAll").unbind('click');
136403     $("#panelSettingSelectAll").bind("click", function (event) {
136404         if ($("#panelSettingSelectAll").is(':checked')) {
136405             $("#select_unselect_text").text("Unselect All");
136406             $(".settings-menu-checkbox").prop('checked', true);
136407         }
136408         else {
136409             $("#select_unselect_text").text("Select All");
136410             $(".settings-menu-checkbox").prop('checked', false);
136411         }
136412     });
136413 }
136414
136415 module.exports = {
136416     initialize: function () {
136417         $("#options-button-panels").bind("click", function (event) {
136418             _showSettingMenu();
136419         });
136420     }
136421 };
136422
136423 });
136424 define('ripple/ui/plugins/settings', function (require, exports, module) {
136425 /*
136426  *  Copyright 2011 Research In Motion Limited.
136427  *
136428  * Licensed under the Apache License, Version 2.0 (the "License");
136429  * you may not use this file except in compliance with the License.
136430  * You may obtain a copy of the License at
136431  *
136432  * http://www.apache.org/licenses/LICENSE-2.0
136433  *
136434  * Unless required by applicable law or agreed to in writing, software
136435  * distributed under the License is distributed on an "AS IS" BASIS,
136436  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
136437  * See the License for the specific language governing permissions and
136438  * limitations under the License.
136439  */
136440 var db = require('ripple/db'),
136441     constants = require('ripple/constants'),
136442     KEY = constants.XHR.PROXY_DISABLED_BUTTON; // TODO: one settings object for all
136443
136444 function _saveAndReload(key, value) {
136445     jWorkflow.order(function (prev, baton) {
136446         baton.take();
136447         db.save(key, value, null, baton.pass);
136448     }).start(function () {
136449         window.tinyHipposReload = true;
136450         location.reload();
136451     });
136452 }
136453
136454 function _initialize(prev, baton) {
136455     var select = document.getElementById("settings-xhr-proxy"),
136456         about = require('ripple/ui/plugins/about-dialog');
136457
136458     select.value = String(db.retrieve(KEY));
136459     select.addEventListener("change", function () {
136460         _saveAndReload(KEY, this.value);
136461     }, false);
136462     
136463     $("#options-menu-about").click(function () {
136464         about.show();
136465     });
136466     // TODO: reload here?
136467 }
136468
136469 module.exports = {
136470     panel: {
136471         domId: "settings-container",
136472         collapsed: true,
136473         pane: "right"
136474     },
136475     initialize: _initialize
136476 };
136477
136478 });
136479 define('ripple/ui/plugins/storage', function (require, exports, module) {
136480 /*
136481  *  Copyright 2011 Research In Motion Limited.
136482  *
136483  * Licensed under the Apache License, Version 2.0 (the "License");
136484  * you may not use this file except in compliance with the License.
136485  * You may obtain a copy of the License at
136486  *
136487  * http://www.apache.org/licenses/LICENSE-2.0
136488  *
136489  * Unless required by applicable law or agreed to in writing, software
136490  * distributed under the License is distributed on an "AS IS" BASIS,
136491  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
136492  * See the License for the specific language governing permissions and
136493  * limitations under the License.
136494  */
136495 var constants = require('ripple/constants'),
136496     event = require('ripple/event'),
136497     platform = require('ripple/platform'),
136498     utils = require('ripple/utils'),
136499     app = require('ripple/app'),
136500     db = require('ripple/db');
136501
136502 function _updatePreferencesView() {
136503     var node = document.getElementById(constants.COMMON.STORAGE_TABLE_BODY_CLASS),
136504         countTitle = document.getElementById(constants.COMMON.STORAGE_COUNT_CONTAINER_ID);
136505
136506     // TODO: convert to appendChild
136507     if (node) {
136508         db.retrieveAll(platform.getPersistencePrefix(), function (results) {
136509             var str = "",
136510                 counter = 0;
136511
136512             utils.forEach(results, function (value, key) {
136513                 // TODO: based of current platform
136514                 if (app.isPreferenceReadOnly(key)) {
136515                     str += '<tr class="ui-text-highlight">';
136516                 } else {
136517                     str += '<tr>';
136518                 }
136519                 str += '<td>' + key + '</td><td>' + value + "</td></tr>";
136520                 counter ++;
136521             });
136522
136523             node.innerHTML = str;
136524             countTitle.innerHTML = counter.toString();
136525
136526             if (counter === 0) {
136527                 jQuery("#" + constants.COMMON.STORAGE_CLEAR_BUTTON_ID).addClass(constants.CSS_PREFIX.IRRELEVANT);
136528             }
136529             else {
136530                 jQuery("#" + constants.COMMON.STORAGE_CLEAR_BUTTON_ID).removeClass(constants.CSS_PREFIX.IRRELEVANT);
136531             }
136532         });
136533     }
136534 }
136535
136536 module.exports = {
136537     panel: {
136538         domId: "preferences",
136539         collapsed: true,
136540         pane: "left"
136541     },
136542     initialize: function () {
136543         jQuery("#preferences-clear-button").bind("click", function () {
136544             db.removeAll(platform.getPersistencePrefix());
136545         });
136546
136547         event.on("StorageUpdatedEvent", function () {
136548             _updatePreferencesView();
136549         });
136550
136551         _updatePreferencesView();
136552     }
136553 };
136554
136555 });
136556 define('ripple/ui/plugins/themeSwitcher', function (require, exports, module) {
136557 /*
136558  *  Copyright 2011 Research In Motion Limited.
136559  *
136560  * Licensed under the Apache License, Version 2.0 (the "License");
136561  * you may not use this file except in compliance with the License.
136562  * You may obtain a copy of the License at
136563  *
136564  * http://www.apache.org/licenses/LICENSE-2.0
136565  *
136566  * Unless required by applicable law or agreed to in writing, software
136567  * distributed under the License is distributed on an "AS IS" BASIS,
136568  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
136569  * See the License for the specific language governing permissions and
136570  * limitations under the License.
136571  */
136572 var utils = require('ripple/utils'),
136573     db = require('ripple/db'),
136574     THEME_KEY = "ui-theme",
136575     THEME_SELECTOR = "#theme-select",
136576     _currentTheme;
136577
136578 function _saveAndReload(key, value) {
136579     jWorkflow.order(function (prev, baton) {
136580                 baton.take();
136581                 db.save(key, value, null, baton.pass);
136582             }).start(function () {
136583                 window.tinyHipposReload = true;
136584                 location.reload();
136585             });
136586 }
136587
136588 module.exports = {
136589     initialize: function () {
136590         var themeToSet = db.retrieve(THEME_KEY);
136591
136592         // Hide the theme switcher and always set the theme to light
136593         jQuery(".theme-switcher").hide();
136594                 if (themeToSet !== "light") {
136595             _saveAndReload(THEME_KEY, "light");
136596                 }
136597                 return;
136598     }
136599 };
136600
136601 });
136602 define('ripple/ui/plugins/time', function (require, exports, module) {
136603 /*
136604  *  Copyright 2012 Intel Corporation.
136605  *
136606  * Licensed under the Apache License, Version 2.0 (the "License");
136607  * you may not use this file except in compliance with the License.
136608  * You may obtain a copy of the License at
136609  *
136610  * http://www.apache.org/licenses/LICENSE-2.0
136611  *
136612  * Unless required by applicable law or agreed to in writing, software
136613  * distributed under the License is distributed on an "AS IS" BASIS,
136614  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
136615  * See the License for the specific language governing permissions and
136616  * limitations under the License.
136617  */
136618
136619 function _init() {
136620     var db = require('ripple/db'),
136621         utils = require('ripple/utils'),
136622         allTZ, dbTZ, node = jQuery("#time-locale-select"),
136623         timezone = require('ripple/platform/tizen/2.0/timezone_info'),
136624         event = require('ripple/event'),
136625         alarms, time;
136626
136627     function triggerAlarm() {
136628         time = new Date();
136629         alarms = db.retrieveObject("tizen1.0-db-alarms");
136630         if (alarms !== null) {
136631             utils.forEach(alarms, function (obj) {
136632                 if (obj.id !== undefined) {
136633                     event.trigger("CheckAlarm", [obj.id]);
136634                 }
136635             });
136636         }
136637     }
136638     window.setInterval(triggerAlarm, 1000);
136639
136640     allTZ = timezone.getAllTimezone();
136641     utils.forEach(allTZ, function (tz) {
136642         node.append(utils.createElement("option", {
136643             "value": tz,
136644             "innerHTML": tz + " - " + timezone.getTimezoneAbbr(tz) + "(" + timezone.getTimezoneDiff(tz) + ")"
136645         }));
136646     });
136647     dbTZ = db.retrieve("tizen-timezone");
136648     if (timezone.isValidTimezone(dbTZ)) {
136649         node.val(dbTZ);
136650     } else {
136651         db.save("tizen-timezone", node.val());
136652     }
136653     node.bind("change", function () {
136654         db.save("tizen-timezone", node.val());
136655     });
136656 /* FIXME: Node "trigger-alarm-id" will be removed from Time panel
136657  *        due to "time" panel will changed to "time zone" panel(PTSDK-875)
136658
136659     event.on("SendTriggerAppId", function (applicationId) {
136660         if (timeId !== undefined)
136661             clearTimeout(timeId);
136662         triggerNode.empty();
136663         triggerNode.append(utils.createElement("p", {
136664             "innerHTML": applicationId + " is triggered"
136665         }));
136666         triggerNode.show();
136667         timeId = setTimeout("jQuery('#trigger-alarm-id').empty();", 10000);// Comments will disappear after 10s
136668     });
136669 */
136670 }
136671
136672 module.exports = {
136673     panel: {
136674         domId: "time-container",
136675         collapsed: true,
136676         pane: "right",
136677         titleName: "Time",
136678         display: true
136679     },
136680     initialize: _init
136681 };
136682
136683 });
136684 define('ripple/ui/plugins/tooltip', function (require, exports, module) {
136685 /*
136686  *  Copyright 2011 Research In Motion Limited.
136687  *
136688  * Licensed under the Apache License, Version 2.0 (the "License");
136689  * you may not use this file except in compliance with the License.
136690  * You may obtain a copy of the License at
136691  *
136692  * http://www.apache.org/licenses/LICENSE-2.0
136693  *
136694  * Unless required by applicable law or agreed to in writing, software
136695  * distributed under the License is distributed on an "AS IS" BASIS,
136696  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
136697  * See the License for the specific language governing permissions and
136698  * limitations under the License.
136699  */
136700 var utils = require('ripple/utils'),
136701     _options = {
136702         track: true,
136703         delay: 0,
136704         showURL: false,
136705         fade: 250,
136706         extraClass: "ui-state-highlight ui-corner-all"
136707     };
136708
136709 module.exports = {
136710     create: function (element, message) {
136711         var options = utils.copy(_options);
136712
136713         options.bodyHandler = function () {
136714             return message;
136715         };
136716
136717         return jQuery(element).tooltip(options);
136718     },
136719
136720     toggle: function () {
136721         jQuery.tooltip.block();
136722         return this.isOff();
136723     },
136724
136725     isOff: function () {
136726         return jQuery.tooltip.blocked;
136727     }
136728 };
136729
136730 });
136731 define('ripple/ui/plugins/tooltips', function (require, exports, module) {
136732 /*
136733  *  Copyright 2011 Research In Motion Limited.
136734  *
136735  * Licensed under the Apache License, Version 2.0 (the "License");
136736  * you may not use this file except in compliance with the License.
136737  * You may obtain a copy of the License at
136738  *
136739  * http://www.apache.org/licenses/LICENSE-2.0
136740  *
136741  * Unless required by applicable law or agreed to in writing, software
136742  * distributed under the License is distributed on an "AS IS" BASIS,
136743  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
136744  * See the License for the specific language governing permissions and
136745  * limitations under the License.
136746  */
136747 // Class: UI.Tooltips
136748 // Purpose: build tooltips for UI
136749 // See here for Tooltip Options
136750 // http://jquery.bassistance.de/tooltip/demo/
136751 var utils = require('ripple/utils'),
136752     tooltip = require('ripple/ui/plugins/tooltip'),
136753     constants = require('ripple/constants'),
136754     db = require('ripple/db'),
136755     utils = require('ripple/utils');
136756
136757 function _updateButtonText() {
136758     document.querySelector("#settings-toggletooltips > span")
136759             .innerHTML = "Turn " + (tooltip.isOff() ? "On" : "Off");
136760 }
136761
136762 module.exports = {
136763     initialize: function () {
136764         var saved = db.retrieve(constants.SETTINGS.TOOLTIPS_KEY);
136765
136766         // blarg, tooltips are always enabled so if its saved to false disable it
136767         if (!tooltip.isOff() && (saved === "false" || saved === false)) {
136768             tooltip.toggle();
136769         }
136770
136771         _updateButtonText();
136772
136773         jQuery(constants.SETTINGS.TOOLTIPS_TOGGLE_DIV).click(function () {
136774             db.save(constants.SETTINGS.TOOLTIPS_KEY, !tooltip.toggle());
136775             _updateButtonText();
136776         });
136777     }
136778 };
136779
136780 });
136781 define('ripple/ui/plugins/touchEvent', function (require, exports, module) {
136782 /*
136783  *  Copyright 2012 Intel Corporation
136784  *
136785  * Licensed under the Apache License, Version 2.0 (the "License");
136786  * you may not use this file except in compliance with the License.
136787  * You may obtain a copy of the License at
136788  *
136789  * http://www.apache.org/licenses/LICENSE-2.0
136790  *
136791  * Unless required by applicable law or agreed to in writing, software
136792  * distributed under the License is distributed on an "AS IS" BASIS,
136793  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
136794  * See the License for the specific language governing permissions and
136795  * limitations under the License.
136796  */
136797
136798 var event = require('ripple/event'),
136799     db = require('ripple/db'),
136800     constants = require('ripple/constants'),
136801     colors  = ["red", "green", "magenta", "blue", "yellow"],
136802     Point,
136803     intervalId,
136804     moveEvents  = {},
136805     currentIndex = 0,
136806     enlargeRatio = 4;
136807
136808 function _exec(operation) {
136809     var canvas = document.getElementById(constants.TOUCHEVENT.CANVAS),
136810         cxt = canvas.getContext("2d"),
136811         altKey = document.getElementById(constants.TOUCHEVENT.ALTKEY),
136812         metaKey = document.getElementById(constants.TOUCHEVENT.METAKEY),
136813         ctrlKey = document.getElementById(constants.TOUCHEVENT.CTRLKEY),
136814         shiftKey = document.getElementById(constants.TOUCHEVENT.SHIFTKEY),
136815         key, eventType;
136816
136817     if (operation === "start") {
136818         altKey.disabled = 'disabled';
136819         metaKey.disabled = 'disabled';
136820         ctrlKey.disabled = 'disabled';
136821         shiftKey.disabled = 'disabled';
136822         clearInterval(intervalId);
136823         currentIndex = 0;
136824         eventType = "touchEvent";
136825     } else if (operation === "cancel") {
136826         altKey.disabled = '';
136827         metaKey.disabled = '';
136828         ctrlKey.disabled = '';
136829         shiftKey.disabled = '';
136830         altKey.checked = false;
136831         metaKey.checked = false;
136832         ctrlKey.checked = false;
136833         shiftKey.checked = false;
136834         cxt.clearRect(0, 0, canvas.width, canvas.height);
136835         moveEvents = {};
136836         eventType = "touchCancel";
136837     }
136838
136839     event.trigger(eventType, [{
136840         data : moveEvents,
136841         keys : [altKey.checked, metaKey.checked, ctrlKey.checked, shiftKey.checked]
136842     }]);
136843 }
136844
136845 Point = function (x, y, color, isDragging) {
136846     var _self = {};
136847
136848     _self.x = x;
136849     _self.y = y;
136850     _self.color = color;
136851     _self.isDragging = isDragging;
136852
136853     return _self;
136854 };
136855
136856 module.exports = {
136857     panel: {
136858         domId: "touchEvent-container",
136859         collapsed: true,
136860         pane: "left",
136861         titleName: "Touch Event",
136862         display: true
136863     },
136864
136865     initialize: function () {
136866         var deviceInfo = require('ripple/devices').getCurrentDevice(),
136867             canvas = document.getElementById(constants.TOUCHEVENT.CANVAS),
136868             button = document.getElementById(constants.TOUCHEVENT.OPTION),
136869             cxt = canvas.getContext("2d"),
136870             points = [],
136871             paint = false,
136872             currentPoint = {};
136873
136874         function drawPoints() {
136875             var key, index, points = [], point;
136876
136877             for (key in moveEvents) {
136878                 points = moveEvents[key];
136879                 cxt.fillStyle = colors[key];
136880
136881                 for (index = 0; index < points.length; index++) {
136882                     point = points[index];
136883                     cxt.beginPath();
136884                     cxt.arc(point.offsetX, point.offsetY, 5, 0, 2 * Math.PI, 1);
136885                     cxt.fill();
136886                 }
136887             }
136888         }
136889
136890         function endDraw(event) {
136891             if (paint) {
136892                 paint = false;
136893                 clearInterval(intervalId);
136894                 moveEvents[currentIndex].push(event);
136895                 drawPoints();
136896
136897                 currentIndex++;
136898                 if (currentIndex === 5)
136899                     currentIndex = 0;
136900             }
136901         }
136902
136903         canvas.addEventListener("mousedown", function (event) {
136904             if (button.value === "Touch Cancel") {
136905                 button.value = "Touch Start";
136906                 _exec("cancel");
136907             }
136908             moveEvents[currentIndex] = [];
136909             currentPoint = event;
136910             moveEvents[currentIndex].push(event);
136911             paint = true;
136912             drawPoints();
136913             intervalId = setInterval(function () {
136914                 moveEvents[currentIndex].push(currentPoint);
136915             }, 100);
136916         });
136917
136918         canvas.addEventListener("mousemove", function (event) {
136919             if (paint) {
136920                 currentPoint = event;
136921                 drawPoints();
136922             }
136923         });
136924
136925         canvas.addEventListener("mouseup", endDraw);
136926         canvas.addEventListener("mouseout", endDraw);
136927         canvas.addEventListener("mouseleave", endDraw);
136928
136929         document.getElementById(constants.TOUCHEVENT.OPTION).addEventListener("click", function () {
136930             if (!moveEvents[0])
136931                 return;
136932
136933             if (this.value === "Touch Start") {
136934                 this.value = "Touch Cancel";
136935                 _exec("start");
136936             } else if (this.value === "Touch Cancel") {
136937                 this.value = "Touch Start";
136938                 _exec("cancel");
136939             }
136940         }, false);
136941
136942         canvas.width = deviceInfo.screen.width / enlargeRatio;
136943         canvas.height = deviceInfo.screen.height / enlargeRatio;
136944     }
136945 };
136946
136947 });
136948 define('ripple/ui/plugins/videoPlayer', function (require, exports, module) {
136949 /*
136950  *  Copyright 2011 Research In Motion Limited.
136951  *
136952  * Licensed under the Apache License, Version 2.0 (the "License");
136953  * you may not use this file except in compliance with the License.
136954  * You may obtain a copy of the License at
136955  *
136956  * http://www.apache.org/licenses/LICENSE-2.0
136957  *
136958  * Unless required by applicable law or agreed to in writing, software
136959  * distributed under the License is distributed on an "AS IS" BASIS,
136960  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
136961  * See the License for the specific language governing permissions and
136962  * limitations under the License.
136963  */
136964 var constants = require('ripple/constants'),
136965     event = require('ripple/event');
136966
136967 module.exports = {
136968     initialize: function () {
136969         var videoObj,
136970             videoProgress = document.getElementById(constants.COMMON.MULTIMEDIA_VIDEO_PROGRESS_ID);
136971
136972         event.on("MultimediaAppVideoPlayerCreated", function (videoDOMObj) {
136973             videoObj = videoDOMObj;
136974
136975             videoObj.addEventListener("timeupdate", function () {
136976                 var s = parseInt(videoObj.currentTime % 60, 10),
136977                     m = parseInt((videoObj.currentTime / 60) % 60, 10);
136978
136979                 videoProgress.innerText = ((m > 9) ? m  : "0" + m) + ':' + ((s > 9) ? s  : "0" + s);
136980             }, false);
136981         });
136982
136983         event.on("MultimediaVolumeChanged", function (volume) {
136984             if (videoObj) {
136985                 videoObj.volume = parseFloat(volume / 10);
136986             }
136987         });
136988
136989         event.on("MultimediaVideoStateChanged", function (state) {
136990             document.getElementById(constants.COMMON.MULTIMEDIA_VIDEO_STATE_FIELD_ID).innerText = state;
136991             document.getElementById(constants.COMMON.MULTIMEDIA_VIDEO_FILE_FIELD_ID).innerText = videoObj.getAttribute("src");
136992         });
136993     }
136994 };
136995
136996 });
136997 define('ripple/ui/plugins/widgetConfig', function (require, exports, module) {
136998 /*
136999  *  Copyright 2011 Research In Motion Limited.
137000  *
137001  * Licensed under the Apache License, Version 2.0 (the "License");
137002  * you may not use this file except in compliance with the License.
137003  * You may obtain a copy of the License at
137004  *
137005  * http://www.apache.org/licenses/LICENSE-2.0
137006  *
137007  * Unless required by applicable law or agreed to in writing, software
137008  * distributed under the License is distributed on an "AS IS" BASIS,
137009  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
137010  * See the License for the specific language governing permissions and
137011  * limitations under the License.
137012  */
137013 var constants = require('ripple/constants'),
137014     event = require('ripple/event'),
137015     utils = require('ripple/utils'),
137016     exception = require('ripple/exception'),
137017     tooltip = require('ripple/ui/plugins/tooltip'),
137018     platform = require('ripple/platform'),
137019     widgetConfig = require('ripple/widgetConfig');
137020
137021 function _buildConfigAccordionNode(node, accordionContainer, counter) {
137022     var nodeDiv, nodeTitleH3, nodeContentDiv, tableString, attribute, child, result,
137023         tableClass, nameClass, attributeNameClass, messageClass, nameId, messageId, attributeName, attributeValue, attributeMessage,
137024         helpText = {},
137025         nodeCounter = 0,
137026         attributeCounter = 0,
137027         moreNodes = node.validationResult,
137028         createTooltip = function (value, index) {
137029             tooltip.create("#" +  index, value);
137030         };
137031
137032     while (moreNodes) {
137033         result = node.validationResult[nodeCounter];
137034
137035         if (!result) {
137036             // this should never happen
137037             return;
137038         }
137039
137040         // the container of the entire accordion block
137041         nodeDiv = utils.createElement("div", {
137042             "id": "config-accordion-node-content-" + counter + "-" + nodeCounter,
137043             "class": "ui-corner-all"
137044         });
137045
137046         // the header bar of the accordion block
137047         nodeTitleH3 = utils.createElement("h3", {
137048             "id": "config-accordion-node-title-" + counter + "-" + nodeCounter,
137049             "class": "config-accordion-node-title"
137050         });
137051
137052         nodeTitleH3.appendChild(utils.createElement("a", {
137053             href: "#",
137054             innerText: node.nodeName,
137055             "class": constants.CONFIG.SUCCESS_CSS[(result.valid === undefined) ? "missing" : result.valid.toString()]
137056         }));
137057         nodeDiv.appendChild(nodeTitleH3);
137058
137059         if (node.helpText) {
137060             helpText[nodeTitleH3.id] = node.helpText;
137061         }
137062
137063         nodeContentDiv = utils.createElement("div");
137064
137065         // display node value (add tool tip if exists)
137066         if (node.type || (!node.type && result && result.value)) {
137067             nodeContentDiv.appendChild(utils.createElement("div", {
137068                 "id": "config-accordion-node-content-value-" + counter + "-" + nodeCounter,
137069                 "class": "config-accordion-node-content-value",
137070                 "innerHTML": "<span>Value:</span>" + (result.value || "")
137071             }));
137072
137073             if (node.helpValueText) {
137074                 helpText["config-accordion-node-content-value-" + counter + "-" + nodeCounter] = node.helpValueText;
137075             }
137076         }
137077
137078         // display node message if failed validation
137079         if (result && result.message) {
137080             nodeContentDiv.appendChild(utils.createElement("div", {
137081                 "id": "config-accordion-node-content-value-message-" + counter + "-" + nodeCounter,
137082                 "class": "config-accordion-node-content-value-message ui-text-fail",
137083                 "innerHTML": "<span>Message:</span>" + result.message
137084             }));
137085         }
137086
137087         // display node attributes with name, value, message if failed validation
137088         if (result.attributes) {
137089             nodeContentDiv.appendChild(utils.createElement("div", {
137090                 "id": "config-accordion-node-content-attributes-title-" + counter + "-" + nodeCounter,
137091                 "class": "config-accordion-node-content-attributes-title",
137092                 "innerHTML": "Attributes..."
137093             }));
137094
137095             tableClass = "preferences-table";
137096             nameClass = "config-attributes-name-value";
137097             attributeNameClass = "ui-text-label";
137098             messageClass = "config-attributes-message";
137099
137100             tableString = '<table class="' + tableClass + ' ui-widget-content">';
137101             for (attribute in result.attributes) {
137102                 if (result.attributes.hasOwnProperty(attribute)) {
137103                     nameId = "config-accordion-node-content-attributes-table-name-" + counter + "-" + nodeCounter + "-" + attributeCounter;
137104                     messageId = "config-accordion-node-content-attributes-table-message-" + counter + "-" + nodeCounter + "-" + attributeCounter;
137105                     attributeName = result.attributes[attribute].attributeName;
137106                     attributeValue = result.attributes[attribute].value || "&nbsp;";
137107                     attributeMessage = result.attributes[attribute].message || null;
137108
137109                     tableString += '<tr class="' + nameClass + '" id="' + nameId + '">' +
137110                             '<td class="' + attributeNameClass + '">' + attributeName + '</td>' +
137111                             '<td>' + attributeValue + '</td></tr>';
137112
137113                     if (node.attributes[attributeName].helpText) {
137114                         helpText[nameId] = node.attributes[attributeName].helpText;
137115                     }
137116
137117                     if (attributeMessage !== null) {
137118                         tableString += "<tr class=" + messageClass + " id=" + messageId + "><td colspan=\"2\">" +
137119                                 attributeMessage + "</td></tr>";
137120                     }
137121                     attributeCounter++;
137122                 }
137123             }
137124             tableString += "</table>";
137125
137126             nodeContentDiv.innerHTML += tableString;
137127         }
137128
137129
137130         nodeDiv.appendChild(nodeContentDiv);
137131         accordionContainer.appendChild(nodeDiv);
137132
137133         utils.forEach(helpText, createTooltip);
137134
137135         nodeCounter ++;
137136
137137         if (!node.validationResult[nodeCounter]) {
137138             nodeCounter = 0;
137139             moreNodes = false;
137140         }
137141     }
137142
137143     if (node.children) {
137144         for (child in node.children) {
137145             if (node.children.hasOwnProperty(child)) {
137146                 counter ++;
137147                 _buildConfigAccordionNode(node.children[child], accordionContainer, counter);
137148             }
137149         }
137150     }
137151 }
137152
137153 function _initializeConfigResultsView(results) {
137154     try {
137155         var rootNode,
137156             accordionContainer = document.getElementById("widget-config");
137157
137158         accordionContainer.innerHTML = "";
137159         if (!results) {
137160             accordionContainer.appendChild(utils.createElement("div", {
137161                 "class": "config-accordion-node-title " + constants.CONFIG.SUCCESS_CSS["false"],
137162                 "innerHTML": "Expected to find a configuration file for your application, but none is present. Please create" +
137163                         " a configuration file with the following name in the root directory of your application: " +
137164                         platform.current().fileName
137165             }));
137166             return;
137167         }
137168
137169         rootNode = results[results.rootElement];
137170
137171         _buildConfigAccordionNode(rootNode, accordionContainer, 0);
137172
137173         jQuery(function () {
137174             var stop = false;
137175             jQuery("#widget-config h3").click(function (event) {
137176                 if (stop) {
137177                     event.stopImmediatePropagation();
137178                     event.preventDefault();
137179                     stop = false;
137180                 }
137181             });
137182             jQuery("#widget-config").accordion("destroy").accordion({
137183                 header: "> div > h3",
137184                 autoHeight: false
137185             });
137186         });
137187     } catch (e) {
137188         exception.handle(e, true);
137189     }
137190 }
137191
137192 event.on("FrameHistoryChange", function () {
137193     module.exports.initialize();
137194 });
137195
137196 module.exports = {
137197     panel: {
137198         domId: "config-container",
137199         collapsed: true,
137200         pane: "right",
137201         titleName: "Application Configuration",
137202         display: true
137203     },
137204     initialize: function () {
137205         var results = widgetConfig.getValidationResults();
137206         _initializeConfigResultsView(results);
137207     }
137208 };
137209
137210 });
137211 define('ripple/ui/themes', function (require, exports, module) {
137212 /*
137213  *  Copyright 2011 Research In Motion Limited.
137214  *
137215  * Licensed under the Apache License, Version 2.0 (the "License");
137216  * you may not use this file except in compliance with the License.
137217  * You may obtain a copy of the License at
137218  *
137219  * http://www.apache.org/licenses/LICENSE-2.0
137220  *
137221  * Unless required by applicable law or agreed to in writing, software
137222  * distributed under the License is distributed on an "AS IS" BASIS,
137223  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
137224  * See the License for the specific language governing permissions and
137225  * limitations under the License.
137226  */
137227 //module.exports = ["dark", "light"];
137228 module.exports = ["light"];
137229
137230 });
137231 define('ripple/ui', function (require, exports, module) {
137232 /*
137233  *  Copyright 2011 Research In Motion Limited.
137234  *
137235  * Licensed under the Apache License, Version 2.0 (the "License");
137236  * you may not use this file except in compliance with the License.
137237  * You may obtain a copy of the License at
137238  *
137239  * http://www.apache.org/licenses/LICENSE-2.0
137240  *
137241  * Unless required by applicable law or agreed to in writing, software
137242  * distributed under the License is distributed on an "AS IS" BASIS,
137243  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
137244  * See the License for the specific language governing permissions and
137245  * limitations under the License.
137246  */
137247 var _self,
137248     db = require('ripple/db'),
137249     platform = require('ripple/platform'),
137250     constants = require('ripple/constants'),
137251     utils = require('ripple/utils'),
137252     exception = require('ripple/exception'),
137253     event = require('ripple/event'),
137254     themes = require('ripple/ui/themes'),
137255     _applicationStateId,
137256     _applicationState,
137257     _availablePanels,
137258     _applicationStateTmp,
137259     _systemPlugins = [
137260         "options",
137261         "about-dialog",
137262         "settings-dialog",
137263         "exec-dialog",
137264         "firstRunCheck",
137265         "eulaCheck",
137266         "devices",
137267         "goodVibrations",
137268         "panelCollapse",
137269         "platform",
137270         "information",
137271         "layout",
137272         "notifications",
137273         "themeSwitcher",
137274         "settings-menu",
137275         "configWindow",
137276         "HWKeys"
137277         //"launchingHistory"
137278     ],
137279     _overlay = {
137280         getOrCreate: function (id) {
137281             var _container = document.getElementById(constants.COMMON.HTML_CONTAINER),
137282                 _overlays = document.getElementById("overlay-views"),
137283                 _overlay = _overlays.children[id],
137284                 _hide = function (node) {
137285                     node.setAttribute("style", "display: none");
137286                 },
137287                 _show = function (node) {
137288                     node.setAttribute("style", "display: block");
137289                 },
137290                 _trigger = function (callback) {
137291                     if (callback) {
137292                         callback.apply(null, [_overlay]);
137293                     }
137294                 };
137295
137296
137297             if (!_overlay) {
137298                 _overlay = utils.createElement("section", {id: id, "class": "overlay"});
137299                 _overlays.appendChild(_overlay);
137300             }
137301
137302             return {
137303                 hide: function (callback) {
137304                     _hide(_overlay);
137305                     _show(_container);
137306                     _trigger(callback);
137307                 },
137308                 show: function (callback, showContainer) {
137309                     _show(_overlay);
137310                     if (!showContainer) {
137311                         _hide(_container);
137312                     }
137313                     _trigger(callback);
137314                 }
137315             };
137316         }
137317     };
137318
137319 function _addUIPaneItemsToApplicationState(arrayObj, pane) {
137320     utils.forEach(arrayObj, function (domId) {
137321         var collapsed = jQuery("#" + domId + " .info")[0];
137322         collapsed = (collapsed.style && collapsed.style.display === "none") ? true : false;
137323         utils.forEach(_applicationStateTmp, function (obj) {
137324             if (obj.domId === domId) {
137325                 _applicationState.push({
137326                     "domId": domId,
137327                     "collapsed": collapsed,
137328                     "pane": pane,
137329                     "titleName" : obj.titleName,
137330                     "display" : obj.display
137331                 });
137332                 _applicationStateTmp.splice(_applicationStateTmp.indexOf(obj), 1);
137333                 return;
137334             }
137335         }, this);
137336     }, this);
137337
137338     utils.forEach(_applicationStateTmp, function (obj) {
137339         _applicationState.push({
137340             "domId": obj.domId,
137341             "collapsed": obj.collapsed,
137342             "pane": obj.pane,
137343             "titleName" : obj.titleName,
137344             "display" : obj.display
137345         });
137346     });
137347 }
137348
137349 function _currentlyEnabledTheme() {
137350     var qsSet = utils.queryString().theme,
137351         current = db.retrieve("ui-theme") || themes[0];
137352
137353     function matches(something) {
137354         return function (item) {
137355             return something === item;
137356         };
137357     }
137358
137359     if (qsSet && themes.some(matches(qsSet))) {
137360         current = qsSet;
137361         db.save("ui-theme", qsSet);
137362     }
137363
137364     return current;
137365 }
137366
137367 function _insertStyleSheets() {
137368     var uiTheme = db.retrieve("ui-theme") || require('ripple/ui/themes')[0],
137369         extensionURL = jQuery("#extension-url").text(),
137370         uiThemeURL = extensionURL + "themes/" + uiTheme + "/theme.css",
137371         head = document.getElementsByTagName('head')[0];
137372
137373     function stylesheet(src) {
137374         var scriptElement = document.createElement("link");
137375         scriptElement.setAttribute("href", src);
137376         scriptElement.setAttribute("type", "text/css");
137377         scriptElement.setAttribute("rel", "stylesheet");
137378         return scriptElement;
137379     }
137380
137381     head.appendChild(stylesheet(uiThemeURL));
137382 }
137383
137384 function _collapsePannels(side) {
137385     var collapseNode = [],
137386         event = document.createEvent("UIEvent");
137387
137388     collapseNode = side === "left" ? document.getElementsByClassName("left-panel-collapse") : 
137389                                      document.getElementsByClassName("right-panel-collapse");
137390     
137391     if (collapseNode.length > 0) {
137392         event.initEvent("click", true, true);
137393         collapseNode[0].dispatchEvent(event);    
137394     }
137395 }
137396
137397 function _initializeUI() {
137398     _applicationStateId = constants.COMMON.APPLICATION_STATE + platform.current().id;
137399     _applicationState = db.retrieveObject(_applicationStateId) || [];
137400     _insertStyleSheets();
137401
137402     var leftPanelSection = jQuery(".left"),
137403         uiBoxToggleEngaged = false;
137404
137405     //clean up
137406     db.remove("ui-application-state");
137407     utils.forEach(_availablePanels, function (obj) {
137408         var matchingDomId = function (panel) {
137409             return panel.domId === obj.domId;
137410         };
137411         if (!utils.some(_applicationState, matchingDomId)) {
137412             _applicationState.push({
137413                 "domId": obj.domId,
137414                 "collapsed": obj.collapsed,
137415                 "pane": obj.pane,
137416                 "titleName" : obj.titleName,
137417                 "display" : obj.display
137418             });
137419         }
137420     });
137421
137422     utils.forEach(_applicationState, function (obj) {
137423         var node = jQuery("#" + obj.domId),
137424             imgNode = node.find(".ui-box-TitleImage"),
137425             matchingDomId = function (panel) {
137426                 return panel.domId === obj.domId;
137427             };
137428
137429         if (node.length > 0) {
137430             if (!utils.some(_availablePanels, matchingDomId)) {
137431                 node.parent()[0].removeChild(node[0]);
137432             }
137433             else {
137434                 if (obj.display !== false) {
137435                     leftPanelSection.append(node.parent()[0].removeChild(node[0]));
137436                     if (!obj.collapsed) {
137437                         node.find(".info")
137438                             .css({
137439                             "display": "block"
137440                         })
137441                         .end()
137442                         .addClass("ui-box-open");
137443                         imgNode.addClass("ui-box-TitleImageOpen");
137444                     }
137445                 }
137446             }
137447         }
137448     });
137449
137450     db.saveObject(_applicationStateId, _applicationState);
137451
137452     event.on("ApplicationState", function () {
137453         try {
137454             var leftArray = jQuery(".left").sortable('toArray');
137455             _applicationStateTmp = [];
137456             _applicationStateTmp = utils.copy(_applicationState);
137457             _applicationState = [];
137458             _addUIPaneItemsToApplicationState(leftArray, "left");
137459
137460             if (leftArray.length === 0) {
137461                 _collapsePannels("left");
137462             }
137463
137464             db.saveObject(_applicationStateId, _applicationState);
137465         }
137466         catch (e) {
137467             exception.handle(e);
137468         }
137469     });
137470
137471     jQuery(".left").sortable({
137472         handle: ".drag-handle",
137473         revert: true,
137474         placeholder: 'ui-sortable-highlight ui-corner-all',
137475         connectWith: [".left"],
137476         scroll: true,
137477         update: function (uiEvent, ui) {
137478             event.trigger("ApplicationState");
137479         }
137480     });
137481
137482     jQuery(".left").sortable({ axis: 'y' });
137483
137484     jQuery(".collapse-handle").bind("click", function () {
137485         if (!uiBoxToggleEngaged) {
137486
137487             uiBoxToggleEngaged = true;
137488
137489             var jNode = jQuery(this).parentsUntil(".ui-box"),
137490                     pNode = jNode.parent(),
137491                     isOpen = pNode.hasClass("ui-box-open"),
137492                     imgNode = jQuery(this).find(".ui-box-TitleImage");
137493
137494             if (!isOpen) {
137495                 pNode.addClass("ui-box-open");
137496                 imgNode.removeClass("ui-box-TitleImageClosed");
137497                 imgNode.addClass("ui-box-TitleImageOpen");
137498             }
137499
137500             jQuery(this).parent().next().toggle("blind", {}, 300, function () {
137501                 if (isOpen) {
137502                     pNode.removeClass("ui-box-open");
137503                     imgNode.removeClass("ui-box-TitleImageOpen");
137504                     imgNode.addClass("ui-box-TitleImageClosed");
137505                 }
137506                 event.trigger("ApplicationState", [pNode]);
137507                 uiBoxToggleEngaged = false;
137508             });
137509         }
137510     });
137511 }
137512
137513 function _db_upgrade_for_release() {
137514     var version = db.retrieve(constants.RELEASE_VERSION);
137515
137516     // version: 20121115 is the first release version
137517     if (version === null || version === undefined || Number(version) < 20130417) {
137518         db.remove(constants.COMMON.APPLICATION_STATE + "tizen");
137519         db.remove(constants.COMMON.APPLICATION_STATE + "cordova");
137520         db.remove("tizen1-db-application");
137521         db.remove("tizen-db-package");
137522         version = 20130417;
137523         db.save(constants.RELEASE_VERSION, version);
137524     }
137525 }
137526
137527 _self = module.exports = {
137528     initialize: function () {
137529         var plugins = _systemPlugins.concat(platform.current().ui.plugins || []).map(function (name) {
137530                 return require('ripple/ui/plugins/' + name);
137531             }),
137532             boot = jWorkflow.order(_initializeUI);
137533
137534         _db_upgrade_for_release();
137535         _availablePanels = [];
137536
137537         plugins.forEach(function (plugin) {
137538             if (plugin.initialize) {
137539                 boot.andThen(plugin.initialize);
137540             }
137541
137542             if (plugin.panel) {
137543                 _availablePanels.push(plugin.panel);
137544             }
137545         });
137546
137547         boot.start();
137548     },
137549
137550     getSystemPlugins: function () {
137551         return utils.copy(_systemPlugins);
137552     },
137553
137554     register: function (plugin) {
137555         _systemPlugins.push(plugin);
137556     },
137557
137558     registered: function (plugin) {
137559         return _systemPlugins.indexOf(plugin) >= 0;
137560     },
137561
137562     getExtensionURL: function () {
137563         return jQuery("#" + constants.COMMON.EXTENSION_URL_CONTAINER).text();
137564     },
137565
137566     showOverlay: function (id, callback, showContainer) {
137567         _overlay.getOrCreate(id).show(callback, showContainer);
137568     },
137569
137570     hideOverlay: function (id, callback) {
137571         _overlay.getOrCreate(id).hide(callback);
137572     }
137573 };
137574
137575 });
137576 define('ripple/utils', function (require, exports, module) {
137577 /*
137578  *  Copyright 2011 Research In Motion Limited.
137579  *
137580  * Licensed under the Apache License, Version 2.0 (the "License");
137581  * you may not use this file except in compliance with the License.
137582  * You may obtain a copy of the License at
137583  *
137584  * http://www.apache.org/licenses/LICENSE-2.0
137585  *
137586  * Unless required by applicable law or agreed to in writing, software
137587  * distributed under the License is distributed on an "AS IS" BASIS,
137588  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
137589  * See the License for the specific language governing permissions and
137590  * limitations under the License.
137591  */
137592 var self,
137593     exception = require('ripple/exception'),
137594     constants = require('ripple/constants'),
137595     _HtmlElements = ['header', 'footer', 'section', 'aside', 'nav', 'article'];
137596
137597 self = module.exports = {
137598     validateNumberOfArguments: function (lowerBound, upperBound, numberOfArguments, customExceptionType, customExceptionMessage, customExceptionObject) {
137599
137600         customExceptionMessage = customExceptionMessage || "";
137601
137602         if (arguments.length < 3 || arguments.length > 6) {
137603             exception.raise(exception.types.Argument, "Wrong number of arguments when calling: validateNumberOfArguments()");
137604         }
137605
137606         if (isNaN(lowerBound) && isNaN(upperBound) && isNaN(numberOfArguments)) {
137607             exception.raise(exception.types.ArgumentType, "(validateNumberOfArguments) Arguments are not numbers");
137608         }
137609
137610         lowerBound = parseInt(lowerBound, 10);
137611         upperBound = parseInt(upperBound, 10);
137612         numberOfArguments = parseInt(numberOfArguments, 10);
137613
137614         if (numberOfArguments < lowerBound || numberOfArguments > upperBound) {
137615             exception.raise((customExceptionType || exception.types.ArgumentLength), (customExceptionMessage + "\n\nWrong number of arguments"), customExceptionObject);
137616         }
137617
137618     },
137619
137620     validateArgumentType: function (arg, argType, customExceptionType, customExceptionMessage, customExceptionObject) {
137621         var invalidArg = false,
137622             msg;
137623
137624         switch (argType) {
137625         case "array":
137626             if (!arg instanceof Array) {
137627                 invalidArg = true;
137628             }
137629             break;
137630         case "date":
137631             if (!arg instanceof Date) {
137632                 invalidArg = true;
137633             }
137634             break;
137635         case "integer":
137636             if (typeof arg === "number") {
137637                 if (arg !== Math.floor(arg)) {
137638                     invalidArg = true;
137639                 }
137640             }
137641             else {
137642                 invalidArg = true;
137643             }
137644             break;
137645         default:
137646             if (typeof arg !== argType) {
137647                 invalidArg = true;
137648             }
137649             break;
137650         }
137651
137652         if (invalidArg) {
137653             msg = customExceptionMessage +  ("\n\nInvalid Argument type. argument: " + arg + " ==> was expected to be of type: " + argType);
137654             exception.raise((customExceptionType || exception.types.ArgumentType), msg, customExceptionObject);
137655         }
137656     },
137657
137658     validateMultipleArgumentTypes: function (argArray, argTypeArray, customExceptionType, customExceptionMessage, customExceptionObject) {
137659         for (var i = 0; i < argArray.length; i++) {
137660             this.validateArgumentType(argArray[i], argTypeArray[i], customExceptionType, customExceptionMessage, customExceptionObject);
137661         }
137662     },
137663
137664     createElement: function (elementType, attributes) {
137665         var d = document.createElement(elementType);
137666
137667         if (attributes) {
137668             this.forEach(attributes, function (attributeValue, attributeName) {
137669
137670                 switch (attributeName.toLowerCase()) {
137671
137672                 case "innerhtml":
137673                     d.innerHTML = attributeValue;
137674                     break;
137675
137676                 case "innertext":
137677                     d.innerText = attributeValue;
137678                     break;
137679
137680                 default:
137681                     d.setAttribute(attributeName, attributeValue);
137682                 }
137683
137684             });
137685         }
137686
137687         return d;
137688     },
137689
137690
137691     loadHTMLElements: function () {
137692         for (var i = 0; i < _HtmlElements.length; i += 1) {
137693             document.createElement(_HtmlElements[i]);
137694         }
137695     },
137696
137697     getAllStylesheetRules: function getAllStylesheetRules(title) {
137698         this.validateNumberOfArguments(1, 1, arguments.length);
137699
137700         var i, x, sheet, rules, styles_array = [];
137701
137702         // get style sheet according to title
137703         for (i = 0; i < document.styleSheets.length; i += 1) {
137704
137705             sheet = document.styleSheets[i];
137706             rules = sheet.cssRules;
137707
137708             if (rules) {
137709                 for (x = 0; x < rules.length; x += 1) {
137710                     if (rules[x].selectorText && rules[x].selectorText === (title.toString())) {
137711                         styles_array.push(rules[x]);
137712                     }
137713                 }
137714             }
137715         }
137716
137717         return (styles_array);
137718     },
137719
137720     location: function () {
137721         return window.location;
137722     },
137723
137724     queryString: function () {
137725         // trim the leading ? and split each name=value
137726         var args = this.location().search.replace(/^\?/, '').split('&');
137727
137728         return args.reduce(function (obj, value) {
137729             if (value) {
137730                 value = value.toLowerCase().split("=");
137731                 obj[value[0]] = value[1];
137732             }
137733             return obj;
137734         }, {});
137735     },
137736
137737     extensionUrl: function () {
137738         return document.getElementById("extension-url").innerText;
137739     },
137740
137741     appLocation: function () {
137742         if (require('ripple/ui').registered("omnibar")) {
137743             /* rootURL can only get url saved from 'FrameHistoryChange' event
137744                it causes trouble when navigating directory through online 
137745                version as index.html is automatically loaded.
137746                Need a way to get more updated URL */
137747
137748             var path = require('ripple/ui/plugins/omnibar').rootURL(),
137749                 parts;
137750
137751             if ((parts = path.match(/^((http[s]?|ftp|file):\/\/)(.+\/)?([^\/].+)$/i)) !== null && parts.length === 5) {
137752                 // this is a path already.
137753                 if (path.search(/\/$/, "") !== -1) {
137754                     return path;
137755                 }
137756                 if (parts[4] === "about:blank") {
137757                     path = "";
137758                 }
137759                 else if (parts[3]) {
137760                     path = parts[1] + parts[3];
137761                     if (parts[4].indexOf(".") === -1) {
137762                         path += parts[4] + "/";
137763                     }
137764                 }
137765                 else {
137766                     path = parts[1] + parts[4] + "/";
137767                 }
137768             }
137769             else {
137770                 path = "";
137771             }
137772             return path;
137773         }
137774         return self.rippleLocation();
137775     },
137776
137777     rippleLocation: function () {
137778         var loc = self.location(),
137779             parts = loc.pathname.replace(/\/$/, "").split("/"),
137780             base = "",
137781             port = loc.port ? ":" + loc.port : "";
137782
137783         if (parts[parts.length - 1].indexOf(".") !== -1) {
137784             parts = parts.splice(0, parts.length - 1);
137785         }
137786         base = parts.join("/");
137787
137788         return loc.protocol + "//" + loc.hostname + port + base + "/";
137789     },
137790
137791     arrayContains: function (array, obj) {
137792         var i = array.length;
137793         while (i--) {
137794             if (array[i] === obj) {
137795                 return true;
137796             }
137797         }
137798         return false;
137799     },
137800
137801     some: function (obj, predicate, scope) {
137802         if (obj instanceof Array) {
137803             return obj.some(predicate, scope);
137804         }
137805         else {
137806             var values = self.map(obj, predicate, scope);
137807
137808             return self.reduce(values, function (some, value) {
137809                 return value ? value : some;
137810             }, false);
137811         }
137812     },
137813
137814     count: function (obj) {
137815         return self.sum(obj, function (total) {
137816             return 1;
137817         });
137818     },
137819
137820     sum: function (obj, selector, scope) {
137821         var values = self.map(obj, selector, scope);
137822         return self.reduce(values, function (total, value) {
137823             return total + value;
137824         });
137825     },
137826
137827     max: function (obj, selector, scope) {
137828         var values = self.map(obj, selector, scope);
137829         return self.reduce(values, function (max, value) {
137830             return max < value ? value : max;
137831         }, Number.MIN_VALUE);
137832     },
137833
137834     min: function (obj, selector, scope) {
137835         var values = self.map(obj, selector, scope);
137836         return self.reduce(values, function (min, value) {
137837             return min > value ? value : min;
137838         }, Number.MAX_VALUE);
137839     },
137840
137841     forEach: function (obj, action, scope) {
137842         if (obj instanceof Array) {
137843             return obj.forEach(action, scope);
137844         }
137845         else {
137846             self.map(obj, action, scope);
137847         }
137848     },
137849
137850     filter: function (obj, predicate, scope) {
137851         if (obj instanceof Array) {
137852             return obj.filter(predicate, scope);
137853         }
137854         else {
137855             var result = [];
137856             self.forEach(obj, function (value, index) {
137857                 if (predicate.apply(scope, [value, index])) {
137858                     result.push(value);
137859                 }
137860
137861             }, scope);
137862
137863             return result;
137864         }
137865     },
137866
137867     reduce: function (obj, func, init, scope) {
137868         var i,
137869             initial = init === undefined ? 0 : init,
137870             result = initial;
137871
137872
137873         if (obj instanceof Array) {
137874             return obj.reduce(func, initial);
137875         }
137876         else if (obj instanceof NamedNodeMap) {
137877             for (i = 0; i < obj.length; i++) {
137878                 result = func.apply(scope, [result, obj[i], i]);
137879             }
137880         }
137881         else {
137882             for (i in obj) {
137883                 if (obj.hasOwnProperty(i)) {
137884                     result = func.apply(scope, [result, obj[i], i]);
137885                 }
137886             }
137887         }
137888
137889         return result;
137890
137891     },
137892
137893     map: function (obj, func, scope) {
137894         var i,
137895             returnVal = null,
137896             result = [];
137897
137898         if (obj instanceof Array) {
137899             return obj.map(func, scope);
137900         }
137901         else if (obj instanceof NamedNodeMap) {
137902             for (i = 0; i < obj.length; i++) {
137903                 returnVal = func.apply(scope, [obj[i], i]);
137904                 result.push(returnVal);
137905             }
137906         }
137907         else {
137908             for (i in obj) {
137909                 if (obj.hasOwnProperty(i)) {
137910                     returnVal = func.apply(scope, [obj[i], i]);
137911                     result.push(returnVal);
137912                 }
137913             }
137914         }
137915
137916         return result;
137917     },
137918
137919     regexSanitize: function (regexString) {
137920         return regexString.replace("^", "\\^")
137921                     .replace("$", "\\$")
137922                     .replace("(", "\\(")
137923                     .replace(")", "\\)")
137924                     .replace("<", "\\<")
137925                     .replace("[", "\\[")
137926                     .replace("{", "\\{")
137927                     .replace(/\\/, "\\\\")
137928                     .replace("|", "\\|")
137929                     .replace(">", "\\>")
137930                     .replace(".", "\\.")
137931                     .replace("*", "\\*")
137932                     .replace("+", "\\+")
137933                     .replace("?", "\\?");
137934     },
137935
137936     bindAutoSaveEvent: function (node, saveCallback) {
137937         var oldSetTimeoutId,
137938             jNode = jQuery(node);
137939
137940         jNode.bind("keyup", function (event) {
137941             if (event.keyCode !== 9) {
137942                 clearTimeout(oldSetTimeoutId);
137943                 oldSetTimeoutId = window.setTimeout(function () {
137944                     saveCallback();
137945                 }, 500);
137946             }
137947         });
137948     },
137949
137950     find: function (comparison, collection, startInx, endInx, callback) {
137951         var results = [],
137952             compare = function (s, pattern) {
137953
137954                 if (typeof(s) !== "string" || pattern === null) {
137955                     return s === pattern;
137956                 }
137957
137958                 var regex = pattern.replace(/\./g, "\\.")
137959                                    .replace(/\^/g, "\\^")
137960                                    .replace(/\*/g, ".*")
137961                                    .replace(/\\\.\*/g, "\\*");
137962
137963                 regex = "^".concat(regex, "$");
137964
137965                 return !!s.match(new RegExp(regex, "i"));
137966             };
137967
137968         self.forEach(collection, function (c) {
137969             var match,
137970                 fail = false;
137971
137972             self.forEach(comparison, function (value, key) {
137973                 if (!fail && value !== undefined) {
137974
137975                     if (compare(c[key], value)) {
137976                         match = c;
137977                     }
137978                     else {
137979                         fail = true;
137980                         match = null;
137981                     }
137982                 }
137983             });
137984
137985             if (match) {
137986                 results.push(match);
137987             }
137988         });
137989
137990         if (callback) {
137991             if (startInx === undefined) {
137992                 startInx = 0;
137993             }
137994             if (endInx === undefined) {
137995                 endInx = results.length;
137996             }
137997             if (startInx === endInx) {
137998                 endInx = startInx + 1;
137999             }
138000
138001             callback.apply(null, [results.slice(startInx, endInx)]);
138002         }
138003     },
138004
138005     mixin: function (mixin, to) {
138006         for (var prop in mixin) {
138007             if (Object.hasOwnProperty.call(mixin, prop)) {
138008                 to[prop] = mixin[prop];
138009             }
138010         }
138011         return to;
138012     },
138013
138014     copy: function (obj) {
138015         var i,
138016             newObj = jQuery.isArray(obj) ? [] : {};
138017
138018         if (typeof obj === 'number' ||
138019             typeof obj === 'string' ||
138020             typeof obj === 'boolean' ||
138021             obj === null ||
138022             obj === undefined) {
138023             return obj;
138024         }
138025
138026         if (obj instanceof Date) {
138027             return new Date(obj);
138028         }
138029
138030         if (obj instanceof RegExp) {
138031             return new RegExp(obj);
138032         }
138033
138034         for (i in obj) {
138035             if (obj.hasOwnProperty(i)) {
138036                 if (obj[i] && typeof obj[i] === "object") {
138037                     if (obj[i] instanceof Date) {
138038                         newObj[i] = obj[i];
138039                     }
138040                     else {
138041                         newObj[i] = self.copy(obj[i]);
138042                     }
138043                 }
138044                 else {
138045                     newObj[i] = obj[i];
138046                 }
138047             }
138048         }
138049
138050         return newObj;
138051     },
138052
138053     navHelper: function () {
138054         return {\r
138055             getHeading: function (lat1, lon1, lat2, lon2) {\r
138056                 var dLon = this.rad(lon2 - lon1),
138057                     llat1 = this.rad(lat1),
138058                     llat2 = this.rad(lat2),
138059                     y = Math.sin(dLon) * Math.cos(llat2),
138060                     x = Math.cos(llat1) * Math.sin(llat2) - Math.sin(llat1) * Math.cos(llat2) * Math.cos(dLon);
138061                 return (this.deg(Math.atan2(y, x)) + 360) % 360;\r
138062             },
138063
138064             getDistance: function (lat1, lon1, lat2, lon2) {\r
138065                 var dLat = this.rad(lat2 - lat1),
138066                     dLon = this.rad(lon2 - lon1),
138067                     a = Math.sin(dLat / 2) * Math.sin(dLat / 2) + Math.cos(this.rad(lat1)) * Math.cos(this.rad(lat2)) * Math.sin(dLon / 2) * Math.sin(dLon / 2),
138068                     c = 2 * Math.asin(Math.sqrt(a)),
138069                     d = 6378100 * c;
138070                 return d;\r
138071             },
138072
138073             simulateTravel: function (lat, lon, hdg, dist) {\r
138074                 var lat1 = this.rad(lat),
138075                     lon1 = this.rad(lon),
138076                     brng = this.rad(hdg),
138077                     angularDistance = dist / 6378100,
138078                     lat2 = Math.asin(Math.sin(lat1) * Math.cos(angularDistance) + Math.cos(lat1) * Math.sin(angularDistance) * Math.cos(brng)),
138079                     lon2 = lon1 + Math.atan2(Math.sin(brng) * Math.sin(angularDistance) * Math.cos(lat1), Math.cos(angularDistance) - Math.sin(lat1) * Math.sin(lat2));
138080                 lon2 = (lon2 + 3 * Math.PI) % (2 * Math.PI) - Math.PI; // Normalise to -180..+180
138081
138082                 return {\r
138083                     latitude: this.deg(lat2),\r
138084                     longitude: this.deg(lon2)\r
138085                 };\r
138086             },
138087
138088             deg: function (num) {\r
138089                 return num * 180 / Math.PI;\r
138090             },
138091
138092             rad: function (num) {\r
138093                 return num * Math.PI / 180;\r
138094             }\r
138095         };
138096     }
138097 };
138098
138099 });
138100 define('ripple/widgetConfig', function (require, exports, module) {
138101 /*
138102  *  Copyright 2011 Research In Motion Limited.
138103  *
138104  * Licensed under the Apache License, Version 2.0 (the "License");
138105  * you may not use this file except in compliance with the License.
138106  * You may obtain a copy of the License at
138107  *
138108  * http://www.apache.org/licenses/LICENSE-2.0
138109  *
138110  * Unless required by applicable law or agreed to in writing, software
138111  * distributed under the License is distributed on an "AS IS" BASIS,
138112  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
138113  * See the License for the specific language governing permissions and
138114  * limitations under the License.
138115  */
138116 var exception = require('ripple/exception'),
138117     event = require('ripple/event'),
138118     app = require('ripple/app'),
138119     _console = require('ripple/console'),
138120     utils = require('ripple/utils'),
138121     platform = require('ripple/platform'),
138122     _validationResult = {
138123         valid: false,
138124         message: "",
138125         value: null
138126     },
138127     _configValidationResults = null;
138128
138129 function _failNodeValidation(schemaNode, message, value, node) {
138130     var validationResult = utils.copy(_validationResult);
138131
138132     if (!schemaNode.validationResult) {
138133         schemaNode.validationResult = [];
138134     }
138135     validationResult.valid = false;
138136     if (value) {
138137         validationResult.value = value;
138138     }
138139     else {
138140         delete(validationResult.value);
138141     }
138142     validationResult.message = schemaNode.nodeName + message;
138143     validationResult.node = node;
138144
138145     schemaNode.validationResult.push(validationResult);
138146 }
138147
138148 function _createEmptyNodeValidation(node) {
138149
138150     var validationResult = utils.copy(_validationResult),
138151         attributeValidationResult, attribute;
138152
138153     if (!node.validationResult) {
138154         node.validationResult = [];
138155     }
138156
138157     validationResult.value = "";
138158     delete(validationResult.valid);
138159     delete(validationResult.message);
138160
138161     if (node.attributes) {
138162         for (attribute in node.attributes) {
138163             if (node.attributes.hasOwnProperty(attribute)) {
138164                 if (!validationResult.attributes) {
138165                     validationResult.attributes = {};
138166                 }
138167
138168                 attributeValidationResult = utils.copy(_validationResult);
138169
138170                 attributeValidationResult.attributeName = node.attributes[attribute].attributeName;
138171                 delete(attributeValidationResult.value);
138172                 delete(attributeValidationResult.valid);
138173                 delete(attributeValidationResult.message);
138174
138175                 validationResult.attributes[attributeValidationResult.attributeName] = attributeValidationResult;
138176             }
138177         }
138178     }
138179
138180     node.validationResult.push(validationResult);
138181 }
138182
138183 function _validateValue(valueToTest, schemaNode) {
138184     var failMessage = "",
138185         nodeValue,
138186         numbers,
138187         numberRangeIndex,
138188         numberRange,
138189         range1,
138190         range2;
138191
138192     switch (schemaNode.type) {
138193     case "string":
138194         if (typeof valueToTest !== "string") {
138195             failMessage = " value was expected to be of type string but was typeof: " + typeof(valueToTest);
138196         }
138197         break;
138198     case "number":
138199         nodeValue = parseFloat(valueToTest);
138200         if (isNaN(nodeValue)) {
138201             failMessage = " value was expected to be of type number but was typeof: " + typeof(valueToTest);
138202         }
138203         break;
138204     case "integer":
138205         nodeValue = parseInt(valueToTest, 10);
138206         if (isNaN(nodeValue)) {
138207             failMessage = " value was expected to be of type number but was typeof: " + typeof(valueToTest);
138208         }
138209         break;
138210     case "boolean":
138211         if (valueToTest !== "false" && valueToTest !== "true") {
138212             failMessage = " value was expected to be of type boolean (i.e. 'true' or 'false' but was: " + valueToTest;
138213         }
138214         break;
138215     case "list":
138216         if (!utils.arrayContains(schemaNode.listValues, valueToTest)) {
138217             failMessage = " value is not recognized as being valid, it was:<br/><br/><span class=\"ui-text-fail\">" + valueToTest +
138218                     "</span><br/><br/>Valid values are:<p class=\"ui-text-pass\">" + schemaNode.listValues.join(" <br/> ") + "</p>";
138219         }
138220         break;
138221     case "listBoolean":
138222     case "listDefault":
138223         if (!utils.arrayContains(schemaNode.listValues, valueToTest)) {
138224             failMessage = " value is not recognized as being valid, it was:<br/><br/><span class=\"ui-text-fail\">" + valueToTest +
138225                     "</span><br/><br/>The framework will assume the value to be:<p class=\"ui-text-pass\">" + schemaNode.defaultValue + "</p>";
138226         }
138227         break;
138228     case "listNumbers":
138229         numbers = valueToTest.split(",");
138230
138231         for (numberRangeIndex = 0; numberRangeIndex < numbers.length; numberRangeIndex++) {
138232             numberRange = valueToTest.split("-");
138233             if (numberRange.length > 1) {
138234                 range1 = parseInt(numberRange[0], 10);
138235                 range2 = parseInt(numberRange[1], 10);
138236                 if (isNaN(range1) || isNaN(range2)) {
138237                     failMessage = " range values where not recognized as being valid, they was: " + range1 +
138238                             " and " + range2 + " :: valid values should be of type 'integer'";
138239                     break;
138240                 }
138241             }
138242             else if (numberRange.length === 1) {
138243                 range1 = parseInt(numberRange[0], 10);
138244                 if (isNaN(range1)) {
138245                     failMessage = " value was not recognized as being valid, it was: " + range1 +
138246                             " :: valid values should be of type 'integer'";
138247                     break;
138248                 }
138249             }
138250         }
138251         break;
138252     case "regex":
138253         if (!valueToTest.match(schemaNode.regex)) {
138254             failMessage = " value does not match expected format. Value should pass this regular expression validation: " + schemaNode.regex;
138255         }
138256         break;
138257     case "iso-language":
138258         break;
138259     default:
138260         exception.raise(exception.types.Application, "Schema node with value type of: " + schemaNode.type + " is not known");
138261     }
138262
138263     return failMessage;
138264 }
138265
138266 function _passNodeValidation(schemaNode, value, node) {
138267     var validationResult = utils.copy(_validationResult);
138268
138269     if (!schemaNode.validationResult) {
138270         schemaNode.validationResult = [];
138271     }
138272     validationResult.valid = true;
138273     validationResult.node = node;
138274     if (value) {
138275         validationResult.value = value;
138276     }
138277     else {
138278         delete(validationResult.value);
138279     }
138280     delete(validationResult.message);
138281
138282     schemaNode.validationResult.push(validationResult);
138283 }
138284
138285 function _validateNodeValue(schemaNode, node) {
138286     var failMessage,
138287         valueToTest = node && node.nodeValue ? node.nodeValue.replace(/^\s\s*/, '').replace(/\s\s*$/, '') : null;
138288
138289     if (schemaNode.type && valueToTest) {
138290
138291         failMessage = _validateValue(valueToTest, schemaNode);
138292
138293         if (failMessage !== "") {
138294             _failNodeValidation(schemaNode, failMessage, valueToTest, node);
138295             return;
138296         }
138297     }
138298     _passNodeValidation(schemaNode, valueToTest, node);
138299 }
138300
138301 function _failNodeAttributeValidation(node, attribute, message, value) {
138302     var nodeValidationResult = node.validationResult ? node.validationResult.pop() : utils.copy(_validationResult),
138303         attributeValidationResult = utils.copy(_validationResult);
138304
138305     if (!nodeValidationResult.attributes) {
138306         nodeValidationResult.attributes = {};
138307     }
138308
138309     nodeValidationResult.valid = false;
138310     nodeValidationResult.message = "One or more attributes failed validation";
138311
138312     attributeValidationResult.attributeName = attribute.attributeName;
138313     attributeValidationResult.valid = false;
138314     if (value) {
138315         attributeValidationResult.value = value;
138316     }
138317     else {
138318         delete(attributeValidationResult.value);
138319     }
138320     attributeValidationResult.message = node.nodeName + "." + attribute.attributeName + message;
138321
138322     nodeValidationResult.attributes[attribute.attributeName] = attributeValidationResult;
138323     node.validationResult.push(nodeValidationResult);
138324 }
138325
138326 function _passNodeAttributeValidation(node, attribute, value) {
138327     var nodeValidationResult = node.validationResult ? node.validationResult.pop() : utils.copy(_validationResult),
138328         attributeValidationResult = utils.copy(_validationResult);
138329
138330     if (!nodeValidationResult.attributes) {
138331         nodeValidationResult.attributes = {};
138332     }
138333
138334     attributeValidationResult.attributeName = attribute.attributeName;
138335     attributeValidationResult.valid = true;
138336     if (value) {
138337         attributeValidationResult.value = value;
138338     }
138339     else {
138340         delete(attributeValidationResult.value);
138341     }
138342     delete(attributeValidationResult.message);
138343
138344     nodeValidationResult.attributes[attribute.attributeName] = attributeValidationResult;
138345     node.validationResult.push(nodeValidationResult);
138346 }
138347
138348 function _validateNodeAttributeValue(schemaNode, schemaNodeAttribute, attribute) {
138349     var failMessage,
138350         valueToTest = attribute ? attribute.value.replace(/^\s\s*/, '').replace(/\s\s*$/, '') : null;
138351
138352     if (schemaNodeAttribute.type && valueToTest) {
138353
138354         failMessage = _validateValue(valueToTest, schemaNodeAttribute);
138355
138356         if (failMessage !== "") {
138357             _failNodeAttributeValidation(schemaNode, schemaNodeAttribute, failMessage, valueToTest);
138358             return;
138359         }
138360     }
138361     _passNodeAttributeValidation(schemaNode, schemaNodeAttribute, valueToTest);
138362 }
138363
138364 function _validateNodeAttributes(schemaNode, node, children) {
138365
138366     var siblings = utils.filter(children, function (child) {
138367             return child !== node;
138368         }),
138369         attributeConverter = function (attribute) {
138370             var _self = {
138371                 toValue: function (n) {
138372                     var obj = _self.toNode(n);
138373                     return obj ? obj.value : null;
138374                 },
138375                 toNode: function (n) {
138376                     return n.attributes.getNamedItem(attribute.attributeName);
138377                 }
138378             };
138379
138380             return _self;
138381         };
138382
138383     utils.forEach(schemaNode.attributes, function (attribute) {
138384
138385         var convert = attributeConverter(attribute),
138386             dupe = false;
138387
138388         if (attribute.unique) {
138389             // this means we need to check and see if there are other node with the same name
138390             // and ensure that they have a different value for this attributes, if not... fail
138391
138392             dupe = siblings.some(function (sibling) {
138393                 return convert.toValue(sibling) === convert.toValue(node);
138394             });
138395
138396             if (dupe) {
138397                 _failNodeAttributeValidation(schemaNode,
138398                         attribute,
138399                         " node is allowed to appear multiple times, however it must be unique based on this attribute and in this case another node with an identical attribute vale was found",
138400                         convert.toValue(node));
138401                 return;
138402             }
138403         }
138404
138405         if (attribute.required && !convert.toValue(node)) {
138406             _failNodeAttributeValidation(schemaNode, attribute, " attribute was expected but not found", null);
138407         }
138408         else {
138409             _validateNodeAttributeValue(schemaNode, attribute, convert.toNode(node));
138410         }
138411     });
138412 }
138413
138414
138415 function _validateNode(schemaNode, parentNode) {
138416     var children = utils.filter(parentNode.childNodes, function (child) {
138417         return child && child.nodeName === schemaNode.nodeName;
138418     });
138419
138420     if (children.length === 0) {
138421         if (schemaNode.required) {
138422             _failNodeValidation(schemaNode, " node expected, but not found", null, null);
138423         }
138424     }
138425
138426     utils.forEach(children, function (child) {
138427         if (schemaNode.occurrence !== 0 && schemaNode.occurrence < children.length) {
138428             _failNodeValidation(schemaNode, " node: more then " + schemaNode.occurrence + " node(s) found", null, child);
138429         }
138430         else {
138431             _validateNodeValue(schemaNode, child.childNodes[0] || child);
138432
138433             _validateNodeAttributes(schemaNode, child, children);
138434         }
138435
138436         utils.forEach(schemaNode.children, function (schema) {
138437             _validateNode(schema, child);
138438         });
138439     });
138440 }
138441
138442 function _validateAgainstSchemaNode(configSchema, configXML) {
138443     var results = utils.copy(configSchema);
138444     try {
138445         _validateNode(results[configSchema.rootElement], configXML);
138446     }
138447     catch (e) {
138448         exception.handle(e, true);
138449     }
138450
138451     return results;
138452 }
138453
138454 function _validate(configXML) {
138455     // traverse the config schema JSON object
138456     // TODO: update to get platform.getPlatformConfigSpec().schema
138457     return _validateAgainstSchemaNode(platform.current().config.schema, configXML);
138458 }
138459
138460 function _process(results) {
138461     // Check to make sure that widget is the correct version (i.e. config.xml needs to match selected platform)
138462     var validVersion = app.validateVersion(results);
138463
138464     if (!validVersion) {
138465         _console.warn("Your application does not appear to match" +
138466                 " the platform you have selected. The version number in your configuration might not " +
138467                 "match the selected platform version or your configuration file has errors in it.");
138468     }
138469
138470     // save widget info
138471     app.saveInfo(results);
138472     event.trigger("WidgetInformationUpdated");
138473
138474     // Check for readonly preferences (WAC only?)
138475
138476     if (app.getInfo().preferences !== {}) {
138477         event.trigger("StorageUpdatedEvent");
138478     }
138479 }
138480
138481 function _xmlToJson(xml) {
138482     var obj = {};
138483
138484     if (xml.nodeType === 1) { // element
138485         if (xml.attributes.length > 0) {
138486             obj["@attributes"] = {};
138487             utils.forEach(xml.attributes, function (attribute) {
138488                 obj["@attributes"][attribute.nodeName] = attribute.nodeValue;
138489             });
138490         }
138491     } 
138492     else if (xml.nodeType === 3) { // text node
138493         obj = xml.nodeValue;
138494     }
138495
138496     if (xml.hasChildNodes && xml.hasChildNodes()) {
138497         utils.forEach(xml.childNodes, function (child) {
138498             if (!child.nodeName) {
138499                 return;
138500             }
138501             if (!obj[child.nodeName]) {
138502                 obj[child.nodeName] = [];
138503             }
138504             obj[child.nodeName].push(_xmlToJson(child));
138505         });
138506     }
138507
138508     return obj;
138509 }
138510
138511 module.exports = {
138512
138513     validate: function (configXML) {
138514         utils.validateNumberOfArguments(1, 1, arguments.length);
138515         return _validate(configXML);
138516     },
138517
138518     initialize: function (previous, baton) {
138519         var xmlHttp = new XMLHttpRequest(),
138520             config = platform.current().config,
138521             fileName = config ? config.fileName : null,
138522             results;
138523
138524         if (!fileName) {
138525             return;
138526         }
138527
138528         try {
138529             xmlHttp.open("GET", utils.appLocation() + fileName, false);
138530             xmlHttp.send();
138531             if (xmlHttp.responseXML) {
138532                 results = _validate(xmlHttp.responseXML);
138533                 results.rawJSON = _xmlToJson(xmlHttp.responseXML);
138534                 _process(results);
138535                 _configValidationResults = results;
138536             }
138537             else {
138538                 _process();
138539                 _configValidationResults = null;
138540                 require('ripple/ui/plugins/widgetConfig').initialize();
138541             }
138542         }
138543         catch (e) {
138544             exception.handle(e);
138545         }
138546     },
138547
138548     getValidationResults: function () {
138549         return _configValidationResults;
138550     }
138551 };
138552
138553 });
138554 define('ripple/xhr/base', function (require, exports, module) {
138555 /*
138556  *  Copyright 2011 Research In Motion Limited.
138557  *
138558  * Licensed under the Apache License, Version 2.0 (the "License");
138559  * you may not use this file except in compliance with the License.
138560  * You may obtain a copy of the License at
138561  *
138562  * http://www.apache.org/licenses/LICENSE-2.0
138563  *
138564  * Unless required by applicable law or agreed to in writing, software
138565  * distributed under the License is distributed on an "AS IS" BASIS,
138566  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
138567  * See the License for the specific language governing permissions and
138568  * limitations under the License.
138569  */
138570 var XHR = window.XMLHttpRequest;
138571
138572 function _handle(object, key) {
138573     return function () {
138574         return object[key].apply(object, Array.prototype.slice.call(arguments));
138575     };
138576 }
138577
138578 function _getter(object, key) {
138579     return function () {
138580         return object[key];
138581     };
138582 }
138583
138584 function _setter(object, key) {
138585     return function (val) {
138586         object[key] = val;
138587     };
138588 }
138589
138590 function _writeable(obj) {
138591     var newObj = {},
138592         key;
138593
138594     // need prototypes
138595     for (key in obj) {
138596         //HACK: don't even know what to say bout this, resonseBlob can go fly a kite: related to this issue:
138597         //https://github.com/blackberry/Ripple-UI/issues/394
138598         if (key !== "responseBlob" && typeof obj[key] === "function") {
138599             newObj[key] = _handle(obj, key);
138600         } else {
138601             newObj.__defineGetter__(key, _getter(obj, key));
138602             newObj.__defineSetter__(key, _setter(obj, key));
138603         }
138604     }
138605
138606     return newObj;
138607 }
138608
138609 function _XMLHttpRequest() {
138610     var Xhr = require('ripple/emulatorBridge').xhr() || XHR;
138611     return _writeable(new Xhr());
138612 }
138613
138614 module.exports = _XMLHttpRequest;
138615
138616 });
138617 define('ripple/xhr/cors', function (require, exports, module) {
138618 /*
138619  *  Copyright 2011 Research In Motion Limited.
138620  *
138621  * Licensed under the Apache License, Version 2.0 (the "License");
138622  * you may not use this file except in compliance with the License.
138623  * You may obtain a copy of the License at
138624  *
138625  * http://www.apache.org/licenses/LICENSE-2.0
138626  *
138627  * Unless required by applicable law or agreed to in writing, software
138628  * distributed under the License is distributed on an "AS IS" BASIS,
138629  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
138630  * See the License for the specific language governing permissions and
138631  * limitations under the License.
138632  */
138633 var helpers = require('ripple/xhr/helpers'),
138634     constants = require('ripple/constants'),
138635     XHR = require('ripple/xhr/base');
138636
138637 function _XMLHttpRequest() {
138638     var xhr = new XHR(),
138639         origMethods = {
138640             setRequestHeader: xhr.setRequestHeader,
138641             open: xhr.open
138642         };
138643
138644     xhr.setRequestHeader = function (header, value) {
138645         // This is done to get around jQuery 1.3.2 setting a header that it shouldn't
138646         if (header && header.toUpperCase() !== "X-REQUESTED-WITH") {
138647             origMethods.setRequestHeader.apply(xhr, Array.prototype.slice.call(arguments));
138648         }
138649     };
138650
138651     xhr.open = function (method, url, async, user, password) {
138652         if (!helpers.isLocalRequest(url)) {
138653             url = constants.API_URL + "/xhr_proxy?tinyhippos_apikey=ABC&tinyhippos_rurl=" + escape(url);
138654         }
138655
138656         origMethods.open.apply(xhr, Array.prototype.slice.call(arguments));
138657     };
138658
138659     return xhr;
138660 }
138661
138662 module.exports = _XMLHttpRequest;
138663
138664 });
138665 define('ripple/xhr/helpers', function (require, exports, module) {
138666 /*
138667  *  Copyright 2011 Research In Motion Limited.
138668  *
138669  * Licensed under the Apache License, Version 2.0 (the "License");
138670  * you may not use this file except in compliance with the License.
138671  * You may obtain a copy of the License at
138672  *
138673  * http://www.apache.org/licenses/LICENSE-2.0
138674  *
138675  * Unless required by applicable law or agreed to in writing, software
138676  * distributed under the License is distributed on an "AS IS" BASIS,
138677  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
138678  * See the License for the specific language governing permissions and
138679  * limitations under the License.
138680  */
138681 var constants = require('ripple/constants'),
138682     db = require('ripple/db');
138683
138684 module.exports = {
138685     isLocalRequest: function (url) {
138686         return (!!(url.match(constants.REGEX.LOCAL_URI)) || !url.match(constants.REGEX.EXTERNAL_URI)) || 
138687                 !!(location.host && url.match(location.host));
138688     },
138689
138690     proxyEnabled: function () {
138691         var isDisabled = db.retrieve(constants.XHR.PROXY_DISABLED_BUTTON);
138692         return !isDisabled || isDisabled === "false" ? true : false;
138693     }
138694 };
138695
138696 });
138697 define('ripple/xhr/jsonp', function (require, exports, module) {
138698 /*
138699  *  Copyright 2011 Research In Motion Limited.
138700  *
138701  * Licensed under the Apache License, Version 2.0 (the "License");
138702  * you may not use this file except in compliance with the License.
138703  * You may obtain a copy of the License at
138704  *
138705  * http://www.apache.org/licenses/LICENSE-2.0
138706  *
138707  * Unless required by applicable law or agreed to in writing, software
138708  * distributed under the License is distributed on an "AS IS" BASIS,
138709  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
138710  * See the License for the specific language governing permissions and
138711  * limitations under the License.
138712  */
138713 var constants = require('ripple/constants'),
138714     exception = require('ripple/exception'),
138715     utils = require('ripple/utils'),
138716     helpers = require('ripple/xhr/helpers'),
138717     _console = require('ripple/console'),
138718     XHR = require('ripple/xhr/base');
138719
138720 function _XMLHttpRequest() {
138721     var xhr = new XHR(),
138722         origMethods = {
138723             setRequestHeader: xhr.setRequestHeader,
138724             getResponseHeader: xhr.getResponseHeader,
138725             getAllResponseHeaders: xhr.getAllResponseHeaders,
138726             open: xhr.open,
138727             send: xhr.send,
138728             abort: xhr.abort
138729         },
138730         _jxhr = new window.jXHR(),
138731         _sendFlag = false,
138732         _headers = [],
138733         _errorFlag = false,
138734         _url,
138735         _async;
138736
138737     function _localURI() {
138738         return _url && helpers.isLocalRequest(_url);
138739     }
138740
138741     function _set(prop, value) {
138742         xhr.__defineGetter__(prop, function () {
138743             return value;
138744         });
138745     }
138746
138747     function _reset() {
138748         _set("response", "");
138749         _set("responseText", "");
138750         _set("responseXML", null);
138751     }
138752
138753     xhr.setRequestHeader = function (header, value) {
138754         if (_localURI()) {
138755             origMethods.setRequestHeader.apply(xhr, Array.prototype.slice.call(arguments));
138756         } else {
138757             _console.error("XMLHttpRequest :: setRequestHeader does not work with JSONP.");
138758         }
138759     };
138760
138761     xhr.getResponseHeader = function (header) {
138762         return _localURI() ?
138763                 origMethods.getAllResponseHeaders.apply(xhr, [header]) :
138764                 _headers[header] || null;
138765     };
138766
138767     xhr.getAllResponseHeaders = function () {
138768         return _localURI() ?
138769                 origMethods.getAllResponseHeaders.apply(xhr) :
138770                 utils.reduce(_headers, function (str, value, key) {
138771                     return str + key + ": " + value + '\n';
138772                 }, "").replace(/\n$/, '');
138773     };
138774
138775     xhr.open = function (method, url, async) {
138776         _url = url;
138777         _async = async !== false ? true : false;
138778
138779         if (_localURI()) {
138780             origMethods.open.apply(xhr, Array.prototype.slice.call(arguments));
138781         } else {
138782             _reset();
138783             method = method.toUpperCase();
138784
138785             if (method === "POST") {
138786                 //HACK: Switch the method to get for now to simulate post
138787                 method = "GET";
138788             }
138789
138790             if (method !== "GET") {
138791                 exception.raise(exception.types.MethodNotImplemented, "Method: " + method + " not supported!");
138792             }
138793
138794             _jxhr.onreadystatechange = function (data) {
138795                 var response;
138796
138797                 try {
138798                     _set("readyState", _jxhr.readyState);
138799
138800                     if (xhr.readyState === xhr.DONE) {
138801                         _sendFlag = false;
138802                         _set("status", data.status);
138803                         _set("statusText", data.statusText);
138804                         _headers = data.headers;
138805
138806                         if (data.responseXML) {
138807                             response = new DOMParser().parseFromString(unescape(data.responseXML), "text/xml");
138808                             _set("responseXML", response);
138809                         } else {
138810                             response = unescape(data.responseText);
138811                             _set("responseText", response);
138812                         }
138813
138814                         _set("response", response);
138815                     }
138816
138817                     if (typeof xhr.onreadystatechange === "function") {
138818                         xhr.onreadystatechange.apply(xhr);
138819                     }
138820                 } catch (e) {
138821                     exception.handle(e);
138822                 }
138823             };
138824
138825             _jxhr.onerror = xhr.onerror;
138826             _jxhr.open(method, constants.API_URL + "/jsonp_xhr_proxy?callback=?&tinyhippos_apikey=ABC&tinyhippos_rurl=" + escape(url));
138827         }
138828     };
138829
138830     xhr.send = function (data) {
138831         if (_localURI()) {
138832             origMethods.send(data);
138833             return;
138834         }
138835
138836         if (!_async) {
138837             exception.raise(exception.types.MethodNotImplemented, "Synchronous not supported.");
138838         }
138839
138840         if (xhr.readyState !== xhr.OPENED || _sendFlag === true) {
138841             exception.raise(exception.types.InvalidState, "Ready state should be OPENED (1)");
138842         }
138843
138844         _errorFlag = false;
138845         _sendFlag = true;
138846         data = null;
138847
138848         _jxhr.send();
138849     };
138850
138851     xhr.abort = function () {
138852         if (_localURI()) {
138853             origMethods.abort();
138854             return;
138855         }
138856
138857         _reset();
138858
138859         _errorFlag = true;
138860
138861         if (xhr.readyState === xhr.UNSENT ||
138862                 (xhr.readyState === xhr.OPENED && _sendFlag === false) ||
138863                 xhr.readyState === xhr.DONE) {
138864             _set("readyState", xhr.UNSENT);
138865         } else {
138866             _set("readyState", xhr.DONE);
138867             _sendFlag = false;
138868
138869             if (typeof xhr.onreadystatechange === "function") {
138870                 xhr.onreadystatechange.apply(xhr);
138871             }
138872         }
138873
138874         _jxhr.onreadystatechange = null;
138875
138876         if (xhr.onabort) {
138877             xhr.onabort.apply(xhr, arguments);
138878         }
138879     };
138880
138881     return xhr;
138882 }
138883
138884 module.exports = _XMLHttpRequest;
138885
138886 });
138887 define('ripple/xhr', function (require, exports, module) {
138888 /*
138889  *  Copyright 2011 Research In Motion Limited.
138890  *
138891  * Licensed under the Apache License, Version 2.0 (the "License");
138892  * you may not use this file except in compliance with the License.
138893  * You may obtain a copy of the License at
138894  *
138895  * http://www.apache.org/licenses/LICENSE-2.0
138896  *
138897  * Unless required by applicable law or agreed to in writing, software
138898  * distributed under the License is distributed on an "AS IS" BASIS,
138899  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
138900  * See the License for the specific language governing permissions and
138901  * limitations under the License.
138902  */
138903 var constants = require('ripple/constants'),
138904     utils = require('ripple/utils'),
138905     ui = require('ripple/ui'),
138906     helpers = require('ripple/xhr/helpers'),
138907     XHR = window.XMLHttpRequest;
138908
138909 module.exports = {
138910     initialize: function (previous, baton) {
138911         window.XMLHttpRequest = require('ripple/xhr/base');
138912
138913         if (helpers.proxyEnabled() && !ui.registered("omnibar")) {
138914             var isFileScheme = utils.location().protocol.match(/^file:/);
138915             window.XMLHttpRequest = require(isFileScheme ? 'ripple/xhr/jsonp' : 'ripple/xhr/cors');
138916         }
138917     }
138918 };
138919
138920 });
138921 define('ripple', function (require, exports, module) {
138922 /*
138923  *  Copyright 2011 Research In Motion Limited.
138924  *
138925  * Licensed under the Apache License, Version 2.0 (the "License");
138926  * you may not use this file except in compliance with the License.
138927  * You may obtain a copy of the License at
138928  *
138929  * http://www.apache.org/licenses/LICENSE-2.0
138930  *
138931  * Unless required by applicable law or agreed to in writing, software
138932  * distributed under the License is distributed on an "AS IS" BASIS,
138933  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
138934  * See the License for the specific language governing permissions and
138935  * limitations under the License.
138936  */
138937 var omgwtf = require('ripple/omgwtf'),
138938     db = require('ripple/db'),
138939     xhr = require('ripple/xhr'),
138940     geo = require('ripple/geo'),
138941     fileSystem = require('ripple/fileSystem'),
138942     fs = require('ripple/dbfs'),
138943     platform = require('ripple/platform'),
138944     emulatorBridge = require('ripple/emulatorBridge'),
138945     devices = require('ripple/devices'),
138946     widgetConfig = require('ripple/widgetConfig'),
138947     deviceSettings = require('ripple/deviceSettings'),
138948     sensorSettings = require('ripple/sensorSettings'),
138949     ui = require('ripple/ui'),
138950     appcache = require('ripple/appcache'),
138951     _self = {
138952         boot: function (booted) {
138953             // techdebt (event registration timing)
138954             // require('ripple/platform/webworks.core/2.0.0/fsCache');
138955
138956             window.addEventListener("keydown", function (event) {
138957                 var hasMetaOrAltPressed = (event.metaKey || event.ctrlKey),
138958                     key = parseInt(event.keyCode, 10);
138959
138960                 if (key === 37 && hasMetaOrAltPressed) { // cmd/ctrl + left arrow
138961                     event.preventDefault();
138962                     emulatorBridge.window().history.back();
138963                 }
138964
138965                 if (key === 39 && hasMetaOrAltPressed) { // cmd/ctrl + right arrow
138966                     event.preventDefault();
138967                     emulatorBridge.window().history.forward();
138968                 }
138969
138970                 if (key === 82 && hasMetaOrAltPressed) { // cmd/ctrl + r
138971                     event.preventDefault();
138972                     window.tinyHipposReload = true;
138973                     emulatorBridge.window().location.reload();
138974                 }
138975
138976                 if (key === 116) { // F5
138977                     event.preventDefault();
138978                     window.tinyHipposReload = true;
138979                     emulatorBridge.window().location.reload();
138980                 }
138981             });
138982
138983             window.onbeforeunload = function () { 
138984                 if (!window.tinyHipposReload) {
138985                     return "Tizen Web Simulator";
138986                 }
138987             };
138988
138989             jWorkflow.order(omgwtf.initialize, omgwtf)
138990                  .andThen(appcache.initialize, appcache)
138991                  .andThen(db.initialize, db)
138992                  .andThen(xhr.initialize, xhr)
138993                  .andThen(geo.initialize, geo)
138994                  .andThen(fileSystem.initialize, fileSystem)
138995                  .andThen(fs.initialize, fs)
138996                  .andThen(platform.initialize, platform)
138997                  .andThen(devices.initialize, devices)
138998                  .andThen(widgetConfig.initialize, widgetConfig)
138999                  .andThen(deviceSettings.initialize, deviceSettings)
139000                  .andThen(ui.initialize, ui)
139001                  .start(booted);
139002         }
139003     };
139004
139005 module.exports = _self;
139006
139007 });
139008 require('ripple/ui').register('omnibar');require('ripple/bootstrap').bootstrap();