Lib_Js_Prototype - Version 1.6.0.3.0

Version Notes

1.6.0.3.0

Download this release

Release Info

Developer Magento Core Team
Extension Lib_Js_Prototype
Version 1.6.0.3.0
Comparing to
See all releases


Version 1.6.0.3.0

Files changed (159) hide show
  1. js/prototype/debug.js +137 -0
  2. js/prototype/deprecation.js +374 -0
  3. js/prototype/effects.js +1094 -0
  4. js/prototype/extended_debug.js +113 -0
  5. js/prototype/prototype.js +4328 -0
  6. js/prototype/tooltip.js +208 -0
  7. js/prototype/tooltip_manager.js +241 -0
  8. js/prototype/validation.js +774 -0
  9. js/prototype/window.js +1855 -0
  10. js/prototype/window_effects.js +157 -0
  11. js/prototype/window_ext.js +115 -0
  12. js/prototype/window_readme.txt +28 -0
  13. js/prototype/windows/MIT-LICENSE +19 -0
  14. js/prototype/windows/README +182 -0
  15. js/prototype/windows/themes/alert.css +119 -0
  16. js/prototype/windows/themes/alert/bottom.gif +0 -0
  17. js/prototype/windows/themes/alert/bottom_left.gif +0 -0
  18. js/prototype/windows/themes/alert/bottom_right.gif +0 -0
  19. js/prototype/windows/themes/alert/left.gif +0 -0
  20. js/prototype/windows/themes/alert/overlay.png +0 -0
  21. js/prototype/windows/themes/alert/progress.gif +0 -0
  22. js/prototype/windows/themes/alert/right.gif +0 -0
  23. js/prototype/windows/themes/alert/top.gif +0 -0
  24. js/prototype/windows/themes/alert/top_left.gif +0 -0
  25. js/prototype/windows/themes/alert/top_right.gif +0 -0
  26. js/prototype/windows/themes/alert_lite.css +88 -0
  27. js/prototype/windows/themes/alphacube.css +150 -0
  28. js/prototype/windows/themes/alphacube/bottom-left-c.gif +0 -0
  29. js/prototype/windows/themes/alphacube/bottom-middle.gif +0 -0
  30. js/prototype/windows/themes/alphacube/bottom-right-c.gif +0 -0
  31. js/prototype/windows/themes/alphacube/button-close-focus.gif +0 -0
  32. js/prototype/windows/themes/alphacube/button-max-focus.gif +0 -0
  33. js/prototype/windows/themes/alphacube/button-min-focus.gif +0 -0
  34. js/prototype/windows/themes/alphacube/frame-left.gif +0 -0
  35. js/prototype/windows/themes/alphacube/frame-right.gif +0 -0
  36. js/prototype/windows/themes/alphacube/left-top.gif +0 -0
  37. js/prototype/windows/themes/alphacube/right-top.gif +0 -0
  38. js/prototype/windows/themes/alphacube/top-middle.gif +0 -0
  39. js/prototype/windows/themes/behavior.htc +51 -0
  40. js/prototype/windows/themes/darkX.css +121 -0
  41. js/prototype/windows/themes/darkX/button-close-focused.png +0 -0
  42. js/prototype/windows/themes/darkX/button-maximize-focused.png +0 -0
  43. js/prototype/windows/themes/darkX/button-minimize-focused.png +0 -0
  44. js/prototype/windows/themes/darkX/frame-bottom-left-focused.png +0 -0
  45. js/prototype/windows/themes/darkX/frame-bottom-mid-focused.png +0 -0
  46. js/prototype/windows/themes/darkX/frame-bottom-right-focused.png +0 -0
  47. js/prototype/windows/themes/darkX/frame-left-focused.png +0 -0
  48. js/prototype/windows/themes/darkX/frame-right-focused.png +0 -0
  49. js/prototype/windows/themes/darkX/titlebar-left-focused.png +0 -0
  50. js/prototype/windows/themes/darkX/titlebar-mid-focused.png +0 -0
  51. js/prototype/windows/themes/darkX/titlebar-right-focused.png +0 -0
  52. js/prototype/windows/themes/debug.css +25 -0
  53. js/prototype/windows/themes/default.css +155 -0
  54. js/prototype/windows/themes/default/bottom_left.gif +0 -0
  55. js/prototype/windows/themes/default/bottom_mid.gif +0 -0
  56. js/prototype/windows/themes/default/bottom_right.gif +0 -0
  57. js/prototype/windows/themes/default/bottom_right_resize.gif +0 -0
  58. js/prototype/windows/themes/default/center_left.gif +0 -0
  59. js/prototype/windows/themes/default/center_right.gif +0 -0
  60. js/prototype/windows/themes/default/clear.gif +0 -0
  61. js/prototype/windows/themes/default/close.gif +0 -0
  62. js/prototype/windows/themes/default/inspect.gif +0 -0
  63. js/prototype/windows/themes/default/maximize.gif +0 -0
  64. js/prototype/windows/themes/default/minimize.gif +0 -0
  65. js/prototype/windows/themes/default/overlay.png +0 -0
  66. js/prototype/windows/themes/default/resize.gif +0 -0
  67. js/prototype/windows/themes/default/sizer.gif +0 -0
  68. js/prototype/windows/themes/default/top_left.gif +0 -0
  69. js/prototype/windows/themes/default/top_mid.gif +0 -0
  70. js/prototype/windows/themes/default/top_right.gif +0 -0
  71. js/prototype/windows/themes/iefix/blank.gif +0 -0
  72. js/prototype/windows/themes/iefix/iepngfix.css +3 -0
  73. js/prototype/windows/themes/iefix/iepngfix.htc +54 -0
  74. js/prototype/windows/themes/lighting.css +960 -0
  75. js/prototype/windows/themes/lighting/background_buttons.gif +0 -0
  76. js/prototype/windows/themes/lighting/bottom-left-blue.png +0 -0
  77. js/prototype/windows/themes/lighting/bottom-left-darkblue.png +0 -0
  78. js/prototype/windows/themes/lighting/bottom-left-green.png +0 -0
  79. js/prototype/windows/themes/lighting/bottom-left-grey.png +0 -0
  80. js/prototype/windows/themes/lighting/bottom-middle-blue.png +0 -0
  81. js/prototype/windows/themes/lighting/bottom-middle-darkblue.png +0 -0
  82. js/prototype/windows/themes/lighting/bottom-middle-green.png +0 -0
  83. js/prototype/windows/themes/lighting/bottom-middle-grey.png +0 -0
  84. js/prototype/windows/themes/lighting/bottom-right-blue.png +0 -0
  85. js/prototype/windows/themes/lighting/bottom-right-darkblue.png +0 -0
  86. js/prototype/windows/themes/lighting/bottom-right-green.png +0 -0
  87. js/prototype/windows/themes/lighting/bottom-right-grey.png +0 -0
  88. js/prototype/windows/themes/lighting/button-close-blue.png +0 -0
  89. js/prototype/windows/themes/lighting/button-close-darkblue.png +0 -0
  90. js/prototype/windows/themes/lighting/button-close-green.png +0 -0
  91. js/prototype/windows/themes/lighting/button-close-grey.png +0 -0
  92. js/prototype/windows/themes/lighting/button-maximize-blue.png +0 -0
  93. js/prototype/windows/themes/lighting/button-maximize-darkblue.png +0 -0
  94. js/prototype/windows/themes/lighting/button-maximize-green.png +0 -0
  95. js/prototype/windows/themes/lighting/button-maximize-grey.png +0 -0
  96. js/prototype/windows/themes/lighting/button-minimize-blue.png +0 -0
  97. js/prototype/windows/themes/lighting/button-minimize-darkblue.png +0 -0
  98. js/prototype/windows/themes/lighting/button-minimize-green.png +0 -0
  99. js/prototype/windows/themes/lighting/button-minimize-grey.png +0 -0
  100. js/prototype/windows/themes/lighting/left-blue.png +0 -0
  101. js/prototype/windows/themes/lighting/left-darkblue.png +0 -0
  102. js/prototype/windows/themes/lighting/left-green.png +0 -0
  103. js/prototype/windows/themes/lighting/left-grey.png +0 -0
  104. js/prototype/windows/themes/lighting/pngbehavior.htc +67 -0
  105. js/prototype/windows/themes/lighting/right-blue.png +0 -0
  106. js/prototype/windows/themes/lighting/right-darkblue.png +0 -0
  107. js/prototype/windows/themes/lighting/right-green.png +0 -0
  108. js/prototype/windows/themes/lighting/right-grey.png +0 -0
  109. js/prototype/windows/themes/lighting/spinner.gif +0 -0
  110. js/prototype/windows/themes/lighting/top-left-blue.png +0 -0
  111. js/prototype/windows/themes/lighting/top-left-darkblue.png +0 -0
  112. js/prototype/windows/themes/lighting/top-left-green.png +0 -0
  113. js/prototype/windows/themes/lighting/top-left-grey.png +0 -0
  114. js/prototype/windows/themes/lighting/top-middle-blue.png +0 -0
  115. js/prototype/windows/themes/lighting/top-middle-darkblue.png +0 -0
  116. js/prototype/windows/themes/lighting/top-middle-green.png +0 -0
  117. js/prototype/windows/themes/lighting/top-middle-grey.png +0 -0
  118. js/prototype/windows/themes/lighting/top-right-blue.png +0 -0
  119. js/prototype/windows/themes/lighting/top-right-darkblue.png +0 -0
  120. js/prototype/windows/themes/lighting/top-right-green.png +0 -0
  121. js/prototype/windows/themes/lighting/top-right-grey.png +0 -0
  122. js/prototype/windows/themes/mac_os_x.css +333 -0
  123. js/prototype/windows/themes/mac_os_x_dialog.css +160 -0
  124. js/prototype/windows/themes/magento.css +122 -0
  125. js/prototype/windows/themes/magento/button-close-focused.png +0 -0
  126. js/prototype/windows/themes/magento/top_bg.gif +0 -0
  127. js/prototype/windows/themes/nuncio.css +164 -0
  128. js/prototype/windows/themes/nuncio/bottom_left.png +0 -0
  129. js/prototype/windows/themes/nuncio/bottom_mid.png +0 -0
  130. js/prototype/windows/themes/nuncio/bottom_right.png +0 -0
  131. js/prototype/windows/themes/nuncio/center_left.png +0 -0
  132. js/prototype/windows/themes/nuncio/center_right.png +0 -0
  133. js/prototype/windows/themes/nuncio/close.png +0 -0
  134. js/prototype/windows/themes/nuncio/minimize.png +0 -0
  135. js/prototype/windows/themes/nuncio/overlay.png +0 -0
  136. js/prototype/windows/themes/nuncio/top_left.png +0 -0
  137. js/prototype/windows/themes/nuncio/top_mid.png +0 -0
  138. js/prototype/windows/themes/nuncio/top_right.png +0 -0
  139. js/prototype/windows/themes/spread.css +108 -0
  140. js/prototype/windows/themes/spread/bottom-left-c.gif +0 -0
  141. js/prototype/windows/themes/spread/bottom-middle.gif +0 -0
  142. js/prototype/windows/themes/spread/bottom-right-c.gif +0 -0
  143. js/prototype/windows/themes/spread/button-close-focus.gif +0 -0
  144. js/prototype/windows/themes/spread/button-max-focus.gif +0 -0
  145. js/prototype/windows/themes/spread/button-min-focus.gif +0 -0
  146. js/prototype/windows/themes/spread/frame-left.gif +0 -0
  147. js/prototype/windows/themes/spread/frame-right.gif +0 -0
  148. js/prototype/windows/themes/spread/left-top.gif +0 -0
  149. js/prototype/windows/themes/spread/right-top.gif +0 -0
  150. js/prototype/windows/themes/spread/top-middle.gif +0 -0
  151. js/scriptaculous/builder.js +136 -0
  152. js/scriptaculous/controls.js +965 -0
  153. js/scriptaculous/dragdrop.js +975 -0
  154. js/scriptaculous/effects.js +1130 -0
  155. js/scriptaculous/scriptaculous.js +60 -0
  156. js/scriptaculous/slider.js +277 -0
  157. js/scriptaculous/sound.js +55 -0
  158. js/scriptaculous/unittest.js +568 -0
  159. package.xml +18 -0
js/prototype/debug.js ADDED
@@ -0,0 +1,137 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ var debugWindow = null;
2
+ function debug(text, reverse) {
3
+ if (debugWindow == null)
4
+ return;
5
+
6
+ time = "-"; //new Date();
7
+ if (reverse) {
8
+ $('debug').innerHTML = time + " " + text + "<br>"+ $('debug').innerHTML;
9
+ debugWindow.getContent().scrollTop=0;
10
+ }
11
+ else {
12
+ $('debug').innerHTML += time + " " + text + "<br>";
13
+ debugWindow.getContent().scrollTop=10000; // Far away
14
+ }
15
+ }
16
+
17
+ function hideDebug() {
18
+ if (debugWindow) {
19
+ debugWindow.destroy();
20
+ debugWindow = null;
21
+ }
22
+ }
23
+
24
+ function showDebug(bShow) {
25
+ if (debugWindow == null) {
26
+ debugWindow = new Window('debug_window', {className: 'dialog',width:250, height:100, right:4, bottom:42, zIndex:1000, opacity:1, showEffect: Element.show, resizable: true, title: "Debug"})
27
+ debugWindow.getContent().innerHTML = "<style>#debug_window .dialog_content {background:#000;}</style> <div id='debug'></div>";
28
+ date=new Date;
29
+ date.setMonth(date.getMonth()+3);
30
+
31
+ //debugWindow.setCookie(null, date);
32
+ }
33
+ if( typeof bShow == 'undefined' || bShow)debugWindow.show()
34
+ }
35
+
36
+
37
+ function clearDebug() {
38
+ if (debugWindow == null)
39
+ return;
40
+ $('debug').innerHTML = "";
41
+ }
42
+
43
+ /**
44
+ * document.createElement convenience wrapper
45
+ *
46
+ * The data parameter is an object that must have the "tag" key, containing
47
+ * a string with the tagname of the element to create. It can optionally have
48
+ * a "children" key which can be: a string, "data" object, or an array of "data"
49
+ * objects to append to this element as children. Any other key is taken as an
50
+ * attribute to be applied to this tag.
51
+ *
52
+ * Available under an MIT license:
53
+ * http://www.opensource.org/licenses/mit-license.php
54
+ *
55
+ * @param {Object} data The data representing the element to create
56
+ * @return {Element} The element created.
57
+ */
58
+ function $E(data) {
59
+ var el;
60
+ if ('string'==typeof data) {
61
+ el=document.createTextNode(data);
62
+ } else {
63
+ //create the element
64
+ el=document.createElement(data.tag);
65
+ delete(data.tag);
66
+
67
+ //append the children
68
+ if ('undefined'!=typeof data.children) {
69
+ if ('string'==typeof data.children ||'undefined'==typeof data.children.length) {
70
+ //strings and single elements
71
+ el.appendChild($E(data.children));
72
+ } else {
73
+ //arrays of elements
74
+ for (var i=0, child=null; 'undefined'!=typeof (child=data.children[i]); i++) {
75
+ el.appendChild($E(child));
76
+ }
77
+ }
78
+ delete(data.children);
79
+ }
80
+
81
+ //any other data is attributes
82
+ for (attr in data) {
83
+ el[attr]=data[attr];
84
+ }
85
+ }
86
+
87
+ return el;
88
+ }
89
+
90
+ // FROM Nick Hemsley
91
+ var Debug = {
92
+ inspectOutput: function (container, within) {
93
+ within = within || debugWindow.getContent()
94
+
95
+ if (debugWindow == null)
96
+ return;
97
+
98
+ within.appendChild(container)
99
+ },
100
+
101
+ inspect: function(object) {
102
+ var cont = $E({tag: "div", className: "inspector"})
103
+ Debug.inspectObj(object, cont)
104
+ debugWindow.getContent().appendChild(cont)
105
+ },
106
+
107
+ inspectObj: function (object, container) {
108
+ for (prop in object) {
109
+ Debug.inspectOutput(Debug.inspectable(object, prop), container)
110
+ }
111
+ },
112
+
113
+ inspectable: function(object, prop) {
114
+ cont = $E({tag: 'div', className: 'inspectable', children: [prop + " value: " + object[prop] ]})
115
+ cont.toInspect = object[prop]
116
+ Event.observe(cont, 'click', Debug.inspectClicked, false)
117
+ return cont
118
+ },
119
+
120
+ inspectClicked: function(e) {
121
+ Debug.inspectContained(Event.element(e))
122
+ Event.stop(e)
123
+ },
124
+
125
+ inspectContained: function(container) {
126
+ if (container.opened) {
127
+ container.parentNode.removeChild(container.opened)
128
+ delete(container.opened)
129
+ } else {
130
+ sibling = container.parentNode.insertBefore($E({tag: "div", className: "child"}), container.nextSibling)
131
+ if (container.toInspect)
132
+ Debug.inspectObj(container.toInspect, sibling)
133
+ container.opened = sibling
134
+ }
135
+ }
136
+ }
137
+ var inspect = Debug.inspect;
js/prototype/deprecation.js ADDED
@@ -0,0 +1,374 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* Prototype Deprecation Notifier for Prototype 1.6.0.2
2
+ * (c) 2008 Tobie Langel
3
+ *
4
+ * Prototype Deprecation Notifier is freely distributable under the same
5
+ * terms as Prototype (MIT-style license).
6
+ * For details, see the Prototype web site: http://www.prototypejs.org/
7
+ *
8
+ * Include this file right below prototype.js. All warning messages
9
+ * will be logged to the console.
10
+ *
11
+ * Note: You can turn off deprecation messages (and log only removal and
12
+ * modification messages) by specifying:
13
+ * DeprecationNotifier.logDeprecation = false;
14
+ *
15
+ * THIS SCRIPT WORKS IN FIREFOX ONLY
16
+ *--------------------------------------------------------------------------*/
17
+
18
+ var DeprecationNotifier = {
19
+ logDeprecation: true,
20
+ MessageTemplate: new Template('Prototype #{type} Warning: #{message}\n#{stack}'),
21
+ Regexp: new RegExp("@" + window.location.protocol + ".*?\\d+\\n", "g"),
22
+
23
+ init: function(deprecatedMethods) {
24
+ if (!Prototype.Browser.Gecko) return;
25
+ deprecatedMethods.each(function(d) {
26
+ var condition = d.condition,
27
+ type = d.type || 'deprecation',
28
+ message = d.message,
29
+ namespace = d.namespace,
30
+ method = d.methodName;
31
+
32
+ namespace[method] = (namespace[method] || function() {}).wrap(function(proceed) {
33
+ var args = $A(arguments).splice(1);
34
+ if (!condition || condition.apply(this, args))
35
+ DeprecationNotifier.notify(message, type);
36
+ return proceed.apply(proceed, args);
37
+ });
38
+ });
39
+ Element.addMethods();
40
+ },
41
+
42
+ notify: function(message, type) {
43
+ if (type == 'deprecation' && !DeprecationNotifier.logDeprecation)
44
+ return false;
45
+ this.log(this.MessageTemplate.evaluate({
46
+ message: message,
47
+ stack: this.getStack(),
48
+ type: type.capitalize()
49
+ }), type);
50
+ return true;
51
+ },
52
+
53
+ getStack: function() {
54
+ try {
55
+ throw new Error("stack");
56
+ } catch(e) {
57
+ return e.stack.match(this.Regexp).reject(function(path) {
58
+ return /(prototype|unittest|deprecation)\.js/.test(path);
59
+ }).join("\n");
60
+ }
61
+ },
62
+
63
+ log: function(message, type) {
64
+ if (type === 'removal') {
65
+ console.error(message);
66
+ } else console.warn(message);
67
+ }
68
+ };
69
+
70
+ DeprecationNotifier.init([
71
+ {
72
+ methodName: 'display',
73
+ namespace: Toggle,
74
+ message: 'Toggle.display has been deprecated, please use Element.toggle instead.'
75
+ },
76
+
77
+ {
78
+ methodName: 'show',
79
+ namespace: Element.Methods,
80
+ message: 'Passing an arbitrary number of elements to Element.show is no longer supported.\n' +
81
+ 'Use [id_1, id_2, ...].each(Element.show) or $(id_1, id_2, ...).invoke("show") instead.',
82
+ type: 'removal',
83
+ condition: function() { return arguments.length > 1 && !Object.isNumber(arguments[1]) }
84
+ },
85
+
86
+ {
87
+ methodName: 'hide',
88
+ namespace: Element.Methods,
89
+ message: 'Passing an arbitrary number of elements to Element.hide is no longer supported.\n' +
90
+ 'Use [id_1, id_2, ...].each(Element.hide) or $(id_1, id_2, ...).invoke("hide") instead.',
91
+ type: 'removal',
92
+ condition: function() { return arguments.length > 1 && !Object.isNumber(arguments[1]) }
93
+ },
94
+
95
+ {
96
+ methodName: 'toggle',
97
+ namespace: Element.Methods,
98
+ message: 'Passing an arbitrary number of elements to Element.toggle is no longer supported.\n' +
99
+ 'Use [id_1, id_2, ...].each(Element.toggle) or $(id_1, id_2, ...).invoke("toggle") instead.',
100
+ type: 'removal',
101
+ condition: function() { return arguments.length > 1 && !Object.isNumber(arguments[1]) }
102
+ },
103
+
104
+ {
105
+ methodName: 'clear',
106
+ namespace: Form.Element.Methods,
107
+ message: 'Passing an arbitrary number of elements to Field.clear is no longer supported.\n' +
108
+ 'Use [id_1, id_2, ...].each(Form.Element.clear) or $(id_1, id_2, ...).invoke("clear") instead.',
109
+ type: 'removal',
110
+ condition: function() { return arguments.length > 1 && !Object.isNumber(arguments[1]) }
111
+ },
112
+
113
+ {
114
+ methodName: 'present',
115
+ namespace: Form.Element.Methods,
116
+ message: 'Passing an arbitrary number of elements to Field.present is no longer supported.\n' +
117
+ 'Use [id_1, id_2, ...].each(Form.Element.present) or $(id_1, id_2, ...).invoke("present") instead.',
118
+ type: 'removal',
119
+ condition: function() { return arguments.length > 1 && !Object.isNumber(arguments[1]) }
120
+ },
121
+
122
+ {
123
+ methodName: 'childOf',
124
+ namespace: Element.Methods,
125
+ message: 'Element#childOf has been deprecated, please use Element#descendantOf instead.'
126
+ },
127
+
128
+ {
129
+ methodName: 'Before',
130
+ namespace: Insertion,
131
+ message: 'Insertion.Before has been deprecated, please use Element#insert instead.'
132
+ },
133
+
134
+ {
135
+ methodName: 'Top',
136
+ namespace: Insertion,
137
+ message: 'Insertion.Top has been deprecated, please use Element#insert instead.'
138
+ },
139
+
140
+ {
141
+ methodName: 'Bottom',
142
+ namespace: Insertion,
143
+ message: 'Insertion.Bottom has been deprecated, please use Element#insert instead.'
144
+ },
145
+
146
+ {
147
+ methodName: 'After',
148
+ namespace: Insertion,
149
+ message: 'Insertion.After has been deprecated, please use Element#insert instead.'
150
+ },
151
+
152
+ {
153
+ methodName: 'prepare',
154
+ namespace: Position,
155
+ message: 'Position.prepare has been deprecated.'
156
+ },
157
+
158
+ {
159
+ methodName: 'within',
160
+ namespace: Position,
161
+ message: 'Position.within has been deprecated.'
162
+ },
163
+
164
+ {
165
+ methodName: 'withinIncludingScrolloffsets',
166
+ namespace: Position,
167
+ message: 'Position.withinIncludingScrolloffsets has been deprecated.'
168
+ },
169
+
170
+ {
171
+ methodName: 'overlap',
172
+ namespace: Position,
173
+ message: 'Position.overlap has been deprecated.'
174
+ },
175
+
176
+ {
177
+ methodName: 'cumulativeOffset',
178
+ namespace: Position,
179
+ message: 'Position.cumulativeOffset has been deprecated, please use Element#cumulativeOffset instead.'
180
+ },
181
+
182
+ {
183
+ methodName: 'positionedOffset',
184
+ namespace: Position,
185
+ message: 'Position.positionedOffset has been deprecated, please use Element#positionedOffset instead.'
186
+ },
187
+
188
+ {
189
+ methodName: 'absolutize',
190
+ namespace: Position,
191
+ message: 'Position.absolutize has been deprecated, please use Element#absolutize instead.'
192
+ },
193
+
194
+ {
195
+ methodName: 'relativize',
196
+ namespace: Position,
197
+ message: 'Position.relativize has been deprecated, please use Element#relativize instead.'
198
+ },
199
+
200
+ {
201
+ methodName: 'realOffset',
202
+ namespace: Position,
203
+ message: 'Position.realOffset has been deprecated, please use Element#cumulativeScrollOffset instead.'
204
+ },
205
+
206
+ {
207
+ methodName: 'offsetParent',
208
+ namespace: Position,
209
+ message: 'Position.offsetParent has been deprecated, please use Element#getOffsetParent instead.'
210
+ },
211
+
212
+ {
213
+ methodName: 'page',
214
+ namespace: Position,
215
+ message: 'Position.page has been deprecated, please use Element#viewportOffset instead.'
216
+ },
217
+
218
+ {
219
+ methodName: 'clone',
220
+ namespace: Position,
221
+ message: 'Position.clone has been deprecated, please use Element#clonePosition instead.'
222
+ },
223
+
224
+ {
225
+ methodName: 'initialize',
226
+ namespace: Element.ClassNames.prototype,
227
+ message: 'Element.ClassNames has been deprecated.'
228
+ },
229
+
230
+ {
231
+ methodName: 'classNames',
232
+ namespace: Element.Methods,
233
+ message: 'Element#classNames has been deprecated.\n' +
234
+ 'If you need to access CSS class names as an array, try: $w(element.classname).'
235
+ },
236
+
237
+ {
238
+ methodName: 'setStyle',
239
+ namespace: Element.Methods,
240
+ message: 'Use of uncamelized style-property names is no longer supported.\n' +
241
+ 'Use either camelized style-property names or a regular CSS string instead (see online documentation).',
242
+ type: 'removal',
243
+ condition: function(element, style) {
244
+ return !Object.isString(style) && Object.keys(style).join('').include('-');
245
+ }
246
+ },
247
+
248
+ {
249
+ methodName: 'getElementsByClassName',
250
+ namespace: document,
251
+ message: 'document.getElementsByClassName has been deprecated, please use $$ instead.'
252
+ },
253
+
254
+ {
255
+ methodName: 'getElementsByClassName',
256
+ namespace: Element.Methods,
257
+ message: 'Element#getElementsByClassName has been deprecated, please use Element#select instead.'
258
+ },
259
+
260
+ {
261
+ methodName: 'immediateDescendants',
262
+ namespace: Element.Methods,
263
+ message: 'Element#immediateDescendants has been deprecated, please use Element#childElements instead.'
264
+ },
265
+
266
+ {
267
+ methodName: 'getElementsBySelector',
268
+ namespace: Element.Methods,
269
+ message: 'Element#getElementsBySelector has been deprecated, please use Element#select instead.'
270
+ },
271
+
272
+ {
273
+ methodName: 'toQueryString',
274
+ namespace: Hash,
275
+ message: 'Hash.toQueryString has been deprecated.\n' +
276
+ 'Use the instance method Hash#toQueryString or Object.toQueryString instead.'
277
+ },
278
+
279
+ {
280
+ methodName: 'remove',
281
+ namespace: Hash.prototype,
282
+ message: 'Hash#remove is no longer supported, use Hash#unset instead.\n' +
283
+ 'Please note that Hash#unset only accepts one argument.',
284
+ type: 'removal'
285
+ },
286
+
287
+ {
288
+ methodName: 'merge',
289
+ namespace: Hash.prototype,
290
+ message: 'Hash#merge is no longer destructive: it operates on a clone of the Hash instance.\n' +
291
+ 'If you need a destructive merge, use Hash#update instead.',
292
+ type: 'modification'
293
+ },
294
+
295
+ {
296
+ methodName: 'unloadCache',
297
+ namespace: Event,
298
+ message: 'Event.unloadCache has been deprecated.'
299
+ }
300
+ ]);
301
+
302
+ // Special casing for Hash.
303
+
304
+ (function() {
305
+ if (!Prototype.Browser.Gecko) return;
306
+
307
+ var __properties = Object.keys(Hash.prototype).concat(['_object', '__properties']);
308
+
309
+ var messages = {
310
+ setting: new Template("Directly setting a property on an instance of Hash is no longer supported.\n" +
311
+ "Please use Hash#set('#{property}', #{value}) instead."),
312
+ getting: new Template("Directly accessing a property of an instance of Hash is no longer supported.\n" +
313
+ "Please use Hash#get('#{property}') instead.")
314
+ };
315
+
316
+ function notify(property, value) {
317
+ var message = messages[arguments.length == 1 ? 'getting' : 'setting'].evaluate({
318
+ property: property,
319
+ value: Object.inspect(value)
320
+ });
321
+ DeprecationNotifier.notify(message, 'removal');
322
+ }
323
+
324
+ function defineSetters(obj, prop) {
325
+ if (obj.__properties.include(prop)) return;
326
+ obj.__properties.push(prop);
327
+ obj.__defineGetter__(prop, function() {
328
+ checkProperties(this);
329
+ notify(prop);
330
+ });
331
+ obj.__defineSetter__(prop, function(value) {
332
+ checkProperties(this);
333
+ notify(prop, value);
334
+ });
335
+ }
336
+
337
+ function checkProperties(hash) {
338
+ var current = Object.keys(hash);
339
+ if (current.length == hash.__properties.length)
340
+ return;
341
+ current.each(function(prop) {
342
+ if (hash.__properties.include(prop)) return;
343
+ notify(prop, hash[prop]);
344
+ defineSetters(hash, prop);
345
+ });
346
+ }
347
+
348
+ Hash.prototype.set = Hash.prototype.set.wrap(function(proceed, property, value) {
349
+ defineSetters(this, property);
350
+ return proceed(property, value);
351
+ });
352
+
353
+ $w('merge update').each(function(name) {
354
+ Hash.prototype[name] = Hash.prototype[name].wrap(function(proceed, object) {
355
+ for (var prop in object) defineSetters(this, prop);
356
+ return proceed(object);
357
+ });
358
+ });
359
+
360
+ $H(Hash.prototype).each(function(method) {
361
+ var key = method.key;
362
+ if (!Object.isFunction(method.value) || key == 'initialize') return;
363
+ Hash.prototype[key] = Hash.prototype[key].wrap(function(proceed) {
364
+ checkProperties(this);
365
+ return proceed.apply(proceed, $A(arguments).splice(1));
366
+ });
367
+ });
368
+
369
+ Hash.prototype.initialize = Hash.prototype.initialize.wrap(function(proceed, object) {
370
+ this.__properties = __properties.clone();
371
+ for (var prop in object) defineSetters(this, prop);
372
+ proceed(object);
373
+ });
374
+ })();
js/prototype/effects.js ADDED
@@ -0,0 +1,1094 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // script.aculo.us effects.js v1.7.1_beta1, Mon Mar 12 14:40:50 +0100 2007
2
+
3
+ // Copyright (c) 2005-2007 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
4
+ // Contributors:
5
+ // Justin Palmer (http://encytemedia.com/)
6
+ // Mark Pilgrim (http://diveintomark.org/)
7
+ // Martin Bialasinki
8
+ //
9
+ // script.aculo.us is freely distributable under the terms of an MIT-style license.
10
+ // For details, see the script.aculo.us web site: http://script.aculo.us/
11
+
12
+ // converts rgb() and #xxx to #xxxxxx format,
13
+ // returns self (or first argument) if not convertable
14
+ String.prototype.parseColor = function() {
15
+ var color = '#';
16
+ if(this.slice(0,4) == 'rgb(') {
17
+ var cols = this.slice(4,this.length-1).split(',');
18
+ var i=0; do { color += parseInt(cols[i]).toColorPart() } while (++i<3);
19
+ } else {
20
+ if(this.slice(0,1) == '#') {
21
+ if(this.length==4) for(var i=1;i<4;i++) color += (this.charAt(i) + this.charAt(i)).toLowerCase();
22
+ if(this.length==7) color = this.toLowerCase();
23
+ }
24
+ }
25
+ return(color.length==7 ? color : (arguments[0] || this));
26
+ }
27
+
28
+ /*--------------------------------------------------------------------------*/
29
+
30
+ Element.collectTextNodes = function(element) {
31
+ return $A($(element).childNodes).collect( function(node) {
32
+ return (node.nodeType==3 ? node.nodeValue :
33
+ (node.hasChildNodes() ? Element.collectTextNodes(node) : ''));
34
+ }).flatten().join('');
35
+ }
36
+
37
+ Element.collectTextNodesIgnoreClass = function(element, className) {
38
+ return $A($(element).childNodes).collect( function(node) {
39
+ return (node.nodeType==3 ? node.nodeValue :
40
+ ((node.hasChildNodes() && !Element.hasClassName(node,className)) ?
41
+ Element.collectTextNodesIgnoreClass(node, className) : ''));
42
+ }).flatten().join('');
43
+ }
44
+
45
+ Element.setContentZoom = function(element, percent) {
46
+ element = $(element);
47
+ element.setStyle({fontSize: (percent/100) + 'em'});
48
+ if(Prototype.Browser.WebKit) window.scrollBy(0,0);
49
+ return element;
50
+ }
51
+
52
+ Element.getInlineOpacity = function(element){
53
+ return $(element).style.opacity || '';
54
+ }
55
+
56
+ Element.forceRerendering = function(element) {
57
+ try {
58
+ element = $(element);
59
+ var n = document.createTextNode(' ');
60
+ element.appendChild(n);
61
+ element.removeChild(n);
62
+ } catch(e) { }
63
+ };
64
+
65
+ /*--------------------------------------------------------------------------*/
66
+
67
+ Array.prototype.call = function() {
68
+ var args = arguments;
69
+ this.each(function(f){ f.apply(this, args) });
70
+ }
71
+
72
+ /*--------------------------------------------------------------------------*/
73
+
74
+ var Effect = {
75
+ _elementDoesNotExistError: {
76
+ name: 'ElementDoesNotExistError',
77
+ message: 'The specified DOM element does not exist, but is required for this effect to operate'
78
+ },
79
+ tagifyText: function(element) {
80
+ if(typeof Builder == 'undefined')
81
+ throw("Effect.tagifyText requires including script.aculo.us' builder.js library");
82
+
83
+ var tagifyStyle = 'position:relative';
84
+ if(Prototype.Browser.IE) tagifyStyle += ';zoom:1';
85
+
86
+ element = $(element);
87
+ $A(element.childNodes).each( function(child) {
88
+ if(child.nodeType==3) {
89
+ child.nodeValue.toArray().each( function(character) {
90
+ element.insertBefore(
91
+ Builder.node('span',{style: tagifyStyle},
92
+ character == ' ' ? String.fromCharCode(160) : character),
93
+ child);
94
+ });
95
+ Element.remove(child);
96
+ }
97
+ });
98
+ },
99
+ multiple: function(element, effect) {
100
+ var elements;
101
+ if(((typeof element == 'object') ||
102
+ (typeof element == 'function')) &&
103
+ (element.length))
104
+ elements = element;
105
+ else
106
+ elements = $(element).childNodes;
107
+
108
+ var options = Object.extend({
109
+ speed: 0.1,
110
+ delay: 0.0
111
+ }, arguments[2] || {});
112
+ var masterDelay = options.delay;
113
+
114
+ $A(elements).each( function(element, index) {
115
+ new effect(element, Object.extend(options, { delay: index * options.speed + masterDelay }));
116
+ });
117
+ },
118
+ PAIRS: {
119
+ 'slide': ['SlideDown','SlideUp'],
120
+ 'blind': ['BlindDown','BlindUp'],
121
+ 'appear': ['Appear','Fade']
122
+ },
123
+ toggle: function(element, effect) {
124
+ element = $(element);
125
+ effect = (effect || 'appear').toLowerCase();
126
+ var options = Object.extend({
127
+ queue: { position:'end', scope:(element.id || 'global'), limit: 1 }
128
+ }, arguments[2] || {});
129
+ Effect[element.visible() ?
130
+ Effect.PAIRS[effect][1] : Effect.PAIRS[effect][0]](element, options);
131
+ }
132
+ };
133
+
134
+ var Effect2 = Effect; // deprecated
135
+
136
+ /* ------------- transitions ------------- */
137
+
138
+ Effect.Transitions = {
139
+ linear: Prototype.K,
140
+ sinoidal: function(pos) {
141
+ return (-Math.cos(pos*Math.PI)/2) + 0.5;
142
+ },
143
+ reverse: function(pos) {
144
+ return 1-pos;
145
+ },
146
+ flicker: function(pos) {
147
+ var pos = ((-Math.cos(pos*Math.PI)/4) + 0.75) + Math.random()/4;
148
+ return (pos > 1 ? 1 : pos);
149
+ },
150
+ wobble: function(pos) {
151
+ return (-Math.cos(pos*Math.PI*(9*pos))/2) + 0.5;
152
+ },
153
+ pulse: function(pos, pulses) {
154
+ pulses = pulses || 5;
155
+ return (
156
+ Math.round((pos % (1/pulses)) * pulses) == 0 ?
157
+ ((pos * pulses * 2) - Math.floor(pos * pulses * 2)) :
158
+ 1 - ((pos * pulses * 2) - Math.floor(pos * pulses * 2))
159
+ );
160
+ },
161
+ none: function(pos) {
162
+ return 0;
163
+ },
164
+ full: function(pos) {
165
+ return 1;
166
+ }
167
+ };
168
+
169
+ /* ------------- core effects ------------- */
170
+
171
+ Effect.ScopedQueue = Class.create();
172
+ Object.extend(Object.extend(Effect.ScopedQueue.prototype, Enumerable), {
173
+ initialize: function() {
174
+ this.effects = [];
175
+ this.interval = null;
176
+ },
177
+ _each: function(iterator) {
178
+ this.effects._each(iterator);
179
+ },
180
+ add: function(effect) {
181
+ var timestamp = new Date().getTime();
182
+
183
+ var position = (typeof effect.options.queue == 'string') ?
184
+ effect.options.queue : effect.options.queue.position;
185
+
186
+ switch(position) {
187
+ case 'front':
188
+ // move unstarted effects after this effect
189
+ this.effects.findAll(function(e){ return e.state=='idle' }).each( function(e) {
190
+ e.startOn += effect.finishOn;
191
+ e.finishOn += effect.finishOn;
192
+ });
193
+ break;
194
+ case 'with-last':
195
+ timestamp = this.effects.pluck('startOn').max() || timestamp;
196
+ break;
197
+ case 'end':
198
+ // start effect after last queued effect has finished
199
+ timestamp = this.effects.pluck('finishOn').max() || timestamp;
200
+ break;
201
+ }
202
+
203
+ effect.startOn += timestamp;
204
+ effect.finishOn += timestamp;
205
+
206
+ if(!effect.options.queue.limit || (this.effects.length < effect.options.queue.limit))
207
+ this.effects.push(effect);
208
+
209
+ if(!this.interval)
210
+ this.interval = setInterval(this.loop.bind(this), 15);
211
+ },
212
+ remove: function(effect) {
213
+ this.effects = this.effects.reject(function(e) { return e==effect });
214
+ if(this.effects.length == 0) {
215
+ clearInterval(this.interval);
216
+ this.interval = null;
217
+ }
218
+ },
219
+ loop: function() {
220
+ var timePos = new Date().getTime();
221
+ for(var i=0, len=this.effects.length;i<len;i++)
222
+ this.effects[i] && this.effects[i].loop(timePos);
223
+ }
224
+ });
225
+
226
+ Effect.Queues = {
227
+ instances: $H(),
228
+ get: function(queueName) {
229
+ if(typeof queueName != 'string') return queueName;
230
+
231
+ if(!this.instances[queueName])
232
+ this.instances[queueName] = new Effect.ScopedQueue();
233
+
234
+ return this.instances[queueName];
235
+ }
236
+ }
237
+ Effect.Queue = Effect.Queues.get('global');
238
+
239
+ Effect.DefaultOptions = {
240
+ transition: Effect.Transitions.sinoidal,
241
+ duration: 1.0, // seconds
242
+ fps: 100, // 100= assume 66fps max.
243
+ sync: false, // true for combining
244
+ from: 0.0,
245
+ to: 1.0,
246
+ delay: 0.0,
247
+ queue: 'parallel'
248
+ }
249
+
250
+ Effect.Base = function() {};
251
+ Effect.Base.prototype = {
252
+ position: null,
253
+ start: function(options) {
254
+ function codeForEvent(options,eventName){
255
+ return (
256
+ (options[eventName+'Internal'] ? 'this.options.'+eventName+'Internal(this);' : '') +
257
+ (options[eventName] ? 'this.options.'+eventName+'(this);' : '')
258
+ );
259
+ }
260
+ if(options.transition === false) options.transition = Effect.Transitions.linear;
261
+ this.options = Object.extend(Object.extend({},Effect.DefaultOptions), options || {});
262
+ this.currentFrame = 0;
263
+ this.state = 'idle';
264
+ this.startOn = this.options.delay*1000;
265
+ this.finishOn = this.startOn+(this.options.duration*1000);
266
+ this.fromToDelta = this.options.to-this.options.from;
267
+ this.totalTime = this.finishOn-this.startOn;
268
+ this.totalFrames = this.options.fps*this.options.duration;
269
+
270
+ eval('this.render = function(pos){ '+
271
+ 'if(this.state=="idle"){this.state="running";'+
272
+ codeForEvent(options,'beforeSetup')+
273
+ (this.setup ? 'this.setup();':'')+
274
+ codeForEvent(options,'afterSetup')+
275
+ '};if(this.state=="running"){'+
276
+ 'pos=this.options.transition(pos)*'+this.fromToDelta+'+'+this.options.from+';'+
277
+ 'this.position=pos;'+
278
+ codeForEvent(options,'beforeUpdate')+
279
+ (this.update ? 'this.update(pos);':'')+
280
+ codeForEvent(options,'afterUpdate')+
281
+ '}}');
282
+
283
+ this.event('beforeStart');
284
+ if(!this.options.sync)
285
+ Effect.Queues.get(typeof this.options.queue == 'string' ?
286
+ 'global' : this.options.queue.scope).add(this);
287
+ },
288
+ loop: function(timePos) {
289
+ if(timePos >= this.startOn) {
290
+ if(timePos >= this.finishOn) {
291
+ this.render(1.0);
292
+ this.cancel();
293
+ this.event('beforeFinish');
294
+ if(this.finish) this.finish();
295
+ this.event('afterFinish');
296
+ return;
297
+ }
298
+ var pos = (timePos - this.startOn) / this.totalTime,
299
+ frame = Math.round(pos * this.totalFrames);
300
+ if(frame > this.currentFrame) {
301
+ this.render(pos);
302
+ this.currentFrame = frame;
303
+ }
304
+ }
305
+ },
306
+ cancel: function() {
307
+ if(!this.options.sync)
308
+ Effect.Queues.get(typeof this.options.queue == 'string' ?
309
+ 'global' : this.options.queue.scope).remove(this);
310
+ this.state = 'finished';
311
+ },
312
+ event: function(eventName) {
313
+ if(this.options[eventName + 'Internal']) this.options[eventName + 'Internal'](this);
314
+ if(this.options[eventName]) this.options[eventName](this);
315
+ },
316
+ inspect: function() {
317
+ var data = $H();
318
+ for(property in this)
319
+ if(typeof this[property] != 'function') data[property] = this[property];
320
+ return '#<Effect:' + data.inspect() + ',options:' + $H(this.options).inspect() + '>';
321
+ }
322
+ }
323
+
324
+ Effect.Parallel = Class.create();
325
+ Object.extend(Object.extend(Effect.Parallel.prototype, Effect.Base.prototype), {
326
+ initialize: function(effects) {
327
+ this.effects = effects || [];
328
+ this.start(arguments[1]);
329
+ },
330
+ update: function(position) {
331
+ this.effects.invoke('render', position);
332
+ },
333
+ finish: function(position) {
334
+ this.effects.each( function(effect) {
335
+ effect.render(1.0);
336
+ effect.cancel();
337
+ effect.event('beforeFinish');
338
+ if(effect.finish) effect.finish(position);
339
+ effect.event('afterFinish');
340
+ });
341
+ }
342
+ });
343
+
344
+ Effect.Event = Class.create();
345
+ Object.extend(Object.extend(Effect.Event.prototype, Effect.Base.prototype), {
346
+ initialize: function() {
347
+ var options = Object.extend({
348
+ duration: 0
349
+ }, arguments[0] || {});
350
+ this.start(options);
351
+ },
352
+ update: Prototype.emptyFunction
353
+ });
354
+
355
+ Effect.Opacity = Class.create();
356
+ Object.extend(Object.extend(Effect.Opacity.prototype, Effect.Base.prototype), {
357
+ initialize: function(element) {
358
+ this.element = $(element);
359
+ if(!this.element) throw(Effect._elementDoesNotExistError);
360
+ // make this work on IE on elements without 'layout'
361
+ if(Prototype.Browser.IE && (!this.element.currentStyle.hasLayout))
362
+ this.element.setStyle({zoom: 1});
363
+ var options = Object.extend({
364
+ from: this.element.getOpacity() || 0.0,
365
+ to: 1.0
366
+ }, arguments[1] || {});
367
+ this.start(options);
368
+ },
369
+ update: function(position) {
370
+ this.element.setOpacity(position);
371
+ }
372
+ });
373
+
374
+ Effect.Move = Class.create();
375
+ Object.extend(Object.extend(Effect.Move.prototype, Effect.Base.prototype), {
376
+ initialize: function(element) {
377
+ this.element = $(element);
378
+ if(!this.element) throw(Effect._elementDoesNotExistError);
379
+ var options = Object.extend({
380
+ x: 0,
381
+ y: 0,
382
+ mode: 'relative'
383
+ }, arguments[1] || {});
384
+ this.start(options);
385
+ },
386
+ setup: function() {
387
+ // Bug in Opera: Opera returns the "real" position of a static element or
388
+ // relative element that does not have top/left explicitly set.
389
+ // ==> Always set top and left for position relative elements in your stylesheets
390
+ // (to 0 if you do not need them)
391
+ this.element.makePositioned();
392
+ this.originalLeft = parseFloat(this.element.getStyle('left') || '0');
393
+ this.originalTop = parseFloat(this.element.getStyle('top') || '0');
394
+ if(this.options.mode == 'absolute') {
395
+ // absolute movement, so we need to calc deltaX and deltaY
396
+ this.options.x = this.options.x - this.originalLeft;
397
+ this.options.y = this.options.y - this.originalTop;
398
+ }
399
+ },
400
+ update: function(position) {
401
+ this.element.setStyle({
402
+ left: Math.round(this.options.x * position + this.originalLeft) + 'px',
403
+ top: Math.round(this.options.y * position + this.originalTop) + 'px'
404
+ });
405
+ }
406
+ });
407
+
408
+ // for backwards compatibility
409
+ Effect.MoveBy = function(element, toTop, toLeft) {
410
+ return new Effect.Move(element,
411
+ Object.extend({ x: toLeft, y: toTop }, arguments[3] || {}));
412
+ };
413
+
414
+ Effect.Scale = Class.create();
415
+ Object.extend(Object.extend(Effect.Scale.prototype, Effect.Base.prototype), {
416
+ initialize: function(element, percent) {
417
+ this.element = $(element);
418
+ if(!this.element) throw(Effect._elementDoesNotExistError);
419
+ var options = Object.extend({
420
+ scaleX: true,
421
+ scaleY: true,
422
+ scaleContent: true,
423
+ scaleFromCenter: false,
424
+ scaleMode: 'box', // 'box' or 'contents' or {} with provided values
425
+ scaleFrom: 100.0,
426
+ scaleTo: percent
427
+ }, arguments[2] || {});
428
+ this.start(options);
429
+ },
430
+ setup: function() {
431
+ this.restoreAfterFinish = this.options.restoreAfterFinish || false;
432
+ this.elementPositioning = this.element.getStyle('position');
433
+
434
+ this.originalStyle = {};
435
+ ['top','left','width','height','fontSize'].each( function(k) {
436
+ this.originalStyle[k] = this.element.style[k];
437
+ }.bind(this));
438
+
439
+ this.originalTop = this.element.offsetTop;
440
+ this.originalLeft = this.element.offsetLeft;
441
+
442
+ var fontSize = this.element.getStyle('font-size') || '100%';
443
+ ['em','px','%','pt'].each( function(fontSizeType) {
444
+ if(fontSize.indexOf(fontSizeType)>0) {
445
+ this.fontSize = parseFloat(fontSize);
446
+ this.fontSizeType = fontSizeType;
447
+ }
448
+ }.bind(this));
449
+
450
+ this.factor = (this.options.scaleTo - this.options.scaleFrom)/100;
451
+
452
+ this.dims = null;
453
+ if(this.options.scaleMode=='box')
454
+ this.dims = [this.element.offsetHeight, this.element.offsetWidth];
455
+ if(/^content/.test(this.options.scaleMode))
456
+ this.dims = [this.element.scrollHeight, this.element.scrollWidth];
457
+ if(!this.dims)
458
+ this.dims = [this.options.scaleMode.originalHeight,
459
+ this.options.scaleMode.originalWidth];
460
+ },
461
+ update: function(position) {
462
+ var currentScale = (this.options.scaleFrom/100.0) + (this.factor * position);
463
+ if(this.options.scaleContent && this.fontSize)
464
+ this.element.setStyle({fontSize: this.fontSize * currentScale + this.fontSizeType });
465
+ this.setDimensions(this.dims[0] * currentScale, this.dims[1] * currentScale);
466
+ },
467
+ finish: function(position) {
468
+ if(this.restoreAfterFinish) this.element.setStyle(this.originalStyle);
469
+ },
470
+ setDimensions: function(height, width) {
471
+ var d = {};
472
+ if(this.options.scaleX) d.width = Math.round(width) + 'px';
473
+ if(this.options.scaleY) d.height = Math.round(height) + 'px';
474
+ if(this.options.scaleFromCenter) {
475
+ var topd = (height - this.dims[0])/2;
476
+ var leftd = (width - this.dims[1])/2;
477
+ if(this.elementPositioning == 'absolute') {
478
+ if(this.options.scaleY) d.top = this.originalTop-topd + 'px';
479
+ if(this.options.scaleX) d.left = this.originalLeft-leftd + 'px';
480
+ } else {
481
+ if(this.options.scaleY) d.top = -topd + 'px';
482
+ if(this.options.scaleX) d.left = -leftd + 'px';
483
+ }
484
+ }
485
+ this.element.setStyle(d);
486
+ }
487
+ });
488
+
489
+ Effect.Highlight = Class.create();
490
+ Object.extend(Object.extend(Effect.Highlight.prototype, Effect.Base.prototype), {
491
+ initialize: function(element) {
492
+ this.element = $(element);
493
+ if(!this.element) throw(Effect._elementDoesNotExistError);
494
+ var options = Object.extend({ startcolor: '#ffff99' }, arguments[1] || {});
495
+ this.start(options);
496
+ },
497
+ setup: function() {
498
+ // Prevent executing on elements not in the layout flow
499
+ if(this.element.getStyle('display')=='none') { this.cancel(); return; }
500
+ // Disable background image during the effect
501
+ this.oldStyle = {};
502
+ if (!this.options.keepBackgroundImage) {
503
+ this.oldStyle.backgroundImage = this.element.getStyle('background-image');
504
+ this.element.setStyle({backgroundImage: 'none'});
505
+ }
506
+ if(!this.options.endcolor)
507
+ this.options.endcolor = this.element.getStyle('background-color').parseColor('#ffffff');
508
+ if(!this.options.restorecolor)
509
+ this.options.restorecolor = this.element.getStyle('background-color');
510
+ // init color calculations
511
+ this._base = $R(0,2).map(function(i){ return parseInt(this.options.startcolor.slice(i*2+1,i*2+3),16) }.bind(this));
512
+ this._delta = $R(0,2).map(function(i){ return parseInt(this.options.endcolor.slice(i*2+1,i*2+3),16)-this._base[i] }.bind(this));
513
+ },
514
+ update: function(position) {
515
+ this.element.setStyle({backgroundColor: $R(0,2).inject('#',function(m,v,i){
516
+ return m+(Math.round(this._base[i]+(this._delta[i]*position)).toColorPart()); }.bind(this)) });
517
+ },
518
+ finish: function() {
519
+ this.element.setStyle(Object.extend(this.oldStyle, {
520
+ backgroundColor: this.options.restorecolor
521
+ }));
522
+ }
523
+ });
524
+
525
+ Effect.ScrollTo = Class.create();
526
+ Object.extend(Object.extend(Effect.ScrollTo.prototype, Effect.Base.prototype), {
527
+ initialize: function(element) {
528
+ this.element = $(element);
529
+ this.start(arguments[1] || {});
530
+ },
531
+ setup: function() {
532
+ Position.prepare();
533
+ var offsets = Position.cumulativeOffset(this.element);
534
+ if(this.options.offset) offsets[1] += this.options.offset;
535
+ var max = window.innerHeight ?
536
+ window.height - window.innerHeight :
537
+ document.body.scrollHeight -
538
+ (document.documentElement.clientHeight ?
539
+ document.documentElement.clientHeight : document.body.clientHeight);
540
+ this.scrollStart = Position.deltaY;
541
+ this.delta = (offsets[1] > max ? max : offsets[1]) - this.scrollStart;
542
+ },
543
+ update: function(position) {
544
+ Position.prepare();
545
+ window.scrollTo(Position.deltaX,
546
+ this.scrollStart + (position*this.delta));
547
+ }
548
+ });
549
+
550
+ /* ------------- combination effects ------------- */
551
+
552
+ Effect.Fade = function(element) {
553
+ element = $(element);
554
+ var oldOpacity = element.getInlineOpacity();
555
+ var options = Object.extend({
556
+ from: element.getOpacity() || 1.0,
557
+ to: 0.0,
558
+ afterFinishInternal: function(effect) {
559
+ if(effect.options.to!=0) return;
560
+ effect.element.hide().setStyle({opacity: oldOpacity});
561
+ }}, arguments[1] || {});
562
+ return new Effect.Opacity(element,options);
563
+ }
564
+
565
+ Effect.Appear = function(element) {
566
+ element = $(element);
567
+ var options = Object.extend({
568
+ from: (element.getStyle('display') == 'none' ? 0.0 : element.getOpacity() || 0.0),
569
+ to: 1.0,
570
+ // force Safari to render floated elements properly
571
+ afterFinishInternal: function(effect) {
572
+ effect.element.forceRerendering();
573
+ },
574
+ beforeSetup: function(effect) {
575
+ effect.element.setOpacity(effect.options.from).show();
576
+ }}, arguments[1] || {});
577
+ return new Effect.Opacity(element,options);
578
+ }
579
+
580
+ Effect.Puff = function(element) {
581
+ element = $(element);
582
+ var oldStyle = {
583
+ opacity: element.getInlineOpacity(),
584
+ position: element.getStyle('position'),
585
+ top: element.style.top,
586
+ left: element.style.left,
587
+ width: element.style.width,
588
+ height: element.style.height
589
+ };
590
+ return new Effect.Parallel(
591
+ [ new Effect.Scale(element, 200,
592
+ { sync: true, scaleFromCenter: true, scaleContent: true, restoreAfterFinish: true }),
593
+ new Effect.Opacity(element, { sync: true, to: 0.0 } ) ],
594
+ Object.extend({ duration: 1.0,
595
+ beforeSetupInternal: function(effect) {
596
+ Position.absolutize(effect.effects[0].element)
597
+ },
598
+ afterFinishInternal: function(effect) {
599
+ effect.effects[0].element.hide().setStyle(oldStyle); }
600
+ }, arguments[1] || {})
601
+ );
602
+ }
603
+
604
+ Effect.BlindUp = function(element) {
605
+ element = $(element);
606
+ element.makeClipping();
607
+ return new Effect.Scale(element, 0,
608
+ Object.extend({ scaleContent: false,
609
+ scaleX: false,
610
+ restoreAfterFinish: true,
611
+ afterFinishInternal: function(effect) {
612
+ effect.element.hide().undoClipping();
613
+ }
614
+ }, arguments[1] || {})
615
+ );
616
+ }
617
+
618
+ Effect.BlindDown = function(element) {
619
+ element = $(element);
620
+ var elementDimensions = element.getDimensions();
621
+ return new Effect.Scale(element, 100, Object.extend({
622
+ scaleContent: false,
623
+ scaleX: false,
624
+ scaleFrom: 0,
625
+ scaleMode: {originalHeight: elementDimensions.height, originalWidth: elementDimensions.width},
626
+ restoreAfterFinish: true,
627
+ afterSetup: function(effect) {
628
+ effect.element.makeClipping().setStyle({height: '0px'}).show();
629
+ },
630
+ afterFinishInternal: function(effect) {
631
+ effect.element.undoClipping();
632
+ }
633
+ }, arguments[1] || {}));
634
+ }
635
+
636
+ Effect.SwitchOff = function(element) {
637
+ element = $(element);
638
+ var oldOpacity = element.getInlineOpacity();
639
+ return new Effect.Appear(element, Object.extend({
640
+ duration: 0.4,
641
+ from: 0,
642
+ transition: Effect.Transitions.flicker,
643
+ afterFinishInternal: function(effect) {
644
+ new Effect.Scale(effect.element, 1, {
645
+ duration: 0.3, scaleFromCenter: true,
646
+ scaleX: false, scaleContent: false, restoreAfterFinish: true,
647
+ beforeSetup: function(effect) {
648
+ effect.element.makePositioned().makeClipping();
649
+ },
650
+ afterFinishInternal: function(effect) {
651
+ effect.element.hide().undoClipping().undoPositioned().setStyle({opacity: oldOpacity});
652
+ }
653
+ })
654
+ }
655
+ }, arguments[1] || {}));
656
+ }
657
+
658
+ Effect.DropOut = function(element) {
659
+ element = $(element);
660
+ var oldStyle = {
661
+ top: element.getStyle('top'),
662
+ left: element.getStyle('left'),
663
+ opacity: element.getInlineOpacity() };
664
+ return new Effect.Parallel(
665
+ [ new Effect.Move(element, {x: 0, y: 100, sync: true }),
666
+ new Effect.Opacity(element, { sync: true, to: 0.0 }) ],
667
+ Object.extend(
668
+ { duration: 0.5,
669
+ beforeSetup: function(effect) {
670
+ effect.effects[0].element.makePositioned();
671
+ },
672
+ afterFinishInternal: function(effect) {
673
+ effect.effects[0].element.hide().undoPositioned().setStyle(oldStyle);
674
+ }
675
+ }, arguments[1] || {}));
676
+ }
677
+
678
+ Effect.Shake = function(element) {
679
+ element = $(element);
680
+ var oldStyle = {
681
+ top: element.getStyle('top'),
682
+ left: element.getStyle('left') };
683
+ return new Effect.Move(element,
684
+ { x: 20, y: 0, duration: 0.05, afterFinishInternal: function(effect) {
685
+ new Effect.Move(effect.element,
686
+ { x: -40, y: 0, duration: 0.1, afterFinishInternal: function(effect) {
687
+ new Effect.Move(effect.element,
688
+ { x: 40, y: 0, duration: 0.1, afterFinishInternal: function(effect) {
689
+ new Effect.Move(effect.element,
690
+ { x: -40, y: 0, duration: 0.1, afterFinishInternal: function(effect) {
691
+ new Effect.Move(effect.element,
692
+ { x: 40, y: 0, duration: 0.1, afterFinishInternal: function(effect) {
693
+ new Effect.Move(effect.element,
694
+ { x: -20, y: 0, duration: 0.05, afterFinishInternal: function(effect) {
695
+ effect.element.undoPositioned().setStyle(oldStyle);
696
+ }}) }}) }}) }}) }}) }});
697
+ }
698
+
699
+ Effect.SlideDown = function(element) {
700
+ element = $(element).cleanWhitespace();
701
+ // SlideDown need to have the content of the element wrapped in a container element with fixed height!
702
+ var oldInnerBottom = element.down().getStyle('bottom');
703
+ var elementDimensions = element.getDimensions();
704
+ return new Effect.Scale(element, 100, Object.extend({
705
+ scaleContent: false,
706
+ scaleX: false,
707
+ scaleFrom: window.opera ? 0 : 1,
708
+ scaleMode: {originalHeight: elementDimensions.height, originalWidth: elementDimensions.width},
709
+ restoreAfterFinish: true,
710
+ afterSetup: function(effect) {
711
+ effect.element.makePositioned();
712
+ effect.element.down().makePositioned();
713
+ if(window.opera) effect.element.setStyle({top: ''});
714
+ effect.element.makeClipping().setStyle({height: '0px'}).show();
715
+ },
716
+ afterUpdateInternal: function(effect) {
717
+ effect.element.down().setStyle({bottom:
718
+ (effect.dims[0] - effect.element.clientHeight) + 'px' });
719
+ },
720
+ afterFinishInternal: function(effect) {
721
+ effect.element.undoClipping().undoPositioned();
722
+ effect.element.down().undoPositioned().setStyle({bottom: oldInnerBottom}); }
723
+ }, arguments[1] || {})
724
+ );
725
+ }
726
+
727
+ Effect.SlideUp = function(element) {
728
+ element = $(element).cleanWhitespace();
729
+ var oldInnerBottom = element.down().getStyle('bottom');
730
+ return new Effect.Scale(element, window.opera ? 0 : 1,
731
+ Object.extend({ scaleContent: false,
732
+ scaleX: false,
733
+ scaleMode: 'box',
734
+ scaleFrom: 100,
735
+ restoreAfterFinish: true,
736
+ beforeStartInternal: function(effect) {
737
+ effect.element.makePositioned();
738
+ effect.element.down().makePositioned();
739
+ if(window.opera) effect.element.setStyle({top: ''});
740
+ effect.element.makeClipping().show();
741
+ },
742
+ afterUpdateInternal: function(effect) {
743
+ effect.element.down().setStyle({bottom:
744
+ (effect.dims[0] - effect.element.clientHeight) + 'px' });
745
+ },
746
+ afterFinishInternal: function(effect) {
747
+ effect.element.hide().undoClipping().undoPositioned().setStyle({bottom: oldInnerBottom});
748
+ effect.element.down().undoPositioned();
749
+ }
750
+ }, arguments[1] || {})
751
+ );
752
+ }
753
+
754
+ // Bug in opera makes the TD containing this element expand for a instance after finish
755
+ Effect.Squish = function(element) {
756
+ return new Effect.Scale(element, window.opera ? 1 : 0, {
757
+ restoreAfterFinish: true,
758
+ beforeSetup: function(effect) {
759
+ effect.element.makeClipping();
760
+ },
761
+ afterFinishInternal: function(effect) {
762
+ effect.element.hide().undoClipping();
763
+ }
764
+ });
765
+ }
766
+
767
+ Effect.Grow = function(element) {
768
+ element = $(element);
769
+ var options = Object.extend({
770
+ direction: 'center',
771
+ moveTransition: Effect.Transitions.sinoidal,
772
+ scaleTransition: Effect.Transitions.sinoidal,
773
+ opacityTransition: Effect.Transitions.full
774
+ }, arguments[1] || {});
775
+ var oldStyle = {
776
+ top: element.style.top,
777
+ left: element.style.left,
778
+ height: element.style.height,
779
+ width: element.style.width,
780
+ opacity: element.getInlineOpacity() };
781
+
782
+ var dims = element.getDimensions();
783
+ var initialMoveX, initialMoveY;
784
+ var moveX, moveY;
785
+
786
+ switch (options.direction) {
787
+ case 'top-left':
788
+ initialMoveX = initialMoveY = moveX = moveY = 0;
789
+ break;
790
+ case 'top-right':
791
+ initialMoveX = dims.width;
792
+ initialMoveY = moveY = 0;
793
+ moveX = -dims.width;
794
+ break;
795
+ case 'bottom-left':
796
+ initialMoveX = moveX = 0;
797
+ initialMoveY = dims.height;
798
+ moveY = -dims.height;
799
+ break;
800
+ case 'bottom-right':
801
+ initialMoveX = dims.width;
802
+ initialMoveY = dims.height;
803
+ moveX = -dims.width;
804
+ moveY = -dims.height;
805
+ break;
806
+ case 'center':
807
+ initialMoveX = dims.width / 2;
808
+ initialMoveY = dims.height / 2;
809
+ moveX = -dims.width / 2;
810
+ moveY = -dims.height / 2;
811
+ break;
812
+ }
813
+
814
+ return new Effect.Move(element, {
815
+ x: initialMoveX,
816
+ y: initialMoveY,
817
+ duration: 0.01,
818
+ beforeSetup: function(effect) {
819
+ effect.element.hide().makeClipping().makePositioned();
820
+ },
821
+ afterFinishInternal: function(effect) {
822
+ new Effect.Parallel(
823
+ [ new Effect.Opacity(effect.element, { sync: true, to: 1.0, from: 0.0, transition: options.opacityTransition }),
824
+ new Effect.Move(effect.element, { x: moveX, y: moveY, sync: true, transition: options.moveTransition }),
825
+ new Effect.Scale(effect.element, 100, {
826
+ scaleMode: { originalHeight: dims.height, originalWidth: dims.width },
827
+ sync: true, scaleFrom: window.opera ? 1 : 0, transition: options.scaleTransition, restoreAfterFinish: true})
828
+ ], Object.extend({
829
+ beforeSetup: function(effect) {
830
+ effect.effects[0].element.setStyle({height: '0px'}).show();
831
+ },
832
+ afterFinishInternal: function(effect) {
833
+ effect.effects[0].element.undoClipping().undoPositioned().setStyle(oldStyle);
834
+ }
835
+ }, options)
836
+ )
837
+ }
838
+ });
839
+ }
840
+
841
+ Effect.Shrink = function(element) {
842
+ element = $(element);
843
+ var options = Object.extend({
844
+ direction: 'center',
845
+ moveTransition: Effect.Transitions.sinoidal,
846
+ scaleTransition: Effect.Transitions.sinoidal,
847
+ opacityTransition: Effect.Transitions.none
848
+ }, arguments[1] || {});
849
+ var oldStyle = {
850
+ top: element.style.top,
851
+ left: element.style.left,
852
+ height: element.style.height,
853
+ width: element.style.width,
854
+ opacity: element.getInlineOpacity() };
855
+
856
+ var dims = element.getDimensions();
857
+ var moveX, moveY;
858
+
859
+ switch (options.direction) {
860
+ case 'top-left':
861
+ moveX = moveY = 0;
862
+ break;
863
+ case 'top-right':
864
+ moveX = dims.width;
865
+ moveY = 0;
866
+ break;
867
+ case 'bottom-left':
868
+ moveX = 0;
869
+ moveY = dims.height;
870
+ break;
871
+ case 'bottom-right':
872
+ moveX = dims.width;
873
+ moveY = dims.height;
874
+ break;
875
+ case 'center':
876
+ moveX = dims.width / 2;
877
+ moveY = dims.height / 2;
878
+ break;
879
+ }
880
+
881
+ return new Effect.Parallel(
882
+ [ new Effect.Opacity(element, { sync: true, to: 0.0, from: 1.0, transition: options.opacityTransition }),
883
+ new Effect.Scale(element, window.opera ? 1 : 0, { sync: true, transition: options.scaleTransition, restoreAfterFinish: true}),
884
+ new Effect.Move(element, { x: moveX, y: moveY, sync: true, transition: options.moveTransition })
885
+ ], Object.extend({
886
+ beforeStartInternal: function(effect) {
887
+ effect.effects[0].element.makePositioned().makeClipping();
888
+ },
889
+ afterFinishInternal: function(effect) {
890
+ effect.effects[0].element.hide().undoClipping().undoPositioned().setStyle(oldStyle); }
891
+ }, options)
892
+ );
893
+ }
894
+
895
+ Effect.Pulsate = function(element) {
896
+ element = $(element);
897
+ var options = arguments[1] || {};
898
+ var oldOpacity = element.getInlineOpacity();
899
+ var transition = options.transition || Effect.Transitions.sinoidal;
900
+ var reverser = function(pos){ return transition(1-Effect.Transitions.pulse(pos, options.pulses)) };
901
+ reverser.bind(transition);
902
+ return new Effect.Opacity(element,
903
+ Object.extend(Object.extend({ duration: 2.0, from: 0,
904
+ afterFinishInternal: function(effect) { effect.element.setStyle({opacity: oldOpacity}); }
905
+ }, options), {transition: reverser}));
906
+ }
907
+
908
+ Effect.Fold = function(element) {
909
+ element = $(element);
910
+ var oldStyle = {
911
+ top: element.style.top,
912
+ left: element.style.left,
913
+ width: element.style.width,
914
+ height: element.style.height };
915
+ element.makeClipping();
916
+ return new Effect.Scale(element, 5, Object.extend({
917
+ scaleContent: false,
918
+ scaleX: false,
919
+ afterFinishInternal: function(effect) {
920
+ new Effect.Scale(element, 1, {
921
+ scaleContent: false,
922
+ scaleY: false,
923
+ afterFinishInternal: function(effect) {
924
+ effect.element.hide().undoClipping().setStyle(oldStyle);
925
+ } });
926
+ }}, arguments[1] || {}));
927
+ };
928
+
929
+ Effect.Morph = Class.create();
930
+ Object.extend(Object.extend(Effect.Morph.prototype, Effect.Base.prototype), {
931
+ initialize: function(element) {
932
+ this.element = $(element);
933
+ if(!this.element) throw(Effect._elementDoesNotExistError);
934
+ var options = Object.extend({
935
+ style: {}
936
+ }, arguments[1] || {});
937
+ if (typeof options.style == 'string') {
938
+ if(options.style.indexOf(':') == -1) {
939
+ var cssText = '', selector = '.' + options.style;
940
+ $A(document.styleSheets).reverse().each(function(styleSheet) {
941
+ if (styleSheet.cssRules) cssRules = styleSheet.cssRules;
942
+ else if (styleSheet.rules) cssRules = styleSheet.rules;
943
+ $A(cssRules).reverse().each(function(rule) {
944
+ if (selector == rule.selectorText) {
945
+ cssText = rule.style.cssText;
946
+ throw $break;
947
+ }
948
+ });
949
+ if (cssText) throw $break;
950
+ });
951
+ this.style = cssText.parseStyle();
952
+ options.afterFinishInternal = function(effect){
953
+ effect.element.addClassName(effect.options.style);
954
+ effect.transforms.each(function(transform) {
955
+ if(transform.style != 'opacity')
956
+ effect.element.style[transform.style] = '';
957
+ });
958
+ }
959
+ } else this.style = options.style.parseStyle();
960
+ } else this.style = $H(options.style)
961
+ this.start(options);
962
+ },
963
+ setup: function(){
964
+ function parseColor(color){
965
+ if(!color || ['rgba(0, 0, 0, 0)','transparent'].include(color)) color = '#ffffff';
966
+ color = color.parseColor();
967
+ return $R(0,2).map(function(i){
968
+ return parseInt( color.slice(i*2+1,i*2+3), 16 )
969
+ });
970
+ }
971
+ this.transforms = this.style.map(function(pair){
972
+ var property = pair[0], value = pair[1], unit = null;
973
+
974
+ if(value.parseColor('#zzzzzz') != '#zzzzzz') {
975
+ value = value.parseColor();
976
+ unit = 'color';
977
+ } else if(property == 'opacity') {
978
+ value = parseFloat(value);
979
+ if(Prototype.Browser.IE && (!this.element.currentStyle.hasLayout))
980
+ this.element.setStyle({zoom: 1});
981
+ } else if(Element.CSS_LENGTH.test(value)) {
982
+ var components = value.match(/^([\+\-]?[0-9\.]+)(.*)$/);
983
+ value = parseFloat(components[1]);
984
+ unit = (components.length == 3) ? components[2] : null;
985
+ }
986
+
987
+ var originalValue = this.element.getStyle(property);
988
+ return {
989
+ style: property.camelize(),
990
+ originalValue: unit=='color' ? parseColor(originalValue) : parseFloat(originalValue || 0),
991
+ targetValue: unit=='color' ? parseColor(value) : value,
992
+ unit: unit
993
+ };
994
+ }.bind(this)).reject(function(transform){
995
+ return (
996
+ (transform.originalValue == transform.targetValue) ||
997
+ (
998
+ transform.unit != 'color' &&
999
+ (isNaN(transform.originalValue) || isNaN(transform.targetValue))
1000
+ )
1001
+ )
1002
+ });
1003
+ },
1004
+ update: function(position) {
1005
+ var style = {}, transform, i = this.transforms.length;
1006
+ while(i--)
1007
+ style[(transform = this.transforms[i]).style] =
1008
+ transform.unit=='color' ? '#'+
1009
+ (Math.round(transform.originalValue[0]+
1010
+ (transform.targetValue[0]-transform.originalValue[0])*position)).toColorPart() +
1011
+ (Math.round(transform.originalValue[1]+
1012
+ (transform.targetValue[1]-transform.originalValue[1])*position)).toColorPart() +
1013
+ (Math.round(transform.originalValue[2]+
1014
+ (transform.targetValue[2]-transform.originalValue[2])*position)).toColorPart() :
1015
+ transform.originalValue + Math.round(
1016
+ ((transform.targetValue - transform.originalValue) * position) * 1000)/1000 + transform.unit;
1017
+ this.element.setStyle(style, true);
1018
+ }
1019
+ });
1020
+
1021
+ Effect.Transform = Class.create();
1022
+ Object.extend(Effect.Transform.prototype, {
1023
+ initialize: function(tracks){
1024
+ this.tracks = [];
1025
+ this.options = arguments[1] || {};
1026
+ this.addTracks(tracks);
1027
+ },
1028
+ addTracks: function(tracks){
1029
+ tracks.each(function(track){
1030
+ var data = $H(track).values().first();
1031
+ this.tracks.push($H({
1032
+ ids: $H(track).keys().first(),
1033
+ effect: Effect.Morph,
1034
+ options: { style: data }
1035
+ }));
1036
+ }.bind(this));
1037
+ return this;
1038
+ },
1039
+ play: function(){
1040
+ return new Effect.Parallel(
1041
+ this.tracks.map(function(track){
1042
+ var elements = [$(track.ids) || $$(track.ids)].flatten();
1043
+ return elements.map(function(e){ return new track.effect(e, Object.extend({ sync:true }, track.options)) });
1044
+ }).flatten(),
1045
+ this.options
1046
+ );
1047
+ }
1048
+ });
1049
+
1050
+ Element.CSS_PROPERTIES = $w(
1051
+ 'backgroundColor backgroundPosition borderBottomColor borderBottomStyle ' +
1052
+ 'borderBottomWidth borderLeftColor borderLeftStyle borderLeftWidth ' +
1053
+ 'borderRightColor borderRightStyle borderRightWidth borderSpacing ' +
1054
+ 'borderTopColor borderTopStyle borderTopWidth bottom clip color ' +
1055
+ 'fontSize fontWeight height left letterSpacing lineHeight ' +
1056
+ 'marginBottom marginLeft marginRight marginTop markerOffset maxHeight '+
1057
+ 'maxWidth minHeight minWidth opacity outlineColor outlineOffset ' +
1058
+ 'outlineWidth paddingBottom paddingLeft paddingRight paddingTop ' +
1059
+ 'right textIndent top width wordSpacing zIndex');
1060
+
1061
+ Element.CSS_LENGTH = /^(([\+\-]?[0-9\.]+)(em|ex|px|in|cm|mm|pt|pc|\%))|0$/;
1062
+
1063
+ String.prototype.parseStyle = function(){
1064
+ var element = document.createElement('div');
1065
+ element.innerHTML = '<div style="' + this + '"></div>';
1066
+ var style = element.childNodes[0].style, styleRules = $H();
1067
+
1068
+ Element.CSS_PROPERTIES.each(function(property){
1069
+ if(style[property]) styleRules[property] = style[property];
1070
+ });
1071
+ if(Prototype.Browser.IE && this.indexOf('opacity') > -1) {
1072
+ styleRules.opacity = this.match(/opacity:\s*((?:0|1)?(?:\.\d*)?)/)[1];
1073
+ }
1074
+ return styleRules;
1075
+ };
1076
+
1077
+ Element.morph = function(element, style) {
1078
+ new Effect.Morph(element, Object.extend({ style: style }, arguments[2] || {}));
1079
+ return element;
1080
+ };
1081
+
1082
+ ['getInlineOpacity','forceRerendering','setContentZoom',
1083
+ 'collectTextNodes','collectTextNodesIgnoreClass','morph'].each(
1084
+ function(f) { Element.Methods[f] = Element[f]; }
1085
+ );
1086
+
1087
+ Element.Methods.visualEffect = function(element, effect, options) {
1088
+ s = effect.dasherize().camelize();
1089
+ effect_class = s.charAt(0).toUpperCase() + s.substring(1);
1090
+ new Effect[effect_class](element, options);
1091
+ return $(element);
1092
+ };
1093
+
1094
+ Element.addMethods();
js/prototype/extended_debug.js ADDED
@@ -0,0 +1,113 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ var commandHistory;
2
+ var historyIndex;
3
+
4
+ function showExtendedDebug() {
5
+ if (debugWindow != null) {
6
+ hideDebug();
7
+ }
8
+
9
+ if (debugWindow == null) {
10
+ commandHistory = new Array();
11
+ historyIndex = 0;
12
+
13
+ debugWindow = new Window('debug_window', {className: 'dialog',width:250, height:100, right:4, minWidth:250, bottom:42, zIndex:1000, opacity:1, showEffect: Element.show, resizable: true, title: "Debug"})
14
+ debugWindow.getContent().innerHTML = "<style>#debug_window .dialog_content {background:#000;}</style> <div font='monaco' id='debug' style='padding:3px;color:#0F0;font-family:monaco'></div>";
15
+
16
+ //create hourglass icon and attach events to it.
17
+ var cont = "<div id=\"debug_window_inspect\" style=\"width: 15px; height: 15px; background: transparent url(themes/default/inspect.gif) no-repeat 0 0; position:absolute; top:5px; left:70px; cursor:pointer; z-index:3000;\"></div>";
18
+
19
+ new Insertion.After('debug_window_maximize', cont);
20
+ Event.observe('debug_window_inspect', 'click', enterInspectionMode, false);
21
+
22
+ //create command text box
23
+ cont = "Eval:<input id=\"debug_window_command\" type=\"textbox\" style=\"width:150px; height: 12px; color: black;\">"
24
+ debugWindow.setStatusBar(cont);
25
+
26
+ Event.observe('debug_window_command', 'mousedown', donothing);
27
+ Event.observe('debug_window_command', 'keypress', evalJS, false);
28
+ }
29
+ debugWindow.show();
30
+ }
31
+
32
+ function donothing(evt){
33
+ Field.activate('debug_window_command');
34
+ return false;
35
+ }
36
+
37
+ function evalJS(evt){
38
+ if(evt.keyCode == Event.KEY_RETURN){
39
+ var js = $F('debug_window_command');
40
+ try{
41
+ var ret = eval(js);
42
+ if(ret != null)
43
+ debug(ret);
44
+ }catch(e){
45
+ debug(e);
46
+ }
47
+ $('debug_window_command').value = '';
48
+
49
+ Field.activate('debug_window_command');
50
+ commandHistory.push(js);
51
+ historyIndex = 0;
52
+ }
53
+
54
+ if(evt.keyCode == Event.KEY_UP){
55
+ if(commandHistory.length > historyIndex){
56
+ historyIndex++;
57
+ var js = commandHistory[commandHistory.length-historyIndex];
58
+ $('debug_window_command').value = js;
59
+ Event.stop(evt);
60
+ Field.activate('debug_window_command');
61
+ }
62
+ }
63
+
64
+ if(evt.keyCode == Event.KEY_DOWN){
65
+ if(commandHistory.length >= historyIndex && historyIndex > 1){
66
+ historyIndex--;
67
+ var js = commandHistory[commandHistory.length-historyIndex];
68
+ $('debug_window_command').value = js;
69
+ Event.stop(evt);
70
+ Field.activate('debug_window_command');
71
+ }
72
+ }
73
+ }
74
+
75
+ function enterInspectionMode(evt){
76
+ //stop observing magnifying glass
77
+ Event.stopObserving('debug_window_inspect', 'click', enterInspectionMode, false);
78
+ //change pointer
79
+ document.body.style.cursor='help';
80
+ //start observing mouse clicks
81
+ Event.observe(window, 'click', inspectItem, false);
82
+ }
83
+
84
+ function inspectItem(evt){
85
+ // the element that triggered the event
86
+ var element = Event.element(evt);
87
+ if(element.id!="debug_window_inspect"){
88
+ clearDebug()
89
+ //change pointer
90
+ document.body.style.cursor='default';
91
+ debug(element.id);
92
+ inspect(element);
93
+ //stop observing mouse clicks
94
+ Event.stopObserving(window, 'click', inspectItem, false);
95
+ //alert('doing something');
96
+ //start observing mag
97
+ Event.observe('debug_window_inspect', 'click', enterInspectionMode, false);
98
+ }
99
+ }
100
+
101
+ function clearDebug() {
102
+ var win = $('debug');
103
+ if (win == null)
104
+ return;
105
+
106
+ win.innerHTML=" ";
107
+ //clear inspections too
108
+ var divs = document.getElementsByClassName('inspector');
109
+ divs.each(function(div){
110
+ Element.remove(div);
111
+ });
112
+ }
113
+
js/prototype/prototype.js ADDED
@@ -0,0 +1,4328 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* Prototype JavaScript framework, version 1.6.0.3
2
+ * (c) 2005-2008 Sam Stephenson
3
+ *
4
+ * Prototype is freely distributable under the terms of an MIT-style license.
5
+ * For details, see the Prototype web site: http://www.prototypejs.org/
6
+ *
7
+ *--------------------------------------------------------------------------*/
8
+
9
+ var Prototype = {
10
+ Version: '1.6.0.3',
11
+
12
+ Browser: {
13
+ IE: !!(window.attachEvent &&
14
+ navigator.userAgent.indexOf('Opera') === -1),
15
+ Opera: navigator.userAgent.indexOf('Opera') > -1,
16
+ WebKit: navigator.userAgent.indexOf('AppleWebKit/') > -1,
17
+ Gecko: navigator.userAgent.indexOf('Gecko') > -1 &&
18
+ navigator.userAgent.indexOf('KHTML') === -1,
19
+ MobileSafari: !!navigator.userAgent.match(/Apple.*Mobile.*Safari/)
20
+ },
21
+
22
+ BrowserFeatures: {
23
+ XPath: !!document.evaluate,
24
+ SelectorsAPI: !!document.querySelector,
25
+ ElementExtensions: !!window.HTMLElement,
26
+ SpecificElementExtensions:
27
+ document.createElement('div')['__proto__'] &&
28
+ document.createElement('div')['__proto__'] !==
29
+ document.createElement('form')['__proto__']
30
+ },
31
+
32
+ ScriptFragment: '<script[^>]*>([\\S\\s]*?)<\/script>',
33
+ JSONFilter: /^\/\*-secure-([\s\S]*)\*\/\s*$/,
34
+
35
+ emptyFunction: function() { },
36
+ K: function(x) { return x }
37
+ };
38
+
39
+ if (Prototype.Browser.MobileSafari)
40
+ Prototype.BrowserFeatures.SpecificElementExtensions = false;
41
+
42
+
43
+ /* Based on Alex Arnell's inheritance implementation. */
44
+ var Class = {
45
+ create: function() {
46
+ var parent = null, properties = $A(arguments);
47
+ if (Object.isFunction(properties[0]))
48
+ parent = properties.shift();
49
+
50
+ function klass() {
51
+ this.initialize.apply(this, arguments);
52
+ }
53
+
54
+ Object.extend(klass, Class.Methods);
55
+ klass.superclass = parent;
56
+ klass.subclasses = [];
57
+
58
+ if (parent) {
59
+ var subclass = function() { };
60
+ subclass.prototype = parent.prototype;
61
+ klass.prototype = new subclass;
62
+ parent.subclasses.push(klass);
63
+ }
64
+
65
+ for (var i = 0; i < properties.length; i++)
66
+ klass.addMethods(properties[i]);
67
+
68
+ if (!klass.prototype.initialize)
69
+ klass.prototype.initialize = Prototype.emptyFunction;
70
+
71
+ klass.prototype.constructor = klass;
72
+
73
+ return klass;
74
+ }
75
+ };
76
+
77
+ Class.Methods = {
78
+ addMethods: function(source) {
79
+ var ancestor = this.superclass && this.superclass.prototype;
80
+ var properties = Object.keys(source);
81
+
82
+ if (!Object.keys({ toString: true }).length)
83
+ properties.push("toString", "valueOf");
84
+
85
+ for (var i = 0, length = properties.length; i < length; i++) {
86
+ var property = properties[i], value = source[property];
87
+ if (ancestor && Object.isFunction(value) &&
88
+ value.argumentNames().first() == "$super") {
89
+ var method = value;
90
+ value = (function(m) {
91
+ return function() { return ancestor[m].apply(this, arguments) };
92
+ })(property).wrap(method);
93
+
94
+ value.valueOf = method.valueOf.bind(method);
95
+ value.toString = method.toString.bind(method);
96
+ }
97
+ this.prototype[property] = value;
98
+ }
99
+
100
+ return this;
101
+ }
102
+ };
103
+
104
+ var Abstract = { };
105
+
106
+ Object.extend = function(destination, source) {
107
+ for (var property in source)
108
+ destination[property] = source[property];
109
+ return destination;
110
+ };
111
+
112
+ Object.extend(Object, {
113
+ inspect: function(object) {
114
+ try {
115
+ if (Object.isUndefined(object)) return 'undefined';
116
+ if (object === null) return 'null';
117
+ return object.inspect ? object.inspect() : String(object);
118
+ } catch (e) {
119
+ if (e instanceof RangeError) return '...';
120
+ throw e;
121
+ }
122
+ },
123
+
124
+ toJSON: function(object) {
125
+ var type = typeof object;
126
+ switch (type) {
127
+ case 'undefined':
128
+ case 'function':
129
+ case 'unknown': return;
130
+ case 'boolean': return object.toString();
131
+ }
132
+
133
+ if (object === null) return 'null';
134
+ if (object.toJSON) return object.toJSON();
135
+ if (Object.isElement(object)) return;
136
+
137
+ var results = [];
138
+ for (var property in object) {
139
+ var value = Object.toJSON(object[property]);
140
+ if (!Object.isUndefined(value))
141
+ results.push(property.toJSON() + ': ' + value);
142
+ }
143
+
144
+ return '{' + results.join(', ') + '}';
145
+ },
146
+
147
+ toQueryString: function(object) {
148
+ return $H(object).toQueryString();
149
+ },
150
+
151
+ toHTML: function(object) {
152
+ return object && object.toHTML ? object.toHTML() : String.interpret(object);
153
+ },
154
+
155
+ keys: function(object) {
156
+ var keys = [];
157
+ for (var property in object)
158
+ keys.push(property);
159
+ return keys;
160
+ },
161
+
162
+ values: function(object) {
163
+ var values = [];
164
+ for (var property in object)
165
+ values.push(object[property]);
166
+ return values;
167
+ },
168
+
169
+ clone: function(object) {
170
+ return Object.extend({ }, object);
171
+ },
172
+
173
+ isElement: function(object) {
174
+ return !!(object && object.nodeType == 1);
175
+ },
176
+
177
+ isArray: function(object) {
178
+ return object != null && typeof object == "object" &&
179
+ 'splice' in object && 'join' in object;
180
+ },
181
+
182
+ isHash: function(object) {
183
+ return object instanceof Hash;
184
+ },
185
+
186
+ isFunction: function(object) {
187
+ return typeof object == "function";
188
+ },
189
+
190
+ isString: function(object) {
191
+ return typeof object == "string";
192
+ },
193
+
194
+ isNumber: function(object) {
195
+ return typeof object == "number";
196
+ },
197
+
198
+ isUndefined: function(object) {
199
+ return typeof object == "undefined";
200
+ }
201
+ });
202
+
203
+ Object.extend(Function.prototype, {
204
+ argumentNames: function() {
205
+ var names = this.toString().match(/^[\s\(]*function[^(]*\(([^\)]*)\)/)[1]
206
+ .replace(/\s+/g, '').split(',');
207
+ return names.length == 1 && !names[0] ? [] : names;
208
+ },
209
+
210
+ bind: function() {
211
+ if (arguments.length < 2 && Object.isUndefined(arguments[0])) return this;
212
+ var __method = this, args = $A(arguments), object = args.shift();
213
+ return function() {
214
+ return __method.apply(object, args.concat($A(arguments)));
215
+ }
216
+ },
217
+
218
+ bindAsEventListener: function() {
219
+ var __method = this, args = $A(arguments), object = args.shift();
220
+ return function(event) {
221
+ return __method.apply(object, [event || window.event].concat(args));
222
+ }
223
+ },
224
+
225
+ curry: function() {
226
+ if (!arguments.length) return this;
227
+ var __method = this, args = $A(arguments);
228
+ return function() {
229
+ return __method.apply(this, args.concat($A(arguments)));
230
+ }
231
+ },
232
+
233
+ delay: function() {
234
+ var __method = this, args = $A(arguments), timeout = args.shift() * 1000;
235
+ return window.setTimeout(function() {
236
+ return __method.apply(__method, args);
237
+ }, timeout);
238
+ },
239
+
240
+ defer: function() {
241
+ var args = [0.01].concat($A(arguments));
242
+ return this.delay.apply(this, args);
243
+ },
244
+
245
+ wrap: function(wrapper) {
246
+ var __method = this;
247
+ return function() {
248
+ return wrapper.apply(this, [__method.bind(this)].concat($A(arguments)));
249
+ }
250
+ },
251
+
252
+ methodize: function() {
253
+ if (this._methodized) return this._methodized;
254
+ var __method = this;
255
+ return this._methodized = function() {
256
+ return __method.apply(null, [this].concat($A(arguments)));
257
+ };
258
+ }
259
+ });
260
+
261
+ Date.prototype.toJSON = function() {
262
+ return '"' + this.getUTCFullYear() + '-' +
263
+ (this.getUTCMonth() + 1).toPaddedString(2) + '-' +
264
+ this.getUTCDate().toPaddedString(2) + 'T' +
265
+ this.getUTCHours().toPaddedString(2) + ':' +
266
+ this.getUTCMinutes().toPaddedString(2) + ':' +
267
+ this.getUTCSeconds().toPaddedString(2) + 'Z"';
268
+ };
269
+
270
+ var Try = {
271
+ these: function() {
272
+ var returnValue;
273
+
274
+ for (var i = 0, length = arguments.length; i < length; i++) {
275
+ var lambda = arguments[i];
276
+ try {
277
+ returnValue = lambda();
278
+ break;
279
+ } catch (e) { }
280
+ }
281
+
282
+ return returnValue;
283
+ }
284
+ };
285
+
286
+ RegExp.prototype.match = RegExp.prototype.test;
287
+
288
+ RegExp.escape = function(str) {
289
+ return String(str).replace(/([.*+?^=!:${}()|[\]\/\\])/g, '\\$1');
290
+ };
291
+
292
+ /*--------------------------------------------------------------------------*/
293
+
294
+ var PeriodicalExecuter = Class.create({
295
+ initialize: function(callback, frequency) {
296
+ this.callback = callback;
297
+ this.frequency = frequency;
298
+ this.currentlyExecuting = false;
299
+
300
+ this.registerCallback();
301
+ },
302
+
303
+ registerCallback: function() {
304
+ this.timer = setInterval(this.onTimerEvent.bind(this), this.frequency * 1000);
305
+ },
306
+
307
+ execute: function() {
308
+ this.callback(this);
309
+ },
310
+
311
+ stop: function() {
312
+ if (!this.timer) return;
313
+ clearInterval(this.timer);
314
+ this.timer = null;
315
+ },
316
+
317
+ onTimerEvent: function() {
318
+ if (!this.currentlyExecuting) {
319
+ try {
320
+ this.currentlyExecuting = true;
321
+ this.execute();
322
+ } finally {
323
+ this.currentlyExecuting = false;
324
+ }
325
+ }
326
+ }
327
+ });
328
+ Object.extend(String, {
329
+ interpret: function(value) {
330
+ return value == null ? '' : String(value);
331
+ },
332
+ specialChar: {
333
+ '\b': '\\b',
334
+ '\t': '\\t',
335
+ '\n': '\\n',
336
+ '\f': '\\f',
337
+ '\r': '\\r',
338
+ '\\': '\\\\'
339
+ }
340
+ });
341
+
342
+ Object.extend(String.prototype, {
343
+ gsub: function(pattern, replacement) {
344
+ var result = '', source = this, match;
345
+ replacement = arguments.callee.prepareReplacement(replacement);
346
+
347
+ while (source.length > 0) {
348
+ if (match = source.match(pattern)) {
349
+ result += source.slice(0, match.index);
350
+ result += String.interpret(replacement(match));
351
+ source = source.slice(match.index + match[0].length);
352
+ } else {
353
+ result += source, source = '';
354
+ }
355
+ }
356
+ return result;
357
+ },
358
+
359
+ sub: function(pattern, replacement, count) {
360
+ replacement = this.gsub.prepareReplacement(replacement);
361
+ count = Object.isUndefined(count) ? 1 : count;
362
+
363
+ return this.gsub(pattern, function(match) {
364
+ if (--count < 0) return match[0];
365
+ return replacement(match);
366
+ });
367
+ },
368
+
369
+ scan: function(pattern, iterator) {
370
+ this.gsub(pattern, iterator);
371
+ return String(this);
372
+ },
373
+
374
+ truncate: function(length, truncation) {
375
+ length = length || 30;
376
+ truncation = Object.isUndefined(truncation) ? '...' : truncation;
377
+ return this.length > length ?
378
+ this.slice(0, length - truncation.length) + truncation : String(this);
379
+ },
380
+
381
+ strip: function() {
382
+ return this.replace(/^\s+/, '').replace(/\s+$/, '');
383
+ },
384
+
385
+ stripTags: function() {
386
+ return this.replace(/<\/?[^>]+>/gi, '');
387
+ },
388
+
389
+ stripScripts: function() {
390
+ return this.replace(new RegExp(Prototype.ScriptFragment, 'img'), '');
391
+ },
392
+
393
+ extractScripts: function() {
394
+ var matchAll = new RegExp(Prototype.ScriptFragment, 'img');
395
+ var matchOne = new RegExp(Prototype.ScriptFragment, 'im');
396
+ return (this.match(matchAll) || []).map(function(scriptTag) {
397
+ return (scriptTag.match(matchOne) || ['', ''])[1];
398
+ });
399
+ },
400
+
401
+ evalScripts: function() {
402
+ return this.extractScripts().map(function(script) { return eval(script) });
403
+ },
404
+
405
+ escapeHTML: function() {
406
+ var self = arguments.callee;
407
+ self.text.data = this;
408
+ return self.div.innerHTML;
409
+ },
410
+
411
+ unescapeHTML: function() {
412
+ var div = new Element('div');
413
+ div.innerHTML = this.stripTags();
414
+ return div.childNodes[0] ? (div.childNodes.length > 1 ?
415
+ $A(div.childNodes).inject('', function(memo, node) { return memo+node.nodeValue }) :
416
+ div.childNodes[0].nodeValue) : '';
417
+ },
418
+
419
+ toQueryParams: function(separator) {
420
+ var match = this.strip().match(/([^?#]*)(#.*)?$/);
421
+ if (!match) return { };
422
+
423
+ return match[1].split(separator || '&').inject({ }, function(hash, pair) {
424
+ if ((pair = pair.split('='))[0]) {
425
+ var key = decodeURIComponent(pair.shift());
426
+ var value = pair.length > 1 ? pair.join('=') : pair[0];
427
+ if (value != undefined) value = decodeURIComponent(value);
428
+
429
+ if (key in hash) {
430
+ if (!Object.isArray(hash[key])) hash[key] = [hash[key]];
431
+ hash[key].push(value);
432
+ }
433
+ else hash[key] = value;
434
+ }
435
+ return hash;
436
+ });
437
+ },
438
+
439
+ toArray: function() {
440
+ return this.split('');
441
+ },
442
+
443
+ succ: function() {
444
+ return this.slice(0, this.length - 1) +
445
+ String.fromCharCode(this.charCodeAt(this.length - 1) + 1);
446
+ },
447
+
448
+ times: function(count) {
449
+ return count < 1 ? '' : new Array(count + 1).join(this);
450
+ },
451
+
452
+ camelize: function() {
453
+ var parts = this.split('-'), len = parts.length;
454
+ if (len == 1) return parts[0];
455
+
456
+ var camelized = this.charAt(0) == '-'
457
+ ? parts[0].charAt(0).toUpperCase() + parts[0].substring(1)
458
+ : parts[0];
459
+
460
+ for (var i = 1; i < len; i++)
461
+ camelized += parts[i].charAt(0).toUpperCase() + parts[i].substring(1);
462
+
463
+ return camelized;
464
+ },
465
+
466
+ capitalize: function() {
467
+ return this.charAt(0).toUpperCase() + this.substring(1).toLowerCase();
468
+ },
469
+
470
+ underscore: function() {
471
+ return this.gsub(/::/, '/').gsub(/([A-Z]+)([A-Z][a-z])/,'#{1}_#{2}').gsub(/([a-z\d])([A-Z])/,'#{1}_#{2}').gsub(/-/,'_').toLowerCase();
472
+ },
473
+
474
+ dasherize: function() {
475
+ return this.gsub(/_/,'-');
476
+ },
477
+
478
+ inspect: function(useDoubleQuotes) {
479
+ var escapedString = this.gsub(/[\x00-\x1f\\]/, function(match) {
480
+ var character = String.specialChar[match[0]];
481
+ return character ? character : '\\u00' + match[0].charCodeAt().toPaddedString(2, 16);
482
+ });
483
+ if (useDoubleQuotes) return '"' + escapedString.replace(/"/g, '\\"') + '"';
484
+ return "'" + escapedString.replace(/'/g, '\\\'') + "'";
485
+ },
486
+
487
+ toJSON: function() {
488
+ return this.inspect(true);
489
+ },
490
+
491
+ unfilterJSON: function(filter) {
492
+ return this.sub(filter || Prototype.JSONFilter, '#{1}');
493
+ },
494
+
495
+ isJSON: function() {
496
+ var str = this;
497
+ if (str.blank()) return false;
498
+ str = this.replace(/\\./g, '@').replace(/"[^"\\\n\r]*"/g, '');
499
+ return (/^[,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t]*$/).test(str);
500
+ },
501
+
502
+ evalJSON: function(sanitize) {
503
+ var json = this.unfilterJSON();
504
+ try {
505
+ if (!sanitize || json.isJSON()) return eval('(' + json + ')');
506
+ } catch (e) { }
507
+ throw new SyntaxError('Badly formed JSON string: ' + this.inspect());
508
+ },
509
+
510
+ include: function(pattern) {
511
+ return this.indexOf(pattern) > -1;
512
+ },
513
+
514
+ startsWith: function(pattern) {
515
+ return this.indexOf(pattern) === 0;
516
+ },
517
+
518
+ endsWith: function(pattern) {
519
+ var d = this.length - pattern.length;
520
+ return d >= 0 && this.lastIndexOf(pattern) === d;
521
+ },
522
+
523
+ empty: function() {
524
+ return this == '';
525
+ },
526
+
527
+ blank: function() {
528
+ return /^\s*$/.test(this);
529
+ },
530
+
531
+ interpolate: function(object, pattern) {
532
+ return new Template(this, pattern).evaluate(object);
533
+ }
534
+ });
535
+
536
+ if (Prototype.Browser.WebKit || Prototype.Browser.IE) Object.extend(String.prototype, {
537
+ escapeHTML: function() {
538
+ return this.replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/g,'&gt;');
539
+ },
540
+ unescapeHTML: function() {
541
+ return this.stripTags().replace(/&amp;/g,'&').replace(/&lt;/g,'<').replace(/&gt;/g,'>');
542
+ }
543
+ });
544
+
545
+ String.prototype.gsub.prepareReplacement = function(replacement) {
546
+ if (Object.isFunction(replacement)) return replacement;
547
+ var template = new Template(replacement);
548
+ return function(match) { return template.evaluate(match) };
549
+ };
550
+
551
+ String.prototype.parseQuery = String.prototype.toQueryParams;
552
+
553
+ Object.extend(String.prototype.escapeHTML, {
554
+ div: document.createElement('div'),
555
+ text: document.createTextNode('')
556
+ });
557
+
558
+ String.prototype.escapeHTML.div.appendChild(String.prototype.escapeHTML.text);
559
+
560
+ var Template = Class.create({
561
+ initialize: function(template, pattern) {
562
+ this.template = template.toString();
563
+ this.pattern = pattern || Template.Pattern;
564
+ },
565
+
566
+ evaluate: function(object) {
567
+ if (Object.isFunction(object.toTemplateReplacements))
568
+ object = object.toTemplateReplacements();
569
+
570
+ return this.template.gsub(this.pattern, function(match) {
571
+ if (object == null) return '';
572
+
573
+ var before = match[1] || '';
574
+ if (before == '\\') return match[2];
575
+
576
+ var ctx = object, expr = match[3];
577
+ var pattern = /^([^.[]+|\[((?:.*?[^\\])?)\])(\.|\[|$)/;
578
+ match = pattern.exec(expr);
579
+ if (match == null) return before;
580
+
581
+ while (match != null) {
582
+ var comp = match[1].startsWith('[') ? match[2].gsub('\\\\]', ']') : match[1];
583
+ ctx = ctx[comp];
584
+ if (null == ctx || '' == match[3]) break;
585
+ expr = expr.substring('[' == match[3] ? match[1].length : match[0].length);
586
+ match = pattern.exec(expr);
587
+ }
588
+
589
+ return before + String.interpret(ctx);
590
+ });
591
+ }
592
+ });
593
+ Template.Pattern = /(^|.|\r|\n)(#\{(.*?)\})/;
594
+
595
+ var $break = { };
596
+
597
+ var Enumerable = {
598
+ each: function(iterator, context) {
599
+ var index = 0;
600
+ try {
601
+ this._each(function(value) {
602
+ iterator.call(context, value, index++);
603
+ });
604
+ } catch (e) {
605
+ if (e != $break) throw e;
606
+ }
607
+ return this;
608
+ },
609
+
610
+ eachSlice: function(number, iterator, context) {
611
+ var index = -number, slices = [], array = this.toArray();
612
+ if (number < 1) return array;
613
+ while ((index += number) < array.length)
614
+ slices.push(array.slice(index, index+number));
615
+ return slices.collect(iterator, context);
616
+ },
617
+
618
+ all: function(iterator, context) {
619
+ iterator = iterator || Prototype.K;
620
+ var result = true;
621
+ this.each(function(value, index) {
622
+ result = result && !!iterator.call(context, value, index);
623
+ if (!result) throw $break;
624
+ });
625
+ return result;
626
+ },
627
+
628
+ any: function(iterator, context) {
629
+ iterator = iterator || Prototype.K;
630
+ var result = false;
631
+ this.each(function(value, index) {
632
+ if (result = !!iterator.call(context, value, index))
633
+ throw $break;
634
+ });
635
+ return result;
636
+ },
637
+
638
+ collect: function(iterator, context) {
639
+ iterator = iterator || Prototype.K;
640
+ var results = [];
641
+ this.each(function(value, index) {
642
+ results.push(iterator.call(context, value, index));
643
+ });
644
+ return results;
645
+ },
646
+
647
+ detect: function(iterator, context) {
648
+ var result;
649
+ this.each(function(value, index) {
650
+ if (iterator.call(context, value, index)) {
651
+ result = value;
652
+ throw $break;
653
+ }
654
+ });
655
+ return result;
656
+ },
657
+
658
+ findAll: function(iterator, context) {
659
+ var results = [];
660
+ this.each(function(value, index) {
661
+ if (iterator.call(context, value, index))
662
+ results.push(value);
663
+ });
664
+ return results;
665
+ },
666
+
667
+ grep: function(filter, iterator, context) {
668
+ iterator = iterator || Prototype.K;
669
+ var results = [];
670
+
671
+ if (Object.isString(filter))
672
+ filter = new RegExp(filter);
673
+
674
+ this.each(function(value, index) {
675
+ if (filter.match(value))
676
+ results.push(iterator.call(context, value, index));
677
+ });
678
+ return results;
679
+ },
680
+
681
+ include: function(object) {
682
+ if (Object.isFunction(this.indexOf))
683
+ if (this.indexOf(object) != -1) return true;
684
+
685
+ var found = false;
686
+ this.each(function(value) {
687
+ if (value == object) {
688
+ found = true;
689
+ throw $break;
690
+ }
691
+ });
692
+ return found;
693
+ },
694
+
695
+ inGroupsOf: function(number, fillWith) {
696
+ fillWith = Object.isUndefined(fillWith) ? null : fillWith;
697
+ return this.eachSlice(number, function(slice) {
698
+ while(slice.length < number) slice.push(fillWith);
699
+ return slice;
700
+ });
701
+ },
702
+
703
+ inject: function(memo, iterator, context) {
704
+ this.each(function(value, index) {
705
+ memo = iterator.call(context, memo, value, index);
706
+ });
707
+ return memo;
708
+ },
709
+
710
+ invoke: function(method) {
711
+ var args = $A(arguments).slice(1);
712
+ return this.map(function(value) {
713
+ return value[method].apply(value, args);
714
+ });
715
+ },
716
+
717
+ max: function(iterator, context) {
718
+ iterator = iterator || Prototype.K;
719
+ var result;
720
+ this.each(function(value, index) {
721
+ value = iterator.call(context, value, index);
722
+ if (result == null || value >= result)
723
+ result = value;
724
+ });
725
+ return result;
726
+ },
727
+
728
+ min: function(iterator, context) {
729
+ iterator = iterator || Prototype.K;
730
+ var result;
731
+ this.each(function(value, index) {
732
+ value = iterator.call(context, value, index);
733
+ if (result == null || value < result)
734
+ result = value;
735
+ });
736
+ return result;
737
+ },
738
+
739
+ partition: function(iterator, context) {
740
+ iterator = iterator || Prototype.K;
741
+ var trues = [], falses = [];
742
+ this.each(function(value, index) {
743
+ (iterator.call(context, value, index) ?
744
+ trues : falses).push(value);
745
+ });
746
+ return [trues, falses];
747
+ },
748
+
749
+ pluck: function(property) {
750
+ var results = [];
751
+ this.each(function(value) {
752
+ results.push(value[property]);
753
+ });
754
+ return results;
755
+ },
756
+
757
+ reject: function(iterator, context) {
758
+ var results = [];
759
+ this.each(function(value, index) {
760
+ if (!iterator.call(context, value, index))
761
+ results.push(value);
762
+ });
763
+ return results;
764
+ },
765
+
766
+ sortBy: function(iterator, context) {
767
+ return this.map(function(value, index) {
768
+ return {
769
+ value: value,
770
+ criteria: iterator.call(context, value, index)
771
+ };
772
+ }).sort(function(left, right) {
773
+ var a = left.criteria, b = right.criteria;
774
+ return a < b ? -1 : a > b ? 1 : 0;
775
+ }).pluck('value');
776
+ },
777
+
778
+ toArray: function() {
779
+ return this.map();
780
+ },
781
+
782
+ zip: function() {
783
+ var iterator = Prototype.K, args = $A(arguments);
784
+ if (Object.isFunction(args.last()))
785
+ iterator = args.pop();
786
+
787
+ var collections = [this].concat(args).map($A);
788
+ return this.map(function(value, index) {
789
+ return iterator(collections.pluck(index));
790
+ });
791
+ },
792
+
793
+ size: function() {
794
+ return this.toArray().length;
795
+ },
796
+
797
+ inspect: function() {
798
+ return '#<Enumerable:' + this.toArray().inspect() + '>';
799
+ }
800
+ };
801
+
802
+ Object.extend(Enumerable, {
803
+ map: Enumerable.collect,
804
+ find: Enumerable.detect,
805
+ select: Enumerable.findAll,
806
+ filter: Enumerable.findAll,
807
+ member: Enumerable.include,
808
+ entries: Enumerable.toArray,
809
+ every: Enumerable.all,
810
+ some: Enumerable.any
811
+ });
812
+ function $A(iterable) {
813
+ if (!iterable) return [];
814
+ if (iterable.toArray) return iterable.toArray();
815
+ var length = iterable.length || 0, results = new Array(length);
816
+ while (length--) results[length] = iterable[length];
817
+ return results;
818
+ }
819
+
820
+ if (Prototype.Browser.WebKit) {
821
+ $A = function(iterable) {
822
+ if (!iterable) return [];
823
+ // In Safari, only use the `toArray` method if it's not a NodeList.
824
+ // A NodeList is a function, has an function `item` property, and a numeric
825
+ // `length` property. Adapted from Google Doctype.
826
+ if (!(typeof iterable === 'function' && typeof iterable.length ===
827
+ 'number' && typeof iterable.item === 'function') && iterable.toArray)
828
+ return iterable.toArray();
829
+ var length = iterable.length || 0, results = new Array(length);
830
+ while (length--) results[length] = iterable[length];
831
+ return results;
832
+ };
833
+ }
834
+
835
+ Array.from = $A;
836
+
837
+ Object.extend(Array.prototype, Enumerable);
838
+
839
+ if (!Array.prototype._reverse) Array.prototype._reverse = Array.prototype.reverse;
840
+
841
+ Object.extend(Array.prototype, {
842
+ _each: function(iterator) {
843
+ for (var i = 0, length = this.length; i < length; i++)
844
+ iterator(this[i]);
845
+ },
846
+
847
+ clear: function() {
848
+ this.length = 0;
849
+ return this;
850
+ },
851
+
852
+ first: function() {
853
+ return this[0];
854
+ },
855
+
856
+ last: function() {
857
+ return this[this.length - 1];
858
+ },
859
+
860
+ compact: function() {
861
+ return this.select(function(value) {
862
+ return value != null;
863
+ });
864
+ },
865
+
866
+ flatten: function() {
867
+ return this.inject([], function(array, value) {
868
+ return array.concat(Object.isArray(value) ?
869
+ value.flatten() : [value]);
870
+ });
871
+ },
872
+
873
+ without: function() {
874
+ var values = $A(arguments);
875
+ return this.select(function(value) {
876
+ return !values.include(value);
877
+ });
878
+ },
879
+
880
+ reverse: function(inline) {
881
+ return (inline !== false ? this : this.toArray())._reverse();
882
+ },
883
+
884
+ reduce: function() {
885
+ return this.length > 1 ? this : this[0];
886
+ },
887
+
888
+ uniq: function(sorted) {
889
+ return this.inject([], function(array, value, index) {
890
+ if (0 == index || (sorted ? array.last() != value : !array.include(value)))
891
+ array.push(value);
892
+ return array;
893
+ });
894
+ },
895
+
896
+ intersect: function(array) {
897
+ return this.uniq().findAll(function(item) {
898
+ return array.detect(function(value) { return item === value });
899
+ });
900
+ },
901
+
902
+ clone: function() {
903
+ return [].concat(this);
904
+ },
905
+
906
+ size: function() {
907
+ return this.length;
908
+ },
909
+
910
+ inspect: function() {
911
+ return '[' + this.map(Object.inspect).join(', ') + ']';
912
+ },
913
+
914
+ toJSON: function() {
915
+ var results = [];
916
+ this.each(function(object) {
917
+ var value = Object.toJSON(object);
918
+ if (!Object.isUndefined(value)) results.push(value);
919
+ });
920
+ return '[' + results.join(', ') + ']';
921
+ }
922
+ });
923
+
924
+ // use native browser JS 1.6 implementation if available
925
+ if (Object.isFunction(Array.prototype.forEach))
926
+ Array.prototype._each = Array.prototype.forEach;
927
+
928
+ if (!Array.prototype.indexOf) Array.prototype.indexOf = function(item, i) {
929
+ i || (i = 0);
930
+ var length = this.length;
931
+ if (i < 0) i = length + i;
932
+ for (; i < length; i++)
933
+ if (this[i] === item) return i;
934
+ return -1;
935
+ };
936
+
937
+ if (!Array.prototype.lastIndexOf) Array.prototype.lastIndexOf = function(item, i) {
938
+ i = isNaN(i) ? this.length : (i < 0 ? this.length + i : i) + 1;
939
+ var n = this.slice(0, i).reverse().indexOf(item);
940
+ return (n < 0) ? n : i - n - 1;
941
+ };
942
+
943
+ Array.prototype.toArray = Array.prototype.clone;
944
+
945
+ function $w(string) {
946
+ if (!Object.isString(string)) return [];
947
+ string = string.strip();
948
+ return string ? string.split(/\s+/) : [];
949
+ }
950
+
951
+ if (Prototype.Browser.Opera){
952
+ Array.prototype.concat = function() {
953
+ var array = [];
954
+ for (var i = 0, length = this.length; i < length; i++) array.push(this[i]);
955
+ for (var i = 0, length = arguments.length; i < length; i++) {
956
+ if (Object.isArray(arguments[i])) {
957
+ for (var j = 0, arrayLength = arguments[i].length; j < arrayLength; j++)
958
+ array.push(arguments[i][j]);
959
+ } else {
960
+ array.push(arguments[i]);
961
+ }
962
+ }
963
+ return array;
964
+ };
965
+ }
966
+ Object.extend(Number.prototype, {
967
+ toColorPart: function() {
968
+ return this.toPaddedString(2, 16);
969
+ },
970
+
971
+ succ: function() {
972
+ return this + 1;
973
+ },
974
+
975
+ times: function(iterator, context) {
976
+ $R(0, this, true).each(iterator, context);
977
+ return this;
978
+ },
979
+
980
+ toPaddedString: function(length, radix) {
981
+ var string = this.toString(radix || 10);
982
+ return '0'.times(length - string.length) + string;
983
+ },
984
+
985
+ toJSON: function() {
986
+ return isFinite(this) ? this.toString() : 'null';
987
+ }
988
+ });
989
+
990
+ $w('abs round ceil floor').each(function(method){
991
+ Number.prototype[method] = Math[method].methodize();
992
+ });
993
+ function $H(object) {
994
+ return new Hash(object);
995
+ };
996
+
997
+ var Hash = Class.create(Enumerable, (function() {
998
+
999
+ function toQueryPair(key, value) {
1000
+ if (Object.isUndefined(value)) return key;
1001
+ return key + '=' + encodeURIComponent(String.interpret(value));
1002
+ }
1003
+
1004
+ return {
1005
+ initialize: function(object) {
1006
+ this._object = Object.isHash(object) ? object.toObject() : Object.clone(object);
1007
+ },
1008
+
1009
+ _each: function(iterator) {
1010
+ for (var key in this._object) {
1011
+ var value = this._object[key], pair = [key, value];
1012
+ pair.key = key;
1013
+ pair.value = value;
1014
+ iterator(pair);
1015
+ }
1016
+ },
1017
+
1018
+ set: function(key, value) {
1019
+ return this._object[key] = value;
1020
+ },
1021
+
1022
+ get: function(key) {
1023
+ // simulating poorly supported hasOwnProperty
1024
+ if (this._object[key] !== Object.prototype[key])
1025
+ return this._object[key];
1026
+ },
1027
+
1028
+ unset: function(key) {
1029
+ var value = this._object[key];
1030
+ delete this._object[key];
1031
+ return value;
1032
+ },
1033
+
1034
+ toObject: function() {
1035
+ return Object.clone(this._object);
1036
+ },
1037
+
1038
+ keys: function() {
1039
+ return this.pluck('key');
1040
+ },
1041
+
1042
+ values: function() {
1043
+ return this.pluck('value');
1044
+ },
1045
+
1046
+ index: function(value) {
1047
+ var match = this.detect(function(pair) {
1048
+ return pair.value === value;
1049
+ });
1050
+ return match && match.key;
1051
+ },
1052
+
1053
+ merge: function(object) {
1054
+ return this.clone().update(object);
1055
+ },
1056
+
1057
+ update: function(object) {
1058
+ return new Hash(object).inject(this, function(result, pair) {
1059
+ result.set(pair.key, pair.value);
1060
+ return result;
1061
+ });
1062
+ },
1063
+
1064
+ toQueryString: function() {
1065
+ return this.inject([], function(results, pair) {
1066
+ var key = encodeURIComponent(pair.key), values = pair.value;
1067
+
1068
+ if (values && typeof values == 'object') {
1069
+ if (Object.isArray(values))
1070
+ return results.concat(values.map(toQueryPair.curry(key)));
1071
+ } else results.push(toQueryPair(key, values));
1072
+ return results;
1073
+ }).join('&');
1074
+ },
1075
+
1076
+ inspect: function() {
1077
+ return '#<Hash:{' + this.map(function(pair) {
1078
+ return pair.map(Object.inspect).join(': ');
1079
+ }).join(', ') + '}>';
1080
+ },
1081
+
1082
+ toJSON: function() {
1083
+ return Object.toJSON(this.toObject());
1084
+ },
1085
+
1086
+ clone: function() {
1087
+ return new Hash(this);
1088
+ }
1089
+ }
1090
+ })());
1091
+
1092
+ Hash.prototype.toTemplateReplacements = Hash.prototype.toObject;
1093
+ Hash.from = $H;
1094
+ var ObjectRange = Class.create(Enumerable, {
1095
+ initialize: function(start, end, exclusive) {
1096
+ this.start = start;
1097
+ this.end = end;
1098
+ this.exclusive = exclusive;
1099
+ },
1100
+
1101
+ _each: function(iterator) {
1102
+ var value = this.start;
1103
+ while (this.include(value)) {
1104
+ iterator(value);
1105
+ value = value.succ();
1106
+ }
1107
+ },
1108
+
1109
+ include: function(value) {
1110
+ if (value < this.start)
1111
+ return false;
1112
+ if (this.exclusive)
1113
+ return value < this.end;
1114
+ return value <= this.end;
1115
+ }
1116
+ });
1117
+
1118
+ var $R = function(start, end, exclusive) {
1119
+ return new ObjectRange(start, end, exclusive);
1120
+ };
1121
+
1122
+ var Ajax = {
1123
+ getTransport: function() {
1124
+ return Try.these(
1125
+ function() {return new XMLHttpRequest()},
1126
+ function() {return new ActiveXObject('Msxml2.XMLHTTP')},
1127
+ function() {return new ActiveXObject('Microsoft.XMLHTTP')}
1128
+ ) || false;
1129
+ },
1130
+
1131
+ activeRequestCount: 0
1132
+ };
1133
+
1134
+ Ajax.Responders = {
1135
+ responders: [],
1136
+
1137
+ _each: function(iterator) {
1138
+ this.responders._each(iterator);
1139
+ },
1140
+
1141
+ register: function(responder) {
1142
+ if (!this.include(responder))
1143
+ this.responders.push(responder);
1144
+ },
1145
+
1146
+ unregister: function(responder) {
1147
+ this.responders = this.responders.without(responder);
1148
+ },
1149
+
1150
+ dispatch: function(callback, request, transport, json) {
1151
+ this.each(function(responder) {
1152
+ if (Object.isFunction(responder[callback])) {
1153
+ try {
1154
+ responder[callback].apply(responder, [request, transport, json]);
1155
+ } catch (e) { }
1156
+ }
1157
+ });
1158
+ }
1159
+ };
1160
+
1161
+ Object.extend(Ajax.Responders, Enumerable);
1162
+
1163
+ Ajax.Responders.register({
1164
+ onCreate: function() { Ajax.activeRequestCount++ },
1165
+ onComplete: function() { Ajax.activeRequestCount-- }
1166
+ });
1167
+
1168
+ Ajax.Base = Class.create({
1169
+ initialize: function(options) {
1170
+ this.options = {
1171
+ method: 'post',
1172
+ asynchronous: true,
1173
+ contentType: 'application/x-www-form-urlencoded',
1174
+ encoding: 'UTF-8',
1175
+ parameters: '',
1176
+ evalJSON: true,
1177
+ evalJS: true
1178
+ };
1179
+ Object.extend(this.options, options || { });
1180
+
1181
+ this.options.method = this.options.method.toLowerCase();
1182
+
1183
+ if (Object.isString(this.options.parameters))
1184
+ this.options.parameters = this.options.parameters.toQueryParams();
1185
+ else if (Object.isHash(this.options.parameters))
1186
+ this.options.parameters = this.options.parameters.toObject();
1187
+ }
1188
+ });
1189
+
1190
+ Ajax.Request = Class.create(Ajax.Base, {
1191
+ _complete: false,
1192
+
1193
+ initialize: function($super, url, options) {
1194
+ $super(options);
1195
+ this.transport = Ajax.getTransport();
1196
+ this.request(url);
1197
+ },
1198
+
1199
+ request: function(url) {
1200
+ this.url = url;
1201
+ this.method = this.options.method;
1202
+ var params = Object.clone(this.options.parameters);
1203
+
1204
+ if (!['get', 'post'].include(this.method)) {
1205
+ // simulate other verbs over post
1206
+ params['_method'] = this.method;
1207
+ this.method = 'post';
1208
+ }
1209
+
1210
+ this.parameters = params;
1211
+
1212
+ if (params = Object.toQueryString(params)) {
1213
+ // when GET, append parameters to URL
1214
+ if (this.method == 'get')
1215
+ this.url += (this.url.include('?') ? '&' : '?') + params;
1216
+ else if (/Konqueror|Safari|KHTML/.test(navigator.userAgent))
1217
+ params += '&_=';
1218
+ }
1219
+
1220
+ try {
1221
+ var response = new Ajax.Response(this);
1222
+ if (this.options.onCreate) this.options.onCreate(response);
1223
+ Ajax.Responders.dispatch('onCreate', this, response);
1224
+
1225
+ this.transport.open(this.method.toUpperCase(), this.url,
1226
+ this.options.asynchronous);
1227
+
1228
+ if (this.options.asynchronous) this.respondToReadyState.bind(this).defer(1);
1229
+
1230
+ this.transport.onreadystatechange = this.onStateChange.bind(this);
1231
+ this.setRequestHeaders();
1232
+
1233
+ this.body = this.method == 'post' ? (this.options.postBody || params) : null;
1234
+ this.transport.send(this.body);
1235
+
1236
+ /* Force Firefox to handle ready state 4 for synchronous requests */
1237
+ if (!this.options.asynchronous && this.transport.overrideMimeType)
1238
+ this.onStateChange();
1239
+
1240
+ }
1241
+ catch (e) {
1242
+ this.dispatchException(e);
1243
+ }
1244
+ },
1245
+
1246
+ onStateChange: function() {
1247
+ var readyState = this.transport.readyState;
1248
+ if (readyState > 1 && !((readyState == 4) && this._complete))
1249
+ this.respondToReadyState(this.transport.readyState);
1250
+ },
1251
+
1252
+ setRequestHeaders: function() {
1253
+ var headers = {
1254
+ 'X-Requested-With': 'XMLHttpRequest',
1255
+ 'X-Prototype-Version': Prototype.Version,
1256
+ 'Accept': 'text/javascript, text/html, application/xml, text/xml, */*'
1257
+ };
1258
+
1259
+ if (this.method == 'post') {
1260
+ headers['Content-type'] = this.options.contentType +
1261
+ (this.options.encoding ? '; charset=' + this.options.encoding : '');
1262
+
1263
+ /* Force "Connection: close" for older Mozilla browsers to work
1264
+ * around a bug where XMLHttpRequest sends an incorrect
1265
+ * Content-length header. See Mozilla Bugzilla #246651.
1266
+ */
1267
+ if (this.transport.overrideMimeType &&
1268
+ (navigator.userAgent.match(/Gecko\/(\d{4})/) || [0,2005])[1] < 2005)
1269
+ headers['Connection'] = 'close';
1270
+ }
1271
+
1272
+ // user-defined headers
1273
+ if (typeof this.options.requestHeaders == 'object') {
1274
+ var extras = this.options.requestHeaders;
1275
+
1276
+ if (Object.isFunction(extras.push))
1277
+ for (var i = 0, length = extras.length; i < length; i += 2)
1278
+ headers[extras[i]] = extras[i+1];
1279
+ else
1280
+ $H(extras).each(function(pair) { headers[pair.key] = pair.value });
1281
+ }
1282
+
1283
+ for (var name in headers)
1284
+ this.transport.setRequestHeader(name, headers[name]);
1285
+ },
1286
+
1287
+ success: function() {
1288
+ var status = this.getStatus();
1289
+ return !status || (status >= 200 && status < 300);
1290
+ },
1291
+
1292
+ getStatus: function() {
1293
+ try {
1294
+ return this.transport.status || 0;
1295
+ } catch (e) { return 0 }
1296
+ },
1297
+
1298
+ respondToReadyState: function(readyState) {
1299
+ var state = Ajax.Request.Events[readyState], response = new Ajax.Response(this);
1300
+
1301
+ if (state == 'Complete') {
1302
+ try {
1303
+ this._complete = true;
1304
+ (this.options['on' + response.status]
1305
+ || this.options['on' + (this.success() ? 'Success' : 'Failure')]
1306
+ || Prototype.emptyFunction)(response, response.headerJSON);
1307
+ } catch (e) {
1308
+ this.dispatchException(e);
1309
+ }
1310
+
1311
+ var contentType = response.getHeader('Content-type');
1312
+ if (this.options.evalJS == 'force'
1313
+ || (this.options.evalJS && this.isSameOrigin() && contentType
1314
+ && contentType.match(/^\s*(text|application)\/(x-)?(java|ecma)script(;.*)?\s*$/i)))
1315
+ this.evalResponse();
1316
+ }
1317
+
1318
+ try {
1319
+ (this.options['on' + state] || Prototype.emptyFunction)(response, response.headerJSON);
1320
+ Ajax.Responders.dispatch('on' + state, this, response, response.headerJSON);
1321
+ } catch (e) {
1322
+ this.dispatchException(e);
1323
+ }
1324
+
1325
+ if (state == 'Complete') {
1326
+ // avoid memory leak in MSIE: clean up
1327
+ this.transport.onreadystatechange = Prototype.emptyFunction;
1328
+ }
1329
+ },
1330
+
1331
+ isSameOrigin: function() {
1332
+ var m = this.url.match(/^\s*https?:\/\/[^\/]*/);
1333
+ return !m || (m[0] == '#{protocol}//#{domain}#{port}'.interpolate({
1334
+ protocol: location.protocol,
1335
+ domain: document.domain,
1336
+ port: location.port ? ':' + location.port : ''
1337
+ }));
1338
+ },
1339
+
1340
+ getHeader: function(name) {
1341
+ try {
1342
+ return this.transport.getResponseHeader(name) || null;
1343
+ } catch (e) { return null }
1344
+ },
1345
+
1346
+ evalResponse: function() {
1347
+ try {
1348
+ return eval((this.transport.responseText || '').unfilterJSON());
1349
+ } catch (e) {
1350
+ this.dispatchException(e);
1351
+ }
1352
+ },
1353
+
1354
+ dispatchException: function(exception) {
1355
+ (this.options.onException || Prototype.emptyFunction)(this, exception);
1356
+ Ajax.Responders.dispatch('onException', this, exception);
1357
+ }
1358
+ });
1359
+
1360
+ Ajax.Request.Events =
1361
+ ['Uninitialized', 'Loading', 'Loaded', 'Interactive', 'Complete'];
1362
+
1363
+ Ajax.Response = Class.create({
1364
+ initialize: function(request){
1365
+ this.request = request;
1366
+ var transport = this.transport = request.transport,
1367
+ readyState = this.readyState = transport.readyState;
1368
+
1369
+ if((readyState > 2 && !Prototype.Browser.IE) || readyState == 4) {
1370
+ this.status = this.getStatus();
1371
+ this.statusText = this.getStatusText();
1372
+ this.responseText = String.interpret(transport.responseText);
1373
+ this.headerJSON = this._getHeaderJSON();
1374
+ }
1375
+
1376
+ if(readyState == 4) {
1377
+ var xml = transport.responseXML;
1378
+ this.responseXML = Object.isUndefined(xml) ? null : xml;
1379
+ this.responseJSON = this._getResponseJSON();
1380
+ }
1381
+ },
1382
+
1383
+ status: 0,
1384
+ statusText: '',
1385
+
1386
+ getStatus: Ajax.Request.prototype.getStatus,
1387
+
1388
+ getStatusText: function() {
1389
+ try {
1390
+ return this.transport.statusText || '';
1391
+ } catch (e) { return '' }
1392
+ },
1393
+
1394
+ getHeader: Ajax.Request.prototype.getHeader,
1395
+
1396
+ getAllHeaders: function() {
1397
+ try {
1398
+ return this.getAllResponseHeaders();
1399
+ } catch (e) { return null }
1400
+ },
1401
+
1402
+ getResponseHeader: function(name) {
1403
+ return this.transport.getResponseHeader(name);
1404
+ },
1405
+
1406
+ getAllResponseHeaders: function() {
1407
+ return this.transport.getAllResponseHeaders();
1408
+ },
1409
+
1410
+ _getHeaderJSON: function() {
1411
+ var json = this.getHeader('X-JSON');
1412
+ if (!json) return null;
1413
+ json = decodeURIComponent(escape(json));
1414
+ try {
1415
+ return json.evalJSON(this.request.options.sanitizeJSON ||
1416
+ !this.request.isSameOrigin());
1417
+ } catch (e) {
1418
+ this.request.dispatchException(e);
1419
+ }
1420
+ },
1421
+
1422
+ _getResponseJSON: function() {
1423
+ var options = this.request.options;
1424
+ if (!options.evalJSON || (options.evalJSON != 'force' &&
1425
+ !(this.getHeader('Content-type') || '').include('application/json')) ||
1426
+ this.responseText.blank())
1427
+ return null;
1428
+ try {
1429
+ return this.responseText.evalJSON(options.sanitizeJSON ||
1430
+ !this.request.isSameOrigin());
1431
+ } catch (e) {
1432
+ this.request.dispatchException(e);
1433
+ }
1434
+ }
1435
+ });
1436
+
1437
+ Ajax.Updater = Class.create(Ajax.Request, {
1438
+ initialize: function($super, container, url, options) {
1439
+ this.container = {
1440
+ success: (container.success || container),
1441
+ failure: (container.failure || (container.success ? null : container))
1442
+ };
1443
+
1444
+ options = Object.clone(options);
1445
+ var onComplete = options.onComplete;
1446
+ options.onComplete = (function(response, json) {
1447
+ this.updateContent(response.responseText);
1448
+ if (Object.isFunction(onComplete)) onComplete(response, json);
1449
+ }).bind(this);
1450
+
1451
+ $super(url, options);
1452
+ },
1453
+
1454
+ updateContent: function(responseText) {
1455
+ var receiver = this.container[this.success() ? 'success' : 'failure'],
1456
+ options = this.options;
1457
+
1458
+ if (!options.evalScripts) responseText = responseText.stripScripts();
1459
+
1460
+ if (receiver = $(receiver)) {
1461
+ if (options.insertion) {
1462
+ if (Object.isString(options.insertion)) {
1463
+ var insertion = { }; insertion[options.insertion] = responseText;
1464
+ receiver.insert(insertion);
1465
+ }
1466
+ else options.insertion(receiver, responseText);
1467
+ }
1468
+ else receiver.update(responseText);
1469
+ }
1470
+ }
1471
+ });
1472
+
1473
+ Ajax.PeriodicalUpdater = Class.create(Ajax.Base, {
1474
+ initialize: function($super, container, url, options) {
1475
+ $super(options);
1476
+ this.onComplete = this.options.onComplete;
1477
+
1478
+ this.frequency = (this.options.frequency || 2);
1479
+ this.decay = (this.options.decay || 1);
1480
+
1481
+ this.updater = { };
1482
+ this.container = container;
1483
+ this.url = url;
1484
+
1485
+ this.start();
1486
+ },
1487
+
1488
+ start: function() {
1489
+ this.options.onComplete = this.updateComplete.bind(this);
1490
+ this.onTimerEvent();
1491
+ },
1492
+
1493
+ stop: function() {
1494
+ this.updater.options.onComplete = undefined;
1495
+ clearTimeout(this.timer);
1496
+ (this.onComplete || Prototype.emptyFunction).apply(this, arguments);
1497
+ },
1498
+
1499
+ updateComplete: function(response) {
1500
+ if (this.options.decay) {
1501
+ this.decay = (response.responseText == this.lastText ?
1502
+ this.decay * this.options.decay : 1);
1503
+
1504
+ this.lastText = response.responseText;
1505
+ }
1506
+ this.timer = this.onTimerEvent.bind(this).delay(this.decay * this.frequency);
1507
+ },
1508
+
1509
+ onTimerEvent: function() {
1510
+ this.updater = new Ajax.Updater(this.container, this.url, this.options);
1511
+ }
1512
+ });
1513
+ function $(element) {
1514
+ if (arguments.length > 1) {
1515
+ for (var i = 0, elements = [], length = arguments.length; i < length; i++)
1516
+ elements.push($(arguments[i]));
1517
+ return elements;
1518
+ }
1519
+ if (Object.isString(element))
1520
+ element = document.getElementById(element);
1521
+ return Element.extend(element);
1522
+ }
1523
+
1524
+ if (Prototype.BrowserFeatures.XPath) {
1525
+ document._getElementsByXPath = function(expression, parentElement) {
1526
+ var results = [];
1527
+ var query = document.evaluate(expression, $(parentElement) || document,
1528
+ null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
1529
+ for (var i = 0, length = query.snapshotLength; i < length; i++)
1530
+ results.push(Element.extend(query.snapshotItem(i)));
1531
+ return results;
1532
+ };
1533
+ }
1534
+
1535
+ /*--------------------------------------------------------------------------*/
1536
+
1537
+ if (!window.Node) var Node = { };
1538
+
1539
+ if (!Node.ELEMENT_NODE) {
1540
+ // DOM level 2 ECMAScript Language Binding
1541
+ Object.extend(Node, {
1542
+ ELEMENT_NODE: 1,
1543
+ ATTRIBUTE_NODE: 2,
1544
+ TEXT_NODE: 3,
1545
+ CDATA_SECTION_NODE: 4,
1546
+ ENTITY_REFERENCE_NODE: 5,
1547
+ ENTITY_NODE: 6,
1548
+ PROCESSING_INSTRUCTION_NODE: 7,
1549
+ COMMENT_NODE: 8,
1550
+ DOCUMENT_NODE: 9,
1551
+ DOCUMENT_TYPE_NODE: 10,
1552
+ DOCUMENT_FRAGMENT_NODE: 11,
1553
+ NOTATION_NODE: 12
1554
+ });
1555
+ }
1556
+
1557
+ (function() {
1558
+ var element = this.Element;
1559
+ this.Element = function(tagName, attributes) {
1560
+ attributes = attributes || { };
1561
+ tagName = tagName.toLowerCase();
1562
+ var cache = Element.cache;
1563
+ if (Prototype.Browser.IE && attributes.name) {
1564
+ tagName = '<' + tagName + ' name="' + attributes.name + '">';
1565
+ delete attributes.name;
1566
+ return Element.writeAttribute(document.createElement(tagName), attributes);
1567
+ }
1568
+ if (!cache[tagName]) cache[tagName] = Element.extend(document.createElement(tagName));
1569
+ return Element.writeAttribute(cache[tagName].cloneNode(false), attributes);
1570
+ };
1571
+ Object.extend(this.Element, element || { });
1572
+ if (element) this.Element.prototype = element.prototype;
1573
+ }).call(window);
1574
+
1575
+ Element.cache = { };
1576
+
1577
+ Element.Methods = {
1578
+ visible: function(element) {
1579
+ return $(element).style.display != 'none';
1580
+ },
1581
+
1582
+ toggle: function(element) {
1583
+ element = $(element);
1584
+ Element[Element.visible(element) ? 'hide' : 'show'](element);
1585
+ return element;
1586
+ },
1587
+
1588
+ hide: function(element) {
1589
+ element = $(element);
1590
+ element.style.display = 'none';
1591
+ return element;
1592
+ },
1593
+
1594
+ show: function(element) {
1595
+ element = $(element);
1596
+ element.style.display = '';
1597
+ return element;
1598
+ },
1599
+
1600
+ remove: function(element) {
1601
+ element = $(element);
1602
+ element.parentNode.removeChild(element);
1603
+ return element;
1604
+ },
1605
+
1606
+ update: function(element, content) {
1607
+ element = $(element);
1608
+ if (content && content.toElement) content = content.toElement();
1609
+ if (Object.isElement(content)) return element.update().insert(content);
1610
+ content = Object.toHTML(content);
1611
+ element.innerHTML = content.stripScripts();
1612
+ content.evalScripts.bind(content).defer();
1613
+ return element;
1614
+ },
1615
+
1616
+ replace: function(element, content) {
1617
+ element = $(element);
1618
+ if (content && content.toElement) content = content.toElement();
1619
+ else if (!Object.isElement(content)) {
1620
+ content = Object.toHTML(content);
1621
+ var range = element.ownerDocument.createRange();
1622
+ range.selectNode(element);
1623
+ content.evalScripts.bind(content).defer();
1624
+ content = range.createContextualFragment(content.stripScripts());
1625
+ }
1626
+ element.parentNode.replaceChild(content, element);
1627
+ return element;
1628
+ },
1629
+
1630
+ insert: function(element, insertions) {
1631
+ element = $(element);
1632
+
1633
+ if (Object.isString(insertions) || Object.isNumber(insertions) ||
1634
+ Object.isElement(insertions) || (insertions && (insertions.toElement || insertions.toHTML)))
1635
+ insertions = {bottom:insertions};
1636
+
1637
+ var content, insert, tagName, childNodes;
1638
+
1639
+ for (var position in insertions) {
1640
+ content = insertions[position];
1641
+ position = position.toLowerCase();
1642
+ insert = Element._insertionTranslations[position];
1643
+
1644
+ if (content && content.toElement) content = content.toElement();
1645
+ if (Object.isElement(content)) {
1646
+ insert(element, content);
1647
+ continue;
1648
+ }
1649
+
1650
+ content = Object.toHTML(content);
1651
+
1652
+ tagName = ((position == 'before' || position == 'after')
1653
+ ? element.parentNode : element).tagName.toUpperCase();
1654
+
1655
+ childNodes = Element._getContentFromAnonymousElement(tagName, content.stripScripts());
1656
+
1657
+ if (position == 'top' || position == 'after') childNodes.reverse();
1658
+ childNodes.each(insert.curry(element));
1659
+
1660
+ content.evalScripts.bind(content).defer();
1661
+ }
1662
+
1663
+ return element;
1664
+ },
1665
+
1666
+ wrap: function(element, wrapper, attributes) {
1667
+ element = $(element);
1668
+ if (Object.isElement(wrapper))
1669
+ $(wrapper).writeAttribute(attributes || { });
1670
+ else if (Object.isString(wrapper)) wrapper = new Element(wrapper, attributes);
1671
+ else wrapper = new Element('div', wrapper);
1672
+ if (element.parentNode)
1673
+ element.parentNode.replaceChild(wrapper, element);
1674
+ wrapper.appendChild(element);
1675
+ return wrapper;
1676
+ },
1677
+
1678
+ inspect: function(element) {
1679
+ element = $(element);
1680
+ var result = '<' + element.tagName.toLowerCase();
1681
+ $H({'id': 'id', 'className': 'class'}).each(function(pair) {
1682
+ var property = pair.first(), attribute = pair.last();
1683
+ var value = (element[property] || '').toString();
1684
+ if (value) result += ' ' + attribute + '=' + value.inspect(true);
1685
+ });
1686
+ return result + '>';
1687
+ },
1688
+
1689
+ recursivelyCollect: function(element, property) {
1690
+ element = $(element);
1691
+ var elements = [];
1692
+ while (element = element[property])
1693
+ if (element.nodeType == 1)
1694
+ elements.push(Element.extend(element));
1695
+ return elements;
1696
+ },
1697
+
1698
+ ancestors: function(element) {
1699
+ return $(element).recursivelyCollect('parentNode');
1700
+ },
1701
+
1702
+ descendants: function(element) {
1703
+ return $(element).select("*");
1704
+ },
1705
+
1706
+ firstDescendant: function(element) {
1707
+ element = $(element).firstChild;
1708
+ while (element && element.nodeType != 1) element = element.nextSibling;
1709
+ return $(element);
1710
+ },
1711
+
1712
+ immediateDescendants: function(element) {
1713
+ if (!(element = $(element).firstChild)) return [];
1714
+ while (element && element.nodeType != 1) element = element.nextSibling;
1715
+ if (element) return [element].concat($(element).nextSiblings());
1716
+ return [];
1717
+ },
1718
+
1719
+ previousSiblings: function(element) {
1720
+ return $(element).recursivelyCollect('previousSibling');
1721
+ },
1722
+
1723
+ nextSiblings: function(element) {
1724
+ return $(element).recursivelyCollect('nextSibling');
1725
+ },
1726
+
1727
+ siblings: function(element) {
1728
+ element = $(element);
1729
+ return element.previousSiblings().reverse().concat(element.nextSiblings());
1730
+ },
1731
+
1732
+ match: function(element, selector) {
1733
+ if (Object.isString(selector))
1734
+ selector = new Selector(selector);
1735
+ return selector.match($(element));
1736
+ },
1737
+
1738
+ up: function(element, expression, index) {
1739
+ element = $(element);
1740
+ if (arguments.length == 1) return $(element.parentNode);
1741
+ var ancestors = element.ancestors();
1742
+ return Object.isNumber(expression) ? ancestors[expression] :
1743
+ Selector.findElement(ancestors, expression, index);
1744
+ },
1745
+
1746
+ down: function(element, expression, index) {
1747
+ element = $(element);
1748
+ if (arguments.length == 1) return element.firstDescendant();
1749
+ return Object.isNumber(expression) ? element.descendants()[expression] :
1750
+ Element.select(element, expression)[index || 0];
1751
+ },
1752
+
1753
+ previous: function(element, expression, index) {
1754
+ element = $(element);
1755
+ if (arguments.length == 1) return $(Selector.handlers.previousElementSibling(element));
1756
+ var previousSiblings = element.previousSiblings();
1757
+ return Object.isNumber(expression) ? previousSiblings[expression] :
1758
+ Selector.findElement(previousSiblings, expression, index);
1759
+ },
1760
+
1761
+ next: function(element, expression, index) {
1762
+ element = $(element);
1763
+ if (arguments.length == 1) return $(Selector.handlers.nextElementSibling(element));
1764
+ var nextSiblings = element.nextSiblings();
1765
+ return Object.isNumber(expression) ? nextSiblings[expression] :
1766
+ Selector.findElement(nextSiblings, expression, index);
1767
+ },
1768
+
1769
+ select: function() {
1770
+ var args = $A(arguments), element = $(args.shift());
1771
+ return Selector.findChildElements(element, args);
1772
+ },
1773
+
1774
+ adjacent: function() {
1775
+ var args = $A(arguments), element = $(args.shift());
1776
+ return Selector.findChildElements(element.parentNode, args).without(element);
1777
+ },
1778
+
1779
+ identify: function(element) {
1780
+ element = $(element);
1781
+ var id = element.readAttribute('id'), self = arguments.callee;
1782
+ if (id) return id;
1783
+ do { id = 'anonymous_element_' + self.counter++ } while ($(id));
1784
+ element.writeAttribute('id', id);
1785
+ return id;
1786
+ },
1787
+
1788
+ readAttribute: function(element, name) {
1789
+ element = $(element);
1790
+ if (Prototype.Browser.IE) {
1791
+ var t = Element._attributeTranslations.read;
1792
+ if (t.values[name]) return t.values[name](element, name);
1793
+ if (t.names[name]) name = t.names[name];
1794
+ if (name.include(':')) {
1795
+ return (!element.attributes || !element.attributes[name]) ? null :
1796
+ element.attributes[name].value;
1797
+ }
1798
+ }
1799
+ return element.getAttribute(name);
1800
+ },
1801
+
1802
+ writeAttribute: function(element, name, value) {
1803
+ element = $(element);
1804
+ var attributes = { }, t = Element._attributeTranslations.write;
1805
+
1806
+ if (typeof name == 'object') attributes = name;
1807
+ else attributes[name] = Object.isUndefined(value) ? true : value;
1808
+
1809
+ for (var attr in attributes) {
1810
+ name = t.names[attr] || attr;
1811
+ value = attributes[attr];
1812
+ if (t.values[attr]) name = t.values[attr](element, value);
1813
+ if (value === false || value === null)
1814
+ element.removeAttribute(name);
1815
+ else if (value === true)
1816
+ element.setAttribute(name, name);
1817
+ else element.setAttribute(name, value);
1818
+ }
1819
+ return element;
1820
+ },
1821
+
1822
+ getHeight: function(element) {
1823
+ return $(element).getDimensions().height;
1824
+ },
1825
+
1826
+ getWidth: function(element) {
1827
+ return $(element).getDimensions().width;
1828
+ },
1829
+
1830
+ classNames: function(element) {
1831
+ return new Element.ClassNames(element);
1832
+ },
1833
+
1834
+ hasClassName: function(element, className) {
1835
+ if (!(element = $(element))) return;
1836
+ var elementClassName = element.className;
1837
+ return (elementClassName.length > 0 && (elementClassName == className ||
1838
+ new RegExp("(^|\\s)" + className + "(\\s|$)").test(elementClassName)));
1839
+ },
1840
+
1841
+ addClassName: function(element, className) {
1842
+ if (!(element = $(element))) return;
1843
+ if (!element.hasClassName(className))
1844
+ element.className += (element.className ? ' ' : '') + className;
1845
+ return element;
1846
+ },
1847
+
1848
+ removeClassName: function(element, className) {
1849
+ if (!(element = $(element))) return;
1850
+ element.className = element.className.replace(
1851
+ new RegExp("(^|\\s+)" + className + "(\\s+|$)"), ' ').strip();
1852
+ return element;
1853
+ },
1854
+
1855
+ toggleClassName: function(element, className) {
1856
+ if (!(element = $(element))) return;
1857
+ return element[element.hasClassName(className) ?
1858
+ 'removeClassName' : 'addClassName'](className);
1859
+ },
1860
+
1861
+ // removes whitespace-only text node children
1862
+ cleanWhitespace: function(element) {
1863
+ element = $(element);
1864
+ var node = element.firstChild;
1865
+ while (node) {
1866
+ var nextNode = node.nextSibling;
1867
+ if (node.nodeType == 3 && !/\S/.test(node.nodeValue))
1868
+ element.removeChild(node);
1869
+ node = nextNode;
1870
+ }
1871
+ return element;
1872
+ },
1873
+
1874
+ empty: function(element) {
1875
+ return $(element).innerHTML.blank();
1876
+ },
1877
+
1878
+ descendantOf: function(element, ancestor) {
1879
+ element = $(element), ancestor = $(ancestor);
1880
+
1881
+ if (element.compareDocumentPosition)
1882
+ return (element.compareDocumentPosition(ancestor) & 8) === 8;
1883
+
1884
+ if (ancestor.contains)
1885
+ return ancestor.contains(element) && ancestor !== element;
1886
+
1887
+ while (element = element.parentNode)
1888
+ if (element == ancestor) return true;
1889
+
1890
+ return false;
1891
+ },
1892
+
1893
+ scrollTo: function(element) {
1894
+ element = $(element);
1895
+ var pos = element.cumulativeOffset();
1896
+ window.scrollTo(pos[0], pos[1]);
1897
+ return element;
1898
+ },
1899
+
1900
+ getStyle: function(element, style) {
1901
+ element = $(element);
1902
+ style = style == 'float' ? 'cssFloat' : style.camelize();
1903
+ var value = element.style[style];
1904
+ if (!value || value == 'auto') {
1905
+ var css = document.defaultView.getComputedStyle(element, null);
1906
+ value = css ? css[style] : null;
1907
+ }
1908
+ if (style == 'opacity') return value ? parseFloat(value) : 1.0;
1909
+ return value == 'auto' ? null : value;
1910
+ },
1911
+
1912
+ getOpacity: function(element) {
1913
+ return $(element).getStyle('opacity');
1914
+ },
1915
+
1916
+ setStyle: function(element, styles) {
1917
+ element = $(element);
1918
+ var elementStyle = element.style, match;
1919
+ if (Object.isString(styles)) {
1920
+ element.style.cssText += ';' + styles;
1921
+ return styles.include('opacity') ?
1922
+ element.setOpacity(styles.match(/opacity:\s*(\d?\.?\d*)/)[1]) : element;
1923
+ }
1924
+ for (var property in styles)
1925
+ if (property == 'opacity') element.setOpacity(styles[property]);
1926
+ else
1927
+ elementStyle[(property == 'float' || property == 'cssFloat') ?
1928
+ (Object.isUndefined(elementStyle.styleFloat) ? 'cssFloat' : 'styleFloat') :
1929
+ property] = styles[property];
1930
+
1931
+ return element;
1932
+ },
1933
+
1934
+ setOpacity: function(element, value) {
1935
+ element = $(element);
1936
+ element.style.opacity = (value == 1 || value === '') ? '' :
1937
+ (value < 0.00001) ? 0 : value;
1938
+ return element;
1939
+ },
1940
+
1941
+ getDimensions: function(element) {
1942
+ element = $(element);
1943
+ var display = element.getStyle('display');
1944
+ if (display != 'none' && display != null) // Safari bug
1945
+ return {width: element.offsetWidth, height: element.offsetHeight};
1946
+
1947
+ // All *Width and *Height properties give 0 on elements with display none,
1948
+ // so enable the element temporarily
1949
+ var els = element.style;
1950
+ var originalVisibility = els.visibility;
1951
+ var originalPosition = els.position;
1952
+ var originalDisplay = els.display;
1953
+ els.visibility = 'hidden';
1954
+ els.position = 'absolute';
1955
+ els.display = 'block';
1956
+ var originalWidth = element.clientWidth;
1957
+ var originalHeight = element.clientHeight;
1958
+ els.display = originalDisplay;
1959
+ els.position = originalPosition;
1960
+ els.visibility = originalVisibility;
1961
+ return {width: originalWidth, height: originalHeight};
1962
+ },
1963
+
1964
+ makePositioned: function(element) {
1965
+ element = $(element);
1966
+ var pos = Element.getStyle(element, 'position');
1967
+ if (pos == 'static' || !pos) {
1968
+ element._madePositioned = true;
1969
+ element.style.position = 'relative';
1970
+ // Opera returns the offset relative to the positioning context, when an
1971
+ // element is position relative but top and left have not been defined
1972
+ if (Prototype.Browser.Opera) {
1973
+ element.style.top = 0;
1974
+ element.style.left = 0;
1975
+ }
1976
+ }
1977
+ return element;
1978
+ },
1979
+
1980
+ undoPositioned: function(element) {
1981
+ element = $(element);
1982
+ if (element._madePositioned) {
1983
+ element._madePositioned = undefined;
1984
+ element.style.position =
1985
+ element.style.top =
1986
+ element.style.left =
1987
+ element.style.bottom =
1988
+ element.style.right = '';
1989
+ }
1990
+ return element;
1991
+ },
1992
+
1993
+ makeClipping: function(element) {
1994
+ element = $(element);
1995
+ if (element._overflow) return element;
1996
+ element._overflow = Element.getStyle(element, 'overflow') || 'auto';
1997
+ if (element._overflow !== 'hidden')
1998
+ element.style.overflow = 'hidden';
1999
+ return element;
2000
+ },
2001
+
2002
+ undoClipping: function(element) {
2003
+ element = $(element);
2004
+ if (!element._overflow) return element;
2005
+ element.style.overflow = element._overflow == 'auto' ? '' : element._overflow;
2006
+ element._overflow = null;
2007
+ return element;
2008
+ },
2009
+
2010
+ cumulativeOffset: function(element) {
2011
+ var valueT = 0, valueL = 0;
2012
+ do {
2013
+ valueT += element.offsetTop || 0;
2014
+ valueL += element.offsetLeft || 0;
2015
+ element = element.offsetParent;
2016
+ } while (element);
2017
+ return Element._returnOffset(valueL, valueT);
2018
+ },
2019
+
2020
+ positionedOffset: function(element) {
2021
+ var valueT = 0, valueL = 0;
2022
+ do {
2023
+ valueT += element.offsetTop || 0;
2024
+ valueL += element.offsetLeft || 0;
2025
+ element = element.offsetParent;
2026
+ if (element) {
2027
+ if (element.tagName.toUpperCase() == 'BODY') break;
2028
+ var p = Element.getStyle(element, 'position');
2029
+ if (p !== 'static') break;
2030
+ }
2031
+ } while (element);
2032
+ return Element._returnOffset(valueL, valueT);
2033
+ },
2034
+
2035
+ absolutize: function(element) {
2036
+ element = $(element);
2037
+ if (element.getStyle('position') == 'absolute') return element;
2038
+ // Position.prepare(); // To be done manually by Scripty when it needs it.
2039
+
2040
+ var offsets = element.positionedOffset();
2041
+ var top = offsets[1];
2042
+ var left = offsets[0];
2043
+ var width = element.clientWidth;
2044
+ var height = element.clientHeight;
2045
+
2046
+ element._originalLeft = left - parseFloat(element.style.left || 0);
2047
+ element._originalTop = top - parseFloat(element.style.top || 0);
2048
+ element._originalWidth = element.style.width;
2049
+ element._originalHeight = element.style.height;
2050
+
2051
+ element.style.position = 'absolute';
2052
+ element.style.top = top + 'px';
2053
+ element.style.left = left + 'px';
2054
+ element.style.width = width + 'px';
2055
+ element.style.height = height + 'px';
2056
+ return element;
2057
+ },
2058
+
2059
+ relativize: function(element) {
2060
+ element = $(element);
2061
+ if (element.getStyle('position') == 'relative') return element;
2062
+ // Position.prepare(); // To be done manually by Scripty when it needs it.
2063
+
2064
+ element.style.position = 'relative';
2065
+ var top = parseFloat(element.style.top || 0) - (element._originalTop || 0);
2066
+ var left = parseFloat(element.style.left || 0) - (element._originalLeft || 0);
2067
+
2068
+ element.style.top = top + 'px';
2069
+ element.style.left = left + 'px';
2070
+ element.style.height = element._originalHeight;
2071
+ element.style.width = element._originalWidth;
2072
+ return element;
2073
+ },
2074
+
2075
+ cumulativeScrollOffset: function(element) {
2076
+ var valueT = 0, valueL = 0;
2077
+ do {
2078
+ valueT += element.scrollTop || 0;
2079
+ valueL += element.scrollLeft || 0;
2080
+ element = element.parentNode;
2081
+ } while (element);
2082
+ return Element._returnOffset(valueL, valueT);
2083
+ },
2084
+
2085
+ getOffsetParent: function(element) {
2086
+ if (element.offsetParent) return $(element.offsetParent);
2087
+ if (element == document.body) return $(element);
2088
+ if(element.tagName.toUpperCase()=='HTML') //for IE6,7
2089
+ return $(document.body); //
2090
+
2091
+ while ((element = element.parentNode) && element != document.body)
2092
+ if (Element.getStyle(element, 'position') != 'static')
2093
+ return $(element);
2094
+
2095
+ return $(document.body);
2096
+ },
2097
+
2098
+ viewportOffset: function(forElement) {
2099
+ var valueT = 0, valueL = 0;
2100
+
2101
+ var element = forElement;
2102
+ do {
2103
+ valueT += element.offsetTop || 0;
2104
+ valueL += element.offsetLeft || 0;
2105
+
2106
+ // Safari fix
2107
+ if (element.offsetParent == document.body &&
2108
+ Element.getStyle(element, 'position') == 'absolute') break;
2109
+
2110
+ } while (element = element.offsetParent);
2111
+
2112
+ element = forElement;
2113
+ do {
2114
+ if (!Prototype.Browser.Opera || (element.tagName && (element.tagName.toUpperCase() == 'BODY'))) {
2115
+ valueT -= element.scrollTop || 0;
2116
+ valueL -= element.scrollLeft || 0;
2117
+ }
2118
+ } while (element = element.parentNode);
2119
+
2120
+ return Element._returnOffset(valueL, valueT);
2121
+ },
2122
+
2123
+ clonePosition: function(element, source) {
2124
+ var options = Object.extend({
2125
+ setLeft: true,
2126
+ setTop: true,
2127
+ setWidth: true,
2128
+ setHeight: true,
2129
+ offsetTop: 0,
2130
+ offsetLeft: 0
2131
+ }, arguments[2] || { });
2132
+
2133
+ // find page position of source
2134
+ source = $(source);
2135
+ var p = source.viewportOffset();
2136
+
2137
+ // find coordinate system to use
2138
+ element = $(element);
2139
+ var delta = [0, 0];
2140
+ var parent = null;
2141
+ // delta [0,0] will do fine with position: fixed elements,
2142
+ // position:absolute needs offsetParent deltas
2143
+ if (Element.getStyle(element, 'position') == 'absolute') {
2144
+ parent = element.getOffsetParent();
2145
+ delta = parent.viewportOffset();
2146
+ }
2147
+
2148
+ // correct by body offsets (fixes Safari)
2149
+ if (parent == document.body) {
2150
+ delta[0] -= document.body.offsetLeft;
2151
+ delta[1] -= document.body.offsetTop;
2152
+ }
2153
+
2154
+ // set position
2155
+ if (options.setLeft) element.style.left = (p[0] - delta[0] + options.offsetLeft) + 'px';
2156
+ if (options.setTop) element.style.top = (p[1] - delta[1] + options.offsetTop) + 'px';
2157
+ if (options.setWidth) element.style.width = source.offsetWidth + 'px';
2158
+ if (options.setHeight) element.style.height = source.offsetHeight + 'px';
2159
+ return element;
2160
+ }
2161
+ };
2162
+
2163
+ Element.Methods.identify.counter = 1;
2164
+
2165
+ Object.extend(Element.Methods, {
2166
+ getElementsBySelector: Element.Methods.select,
2167
+ childElements: Element.Methods.immediateDescendants
2168
+ });
2169
+
2170
+ Element._attributeTranslations = {
2171
+ write: {
2172
+ names: {
2173
+ className: 'class',
2174
+ htmlFor: 'for'
2175
+ },
2176
+ values: { }
2177
+ }
2178
+ };
2179
+
2180
+ if (Prototype.Browser.Opera) {
2181
+ Element.Methods.getStyle = Element.Methods.getStyle.wrap(
2182
+ function(proceed, element, style) {
2183
+ switch (style) {
2184
+ case 'left': case 'top': case 'right': case 'bottom':
2185
+ if (proceed(element, 'position') === 'static') return null;
2186
+ case 'height': case 'width':
2187
+ // returns '0px' for hidden elements; we want it to return null
2188
+ if (!Element.visible(element)) return null;
2189
+
2190
+ // returns the border-box dimensions rather than the content-box
2191
+ // dimensions, so we subtract padding and borders from the value
2192
+ var dim = parseInt(proceed(element, style), 10);
2193
+
2194
+ if (dim !== element['offset' + style.capitalize()])
2195
+ return dim + 'px';
2196
+
2197
+ var properties;
2198
+ if (style === 'height') {
2199
+ properties = ['border-top-width', 'padding-top',
2200
+ 'padding-bottom', 'border-bottom-width'];
2201
+ }
2202
+ else {
2203
+ properties = ['border-left-width', 'padding-left',
2204
+ 'padding-right', 'border-right-width'];
2205
+ }
2206
+ return properties.inject(dim, function(memo, property) {
2207
+ var val = proceed(element, property);
2208
+ return val === null ? memo : memo - parseInt(val, 10);
2209
+ }) + 'px';
2210
+ default: return proceed(element, style);
2211
+ }
2212
+ }
2213
+ );
2214
+
2215
+ Element.Methods.readAttribute = Element.Methods.readAttribute.wrap(
2216
+ function(proceed, element, attribute) {
2217
+ if (attribute === 'title') return element.title;
2218
+ return proceed(element, attribute);
2219
+ }
2220
+ );
2221
+ }
2222
+
2223
+ else if (Prototype.Browser.IE) {
2224
+ // IE doesn't report offsets correctly for static elements, so we change them
2225
+ // to "relative" to get the values, then change them back.
2226
+ Element.Methods.getOffsetParent = Element.Methods.getOffsetParent.wrap(
2227
+ function(proceed, element) {
2228
+ element = $(element);
2229
+ // IE throws an error if element is not in document
2230
+ try { element.offsetParent }
2231
+ catch(e) { return $(document.body) }
2232
+ var position = element.getStyle('position');
2233
+ if (position !== 'static') return proceed(element);
2234
+ element.setStyle({ position: 'relative' });
2235
+ var value = proceed(element);
2236
+ element.setStyle({ position: position });
2237
+ return value;
2238
+ }
2239
+ );
2240
+
2241
+ $w('positionedOffset viewportOffset').each(function(method) {
2242
+ Element.Methods[method] = Element.Methods[method].wrap(
2243
+ function(proceed, element) {
2244
+ element = $(element);
2245
+ try { element.offsetParent }
2246
+ catch(e) { return Element._returnOffset(0,0) }
2247
+ var position = element.getStyle('position');
2248
+ if (position !== 'static') return proceed(element);
2249
+ // Trigger hasLayout on the offset parent so that IE6 reports
2250
+ // accurate offsetTop and offsetLeft values for position: fixed.
2251
+ var offsetParent = element.getOffsetParent();
2252
+ if (offsetParent && offsetParent.getStyle('position') === 'fixed')
2253
+ offsetParent.setStyle({ zoom: 1 });
2254
+ element.setStyle({ position: 'relative' });
2255
+ var value = proceed(element);
2256
+ element.setStyle({ position: position });
2257
+ return value;
2258
+ }
2259
+ );
2260
+ });
2261
+
2262
+ Element.Methods.cumulativeOffset = Element.Methods.cumulativeOffset.wrap(
2263
+ function(proceed, element) {
2264
+ try { element.offsetParent }
2265
+ catch(e) { return Element._returnOffset(0,0) }
2266
+ return proceed(element);
2267
+ }
2268
+ );
2269
+
2270
+ Element.Methods.getStyle = function(element, style) {
2271
+ element = $(element);
2272
+ style = (style == 'float' || style == 'cssFloat') ? 'styleFloat' : style.camelize();
2273
+ var value = element.style[style];
2274
+ if (!value && element.currentStyle) value = element.currentStyle[style];
2275
+
2276
+ if (style == 'opacity') {
2277
+ if (value = (element.getStyle('filter') || '').match(/alpha\(opacity=(.*)\)/))
2278
+ if (value[1]) return parseFloat(value[1]) / 100;
2279
+ return 1.0;
2280
+ }
2281
+
2282
+ if (value == 'auto') {
2283
+ if ((style == 'width' || style == 'height') && (element.getStyle('display') != 'none'))
2284
+ return element['offset' + style.capitalize()] + 'px';
2285
+ return null;
2286
+ }
2287
+ return value;
2288
+ };
2289
+
2290
+ Element.Methods.setOpacity = function(element, value) {
2291
+ function stripAlpha(filter){
2292
+ return filter.replace(/alpha\([^\)]*\)/gi,'');
2293
+ }
2294
+ element = $(element);
2295
+ var currentStyle = element.currentStyle;
2296
+ if ((currentStyle && !currentStyle.hasLayout) ||
2297
+ (!currentStyle && element.style.zoom == 'normal'))
2298
+ element.style.zoom = 1;
2299
+
2300
+ var filter = element.getStyle('filter'), style = element.style;
2301
+ if (value == 1 || value === '') {
2302
+ (filter = stripAlpha(filter)) ?
2303
+ style.filter = filter : style.removeAttribute('filter');
2304
+ return element;
2305
+ } else if (value < 0.00001) value = 0;
2306
+ style.filter = stripAlpha(filter) +
2307
+ 'alpha(opacity=' + (value * 100) + ')';
2308
+ return element;
2309
+ };
2310
+
2311
+ Element._attributeTranslations = {
2312
+ read: {
2313
+ names: {
2314
+ 'class': 'className',
2315
+ 'for': 'htmlFor'
2316
+ },
2317
+ values: {
2318
+ _getAttr: function(element, attribute) {
2319
+ return element.getAttribute(attribute, 2);
2320
+ },
2321
+ _getAttrNode: function(element, attribute) {
2322
+ var node = element.getAttributeNode(attribute);
2323
+ return node ? node.value : "";
2324
+ },
2325
+ _getEv: function(element, attribute) {
2326
+ attribute = element.getAttribute(attribute);
2327
+ return attribute ? attribute.toString().slice(23, -2) : null;
2328
+ },
2329
+ _flag: function(element, attribute) {
2330
+ return $(element).hasAttribute(attribute) ? attribute : null;
2331
+ },
2332
+ style: function(element) {
2333
+ return element.style.cssText.toLowerCase();
2334
+ },
2335
+ title: function(element) {
2336
+ return element.title;
2337
+ }
2338
+ }
2339
+ }
2340
+ };
2341
+
2342
+ Element._attributeTranslations.write = {
2343
+ names: Object.extend({
2344
+ cellpadding: 'cellPadding',
2345
+ cellspacing: 'cellSpacing'
2346
+ }, Element._attributeTranslations.read.names),
2347
+ values: {
2348
+ checked: function(element, value) {
2349
+ element.checked = !!value;
2350
+ },
2351
+
2352
+ style: function(element, value) {
2353
+ element.style.cssText = value ? value : '';
2354
+ }
2355
+ }
2356
+ };
2357
+
2358
+ Element._attributeTranslations.has = {};
2359
+
2360
+ $w('colSpan rowSpan vAlign dateTime accessKey tabIndex ' +
2361
+ 'encType maxLength readOnly longDesc frameBorder').each(function(attr) {
2362
+ Element._attributeTranslations.write.names[attr.toLowerCase()] = attr;
2363
+ Element._attributeTranslations.has[attr.toLowerCase()] = attr;
2364
+ });
2365
+
2366
+ (function(v) {
2367
+ Object.extend(v, {
2368
+ href: v._getAttr,
2369
+ src: v._getAttr,
2370
+ type: v._getAttr,
2371
+ action: v._getAttrNode,
2372
+ disabled: v._flag,
2373
+ checked: v._flag,
2374
+ readonly: v._flag,
2375
+ multiple: v._flag,
2376
+ onload: v._getEv,
2377
+ onunload: v._getEv,
2378
+ onclick: v._getEv,
2379
+ ondblclick: v._getEv,
2380
+ onmousedown: v._getEv,
2381
+ onmouseup: v._getEv,
2382
+ onmouseover: v._getEv,
2383
+ onmousemove: v._getEv,
2384
+ onmouseout: v._getEv,
2385
+ onfocus: v._getEv,
2386
+ onblur: v._getEv,
2387
+ onkeypress: v._getEv,
2388
+ onkeydown: v._getEv,
2389
+ onkeyup: v._getEv,
2390
+ onsubmit: v._getEv,
2391
+ onreset: v._getEv,
2392
+ onselect: v._getEv,
2393
+ onchange: v._getEv
2394
+ });
2395
+ })(Element._attributeTranslations.read.values);
2396
+ }
2397
+
2398
+ else if (Prototype.Browser.Gecko && /rv:1\.8\.0/.test(navigator.userAgent)) {
2399
+ Element.Methods.setOpacity = function(element, value) {
2400
+ element = $(element);
2401
+ element.style.opacity = (value == 1) ? 0.999999 :
2402
+ (value === '') ? '' : (value < 0.00001) ? 0 : value;
2403
+ return element;
2404
+ };
2405
+ }
2406
+
2407
+ else if (Prototype.Browser.WebKit) {
2408
+ Element.Methods.setOpacity = function(element, value) {
2409
+ element = $(element);
2410
+ element.style.opacity = (value == 1 || value === '') ? '' :
2411
+ (value < 0.00001) ? 0 : value;
2412
+
2413
+ if (value == 1)
2414
+ if(element.tagName.toUpperCase() == 'IMG' && element.width) {
2415
+ element.width++; element.width--;
2416
+ } else try {
2417
+ var n = document.createTextNode(' ');
2418
+ element.appendChild(n);
2419
+ element.removeChild(n);
2420
+ } catch (e) { }
2421
+
2422
+ return element;
2423
+ };
2424
+
2425
+ // Safari returns margins on body which is incorrect if the child is absolutely
2426
+ // positioned. For performance reasons, redefine Element#cumulativeOffset for
2427
+ // KHTML/WebKit only.
2428
+ Element.Methods.cumulativeOffset = function(element) {
2429
+ var valueT = 0, valueL = 0;
2430
+ do {
2431
+ valueT += element.offsetTop || 0;
2432
+ valueL += element.offsetLeft || 0;
2433
+ if (element.offsetParent == document.body)
2434
+ if (Element.getStyle(element, 'position') == 'absolute') break;
2435
+
2436
+ element = element.offsetParent;
2437
+ } while (element);
2438
+
2439
+ return Element._returnOffset(valueL, valueT);
2440
+ };
2441
+ }
2442
+
2443
+ if (Prototype.Browser.IE || Prototype.Browser.Opera) {
2444
+ // IE and Opera are missing .innerHTML support for TABLE-related and SELECT elements
2445
+ Element.Methods.update = function(element, content) {
2446
+ element = $(element);
2447
+
2448
+ if (content && content.toElement) content = content.toElement();
2449
+ if (Object.isElement(content)) return element.update().insert(content);
2450
+
2451
+ content = Object.toHTML(content);
2452
+ var tagName = element.tagName.toUpperCase();
2453
+
2454
+ if (tagName in Element._insertionTranslations.tags) {
2455
+ $A(element.childNodes).each(function(node) { element.removeChild(node) });
2456
+ Element._getContentFromAnonymousElement(tagName, content.stripScripts())
2457
+ .each(function(node) { element.appendChild(node) });
2458
+ }
2459
+ else element.innerHTML = content.stripScripts();
2460
+
2461
+ content.evalScripts.bind(content).defer();
2462
+ return element;
2463
+ };
2464
+ }
2465
+
2466
+ if ('outerHTML' in document.createElement('div')) {
2467
+ Element.Methods.replace = function(element, content) {
2468
+ element = $(element);
2469
+
2470
+ if (content && content.toElement) content = content.toElement();
2471
+ if (Object.isElement(content)) {
2472
+ element.parentNode.replaceChild(content, element);
2473
+ return element;
2474
+ }
2475
+
2476
+ content = Object.toHTML(content);
2477
+ var parent = element.parentNode, tagName = parent.tagName.toUpperCase();
2478
+
2479
+ if (Element._insertionTranslations.tags[tagName]) {
2480
+ var nextSibling = element.next();
2481
+ var fragments = Element._getContentFromAnonymousElement(tagName, content.stripScripts());
2482
+ parent.removeChild(element);
2483
+ if (nextSibling)
2484
+ fragments.each(function(node) { parent.insertBefore(node, nextSibling) });
2485
+ else
2486
+ fragments.each(function(node) { parent.appendChild(node) });
2487
+ }
2488
+ else element.outerHTML = content.stripScripts();
2489
+
2490
+ content.evalScripts.bind(content).defer();
2491
+ return element;
2492
+ };
2493
+ }
2494
+
2495
+ Element._returnOffset = function(l, t) {
2496
+ var result = [l, t];
2497
+ result.left = l;
2498
+ result.top = t;
2499
+ return result;
2500
+ };
2501
+
2502
+ Element._getContentFromAnonymousElement = function(tagName, html) {
2503
+ var div = new Element('div'), t = Element._insertionTranslations.tags[tagName];
2504
+ if (t) {
2505
+ div.innerHTML = t[0] + html + t[1];
2506
+ t[2].times(function() { div = div.firstChild });
2507
+ } else div.innerHTML = html;
2508
+ return $A(div.childNodes);
2509
+ };
2510
+
2511
+ Element._insertionTranslations = {
2512
+ before: function(element, node) {
2513
+ element.parentNode.insertBefore(node, element);
2514
+ },
2515
+ top: function(element, node) {
2516
+ element.insertBefore(node, element.firstChild);
2517
+ },
2518
+ bottom: function(element, node) {
2519
+ element.appendChild(node);
2520
+ },
2521
+ after: function(element, node) {
2522
+ element.parentNode.insertBefore(node, element.nextSibling);
2523
+ },
2524
+ tags: {
2525
+ TABLE: ['<table>', '</table>', 1],
2526
+ TBODY: ['<table><tbody>', '</tbody></table>', 2],
2527
+ TR: ['<table><tbody><tr>', '</tr></tbody></table>', 3],
2528
+ TD: ['<table><tbody><tr><td>', '</td></tr></tbody></table>', 4],
2529
+ SELECT: ['<select>', '</select>', 1]
2530
+ }
2531
+ };
2532
+
2533
+ (function() {
2534
+ Object.extend(this.tags, {
2535
+ THEAD: this.tags.TBODY,
2536
+ TFOOT: this.tags.TBODY,
2537
+ TH: this.tags.TD
2538
+ });
2539
+ }).call(Element._insertionTranslations);
2540
+
2541
+ Element.Methods.Simulated = {
2542
+ hasAttribute: function(element, attribute) {
2543
+ attribute = Element._attributeTranslations.has[attribute] || attribute;
2544
+ var node = $(element).getAttributeNode(attribute);
2545
+ return !!(node && node.specified);
2546
+ }
2547
+ };
2548
+
2549
+ Element.Methods.ByTag = { };
2550
+
2551
+ Object.extend(Element, Element.Methods);
2552
+
2553
+ if (!Prototype.BrowserFeatures.ElementExtensions &&
2554
+ document.createElement('div')['__proto__']) {
2555
+ window.HTMLElement = { };
2556
+ window.HTMLElement.prototype = document.createElement('div')['__proto__'];
2557
+ Prototype.BrowserFeatures.ElementExtensions = true;
2558
+ }
2559
+
2560
+ Element.extend = (function() {
2561
+ if (Prototype.BrowserFeatures.SpecificElementExtensions)
2562
+ return Prototype.K;
2563
+
2564
+ var Methods = { }, ByTag = Element.Methods.ByTag;
2565
+
2566
+ var extend = Object.extend(function(element) {
2567
+ if (!element || element._extendedByPrototype ||
2568
+ element.nodeType != 1 || element == window) return element;
2569
+
2570
+ var methods = Object.clone(Methods),
2571
+ tagName = element.tagName.toUpperCase(), property, value;
2572
+
2573
+ // extend methods for specific tags
2574
+ if (ByTag[tagName]) Object.extend(methods, ByTag[tagName]);
2575
+
2576
+ for (property in methods) {
2577
+ value = methods[property];
2578
+ if (Object.isFunction(value) && !(property in element))
2579
+ element[property] = value.methodize();
2580
+ }
2581
+
2582
+ element._extendedByPrototype = Prototype.emptyFunction;
2583
+ return element;
2584
+
2585
+ }, {
2586
+ refresh: function() {
2587
+ // extend methods for all tags (Safari doesn't need this)
2588
+ if (!Prototype.BrowserFeatures.ElementExtensions) {
2589
+ Object.extend(Methods, Element.Methods);
2590
+ Object.extend(Methods, Element.Methods.Simulated);
2591
+ }
2592
+ }
2593
+ });
2594
+
2595
+ extend.refresh();
2596
+ return extend;
2597
+ })();
2598
+
2599
+ Element.hasAttribute = function(element, attribute) {
2600
+ if (element.hasAttribute) return element.hasAttribute(attribute);
2601
+ return Element.Methods.Simulated.hasAttribute(element, attribute);
2602
+ };
2603
+
2604
+ Element.addMethods = function(methods) {
2605
+ var F = Prototype.BrowserFeatures, T = Element.Methods.ByTag;
2606
+
2607
+ if (!methods) {
2608
+ Object.extend(Form, Form.Methods);
2609
+ Object.extend(Form.Element, Form.Element.Methods);
2610
+ Object.extend(Element.Methods.ByTag, {
2611
+ "FORM": Object.clone(Form.Methods),
2612
+ "INPUT": Object.clone(Form.Element.Methods),
2613
+ "SELECT": Object.clone(Form.Element.Methods),
2614
+ "TEXTAREA": Object.clone(Form.Element.Methods)
2615
+ });
2616
+ }
2617
+
2618
+ if (arguments.length == 2) {
2619
+ var tagName = methods;
2620
+ methods = arguments[1];
2621
+ }
2622
+
2623
+ if (!tagName) Object.extend(Element.Methods, methods || { });
2624
+ else {
2625
+ if (Object.isArray(tagName)) tagName.each(extend);
2626
+ else extend(tagName);
2627
+ }
2628
+
2629
+ function extend(tagName) {
2630
+ tagName = tagName.toUpperCase();
2631
+ if (!Element.Methods.ByTag[tagName])
2632
+ Element.Methods.ByTag[tagName] = { };
2633
+ Object.extend(Element.Methods.ByTag[tagName], methods);
2634
+ }
2635
+
2636
+ function copy(methods, destination, onlyIfAbsent) {
2637
+ onlyIfAbsent = onlyIfAbsent || false;
2638
+ for (var property in methods) {
2639
+ var value = methods[property];
2640
+ if (!Object.isFunction(value)) continue;
2641
+ if (!onlyIfAbsent || !(property in destination))
2642
+ destination[property] = value.methodize();
2643
+ }
2644
+ }
2645
+
2646
+ function findDOMClass(tagName) {
2647
+ var klass;
2648
+ var trans = {
2649
+ "OPTGROUP": "OptGroup", "TEXTAREA": "TextArea", "P": "Paragraph",
2650
+ "FIELDSET": "FieldSet", "UL": "UList", "OL": "OList", "DL": "DList",
2651
+ "DIR": "Directory", "H1": "Heading", "H2": "Heading", "H3": "Heading",
2652
+ "H4": "Heading", "H5": "Heading", "H6": "Heading", "Q": "Quote",
2653
+ "INS": "Mod", "DEL": "Mod", "A": "Anchor", "IMG": "Image", "CAPTION":
2654
+ "TableCaption", "COL": "TableCol", "COLGROUP": "TableCol", "THEAD":
2655
+ "TableSection", "TFOOT": "TableSection", "TBODY": "TableSection", "TR":
2656
+ "TableRow", "TH": "TableCell", "TD": "TableCell", "FRAMESET":
2657
+ "FrameSet", "IFRAME": "IFrame"
2658
+ };
2659
+ if (trans[tagName]) klass = 'HTML' + trans[tagName] + 'Element';
2660
+ if (window[klass]) return window[klass];
2661
+ klass = 'HTML' + tagName + 'Element';
2662
+ if (window[klass]) return window[klass];
2663
+ klass = 'HTML' + tagName.capitalize() + 'Element';
2664
+ if (window[klass]) return window[klass];
2665
+
2666
+ window[klass] = { };
2667
+ window[klass].prototype = document.createElement(tagName)['__proto__'];
2668
+ return window[klass];
2669
+ }
2670
+
2671
+ if (F.ElementExtensions) {
2672
+ copy(Element.Methods, HTMLElement.prototype);
2673
+ copy(Element.Methods.Simulated, HTMLElement.prototype, true);
2674
+ }
2675
+
2676
+ if (F.SpecificElementExtensions) {
2677
+ for (var tag in Element.Methods.ByTag) {
2678
+ var klass = findDOMClass(tag);
2679
+ if (Object.isUndefined(klass)) continue;
2680
+ copy(T[tag], klass.prototype);
2681
+ }
2682
+ }
2683
+
2684
+ Object.extend(Element, Element.Methods);
2685
+ delete Element.ByTag;
2686
+
2687
+ if (Element.extend.refresh) Element.extend.refresh();
2688
+ Element.cache = { };
2689
+ };
2690
+
2691
+ document.viewport = {
2692
+ getDimensions: function() {
2693
+ var dimensions = { }, B = Prototype.Browser;
2694
+ $w('width height').each(function(d) {
2695
+ var D = d.capitalize();
2696
+ if (B.WebKit && !document.evaluate) {
2697
+ // Safari <3.0 needs self.innerWidth/Height
2698
+ dimensions[d] = self['inner' + D];
2699
+ } else if (B.Opera && parseFloat(window.opera.version()) < 9.5) {
2700
+ // Opera <9.5 needs document.body.clientWidth/Height
2701
+ dimensions[d] = document.body['client' + D]
2702
+ } else {
2703
+ dimensions[d] = document.documentElement['client' + D];
2704
+ }
2705
+ });
2706
+ return dimensions;
2707
+ },
2708
+
2709
+ getWidth: function() {
2710
+ return this.getDimensions().width;
2711
+ },
2712
+
2713
+ getHeight: function() {
2714
+ return this.getDimensions().height;
2715
+ },
2716
+
2717
+ getScrollOffsets: function() {
2718
+ return Element._returnOffset(
2719
+ window.pageXOffset || document.documentElement.scrollLeft || document.body.scrollLeft,
2720
+ window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop);
2721
+ }
2722
+ };
2723
+ /* Portions of the Selector class are derived from Jack Slocum's DomQuery,
2724
+ * part of YUI-Ext version 0.40, distributed under the terms of an MIT-style
2725
+ * license. Please see http://www.yui-ext.com/ for more information. */
2726
+
2727
+ var Selector = Class.create({
2728
+ initialize: function(expression) {
2729
+ this.expression = expression.strip();
2730
+
2731
+ if (this.shouldUseSelectorsAPI()) {
2732
+ this.mode = 'selectorsAPI';
2733
+ } else if (this.shouldUseXPath()) {
2734
+ this.mode = 'xpath';
2735
+ this.compileXPathMatcher();
2736
+ } else {
2737
+ this.mode = "normal";
2738
+ this.compileMatcher();
2739
+ }
2740
+
2741
+ },
2742
+
2743
+ shouldUseXPath: function() {
2744
+ if (!Prototype.BrowserFeatures.XPath) return false;
2745
+
2746
+ var e = this.expression;
2747
+
2748
+ // Safari 3 chokes on :*-of-type and :empty
2749
+ if (Prototype.Browser.WebKit &&
2750
+ (e.include("-of-type") || e.include(":empty")))
2751
+ return false;
2752
+
2753
+ // XPath can't do namespaced attributes, nor can it read
2754
+ // the "checked" property from DOM nodes
2755
+ if ((/(\[[\w-]*?:|:checked)/).test(e))
2756
+ return false;
2757
+
2758
+ return true;
2759
+ },
2760
+
2761
+ shouldUseSelectorsAPI: function() {
2762
+ if (!Prototype.BrowserFeatures.SelectorsAPI) return false;
2763
+
2764
+ if (!Selector._div) Selector._div = new Element('div');
2765
+
2766
+ // Make sure the browser treats the selector as valid. Test on an
2767
+ // isolated element to minimize cost of this check.
2768
+ try {
2769
+ Selector._div.querySelector(this.expression);
2770
+ } catch(e) {
2771
+ return false;
2772
+ }
2773
+
2774
+ return true;
2775
+ },
2776
+
2777
+ compileMatcher: function() {
2778
+ var e = this.expression, ps = Selector.patterns, h = Selector.handlers,
2779
+ c = Selector.criteria, le, p, m;
2780
+
2781
+ if (Selector._cache[e]) {
2782
+ this.matcher = Selector._cache[e];
2783
+ return;
2784
+ }
2785
+
2786
+ this.matcher = ["this.matcher = function(root) {",
2787
+ "var r = root, h = Selector.handlers, c = false, n;"];
2788
+
2789
+ while (e && le != e && (/\S/).test(e)) {
2790
+ le = e;
2791
+ for (var i in ps) {
2792
+ p = ps[i];
2793
+ if (m = e.match(p)) {
2794
+ this.matcher.push(Object.isFunction(c[i]) ? c[i](m) :
2795
+ new Template(c[i]).evaluate(m));
2796
+ e = e.replace(m[0], '');
2797
+ break;
2798
+ }
2799
+ }
2800
+ }
2801
+
2802
+ this.matcher.push("return h.unique(n);\n}");
2803
+ eval(this.matcher.join('\n'));
2804
+ Selector._cache[this.expression] = this.matcher;
2805
+ },
2806
+
2807
+ compileXPathMatcher: function() {
2808
+ var e = this.expression, ps = Selector.patterns,
2809
+ x = Selector.xpath, le, m;
2810
+
2811
+ if (Selector._cache[e]) {
2812
+ this.xpath = Selector._cache[e]; return;
2813
+ }
2814
+
2815
+ this.matcher = ['.//*'];
2816
+ while (e && le != e && (/\S/).test(e)) {
2817
+ le = e;
2818
+ for (var i in ps) {
2819
+ if (m = e.match(ps[i])) {
2820
+ this.matcher.push(Object.isFunction(x[i]) ? x[i](m) :
2821
+ new Template(x[i]).evaluate(m));
2822
+ e = e.replace(m[0], '');
2823
+ break;
2824
+ }
2825
+ }
2826
+ }
2827
+
2828
+ this.xpath = this.matcher.join('');
2829
+ Selector._cache[this.expression] = this.xpath;
2830
+ },
2831
+
2832
+ findElements: function(root) {
2833
+ root = root || document;
2834
+ var e = this.expression, results;
2835
+
2836
+ switch (this.mode) {
2837
+ case 'selectorsAPI':
2838
+ // querySelectorAll queries document-wide, then filters to descendants
2839
+ // of the context element. That's not what we want.
2840
+ // Add an explicit context to the selector if necessary.
2841
+ if (root !== document) {
2842
+ var oldId = root.id, id = $(root).identify();
2843
+ e = "#" + id + " " + e;
2844
+ }
2845
+
2846
+ results = $A(root.querySelectorAll(e)).map(Element.extend);
2847
+ root.id = oldId;
2848
+
2849
+ return results;
2850
+ case 'xpath':
2851
+ return document._getElementsByXPath(this.xpath, root);
2852
+ default:
2853
+ return this.matcher(root);
2854
+ }
2855
+ },
2856
+
2857
+ match: function(element) {
2858
+ this.tokens = [];
2859
+
2860
+ var e = this.expression, ps = Selector.patterns, as = Selector.assertions;
2861
+ var le, p, m;
2862
+
2863
+ while (e && le !== e && (/\S/).test(e)) {
2864
+ le = e;
2865
+ for (var i in ps) {
2866
+ p = ps[i];
2867
+ if (m = e.match(p)) {
2868
+ // use the Selector.assertions methods unless the selector
2869
+ // is too complex.
2870
+ if (as[i]) {
2871
+ this.tokens.push([i, Object.clone(m)]);
2872
+ e = e.replace(m[0], '');
2873
+ } else {
2874
+ // reluctantly do a document-wide search
2875
+ // and look for a match in the array
2876
+ return this.findElements(document).include(element);
2877
+ }
2878
+ }
2879
+ }
2880
+ }
2881
+
2882
+ var match = true, name, matches;
2883
+ for (var i = 0, token; token = this.tokens[i]; i++) {
2884
+ name = token[0], matches = token[1];
2885
+ if (!Selector.assertions[name](element, matches)) {
2886
+ match = false; break;
2887
+ }
2888
+ }
2889
+
2890
+ return match;
2891
+ },
2892
+
2893
+ toString: function() {
2894
+ return this.expression;
2895
+ },
2896
+
2897
+ inspect: function() {
2898
+ return "#<Selector:" + this.expression.inspect() + ">";
2899
+ }
2900
+ });
2901
+
2902
+ Object.extend(Selector, {
2903
+ _cache: { },
2904
+
2905
+ xpath: {
2906
+ descendant: "//*",
2907
+ child: "/*",
2908
+ adjacent: "/following-sibling::*[1]",
2909
+ laterSibling: '/following-sibling::*',
2910
+ tagName: function(m) {
2911
+ if (m[1] == '*') return '';
2912
+ return "[local-name()='" + m[1].toLowerCase() +
2913
+ "' or local-name()='" + m[1].toUpperCase() + "']";
2914
+ },
2915
+ className: "[contains(concat(' ', @class, ' '), ' #{1} ')]",
2916
+ id: "[@id='#{1}']",
2917
+ attrPresence: function(m) {
2918
+ m[1] = m[1].toLowerCase();
2919
+ return new Template("[@#{1}]").evaluate(m);
2920
+ },
2921
+ attr: function(m) {
2922
+ m[1] = m[1].toLowerCase();
2923
+ m[3] = m[5] || m[6];
2924
+ return new Template(Selector.xpath.operators[m[2]]).evaluate(m);
2925
+ },
2926
+ pseudo: function(m) {
2927
+ var h = Selector.xpath.pseudos[m[1]];
2928
+ if (!h) return '';
2929
+ if (Object.isFunction(h)) return h(m);
2930
+ return new Template(Selector.xpath.pseudos[m[1]]).evaluate(m);
2931
+ },
2932
+ operators: {
2933
+ '=': "[@#{1}='#{3}']",
2934
+ '!=': "[@#{1}!='#{3}']",
2935
+ '^=': "[starts-with(@#{1}, '#{3}')]",
2936
+ '$=': "[substring(@#{1}, (string-length(@#{1}) - string-length('#{3}') + 1))='#{3}']",
2937
+ '*=': "[contains(@#{1}, '#{3}')]",
2938
+ '~=': "[contains(concat(' ', @#{1}, ' '), ' #{3} ')]",
2939
+ '|=': "[contains(concat('-', @#{1}, '-'), '-#{3}-')]"
2940
+ },
2941
+ pseudos: {
2942
+ 'first-child': '[not(preceding-sibling::*)]',
2943
+ 'last-child': '[not(following-sibling::*)]',
2944
+ 'only-child': '[not(preceding-sibling::* or following-sibling::*)]',
2945
+ 'empty': "[count(*) = 0 and (count(text()) = 0)]",
2946
+ 'checked': "[@checked]",
2947
+ 'disabled': "[(@disabled) and (@type!='hidden')]",
2948
+ 'enabled': "[not(@disabled) and (@type!='hidden')]",
2949
+ 'not': function(m) {
2950
+ var e = m[6], p = Selector.patterns,
2951
+ x = Selector.xpath, le, v;
2952
+
2953
+ var exclusion = [];
2954
+ while (e && le != e && (/\S/).test(e)) {
2955
+ le = e;
2956
+ for (var i in p) {
2957
+ if (m = e.match(p[i])) {
2958
+ v = Object.isFunction(x[i]) ? x[i](m) : new Template(x[i]).evaluate(m);
2959
+ exclusion.push("(" + v.substring(1, v.length - 1) + ")");
2960
+ e = e.replace(m[0], '');
2961
+ break;
2962
+ }
2963
+ }
2964
+ }
2965
+ return "[not(" + exclusion.join(" and ") + ")]";
2966
+ },
2967
+ 'nth-child': function(m) {
2968
+ return Selector.xpath.pseudos.nth("(count(./preceding-sibling::*) + 1) ", m);
2969
+ },
2970
+ 'nth-last-child': function(m) {
2971
+ return Selector.xpath.pseudos.nth("(count(./following-sibling::*) + 1) ", m);
2972
+ },
2973
+ 'nth-of-type': function(m) {
2974
+ return Selector.xpath.pseudos.nth("position() ", m);
2975
+ },
2976
+ 'nth-last-of-type': function(m) {
2977
+ return Selector.xpath.pseudos.nth("(last() + 1 - position()) ", m);
2978
+ },
2979
+ 'first-of-type': function(m) {
2980
+ m[6] = "1"; return Selector.xpath.pseudos['nth-of-type'](m);
2981
+ },
2982
+ 'last-of-type': function(m) {
2983
+ m[6] = "1"; return Selector.xpath.pseudos['nth-last-of-type'](m);
2984
+ },
2985
+ 'only-of-type': function(m) {
2986
+ var p = Selector.xpath.pseudos; return p['first-of-type'](m) + p['last-of-type'](m);
2987
+ },
2988
+ nth: function(fragment, m) {
2989
+ var mm, formula = m[6], predicate;
2990
+ if (formula == 'even') formula = '2n+0';
2991
+ if (formula == 'odd') formula = '2n+1';
2992
+ if (mm = formula.match(/^(\d+)$/)) // digit only
2993
+ return '[' + fragment + "= " + mm[1] + ']';
2994
+ if (mm = formula.match(/^(-?\d*)?n(([+-])(\d+))?/)) { // an+b
2995
+ if (mm[1] == "-") mm[1] = -1;
2996
+ var a = mm[1] ? Number(mm[1]) : 1;
2997
+ var b = mm[2] ? Number(mm[2]) : 0;
2998
+ predicate = "[((#{fragment} - #{b}) mod #{a} = 0) and " +
2999
+ "((#{fragment} - #{b}) div #{a} >= 0)]";
3000
+ return new Template(predicate).evaluate({
3001
+ fragment: fragment, a: a, b: b });
3002
+ }
3003
+ }
3004
+ }
3005
+ },
3006
+
3007
+ criteria: {
3008
+ tagName: 'n = h.tagName(n, r, "#{1}", c); c = false;',
3009
+ className: 'n = h.className(n, r, "#{1}", c); c = false;',
3010
+ id: 'n = h.id(n, r, "#{1}", c); c = false;',
3011
+ attrPresence: 'n = h.attrPresence(n, r, "#{1}", c); c = false;',
3012
+ attr: function(m) {
3013
+ m[3] = (m[5] || m[6]);
3014
+ return new Template('n = h.attr(n, r, "#{1}", "#{3}", "#{2}", c); c = false;').evaluate(m);
3015
+ },
3016
+ pseudo: function(m) {
3017
+ if (m[6]) m[6] = m[6].replace(/"/g, '\\"');
3018
+ return new Template('n = h.pseudo(n, "#{1}", "#{6}", r, c); c = false;').evaluate(m);
3019
+ },
3020
+ descendant: 'c = "descendant";',
3021
+ child: 'c = "child";',
3022
+ adjacent: 'c = "adjacent";',
3023
+ laterSibling: 'c = "laterSibling";'
3024
+ },
3025
+
3026
+ patterns: {
3027
+ // combinators must be listed first
3028
+ // (and descendant needs to be last combinator)
3029
+ laterSibling: /^\s*~\s*/,
3030
+ child: /^\s*>\s*/,
3031
+ adjacent: /^\s*\+\s*/,
3032
+ descendant: /^\s/,
3033
+
3034
+ // selectors follow
3035
+ tagName: /^\s*(\*|[\w\-]+)(\b|$)?/,
3036
+ id: /^#([\w\-\*]+)(\b|$)/,
3037
+ className: /^\.([\w\-\*]+)(\b|$)/,
3038
+ pseudo:
3039
+ /^:((first|last|nth|nth-last|only)(-child|-of-type)|empty|checked|(en|dis)abled|not)(\((.*?)\))?(\b|$|(?=\s|[:+~>]))/,
3040
+ attrPresence: /^\[((?:[\w]+:)?[\w]+)\]/,
3041
+ attr: /\[((?:[\w-]*:)?[\w-]+)\s*(?:([!^$*~|]?=)\s*((['"])([^\4]*?)\4|([^'"][^\]]*?)))?\]/
3042
+ },
3043
+
3044
+ // for Selector.match and Element#match
3045
+ assertions: {
3046
+ tagName: function(element, matches) {
3047
+ return matches[1].toUpperCase() == element.tagName.toUpperCase();
3048
+ },
3049
+
3050
+ className: function(element, matches) {
3051
+ return Element.hasClassName(element, matches[1]);
3052
+ },
3053
+
3054
+ id: function(element, matches) {
3055
+ return element.id === matches[1];
3056
+ },
3057
+
3058
+ attrPresence: function(element, matches) {
3059
+ return Element.hasAttribute(element, matches[1]);
3060
+ },
3061
+
3062
+ attr: function(element, matches) {
3063
+ var nodeValue = Element.readAttribute(element, matches[1]);
3064
+ return nodeValue && Selector.operators[matches[2]](nodeValue, matches[5] || matches[6]);
3065
+ }
3066
+ },
3067
+
3068
+ handlers: {
3069
+ // UTILITY FUNCTIONS
3070
+ // joins two collections
3071
+ concat: function(a, b) {
3072
+ for (var i = 0, node; node = b[i]; i++)
3073
+ a.push(node);
3074
+ return a;
3075
+ },
3076
+
3077
+ // marks an array of nodes for counting
3078
+ mark: function(nodes) {
3079
+ var _true = Prototype.emptyFunction;
3080
+ for (var i = 0, node; node = nodes[i]; i++)
3081
+ node._countedByPrototype = _true;
3082
+ return nodes;
3083
+ },
3084
+
3085
+ unmark: function(nodes) {
3086
+ for (var i = 0, node; node = nodes[i]; i++)
3087
+ node._countedByPrototype = undefined;
3088
+ return nodes;
3089
+ },
3090
+
3091
+ // mark each child node with its position (for nth calls)
3092
+ // "ofType" flag indicates whether we're indexing for nth-of-type
3093
+ // rather than nth-child
3094
+ index: function(parentNode, reverse, ofType) {
3095
+ parentNode._countedByPrototype = Prototype.emptyFunction;
3096
+ if (reverse) {
3097
+ for (var nodes = parentNode.childNodes, i = nodes.length - 1, j = 1; i >= 0; i--) {
3098
+ var node = nodes[i];
3099
+ if (node.nodeType == 1 && (!ofType || node._countedByPrototype)) node.nodeIndex = j++;
3100
+ }
3101
+ } else {
3102
+ for (var i = 0, j = 1, nodes = parentNode.childNodes; node = nodes[i]; i++)
3103
+ if (node.nodeType == 1 && (!ofType || node._countedByPrototype)) node.nodeIndex = j++;
3104
+ }
3105
+ },
3106
+
3107
+ // filters out duplicates and extends all nodes
3108
+ unique: function(nodes) {
3109
+ if (nodes.length == 0) return nodes;
3110
+ var results = [], n;
3111
+ for (var i = 0, l = nodes.length; i < l; i++)
3112
+ if (!(n = nodes[i])._countedByPrototype) {
3113
+ n._countedByPrototype = Prototype.emptyFunction;
3114
+ results.push(Element.extend(n));
3115
+ }
3116
+ return Selector.handlers.unmark(results);
3117
+ },
3118
+
3119
+ // COMBINATOR FUNCTIONS
3120
+ descendant: function(nodes) {
3121
+ var h = Selector.handlers;
3122
+ for (var i = 0, results = [], node; node = nodes[i]; i++)
3123
+ h.concat(results, node.getElementsByTagName('*'));
3124
+ return results;
3125
+ },
3126
+
3127
+ child: function(nodes) {
3128
+ var h = Selector.handlers;
3129
+ for (var i = 0, results = [], node; node = nodes[i]; i++) {
3130
+ for (var j = 0, child; child = node.childNodes[j]; j++)
3131
+ if (child.nodeType == 1 && child.tagName != '!') results.push(child);
3132
+ }
3133
+ return results;
3134
+ },
3135
+
3136
+ adjacent: function(nodes) {
3137
+ for (var i = 0, results = [], node; node = nodes[i]; i++) {
3138
+ var next = this.nextElementSibling(node);
3139
+ if (next) results.push(next);
3140
+ }
3141
+ return results;
3142
+ },
3143
+
3144
+ laterSibling: function(nodes) {
3145
+ var h = Selector.handlers;
3146
+ for (var i = 0, results = [], node; node = nodes[i]; i++)
3147
+ h.concat(results, Element.nextSiblings(node));
3148
+ return results;
3149
+ },
3150
+
3151
+ nextElementSibling: function(node) {
3152
+ while (node = node.nextSibling)
3153
+ if (node.nodeType == 1) return node;
3154
+ return null;
3155
+ },
3156
+
3157
+ previousElementSibling: function(node) {
3158
+ while (node = node.previousSibling)
3159
+ if (node.nodeType == 1) return node;
3160
+ return null;
3161
+ },
3162
+
3163
+ // TOKEN FUNCTIONS
3164
+ tagName: function(nodes, root, tagName, combinator) {
3165
+ var uTagName = tagName.toUpperCase();
3166
+ var results = [], h = Selector.handlers;
3167
+ if (nodes) {
3168
+ if (combinator) {
3169
+ // fastlane for ordinary descendant combinators
3170
+ if (combinator == "descendant") {
3171
+ for (var i = 0, node; node = nodes[i]; i++)
3172
+ h.concat(results, node.getElementsByTagName(tagName));
3173
+ return results;
3174
+ } else nodes = this[combinator](nodes);
3175
+ if (tagName == "*") return nodes;
3176
+ }
3177
+ for (var i = 0, node; node = nodes[i]; i++)
3178
+ if (node.tagName.toUpperCase() === uTagName) results.push(node);
3179
+ return results;
3180
+ } else return root.getElementsByTagName(tagName);
3181
+ },
3182
+
3183
+ id: function(nodes, root, id, combinator) {
3184
+ var targetNode = $(id), h = Selector.handlers;
3185
+ if (!targetNode) return [];
3186
+ if (!nodes && root == document) return [targetNode];
3187
+ if (nodes) {
3188
+ if (combinator) {
3189
+ if (combinator == 'child') {
3190
+ for (var i = 0, node; node = nodes[i]; i++)
3191
+ if (targetNode.parentNode == node) return [targetNode];
3192
+ } else if (combinator == 'descendant') {
3193
+ for (var i = 0, node; node = nodes[i]; i++)
3194
+ if (Element.descendantOf(targetNode, node)) return [targetNode];
3195
+ } else if (combinator == 'adjacent') {
3196
+ for (var i = 0, node; node = nodes[i]; i++)
3197
+ if (Selector.handlers.previousElementSibling(targetNode) == node)
3198
+ return [targetNode];
3199
+ } else nodes = h[combinator](nodes);
3200
+ }
3201
+ for (var i = 0, node; node = nodes[i]; i++)
3202
+ if (node == targetNode) return [targetNode];
3203
+ return [];
3204
+ }
3205
+ return (targetNode && Element.descendantOf(targetNode, root)) ? [targetNode] : [];
3206
+ },
3207
+
3208
+ className: function(nodes, root, className, combinator) {
3209
+ if (nodes && combinator) nodes = this[combinator](nodes);
3210
+ return Selector.handlers.byClassName(nodes, root, className);
3211
+ },
3212
+
3213
+ byClassName: function(nodes, root, className) {
3214
+ if (!nodes) nodes = Selector.handlers.descendant([root]);
3215
+ var needle = ' ' + className + ' ';
3216
+ for (var i = 0, results = [], node, nodeClassName; node = nodes[i]; i++) {
3217
+ nodeClassName = node.className;
3218
+ if (nodeClassName.length == 0) continue;
3219
+ if (nodeClassName == className || (' ' + nodeClassName + ' ').include(needle))
3220
+ results.push(node);
3221
+ }
3222
+ return results;
3223
+ },
3224
+
3225
+ attrPresence: function(nodes, root, attr, combinator) {
3226
+ if (!nodes) nodes = root.getElementsByTagName("*");
3227
+ if (nodes && combinator) nodes = this[combinator](nodes);
3228
+ var results = [];
3229
+ for (var i = 0, node; node = nodes[i]; i++)
3230
+ if (Element.hasAttribute(node, attr)) results.push(node);
3231
+ return results;
3232
+ },
3233
+
3234
+ attr: function(nodes, root, attr, value, operator, combinator) {
3235
+ if (!nodes) nodes = root.getElementsByTagName("*");
3236
+ if (nodes && combinator) nodes = this[combinator](nodes);
3237
+ var handler = Selector.operators[operator], results = [];
3238
+ for (var i = 0, node; node = nodes[i]; i++) {
3239
+ var nodeValue = Element.readAttribute(node, attr);
3240
+ if (nodeValue === null) continue;
3241
+ if (handler(nodeValue, value)) results.push(node);
3242
+ }
3243
+ return results;
3244
+ },
3245
+
3246
+ pseudo: function(nodes, name, value, root, combinator) {
3247
+ if (nodes && combinator) nodes = this[combinator](nodes);
3248
+ if (!nodes) nodes = root.getElementsByTagName("*");
3249
+ return Selector.pseudos[name](nodes, value, root);
3250
+ }
3251
+ },
3252
+
3253
+ pseudos: {
3254
+ 'first-child': function(nodes, value, root) {
3255
+ for (var i = 0, results = [], node; node = nodes[i]; i++) {
3256
+ if (Selector.handlers.previousElementSibling(node)) continue;
3257
+ results.push(node);
3258
+ }
3259
+ return results;
3260
+ },
3261
+ 'last-child': function(nodes, value, root) {
3262
+ for (var i = 0, results = [], node; node = nodes[i]; i++) {
3263
+ if (Selector.handlers.nextElementSibling(node)) continue;
3264
+ results.push(node);
3265
+ }
3266
+ return results;
3267
+ },
3268
+ 'only-child': function(nodes, value, root) {
3269
+ var h = Selector.handlers;
3270
+ for (var i = 0, results = [], node; node = nodes[i]; i++)
3271
+ if (!h.previousElementSibling(node) && !h.nextElementSibling(node))
3272
+ results.push(node);
3273
+ return results;
3274
+ },
3275
+ 'nth-child': function(nodes, formula, root) {
3276
+ return Selector.pseudos.nth(nodes, formula, root);
3277
+ },
3278
+ 'nth-last-child': function(nodes, formula, root) {
3279
+ return Selector.pseudos.nth(nodes, formula, root, true);
3280
+ },
3281
+ 'nth-of-type': function(nodes, formula, root) {
3282
+ return Selector.pseudos.nth(nodes, formula, root, false, true);
3283
+ },
3284
+ 'nth-last-of-type': function(nodes, formula, root) {
3285
+ return Selector.pseudos.nth(nodes, formula, root, true, true);
3286
+ },
3287
+ 'first-of-type': function(nodes, formula, root) {
3288
+ return Selector.pseudos.nth(nodes, "1", root, false, true);
3289
+ },
3290
+ 'last-of-type': function(nodes, formula, root) {
3291
+ return Selector.pseudos.nth(nodes, "1", root, true, true);
3292
+ },
3293
+ 'only-of-type': function(nodes, formula, root) {
3294
+ var p = Selector.pseudos;
3295
+ return p['last-of-type'](p['first-of-type'](nodes, formula, root), formula, root);
3296
+ },
3297
+
3298
+ // handles the an+b logic
3299
+ getIndices: function(a, b, total) {
3300
+ if (a == 0) return b > 0 ? [b] : [];
3301
+ return $R(1, total).inject([], function(memo, i) {
3302
+ if (0 == (i - b) % a && (i - b) / a >= 0) memo.push(i);
3303
+ return memo;
3304
+ });
3305
+ },
3306
+
3307
+ // handles nth(-last)-child, nth(-last)-of-type, and (first|last)-of-type
3308
+ nth: function(nodes, formula, root, reverse, ofType) {
3309
+ if (nodes.length == 0) return [];
3310
+ if (formula == 'even') formula = '2n+0';
3311
+ if (formula == 'odd') formula = '2n+1';
3312
+ var h = Selector.handlers, results = [], indexed = [], m;
3313
+ h.mark(nodes);
3314
+ for (var i = 0, node; node = nodes[i]; i++) {
3315
+ if (!node.parentNode._countedByPrototype) {
3316
+ h.index(node.parentNode, reverse, ofType);
3317
+ indexed.push(node.parentNode);
3318
+ }
3319
+ }
3320
+ if (formula.match(/^\d+$/)) { // just a number
3321
+ formula = Number(formula);
3322
+ for (var i = 0, node; node = nodes[i]; i++)
3323
+ if (node.nodeIndex == formula) results.push(node);
3324
+ } else if (m = formula.match(/^(-?\d*)?n(([+-])(\d+))?/)) { // an+b
3325
+ if (m[1] == "-") m[1] = -1;
3326
+ var a = m[1] ? Number(m[1]) : 1;
3327
+ var b = m[2] ? Number(m[2]) : 0;
3328
+ var indices = Selector.pseudos.getIndices(a, b, nodes.length);
3329
+ for (var i = 0, node, l = indices.length; node = nodes[i]; i++) {
3330
+ for (var j = 0; j < l; j++)
3331
+ if (node.nodeIndex == indices[j]) results.push(node);
3332
+ }
3333
+ }
3334
+ h.unmark(nodes);
3335
+ h.unmark(indexed);
3336
+ return results;
3337
+ },
3338
+
3339
+ 'empty': function(nodes, value, root) {
3340
+ for (var i = 0, results = [], node; node = nodes[i]; i++) {
3341
+ // IE treats comments as element nodes
3342
+ if (node.tagName == '!' || node.firstChild) continue;
3343
+ results.push(node);
3344
+ }
3345
+ return results;
3346
+ },
3347
+
3348
+ 'not': function(nodes, selector, root) {
3349
+ var h = Selector.handlers, selectorType, m;
3350
+ var exclusions = new Selector(selector).findElements(root);
3351
+ h.mark(exclusions);
3352
+ for (var i = 0, results = [], node; node = nodes[i]; i++)
3353
+ if (!node._countedByPrototype) results.push(node);
3354
+ h.unmark(exclusions);
3355
+ return results;
3356
+ },
3357
+
3358
+ 'enabled': function(nodes, value, root) {
3359
+ for (var i = 0, results = [], node; node = nodes[i]; i++)
3360
+ if (!node.disabled && (!node.type || node.type !== 'hidden'))
3361
+ results.push(node);
3362
+ return results;
3363
+ },
3364
+
3365
+ 'disabled': function(nodes, value, root) {
3366
+ for (var i = 0, results = [], node; node = nodes[i]; i++)
3367
+ if (node.disabled) results.push(node);
3368
+ return results;
3369
+ },
3370
+
3371
+ 'checked': function(nodes, value, root) {
3372
+ for (var i = 0, results = [], node; node = nodes[i]; i++)
3373
+ if (node.checked) results.push(node);
3374
+ return results;
3375
+ }
3376
+ },
3377
+
3378
+ operators: {
3379
+ '=': function(nv, v) { return nv == v; },
3380
+ '!=': function(nv, v) { return nv != v; },
3381
+ '^=': function(nv, v) { return nv == v || nv && nv.startsWith(v); },
3382
+ '$=': function(nv, v) { return nv == v || nv && nv.endsWith(v); },
3383
+ '*=': function(nv, v) { return nv == v || nv && nv.include(v); },
3384
+ '$=': function(nv, v) { return nv.endsWith(v); },
3385
+ '*=': function(nv, v) { return nv.include(v); },
3386
+ '~=': function(nv, v) { return (' ' + nv + ' ').include(' ' + v + ' '); },
3387
+ '|=': function(nv, v) { return ('-' + (nv || "").toUpperCase() +
3388
+ '-').include('-' + (v || "").toUpperCase() + '-'); }
3389
+ },
3390
+
3391
+ split: function(expression) {
3392
+ var expressions = [];
3393
+ expression.scan(/(([\w#:.~>+()\s-]+|\*|\[.*?\])+)\s*(,|$)/, function(m) {
3394
+ expressions.push(m[1].strip());
3395
+ });
3396
+ return expressions;
3397
+ },
3398
+
3399
+ matchElements: function(elements, expression) {
3400
+ var matches = $$(expression), h = Selector.handlers;
3401
+ h.mark(matches);
3402
+ for (var i = 0, results = [], element; element = elements[i]; i++)
3403
+ if (element._countedByPrototype) results.push(element);
3404
+ h.unmark(matches);
3405
+ return results;
3406
+ },
3407
+
3408
+ findElement: function(elements, expression, index) {
3409
+ if (Object.isNumber(expression)) {
3410
+ index = expression; expression = false;
3411
+ }
3412
+ return Selector.matchElements(elements, expression || '*')[index || 0];
3413
+ },
3414
+
3415
+ findChildElements: function(element, expressions) {
3416
+ expressions = Selector.split(expressions.join(','));
3417
+ var results = [], h = Selector.handlers;
3418
+ for (var i = 0, l = expressions.length, selector; i < l; i++) {
3419
+ selector = new Selector(expressions[i].strip());
3420
+ h.concat(results, selector.findElements(element));
3421
+ }
3422
+ return (l > 1) ? h.unique(results) : results;
3423
+ }
3424
+ });
3425
+
3426
+ if (Prototype.Browser.IE) {
3427
+ Object.extend(Selector.handlers, {
3428
+ // IE returns comment nodes on getElementsByTagName("*").
3429
+ // Filter them out.
3430
+ concat: function(a, b) {
3431
+ for (var i = 0, node; node = b[i]; i++)
3432
+ if (node.tagName !== "!") a.push(node);
3433
+ return a;
3434
+ },
3435
+
3436
+ // IE improperly serializes _countedByPrototype in (inner|outer)HTML.
3437
+ unmark: function(nodes) {
3438
+ for (var i = 0, node; node = nodes[i]; i++)
3439
+ node.removeAttribute('_countedByPrototype');
3440
+ return nodes;
3441
+ }
3442
+ });
3443
+ }
3444
+
3445
+ function $$() {
3446
+ return Selector.findChildElements(document, $A(arguments));
3447
+ }
3448
+ var Form = {
3449
+ reset: function(form) {
3450
+ $(form).reset();
3451
+ return form;
3452
+ },
3453
+
3454
+ serializeElements: function(elements, options) {
3455
+ if (typeof options != 'object') options = { hash: !!options };
3456
+ else if (Object.isUndefined(options.hash)) options.hash = true;
3457
+ var key, value, submitted = false, submit = options.submit;
3458
+
3459
+ var data = elements.inject({ }, function(result, element) {
3460
+ if (!element.disabled && element.name) {
3461
+ key = element.name; value = $(element).getValue();
3462
+ if (value != null && element.type != 'file' && (element.type != 'submit' || (!submitted &&
3463
+ submit !== false && (!submit || key == submit) && (submitted = true)))) {
3464
+ if (key in result) {
3465
+ // a key is already present; construct an array of values
3466
+ if (!Object.isArray(result[key])) result[key] = [result[key]];
3467
+ result[key].push(value);
3468
+ }
3469
+ else result[key] = value;
3470
+ }
3471
+ }
3472
+ return result;
3473
+ });
3474
+
3475
+ return options.hash ? data : Object.toQueryString(data);
3476
+ }
3477
+ };
3478
+
3479
+ Form.Methods = {
3480
+ serialize: function(form, options) {
3481
+ return Form.serializeElements(Form.getElements(form), options);
3482
+ },
3483
+
3484
+ getElements: function(form) {
3485
+ return $A($(form).getElementsByTagName('*')).inject([],
3486
+ function(elements, child) {
3487
+ if (Form.Element.Serializers[child.tagName.toLowerCase()])
3488
+ elements.push(Element.extend(child));
3489
+ return elements;
3490
+ }
3491
+ );
3492
+ },
3493
+
3494
+ getInputs: function(form, typeName, name) {
3495
+ form = $(form);
3496
+ var inputs = form.getElementsByTagName('input');
3497
+
3498
+ if (!typeName && !name) return $A(inputs).map(Element.extend);
3499
+
3500
+ for (var i = 0, matchingInputs = [], length = inputs.length; i < length; i++) {
3501
+ var input = inputs[i];
3502
+ if ((typeName && input.type != typeName) || (name && input.name != name))
3503
+ continue;
3504
+ matchingInputs.push(Element.extend(input));
3505
+ }
3506
+
3507
+ return matchingInputs;
3508
+ },
3509
+
3510
+ disable: function(form) {
3511
+ form = $(form);
3512
+ Form.getElements(form).invoke('disable');
3513
+ return form;
3514
+ },
3515
+
3516
+ enable: function(form) {
3517
+ form = $(form);
3518
+ Form.getElements(form).invoke('enable');
3519
+ return form;
3520
+ },
3521
+
3522
+ findFirstElement: function(form) {
3523
+ var elements = $(form).getElements().findAll(function(element) {
3524
+ return 'hidden' != element.type && !element.disabled;
3525
+ });
3526
+ var firstByIndex = elements.findAll(function(element) {
3527
+ return element.hasAttribute('tabIndex') && element.tabIndex >= 0;
3528
+ }).sortBy(function(element) { return element.tabIndex }).first();
3529
+
3530
+ return firstByIndex ? firstByIndex : elements.find(function(element) {
3531
+ return ['input', 'select', 'textarea'].include(element.tagName.toLowerCase());
3532
+ });
3533
+ },
3534
+
3535
+ focusFirstElement: function(form) {
3536
+ form = $(form);
3537
+ form.findFirstElement().activate();
3538
+ return form;
3539
+ },
3540
+
3541
+ request: function(form, options) {
3542
+ form = $(form), options = Object.clone(options || { });
3543
+
3544
+ var params = options.parameters, action = form.readAttribute('action') || '';
3545
+ if (action.blank()) action = window.location.href;
3546
+ options.parameters = form.serialize(true);
3547
+
3548
+ if (params) {
3549
+ if (Object.isString(params)) params = params.toQueryParams();
3550
+ Object.extend(options.parameters, params);
3551
+ }
3552
+
3553
+ if (form.hasAttribute('method') && !options.method)
3554
+ options.method = form.method;
3555
+
3556
+ return new Ajax.Request(action, options);
3557
+ }
3558
+ };
3559
+
3560
+ /*--------------------------------------------------------------------------*/
3561
+
3562
+ Form.Element = {
3563
+ focus: function(element) {
3564
+ $(element).focus();
3565
+ return element;
3566
+ },
3567
+
3568
+ select: function(element) {
3569
+ $(element).select();
3570
+ return element;
3571
+ }
3572
+ };
3573
+
3574
+ Form.Element.Methods = {
3575
+ serialize: function(element) {
3576
+ element = $(element);
3577
+ if (!element.disabled && element.name) {
3578
+ var value = element.getValue();
3579
+ if (value != undefined) {
3580
+ var pair = { };
3581
+ pair[element.name] = value;
3582
+ return Object.toQueryString(pair);
3583
+ }
3584
+ }
3585
+ return '';
3586
+ },
3587
+
3588
+ getValue: function(element) {
3589
+ element = $(element);
3590
+ var method = element.tagName.toLowerCase();
3591
+ return Form.Element.Serializers[method](element);
3592
+ },
3593
+
3594
+ setValue: function(element, value) {
3595
+ element = $(element);
3596
+ var method = element.tagName.toLowerCase();
3597
+ Form.Element.Serializers[method](element, value);
3598
+ return element;
3599
+ },
3600
+
3601
+ clear: function(element) {
3602
+ $(element).value = '';
3603
+ return element;
3604
+ },
3605
+
3606
+ present: function(element) {
3607
+ return $(element).value != '';
3608
+ },
3609
+
3610
+ activate: function(element) {
3611
+ element = $(element);
3612
+ try {
3613
+ element.focus();
3614
+ if (element.select && (element.tagName.toLowerCase() != 'input' ||
3615
+ !['button', 'reset', 'submit'].include(element.type)))
3616
+ element.select();
3617
+ } catch (e) { }
3618
+ return element;
3619
+ },
3620
+
3621
+ disable: function(element) {
3622
+ element = $(element);
3623
+ element.disabled = true;
3624
+ return element;
3625
+ },
3626
+
3627
+ enable: function(element) {
3628
+ element = $(element);
3629
+ element.disabled = false;
3630
+ return element;
3631
+ }
3632
+ };
3633
+
3634
+ /*--------------------------------------------------------------------------*/
3635
+
3636
+ var Field = Form.Element;
3637
+ var $F = Form.Element.Methods.getValue;
3638
+
3639
+ /*--------------------------------------------------------------------------*/
3640
+
3641
+ Form.Element.Serializers = {
3642
+ input: function(element, value) {
3643
+ switch (element.type.toLowerCase()) {
3644
+ case 'checkbox':
3645
+ case 'radio':
3646
+ return Form.Element.Serializers.inputSelector(element, value);
3647
+ default:
3648
+ return Form.Element.Serializers.textarea(element, value);
3649
+ }
3650
+ },
3651
+
3652
+ inputSelector: function(element, value) {
3653
+ if (Object.isUndefined(value)) return element.checked ? element.value : null;
3654
+ else element.checked = !!value;
3655
+ },
3656
+
3657
+ textarea: function(element, value) {
3658
+ if (Object.isUndefined(value)) return element.value;
3659
+ else element.value = value;
3660
+ },
3661
+
3662
+ select: function(element, value) {
3663
+ if (Object.isUndefined(value))
3664
+ return this[element.type == 'select-one' ?
3665
+ 'selectOne' : 'selectMany'](element);
3666
+ else {
3667
+ var opt, currentValue, single = !Object.isArray(value);
3668
+ for (var i = 0, length = element.length; i < length; i++) {
3669
+ opt = element.options[i];
3670
+ currentValue = this.optionValue(opt);
3671
+ if (single) {
3672
+ if (currentValue == value) {
3673
+ opt.selected = true;
3674
+ return;
3675
+ }
3676
+ }
3677
+ else opt.selected = value.include(currentValue);
3678
+ }
3679
+ }
3680
+ },
3681
+
3682
+ selectOne: function(element) {
3683
+ var index = element.selectedIndex;
3684
+ return index >= 0 ? this.optionValue(element.options[index]) : null;
3685
+ },
3686
+
3687
+ selectMany: function(element) {
3688
+ var values, length = element.length;
3689
+ if (!length) return null;
3690
+
3691
+ for (var i = 0, values = []; i < length; i++) {
3692
+ var opt = element.options[i];
3693
+ if (opt.selected) values.push(this.optionValue(opt));
3694
+ }
3695
+ return values;
3696
+ },
3697
+
3698
+ optionValue: function(opt) {
3699
+ // extend element because hasAttribute may not be native
3700
+ return Element.extend(opt).hasAttribute('value') ? opt.value : opt.text;
3701
+ }
3702
+ };
3703
+
3704
+ /*--------------------------------------------------------------------------*/
3705
+
3706
+ Abstract.TimedObserver = Class.create(PeriodicalExecuter, {
3707
+ initialize: function($super, element, frequency, callback) {
3708
+ $super(callback, frequency);
3709
+ this.element = $(element);
3710
+ this.lastValue = this.getValue();
3711
+ },
3712
+
3713
+ execute: function() {
3714
+ var value = this.getValue();
3715
+ if (Object.isString(this.lastValue) && Object.isString(value) ?
3716
+ this.lastValue != value : String(this.lastValue) != String(value)) {
3717
+ this.callback(this.element, value);
3718
+ this.lastValue = value;
3719
+ }
3720
+ }
3721
+ });
3722
+
3723
+ Form.Element.Observer = Class.create(Abstract.TimedObserver, {
3724
+ getValue: function() {
3725
+ return Form.Element.getValue(this.element);
3726
+ }
3727
+ });
3728
+
3729
+ Form.Observer = Class.create(Abstract.TimedObserver, {
3730
+ getValue: function() {
3731
+ return Form.serialize(this.element);
3732
+ }
3733
+ });
3734
+
3735
+ /*--------------------------------------------------------------------------*/
3736
+
3737
+ Abstract.EventObserver = Class.create({
3738
+ initialize: function(element, callback) {
3739
+ this.element = $(element);
3740
+ this.callback = callback;
3741
+
3742
+ this.lastValue = this.getValue();
3743
+ if (this.element.tagName.toLowerCase() == 'form')
3744
+ this.registerFormCallbacks();
3745
+ else
3746
+ this.registerCallback(this.element);
3747
+ },
3748
+
3749
+ onElementEvent: function() {
3750
+ var value = this.getValue();
3751
+ if (this.lastValue != value) {
3752
+ this.callback(this.element, value);
3753
+ this.lastValue = value;
3754
+ }
3755
+ },
3756
+
3757
+ registerFormCallbacks: function() {
3758
+ Form.getElements(this.element).each(this.registerCallback, this);
3759
+ },
3760
+
3761
+ registerCallback: function(element) {
3762
+ if (element.type) {
3763
+ switch (element.type.toLowerCase()) {
3764
+ case 'checkbox':
3765
+ case 'radio':
3766
+ Event.observe(element, 'click', this.onElementEvent.bind(this));
3767
+ break;
3768
+ default:
3769
+ Event.observe(element, 'change', this.onElementEvent.bind(this));
3770
+ break;
3771
+ }
3772
+ }
3773
+ }
3774
+ });
3775
+
3776
+ Form.Element.EventObserver = Class.create(Abstract.EventObserver, {
3777
+ getValue: function() {
3778
+ return Form.Element.getValue(this.element);
3779
+ }
3780
+ });
3781
+
3782
+ Form.EventObserver = Class.create(Abstract.EventObserver, {
3783
+ getValue: function() {
3784
+ return Form.serialize(this.element);
3785
+ }
3786
+ });
3787
+ if (!window.Event) var Event = { };
3788
+
3789
+ Object.extend(Event, {
3790
+ KEY_BACKSPACE: 8,
3791
+ KEY_TAB: 9,
3792
+ KEY_RETURN: 13,
3793
+ KEY_ESC: 27,
3794
+ KEY_LEFT: 37,
3795
+ KEY_UP: 38,
3796
+ KEY_RIGHT: 39,
3797
+ KEY_DOWN: 40,
3798
+ KEY_DELETE: 46,
3799
+ KEY_HOME: 36,
3800
+ KEY_END: 35,
3801
+ KEY_PAGEUP: 33,
3802
+ KEY_PAGEDOWN: 34,
3803
+ KEY_INSERT: 45,
3804
+
3805
+ cache: { },
3806
+
3807
+ relatedTarget: function(event) {
3808
+ var element;
3809
+ switch(event.type) {
3810
+ case 'mouseover': element = event.fromElement; break;
3811
+ case 'mouseout': element = event.toElement; break;
3812
+ default: return null;
3813
+ }
3814
+ return Element.extend(element);
3815
+ }
3816
+ });
3817
+
3818
+ Event.Methods = (function() {
3819
+ var isButton;
3820
+
3821
+ if (Prototype.Browser.IE) {
3822
+ var buttonMap = { 0: 1, 1: 4, 2: 2 };
3823
+ isButton = function(event, code) {
3824
+ return event.button == buttonMap[code];
3825
+ };
3826
+
3827
+ } else if (Prototype.Browser.WebKit) {
3828
+ isButton = function(event, code) {
3829
+ switch (code) {
3830
+ case 0: return event.which == 1 && !event.metaKey;
3831
+ case 1: return event.which == 1 && event.metaKey;
3832
+ default: return false;
3833
+ }
3834
+ };
3835
+
3836
+ } else {
3837
+ isButton = function(event, code) {
3838
+ return event.which ? (event.which === code + 1) : (event.button === code);
3839
+ };
3840
+ }
3841
+
3842
+ return {
3843
+ isLeftClick: function(event) { return isButton(event, 0) },
3844
+ isMiddleClick: function(event) { return isButton(event, 1) },
3845
+ isRightClick: function(event) { return isButton(event, 2) },
3846
+
3847
+ element: function(event) {
3848
+ event = Event.extend(event);
3849
+
3850
+ var node = event.target,
3851
+ type = event.type,
3852
+ currentTarget = event.currentTarget;
3853
+
3854
+ if (currentTarget && currentTarget.tagName) {
3855
+ // Firefox screws up the "click" event when moving between radio buttons
3856
+ // via arrow keys. It also screws up the "load" and "error" events on images,
3857
+ // reporting the document as the target instead of the original image.
3858
+ if (type === 'load' || type === 'error' ||
3859
+ (type === 'click' && currentTarget.tagName.toLowerCase() === 'input'
3860
+ && currentTarget.type === 'radio'))
3861
+ node = currentTarget;
3862
+ }
3863
+ if (node) {
3864
+ if (node.nodeType == Node.TEXT_NODE) node = node.parentNode;
3865
+ return Element.extend(node);
3866
+ } else return false;
3867
+ },
3868
+
3869
+ findElement: function(event, expression) {
3870
+ var element = Event.element(event);
3871
+ if (!expression) return element;
3872
+ var elements = [element].concat(element.ancestors());
3873
+ return Selector.findElement(elements, expression, 0);
3874
+ },
3875
+
3876
+ pointer: function(event) {
3877
+ var docElement = document.documentElement,
3878
+ body = document.body || { scrollLeft: 0, scrollTop: 0 };
3879
+ return {
3880
+ x: event.pageX || (event.clientX +
3881
+ (docElement.scrollLeft || body.scrollLeft) -
3882
+ (docElement.clientLeft || 0)),
3883
+ y: event.pageY || (event.clientY +
3884
+ (docElement.scrollTop || body.scrollTop) -
3885
+ (docElement.clientTop || 0))
3886
+ };
3887
+ },
3888
+
3889
+ pointerX: function(event) { return Event.pointer(event).x },
3890
+ pointerY: function(event) { return Event.pointer(event).y },
3891
+
3892
+ stop: function(event) {
3893
+ Event.extend(event);
3894
+ event.preventDefault();
3895
+ event.stopPropagation();
3896
+ event.stopped = true;
3897
+ }
3898
+ };
3899
+ })();
3900
+
3901
+ Event.extend = (function() {
3902
+ var methods = Object.keys(Event.Methods).inject({ }, function(m, name) {
3903
+ m[name] = Event.Methods[name].methodize();
3904
+ return m;
3905
+ });
3906
+
3907
+ if (Prototype.Browser.IE) {
3908
+ Object.extend(methods, {
3909
+ stopPropagation: function() { this.cancelBubble = true },
3910
+ preventDefault: function() { this.returnValue = false },
3911
+ inspect: function() { return "[object Event]" }
3912
+ });
3913
+
3914
+ return function(event) {
3915
+ if (!event) return false;
3916
+ if (event._extendedByPrototype) return event;
3917
+
3918
+ event._extendedByPrototype = Prototype.emptyFunction;
3919
+ var pointer = Event.pointer(event);
3920
+ Object.extend(event, {
3921
+ target: event.srcElement,
3922
+ relatedTarget: Event.relatedTarget(event),
3923
+ pageX: pointer.x,
3924
+ pageY: pointer.y
3925
+ });
3926
+ return Object.extend(event, methods);
3927
+ };
3928
+
3929
+ } else {
3930
+ Event.prototype = Event.prototype || document.createEvent("HTMLEvents")['__proto__'];
3931
+ Object.extend(Event.prototype, methods);
3932
+ return Prototype.K;
3933
+ }
3934
+ })();
3935
+
3936
+ Object.extend(Event, (function() {
3937
+ var cache = Event.cache;
3938
+
3939
+ function getEventID(element) {
3940
+ try {
3941
+ if (element._prototypeEventID) return element._prototypeEventID[0];
3942
+ arguments.callee.id = arguments.callee.id || 1;
3943
+ return element._prototypeEventID = [++arguments.callee.id];
3944
+ } catch (error) {
3945
+ return false;
3946
+ }
3947
+ }
3948
+
3949
+ function getDOMEventName(eventName) {
3950
+ if (eventName && eventName.include(':')) return "dataavailable";
3951
+ return eventName;
3952
+ }
3953
+
3954
+ function getCacheForID(id) {
3955
+ return cache[id] = cache[id] || { };
3956
+ }
3957
+
3958
+ function getWrappersForEventName(id, eventName) {
3959
+ var c = getCacheForID(id);
3960
+ return c[eventName] = c[eventName] || [];
3961
+ }
3962
+
3963
+ function createWrapper(element, eventName, handler) {
3964
+ var id = getEventID(element);
3965
+ var c = getWrappersForEventName(id, eventName);
3966
+ if (c.pluck("handler").include(handler)) return false;
3967
+
3968
+ var wrapper = function(event) {
3969
+ if (!Event || !Event.extend ||
3970
+ (event.eventName && event.eventName != eventName))
3971
+ return false;
3972
+
3973
+ Event.extend(event);
3974
+ handler.call(element, event);
3975
+ };
3976
+
3977
+ wrapper.handler = handler;
3978
+ c.push(wrapper);
3979
+ return wrapper;
3980
+ }
3981
+
3982
+ function findWrapper(id, eventName, handler) {
3983
+ var c = getWrappersForEventName(id, eventName);
3984
+ return c.find(function(wrapper) { return wrapper.handler == handler });
3985
+ }
3986
+
3987
+ function destroyWrapper(id, eventName, handler) {
3988
+ var c = getCacheForID(id);
3989
+ if (!c[eventName]) return false;
3990
+ c[eventName] = c[eventName].without(findWrapper(id, eventName, handler));
3991
+ }
3992
+
3993
+ function destroyCache() {
3994
+ for (var id in cache)
3995
+ for (var eventName in cache[id])
3996
+ cache[id][eventName] = null;
3997
+ }
3998
+
3999
+
4000
+ // Internet Explorer needs to remove event handlers on page unload
4001
+ // in order to avoid memory leaks.
4002
+ if (window.attachEvent) {
4003
+ window.attachEvent("onunload", destroyCache);
4004
+ }
4005
+
4006
+ // Safari has a dummy event handler on page unload so that it won't
4007
+ // use its bfcache. Safari <= 3.1 has an issue with restoring the "document"
4008
+ // object when page is returned to via the back button using its bfcache.
4009
+ if (Prototype.Browser.WebKit) {
4010
+ window.addEventListener('unload', Prototype.emptyFunction, false);
4011
+ }
4012
+
4013
+ return {
4014
+ observe: function(element, eventName, handler) {
4015
+ element = $(element);
4016
+ var name = getDOMEventName(eventName);
4017
+
4018
+ var wrapper = createWrapper(element, eventName, handler);
4019
+ if (!wrapper) return element;
4020
+
4021
+ if (element.addEventListener) {
4022
+ element.addEventListener(name, wrapper, false);
4023
+ } else {
4024
+ element.attachEvent("on" + name, wrapper);
4025
+ }
4026
+
4027
+ return element;
4028
+ },
4029
+
4030
+ stopObserving: function(element, eventName, handler) {
4031
+ element = $(element);
4032
+ var id = getEventID(element), name = getDOMEventName(eventName);
4033
+
4034
+ if (!handler && eventName) {
4035
+ getWrappersForEventName(id, eventName).each(function(wrapper) {
4036
+ element.stopObserving(eventName, wrapper.handler);
4037
+ });
4038
+ return element;
4039
+
4040
+ } else if (!eventName) {
4041
+ Object.keys(getCacheForID(id)).each(function(eventName) {
4042
+ element.stopObserving(eventName);
4043
+ });
4044
+ return element;
4045
+ }
4046
+
4047
+ var wrapper = findWrapper(id, eventName, handler);
4048
+ if (!wrapper) return element;
4049
+
4050
+ if (element.removeEventListener) {
4051
+ element.removeEventListener(name, wrapper, false);
4052
+ } else {
4053
+ element.detachEvent("on" + name, wrapper);
4054
+ }
4055
+
4056
+ destroyWrapper(id, eventName, handler);
4057
+
4058
+ return element;
4059
+ },
4060
+
4061
+ fire: function(element, eventName, memo) {
4062
+ element = $(element);
4063
+ if (element == document && document.createEvent && !element.dispatchEvent)
4064
+ element = document.documentElement;
4065
+
4066
+ var event;
4067
+ if (document.createEvent) {
4068
+ event = document.createEvent("HTMLEvents");
4069
+ event.initEvent("dataavailable", true, true);
4070
+ } else {
4071
+ event = document.createEventObject();
4072
+ event.eventType = "ondataavailable";
4073
+ }
4074
+
4075
+ event.eventName = eventName;
4076
+ event.memo = memo || { };
4077
+
4078
+ if (document.createEvent) {
4079
+ element.dispatchEvent(event);
4080
+ } else {
4081
+ element.fireEvent(event.eventType, event);
4082
+ }
4083
+
4084
+ return Event.extend(event);
4085
+ }
4086
+ };
4087
+ })());
4088
+
4089
+ Object.extend(Event, Event.Methods);
4090
+
4091
+ Element.addMethods({
4092
+ fire: Event.fire,
4093
+ observe: Event.observe,
4094
+ stopObserving: Event.stopObserving
4095
+ });
4096
+
4097
+ Object.extend(document, {
4098
+ fire: Element.Methods.fire.methodize(),
4099
+ observe: Element.Methods.observe.methodize(),
4100
+ stopObserving: Element.Methods.stopObserving.methodize(),
4101
+ loaded: false
4102
+ });
4103
+
4104
+ (function() {
4105
+ /* Support for the DOMContentLoaded event is based on work by Dan Webb,
4106
+ Matthias Miller, Dean Edwards and John Resig. */
4107
+
4108
+ var timer;
4109
+
4110
+ function fireContentLoadedEvent() {
4111
+ if (document.loaded) return;
4112
+ if (timer) window.clearInterval(timer);
4113
+ document.fire("dom:loaded");
4114
+ document.loaded = true;
4115
+ }
4116
+
4117
+ if (document.addEventListener) {
4118
+ if (Prototype.Browser.WebKit) {
4119
+ timer = window.setInterval(function() {
4120
+ if (/loaded|complete/.test(document.readyState))
4121
+ fireContentLoadedEvent();
4122
+ }, 0);
4123
+
4124
+ Event.observe(window, "load", fireContentLoadedEvent);
4125
+
4126
+ } else {
4127
+ document.addEventListener("DOMContentLoaded",
4128
+ fireContentLoadedEvent, false);
4129
+ }
4130
+
4131
+ } else {
4132
+ document.write("<script id=__onDOMContentLoaded defer src=//:><\/script>");
4133
+ $("__onDOMContentLoaded").onreadystatechange = function() {
4134
+ if (this.readyState == "complete") {
4135
+ this.onreadystatechange = null;
4136
+ fireContentLoadedEvent();
4137
+ }
4138
+ };
4139
+ }
4140
+ })();
4141
+ /*------------------------------- DEPRECATED -------------------------------*/
4142
+
4143
+ Hash.toQueryString = Object.toQueryString;
4144
+
4145
+ var Toggle = { display: Element.toggle };
4146
+
4147
+ Element.Methods.childOf = Element.Methods.descendantOf;
4148
+
4149
+ var Insertion = {
4150
+ Before: function(element, content) {
4151
+ return Element.insert(element, {before:content});
4152
+ },
4153
+
4154
+ Top: function(element, content) {
4155
+ return Element.insert(element, {top:content});
4156
+ },
4157
+
4158
+ Bottom: function(element, content) {
4159
+ return Element.insert(element, {bottom:content});
4160
+ },
4161
+
4162
+ After: function(element, content) {
4163
+ return Element.insert(element, {after:content});
4164
+ }
4165
+ };
4166
+
4167
+ var $continue = new Error('"throw $continue" is deprecated, use "return" instead');
4168
+
4169
+ // This should be moved to script.aculo.us; notice the deprecated methods
4170
+ // further below, that map to the newer Element methods.
4171
+ var Position = {
4172
+ // set to true if needed, warning: firefox performance problems
4173
+ // NOT neeeded for page scrolling, only if draggable contained in
4174
+ // scrollable elements
4175
+ includeScrollOffsets: false,
4176
+
4177
+ // must be called before calling withinIncludingScrolloffset, every time the
4178
+ // page is scrolled
4179
+ prepare: function() {
4180
+ this.deltaX = window.pageXOffset
4181
+ || document.documentElement.scrollLeft
4182
+ || document.body.scrollLeft
4183
+ || 0;
4184
+ this.deltaY = window.pageYOffset
4185
+ || document.documentElement.scrollTop
4186
+ || document.body.scrollTop
4187
+ || 0;
4188
+ },
4189
+
4190
+ // caches x/y coordinate pair to use with overlap
4191
+ within: function(element, x, y) {
4192
+ if (this.includeScrollOffsets)
4193
+ return this.withinIncludingScrolloffsets(element, x, y);
4194
+ this.xcomp = x;
4195
+ this.ycomp = y;
4196
+ this.offset = Element.cumulativeOffset(element);
4197
+
4198
+ return (y >= this.offset[1] &&
4199
+ y < this.offset[1] + element.offsetHeight &&
4200
+ x >= this.offset[0] &&
4201
+ x < this.offset[0] + element.offsetWidth);
4202
+ },
4203
+
4204
+ withinIncludingScrolloffsets: function(element, x, y) {
4205
+ var offsetcache = Element.cumulativeScrollOffset(element);
4206
+
4207
+ this.xcomp = x + offsetcache[0] - this.deltaX;
4208
+ this.ycomp = y + offsetcache[1] - this.deltaY;
4209
+ this.offset = Element.cumulativeOffset(element);
4210
+
4211
+ return (this.ycomp >= this.offset[1] &&
4212
+ this.ycomp < this.offset[1] + element.offsetHeight &&
4213
+ this.xcomp >= this.offset[0] &&
4214
+ this.xcomp < this.offset[0] + element.offsetWidth);
4215
+ },
4216
+
4217
+ // within must be called directly before
4218
+ overlap: function(mode, element) {
4219
+ if (!mode) return 0;
4220
+ if (mode == 'vertical')
4221
+ return ((this.offset[1] + element.offsetHeight) - this.ycomp) /
4222
+ element.offsetHeight;
4223
+ if (mode == 'horizontal')
4224
+ return ((this.offset[0] + element.offsetWidth) - this.xcomp) /
4225
+ element.offsetWidth;
4226
+ },
4227
+
4228
+ // Deprecation layer -- use newer Element methods now (1.5.2).
4229
+
4230
+ cumulativeOffset: Element.Methods.cumulativeOffset,
4231
+
4232
+ positionedOffset: Element.Methods.positionedOffset,
4233
+
4234
+ absolutize: function(element) {
4235
+ Position.prepare();
4236
+ return Element.absolutize(element);
4237
+ },
4238
+
4239
+ relativize: function(element) {
4240
+ Position.prepare();
4241
+ return Element.relativize(element);
4242
+ },
4243
+
4244
+ realOffset: Element.Methods.cumulativeScrollOffset,
4245
+
4246
+ offsetParent: Element.Methods.getOffsetParent,
4247
+
4248
+ page: Element.Methods.viewportOffset,
4249
+
4250
+ clone: function(source, target, options) {
4251
+ options = options || { };
4252
+ return Element.clonePosition(target, source, options);
4253
+ }
4254
+ };
4255
+
4256
+ /*--------------------------------------------------------------------------*/
4257
+
4258
+ if (!document.getElementsByClassName) document.getElementsByClassName = function(instanceMethods){
4259
+ function iter(name) {
4260
+ return name.blank() ? null : "[contains(concat(' ', @class, ' '), ' " + name + " ')]";
4261
+ }
4262
+
4263
+ instanceMethods.getElementsByClassName = Prototype.BrowserFeatures.XPath ?
4264
+ function(element, className) {
4265
+ className = className.toString().strip();
4266
+ var cond = /\s/.test(className) ? $w(className).map(iter).join('') : iter(className);
4267
+ return cond ? document._getElementsByXPath('.//*' + cond, element) : [];
4268
+ } : function(element, className) {
4269
+ className = className.toString().strip();
4270
+ var elements = [], classNames = (/\s/.test(className) ? $w(className) : null);
4271
+ if (!classNames && !className) return elements;
4272
+
4273
+ var nodes = $(element).getElementsByTagName('*');
4274
+ className = ' ' + className + ' ';
4275
+
4276
+ for (var i = 0, child, cn; child = nodes[i]; i++) {
4277
+ if (child.className && (cn = ' ' + child.className + ' ') && (cn.include(className) ||
4278
+ (classNames && classNames.all(function(name) {
4279
+ return !name.toString().blank() && cn.include(' ' + name + ' ');
4280
+ }))))
4281
+ elements.push(Element.extend(child));
4282
+ }
4283
+ return elements;
4284
+ };
4285
+
4286
+ return function(className, parentElement) {
4287
+ return $(parentElement || document.body).getElementsByClassName(className);
4288
+ };
4289
+ }(Element.Methods);
4290
+
4291
+ /*--------------------------------------------------------------------------*/
4292
+
4293
+ Element.ClassNames = Class.create();
4294
+ Element.ClassNames.prototype = {
4295
+ initialize: function(element) {
4296
+ this.element = $(element);
4297
+ },
4298
+
4299
+ _each: function(iterator) {
4300
+ this.element.className.split(/\s+/).select(function(name) {
4301
+ return name.length > 0;
4302
+ })._each(iterator);
4303
+ },
4304
+
4305
+ set: function(className) {
4306
+ this.element.className = className;
4307
+ },
4308
+
4309
+ add: function(classNameToAdd) {
4310
+ if (this.include(classNameToAdd)) return;
4311
+ this.set($A(this).concat(classNameToAdd).join(' '));
4312
+ },
4313
+
4314
+ remove: function(classNameToRemove) {
4315
+ if (!this.include(classNameToRemove)) return;
4316
+ this.set($A(this).without(classNameToRemove).join(' '));
4317
+ },
4318
+
4319
+ toString: function() {
4320
+ return $A(this).join(' ');
4321
+ }
4322
+ };
4323
+
4324
+ Object.extend(Element.ClassNames.prototype, Enumerable);
4325
+
4326
+ /*--------------------------------------------------------------------------*/
4327
+
4328
+ Element.addMethods();
js/prototype/tooltip.js ADDED
@@ -0,0 +1,208 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /*
2
+ * Copyright (c) 2006 Jonathan Weiss <jw@innerewut.de>
3
+ *
4
+ * Permission to use, copy, modify, and distribute this software for any
5
+ * purpose with or without fee is hereby granted, provided that the above
6
+ * copyright notice and this permission notice appear in all copies.
7
+ *
8
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15
+ */
16
+
17
+
18
+ /* tooltip-0.2.js - Small tooltip library on top of Prototype
19
+ * by Jonathan Weiss <jw@innerewut.de> distributed under the BSD license.
20
+ *
21
+ * This tooltip library works in two modes. If it gets a valid DOM element
22
+ * or DOM id as an argument it uses this element as the tooltip. This
23
+ * element will be placed (and shown) near the mouse pointer when a trigger-
24
+ * element is moused-over.
25
+ * If it gets only a text as an argument instead of a DOM id or DOM element
26
+ * it will create a div with the classname 'tooltip' that holds the given text.
27
+ * This newly created div will be used as the tooltip. This is usefull if you
28
+ * want to use tooltip.js to create popups out of title attributes.
29
+ *
30
+ *
31
+ * Usage:
32
+ * <script src="/javascripts/prototype.js" type="text/javascript"></script>
33
+ * <script src="/javascripts/tooltip.js" type="text/javascript"></script>
34
+ * <script type="text/javascript">
35
+ * // with valid DOM id
36
+ * var my_tooltip = new Tooltip('id_of_trigger_element', 'id_of_tooltip_to_show_element')
37
+ *
38
+ * // with text
39
+ * var my_other_tooltip = new Tooltip('id_of_trigger_element', 'a nice description')
40
+ *
41
+ * // create popups for each element with a title attribute
42
+ * Event.observe(window,"load",function() {
43
+ * $$("*").findAll(function(node){
44
+ * return node.getAttribute('title');
45
+ * }).each(function(node){
46
+ * new Tooltip(node,node.title);
47
+ * node.removeAttribute("title");
48
+ * });
49
+ * });
50
+ *
51
+ * </script>
52
+ *
53
+ * Now whenever you trigger a mouseOver on the `trigger` element, the tooltip element will
54
+ * be shown. On o mouseOut the tooltip disappears.
55
+ *
56
+ * Example:
57
+ *
58
+ * <script src="/javascripts/prototype.js" type="text/javascript"></script>
59
+ * <script src="/javascripts/scriptaculous.js" type="text/javascript"></script>
60
+ * <script src="/javascripts/tooltip.js" type="text/javascript"></script>
61
+ *
62
+ * <div id='tooltip' style="display:none; margin: 5px; background-color: red;">
63
+ * Detail infos on product 1....<br />
64
+ * </div>
65
+ *
66
+ * <div id='product_1'>
67
+ * This is product 1
68
+ * </div>
69
+ *
70
+ * <script type="text/javascript">
71
+ * var my_tooltip = new Tooltip('product_1', 'tooltip')
72
+ * </script>
73
+ *
74
+ * You can use my_tooltip.destroy() to remove the event observers and thereby the tooltip.
75
+ */
76
+
77
+ var Tooltip = Class.create();
78
+ Tooltip.prototype = {
79
+ initialize: function(element, tool_tip) {
80
+ var options = Object.extend({
81
+ default_css: false,
82
+ margin: "0px",
83
+ padding: "5px",
84
+ backgroundColor: "#d6d6fc",
85
+ min_distance_x: 5,
86
+ min_distance_y: 5,
87
+ delta_x: 0,
88
+ delta_y: 0,
89
+ zindex: 1000
90
+ }, arguments[2] || {});
91
+
92
+ this.element = $(element);
93
+
94
+ this.options = options;
95
+
96
+ // use the supplied tooltip element or create our own div
97
+ if($(tool_tip)) {
98
+ this.tool_tip = $(tool_tip);
99
+ } else {
100
+ this.tool_tip = $(document.createElement("div"));
101
+ document.body.appendChild(this.tool_tip);
102
+ this.tool_tip.addClassName("tooltip");
103
+ this.tool_tip.appendChild(document.createTextNode(tool_tip));
104
+ }
105
+
106
+ // hide the tool-tip by default
107
+ this.tool_tip.hide();
108
+
109
+ this.eventMouseOver = this.showTooltip.bindAsEventListener(this);
110
+ this.eventMouseOut = this.hideTooltip.bindAsEventListener(this);
111
+ this.eventMouseMove = this.moveTooltip.bindAsEventListener(this);
112
+
113
+ this.registerEvents();
114
+ },
115
+
116
+ destroy: function() {
117
+ Event.stopObserving(this.element, "mouseover", this.eventMouseOver);
118
+ Event.stopObserving(this.element, "mouseout", this.eventMouseOut);
119
+ Event.stopObserving(this.element, "mousemove", this.eventMouseMove);
120
+ },
121
+
122
+ registerEvents: function() {
123
+ Event.observe(this.element, "mouseover", this.eventMouseOver);
124
+ Event.observe(this.element, "mouseout", this.eventMouseOut);
125
+ Event.observe(this.element, "mousemove", this.eventMouseMove);
126
+ },
127
+
128
+ moveTooltip: function(event){
129
+ Event.stop(event);
130
+ // get Mouse position
131
+ var mouse_x = Event.pointerX(event);
132
+ var mouse_y = Event.pointerY(event);
133
+
134
+ // decide if wee need to switch sides for the tooltip
135
+ var dimensions = Element.getDimensions( this.tool_tip );
136
+ var element_width = dimensions.width;
137
+ var element_height = dimensions.height;
138
+
139
+ if ( (element_width + mouse_x) >= ( this.getWindowWidth() - this.options.min_distance_x) ){ // too big for X
140
+ mouse_x = mouse_x - element_width;
141
+ // apply min_distance to make sure that the mouse is not on the tool-tip
142
+ mouse_x = mouse_x - this.options.min_distance_x;
143
+ } else {
144
+ mouse_x = mouse_x + this.options.min_distance_x;
145
+ }
146
+
147
+ if ( (element_height + mouse_y) >= ( this.getWindowHeight() - this.options.min_distance_y) ){ // too big for Y
148
+ mouse_y = mouse_y - element_height;
149
+ // apply min_distance to make sure that the mouse is not on the tool-tip
150
+ mouse_y = mouse_y - this.options.min_distance_y;
151
+ } else {
152
+ mouse_y = mouse_y + this.options.min_distance_y;
153
+ }
154
+
155
+ // now set the right styles
156
+ this.setStyles(mouse_x, mouse_y);
157
+ },
158
+
159
+
160
+ showTooltip: function(event) {
161
+ Event.stop(event);
162
+ this.moveTooltip(event);
163
+ new Element.show(this.tool_tip);
164
+ },
165
+
166
+ setStyles: function(x, y){
167
+ // set the right styles to position the tool tip
168
+ Element.setStyle(this.tool_tip, { position:'absolute',
169
+ top:y + this.options.delta_y + "px",
170
+ left:x + this.options.delta_x + "px",
171
+ zindex:this.options.zindex
172
+ });
173
+
174
+ // apply default theme if wanted
175
+ if (this.options.default_css){
176
+ Element.setStyle(this.tool_tip, { margin:this.options.margin,
177
+ padding:this.options.padding,
178
+ backgroundColor:this.options.backgroundColor,
179
+ zindex:this.options.zindex
180
+ });
181
+ }
182
+ },
183
+
184
+ hideTooltip: function(event){
185
+ new Element.hide(this.tool_tip);
186
+ },
187
+
188
+ getWindowHeight: function(){
189
+ var innerHeight;
190
+ if (navigator.appVersion.indexOf('MSIE')>0) {
191
+ innerHeight = document.body.clientHeight;
192
+ } else {
193
+ innerHeight = window.innerHeight;
194
+ }
195
+ return innerHeight;
196
+ },
197
+
198
+ getWindowWidth: function(){
199
+ var innerWidth;
200
+ if (navigator.appVersion.indexOf('MSIE')>0) {
201
+ innerWidth = document.body.clientWidth;
202
+ } else {
203
+ innerWidth = window.innerWidth;
204
+ }
205
+ return innerWidth;
206
+ }
207
+
208
+ }
js/prototype/tooltip_manager.js ADDED
@@ -0,0 +1,241 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // Singleton class TooltipWindow
2
+ // This class works with special className. The tooltip content could be in your HTML page as an hidden element or
3
+ // can be retreive by an AJAX call.
4
+ //
5
+ // To work, You just need to set two class name on elements that should show tooltips
6
+ // - One to say to TooltipManager that this element must have a tooltip ('tooltip' by default)
7
+ // - Another to indicate how to find the tooltip content
8
+ // It could be html_XXXX if tootltip content is somewhere hidden in your page, XXX must be DOM ID of this hidden element
9
+ // It could be ajax_XXXX if tootltip content must be find by an ajax request, XXX will be the string send as id parameter to your server.
10
+ // Check samples/tooltips/tooltip.html to see how it works
11
+ //
12
+ TooltipManager = {
13
+ options: {cssClassName: 'tooltip', delayOver: 200, delayOut: 1000, shiftX: 10, shiftY: 10,
14
+ className: 'alphacube', width: 200, height: null,
15
+ draggable: false, minimizable: false, maximizable: false, showEffect: Element.show, hideEffect: Element.hide},
16
+ ajaxInfo: null,
17
+ elements: null,
18
+ showTimer: null,
19
+ hideTimer: null,
20
+
21
+ // Init tooltip manager
22
+ // parameters:
23
+ // - cssClassName (string) : CSS class name where tooltip should be shown.
24
+ // - ajaxOptions (hash) : Ajax options for ajax tooltip.
25
+ // For examples {url: "/tooltip/get.php", options: {method: 'get'}}
26
+ // see Ajax.Request documentation for details
27
+ //- tooltipOptions (hash) : available keys
28
+ // - delayOver: int in ms (default 10) delay before showing tooltip
29
+ // - delayOut: int in ms (default 1000) delay before hidding tooltip
30
+ // - shiftX: int in pixels (default 10) left shift of the tooltip window
31
+ // - shiftY: int in pixels (default 10) top shift of the tooltip window
32
+ // and All window options like showEffect: Element.show, hideEffect: Element.hide to remove animation
33
+ // default: {className: 'alphacube', width: 200, height: null, draggable: false, minimizable: false, maximizable: false}
34
+
35
+ init: function(cssClassName, ajaxInfo, tooltipOptions) {
36
+ TooltipManager.options = Object.extend(TooltipManager.options, tooltipOptions || {});
37
+
38
+ cssClassName = TooltipManager.options.cssClassName || "tooltip";
39
+ TooltipManager.ajaxInfo = ajaxInfo;
40
+ TooltipManager.elements = $$("." + cssClassName);
41
+ TooltipManager.elements.each(function(element) {
42
+ element = $(element)
43
+ var info = TooltipManager._getInfo(element);
44
+ if (info.ajax) {
45
+ element.ajaxId = info.id;
46
+ element.ajaxInfo = ajaxInfo;
47
+ }
48
+ else {
49
+ element.tooltipElement = $(info.id);
50
+ }
51
+ element.observe("mouseover", TooltipManager._mouseOver);
52
+ element.observe("mouseout", TooltipManager._mouseOut);
53
+ });
54
+ Windows.addObserver(this);
55
+ },
56
+
57
+ addHTML: function(element, tooltipElement) {
58
+ element = $(element);
59
+ tooltipElement = $(tooltipElement);
60
+ element.tooltipElement = tooltipElement;
61
+
62
+ element.observe("mouseover", TooltipManager._mouseOver);
63
+ element.observe("mouseout", TooltipManager._mouseOut);
64
+ },
65
+
66
+ addAjax: function(element, ajaxInfo) {
67
+ element = $(element);
68
+ element.ajaxInfo = ajaxInfo;
69
+ element.observe("mouseover", TooltipManager._mouseOver);
70
+ element.observe("mouseout", TooltipManager._mouseOut);
71
+ },
72
+
73
+ addURL: function(element, url, width, height) {
74
+ element = $(element);
75
+ element.url = url;
76
+ element.frameWidth = width;
77
+ element.frameHeight = height;
78
+ element.observe("mouseover", TooltipManager._mouseOver);
79
+ element.observe("mouseout", TooltipManager._mouseOut);
80
+ },
81
+
82
+ close: function() {
83
+ if (TooltipManager.tooltipWindow)
84
+ TooltipManager.tooltipWindow.hide();
85
+ },
86
+
87
+ preloadImages: function(path, images, extension) {
88
+ if (!extension)
89
+ extension = ".gif";
90
+
91
+ //preload images
92
+ $A(images).each(function(i) {
93
+ var image = new Image();
94
+ image.src= path + "/" + i + extension;
95
+ });
96
+ },
97
+
98
+ _showTooltip: function(element) {
99
+ if (this.element == element)
100
+ return;
101
+ // Get original element
102
+ while (element && (!element.tooltipElement && !element.ajaxInfo && !element.url))
103
+ element = element.parentNode;
104
+ this.element = element;
105
+
106
+ TooltipManager.showTimer = null;
107
+ if (TooltipManager.hideTimer)
108
+ clearTimeout(TooltipManager.hideTimer);
109
+
110
+ var position = Position.cumulativeOffset(element);
111
+ var dimension = element.getDimensions();
112
+
113
+ if (! this.tooltipWindow)
114
+ this.tooltipWindow = new Window("__tooltip__", TooltipManager.options);
115
+
116
+ this.tooltipWindow.hide();
117
+ this.tooltipWindow.setLocation(position[1] + dimension.height + TooltipManager.options.shiftY, position[0] + TooltipManager.options.shiftX);
118
+
119
+ Event.observe(this.tooltipWindow.element, "mouseover", function(event) {TooltipManager._tooltipOver(event, element)});
120
+ Event.observe(this.tooltipWindow.element, "mouseout", function(event) {TooltipManager._tooltipOut(event, element)});
121
+
122
+ // Reset width/height for computation
123
+ this.tooltipWindow.height = TooltipManager.options.height;
124
+ this.tooltipWindow.width = TooltipManager.options.width;
125
+
126
+ // Ajax content
127
+ if (element.ajaxInfo) {
128
+ var p = element.ajaxInfo.options.parameters;
129
+ var saveParam = p;
130
+
131
+ // Set by CSS
132
+ if (element.ajaxId) {
133
+ if (p)
134
+ p += "&id=" + element.ajaxId;
135
+ else
136
+ p = "id=" + element.ajaxId;
137
+ }
138
+ element.ajaxInfo.options.parameters = p || "";
139
+ this.tooltipWindow.setHTMLContent("");
140
+ this.tooltipWindow.setAjaxContent(element.ajaxInfo.url, element.ajaxInfo.options);
141
+ element.ajaxInfo.options.parameters = saveParam;
142
+ }
143
+ // URL content
144
+ else if (element.url) {
145
+ this.tooltipWindow.setURL(element.url);
146
+ this.tooltipWindow.setSize(element.frameWidth, element.frameHeight);
147
+
148
+ // Set tooltip size
149
+ this.tooltipWindow.height = element.frameHeight;
150
+ this.tooltipWindow.width = element.frameWidth;
151
+ }
152
+ // HTML content
153
+ else
154
+ this.tooltipWindow.setHTMLContent(element.tooltipElement.innerHTML);
155
+
156
+ if (!element.ajaxInfo) {
157
+ this.tooltipWindow.show();
158
+ this.tooltipWindow.toFront();
159
+ }
160
+ },
161
+
162
+ _hideTooltip: function(element) {
163
+ if (this.tooltipWindow) {
164
+ this.tooltipWindow.hide();
165
+ this.element = null;
166
+ }
167
+ },
168
+
169
+ _mouseOver: function (event) {
170
+ var element = Event.element(event);
171
+ if (TooltipManager.showTimer)
172
+ clearTimeout(TooltipManager.showTimer);
173
+
174
+ TooltipManager.showTimer = setTimeout(function() {TooltipManager._showTooltip(element)}, TooltipManager.options.delayOver)
175
+ },
176
+
177
+ _mouseOut: function(event) {
178
+ var element = Event.element(event);
179
+ if (TooltipManager.showTimer) {
180
+ clearTimeout(TooltipManager.showTimer);
181
+ TooltipManager.showTimer = null;
182
+ return;
183
+ }
184
+ if (TooltipManager.tooltipWindow)
185
+ TooltipManager.hideTimer = setTimeout(function() {TooltipManager._hideTooltip(element)}, TooltipManager.options.delayOut)
186
+ },
187
+
188
+ _tooltipOver: function(event, element) {
189
+ if (TooltipManager.hideTimer) {
190
+ clearTimeout(TooltipManager.hideTimer);
191
+ TooltipManager.hideTimer = null;
192
+ }
193
+ },
194
+
195
+ _tooltipOut: function(event, element) {
196
+ if (TooltipManager.hideTimer == null)
197
+ TooltipManager.hideTimer = setTimeout(function() {TooltipManager._hideTooltip(element)}, TooltipManager.options.delayOut)
198
+ },
199
+
200
+ _getInfo: function(element) {
201
+ // Find html_ for static content
202
+ var id = element.className.split(' ').detect(function(name) {return name.indexOf("html_") == 0});
203
+ var ajax = true;
204
+ if (id)
205
+ ajax = false;
206
+ else
207
+ // Find ajax_ for ajax content
208
+ id = element.className.split(' ').detect(function(name) {return name.indexOf("ajax_") == 0});
209
+
210
+ id = id.substr(id.indexOf('_')+1, id.length)
211
+ return id ? {ajax: ajax, id: id} : null;
212
+ },
213
+
214
+ onBeforeShow: function(eventName, win) {
215
+ var top = parseFloat(win.getLocation().top);
216
+ var dim = win.element.getDimensions();
217
+
218
+ if (top + dim.height > TooltipManager._getScrollTop() + TooltipManager._getPageHeight()) {
219
+ var position = Position.cumulativeOffset(this.element);
220
+
221
+ var top = position[1] - TooltipManager.options.shiftY - dim.height;
222
+ win.setLocation(top, position[0] + TooltipManager.options.shiftX)
223
+ }
224
+ },
225
+
226
+ _getPageWidth: function(){
227
+ return window.innerWidth || document.documentElement.clientWidth || 0;
228
+ },
229
+
230
+ _getPageHeight: function(){
231
+ return window.innerHeight || document.documentElement.clientHeight || 0;
232
+ },
233
+
234
+ _getScrollTop: function(){
235
+ return document.documentElement.scrollTop || window.pageYOffset || 0;
236
+ },
237
+
238
+ _getScrollLeft: function(){
239
+ return document.documentElement.scrollLeft || window.pageXOffset || 0;
240
+ }
241
+ };
js/prototype/validation.js ADDED
@@ -0,0 +1,774 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /*
2
+ * Really easy field validation with Prototype
3
+ * http://tetlaw.id.au/view/javascript/really-easy-field-validation
4
+ * Andrew Tetlaw
5
+ * Version 1.5.4.1 (2007-01-05)
6
+ *
7
+ * Copyright (c) 2007 Andrew Tetlaw
8
+ * Permission is hereby granted, free of charge, to any person
9
+ * obtaining a copy of this software and associated documentation
10
+ * files (the "Software"), to deal in the Software without
11
+ * restriction, including without limitation the rights to use, copy,
12
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
13
+ * of the Software, and to permit persons to whom the Software is
14
+ * furnished to do so, subject to the following conditions:
15
+ *
16
+ * The above copyright notice and this permission notice shall be
17
+ * included in all copies or substantial portions of the Software.
18
+ *
19
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
20
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
21
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
22
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
23
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
24
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
25
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
26
+ * SOFTWARE.
27
+ *
28
+ */
29
+ var Validator = Class.create();
30
+
31
+ Validator.prototype = {
32
+ initialize : function(className, error, test, options) {
33
+ if(typeof test == 'function'){
34
+ this.options = $H(options);
35
+ this._test = test;
36
+ } else {
37
+ this.options = $H(test);
38
+ this._test = function(){return true};
39
+ }
40
+ this.error = error || 'Validation failed.';
41
+ this.className = className;
42
+ },
43
+ test : function(v, elm) {
44
+ return (this._test(v,elm) && this.options.all(function(p){
45
+ return Validator.methods[p.key] ? Validator.methods[p.key](v,elm,p.value) : true;
46
+ }));
47
+ }
48
+ }
49
+ Validator.methods = {
50
+ pattern : function(v,elm,opt) {return Validation.get('IsEmpty').test(v) || opt.test(v)},
51
+ minLength : function(v,elm,opt) {return v.length >= opt},
52
+ maxLength : function(v,elm,opt) {return v.length <= opt},
53
+ min : function(v,elm,opt) {return v >= parseFloat(opt)},
54
+ max : function(v,elm,opt) {return v <= parseFloat(opt)},
55
+ notOneOf : function(v,elm,opt) {return $A(opt).all(function(value) {
56
+ return v != value;
57
+ })},
58
+ oneOf : function(v,elm,opt) {return $A(opt).any(function(value) {
59
+ return v == value;
60
+ })},
61
+ is : function(v,elm,opt) {return v == opt},
62
+ isNot : function(v,elm,opt) {return v != opt},
63
+ equalToField : function(v,elm,opt) {return v == $F(opt)},
64
+ notEqualToField : function(v,elm,opt) {return v != $F(opt)},
65
+ include : function(v,elm,opt) {return $A(opt).all(function(value) {
66
+ return Validation.get(value).test(v,elm);
67
+ })}
68
+ }
69
+
70
+ var Validation = Class.create();
71
+ Validation.defaultOptions = {
72
+ onSubmit : true,
73
+ stopOnFirst : false,
74
+ immediate : false,
75
+ focusOnError : true,
76
+ useTitles : false,
77
+ addClassNameToContainer: false,
78
+ containerClassName: '.input-box',
79
+ onFormValidate : function(result, form) {},
80
+ onElementValidate : function(result, elm) {}
81
+ };
82
+
83
+ Validation.prototype = {
84
+ initialize : function(form, options){
85
+ this.form = $(form);
86
+ if (!this.form) {
87
+ return;
88
+ }
89
+ this.options = Object.extend({
90
+ onSubmit : Validation.defaultOptions.onSubmit,
91
+ stopOnFirst : Validation.defaultOptions.stopOnFirst,
92
+ immediate : Validation.defaultOptions.immediate,
93
+ focusOnError : Validation.defaultOptions.focusOnError,
94
+ useTitles : Validation.defaultOptions.useTitles,
95
+ onFormValidate : Validation.defaultOptions.onFormValidate,
96
+ onElementValidate : Validation.defaultOptions.onElementValidate
97
+ }, options || {});
98
+ if(this.options.onSubmit) Event.observe(this.form,'submit',this.onSubmit.bind(this),false);
99
+ if(this.options.immediate) {
100
+ Form.getElements(this.form).each(function(input) { // Thanks Mike!
101
+ if (input.tagName.toLowerCase() == 'select') {
102
+ Event.observe(input, 'blur', this.onChange.bindAsEventListener(this));
103
+ }
104
+ if (input.type.toLowerCase() == 'radio' || input.type.toLowerCase() == 'checkbox') {
105
+ Event.observe(input, 'click', this.onChange.bindAsEventListener(this));
106
+ } else {
107
+ Event.observe(input, 'change', this.onChange.bindAsEventListener(this));
108
+ }
109
+ }, this);
110
+ }
111
+ },
112
+ onChange : function (ev) {
113
+ Validation.isOnChange = true;
114
+ Validation.validate(Event.element(ev),{
115
+ useTitle : this.options.useTitles,
116
+ onElementValidate : this.options.onElementValidate
117
+ });
118
+ Validation.isOnChange = false;
119
+ },
120
+ onSubmit : function(ev){
121
+ if(!this.validate()) Event.stop(ev);
122
+ },
123
+ validate : function() {
124
+ var result = false;
125
+ var useTitles = this.options.useTitles;
126
+ var callback = this.options.onElementValidate;
127
+ try {
128
+ if(this.options.stopOnFirst) {
129
+ result = Form.getElements(this.form).all(function(elm) {
130
+ if (elm.hasClassName('local-validation') && !this.isElementInForm(elm, this.form)) {
131
+ return true;
132
+ }
133
+ return Validation.validate(elm,{useTitle : useTitles, onElementValidate : callback});
134
+ }, this);
135
+ } else {
136
+ result = Form.getElements(this.form).collect(function(elm) {
137
+ if (elm.hasClassName('local-validation') && !this.isElementInForm(elm, this.form)) {
138
+ return true;
139
+ }
140
+ return Validation.validate(elm,{useTitle : useTitles, onElementValidate : callback});
141
+ }, this).all();
142
+ }
143
+ } catch (e) {
144
+
145
+ }
146
+ if(!result && this.options.focusOnError) {
147
+ try{
148
+ Form.getElements(this.form).findAll(function(elm){return $(elm).hasClassName('validation-failed')}).first().focus()
149
+ }
150
+ catch(e){
151
+
152
+ }
153
+ }
154
+ this.options.onFormValidate(result, this.form);
155
+ return result;
156
+ },
157
+ reset : function() {
158
+ Form.getElements(this.form).each(Validation.reset);
159
+ },
160
+ isElementInForm : function(elm, form) {
161
+ var domForm = elm.up('form');
162
+ if (domForm == form) {
163
+ return true;
164
+ }
165
+ return false;
166
+ }
167
+ }
168
+
169
+ Object.extend(Validation, {
170
+ validate : function(elm, options){
171
+ options = Object.extend({
172
+ useTitle : false,
173
+ onElementValidate : function(result, elm) {}
174
+ }, options || {});
175
+ elm = $(elm);
176
+
177
+ var cn = $w(elm.className);
178
+ return result = cn.all(function(value) {
179
+ var test = Validation.test(value,elm,options.useTitle);
180
+ options.onElementValidate(test, elm);
181
+ return test;
182
+ });
183
+ },
184
+ insertAdvice : function(elm, advice){
185
+ var container = $(elm).up('.field-row');
186
+ if(container){
187
+ Element.insert(container, {after: advice});
188
+ } else if (elm.up('td.value')) {
189
+ elm.up('td.value').insert({bottom: advice});
190
+ } else if (elm.advaiceContainer && $(elm.advaiceContainer)) {
191
+ $(elm.advaiceContainer).update(advice);
192
+ }
193
+ else {
194
+ switch (elm.type.toLowerCase()) {
195
+ case 'checkbox':
196
+ case 'radio':
197
+ var p = elm.parentNode;
198
+ if(p) {
199
+ Element.insert(p, {'bottom': advice});
200
+ } else {
201
+ Element.insert(elm, {'after': advice});
202
+ }
203
+ break;
204
+ default:
205
+ Element.insert(elm, {'after': advice});
206
+ }
207
+ }
208
+ },
209
+ showAdvice : function(elm, advice, adviceName){
210
+ if(!elm.advices){
211
+ elm.advices = new Hash();
212
+ }
213
+ else{
214
+ elm.advices.each(function(pair){
215
+ this.hideAdvice(elm, pair.value);
216
+ }.bind(this));
217
+ }
218
+ elm.advices.set(adviceName, advice);
219
+ if(typeof Effect == 'undefined') {
220
+ advice.style.display = 'block';
221
+ } else {
222
+ if(!advice._adviceAbsolutize) {
223
+ new Effect.Appear(advice, {duration : 1 });
224
+ } else {
225
+ Position.absolutize(advice);
226
+ advice.show();
227
+ advice.setStyle({
228
+ 'top':advice._adviceTop,
229
+ 'left': advice._adviceLeft,
230
+ 'width': advice._adviceWidth,
231
+ 'z-index': 1000
232
+ });
233
+ advice.addClassName('advice-absolute');
234
+ }
235
+ }
236
+ },
237
+ hideAdvice : function(elm, advice){
238
+ if(advice != null) advice.hide();
239
+ },
240
+ updateCallback : function(elm, status) {
241
+ if (typeof elm.callbackFunction != 'undefined') {
242
+ eval(elm.callbackFunction+'(\''+elm.id+'\',\''+status+'\')');
243
+ }
244
+ },
245
+ ajaxError : function(elm, errorMsg) {
246
+ var name = 'validate-ajax';
247
+ var advice = Validation.getAdvice(name, elm);
248
+ if (advice == null) {
249
+ advice = this.createAdvice(name, elm, false, errorMsg);
250
+ }
251
+ this.showAdvice(elm, advice, 'validate-ajax');
252
+ this.updateCallback(elm, 'failed');
253
+
254
+ elm.addClassName('validation-failed');
255
+ elm.addClassName('validate-ajax');
256
+ if (Validation.defaultOptions.addClassNameToContainer && Validation.defaultOptions.containerClassName != '') {
257
+ var container = elm.up(Validation.defaultOptions.containerClassName);
258
+ if (container && this.allowContainerClassName(elm)) {
259
+ container.removeClassName('validation-passed');
260
+ container.addClassName('validation-error');
261
+ }
262
+ }
263
+ },
264
+ allowContainerClassName: function (elm) {
265
+ if (elm.type == 'radio' || elm.type == 'checkbox') {
266
+ return elm.hasClassName('change-container-classname');
267
+ }
268
+
269
+ return true;
270
+ },
271
+ test : function(name, elm, useTitle) {
272
+ var v = Validation.get(name);
273
+ var prop = '__advice'+name.camelize();
274
+ try {
275
+ if(Validation.isVisible(elm) && !v.test($F(elm), elm)) {
276
+ //if(!elm[prop]) {
277
+ var advice = Validation.getAdvice(name, elm);
278
+ if (advice == null) {
279
+ advice = this.createAdvice(name, elm, useTitle);
280
+ }
281
+ this.showAdvice(elm, advice, name);
282
+ this.updateCallback(elm, 'failed');
283
+ //}
284
+ elm[prop] = 1;
285
+ if (!elm.advaiceContainer) {
286
+ elm.removeClassName('validation-passed');
287
+ elm.addClassName('validation-failed');
288
+ }
289
+
290
+ if (Validation.defaultOptions.addClassNameToContainer && Validation.defaultOptions.containerClassName != '') {
291
+ var container = elm.up(Validation.defaultOptions.containerClassName);
292
+ if (container && this.allowContainerClassName(elm)) {
293
+ container.removeClassName('validation-passed');
294
+ container.addClassName('validation-error');
295
+ }
296
+ }
297
+ return false;
298
+ } else {
299
+ var advice = Validation.getAdvice(name, elm);
300
+ this.hideAdvice(elm, advice);
301
+ this.updateCallback(elm, 'passed');
302
+ elm[prop] = '';
303
+ elm.removeClassName('validation-failed');
304
+ elm.addClassName('validation-passed');
305
+ if (Validation.defaultOptions.addClassNameToContainer && Validation.defaultOptions.containerClassName != '') {
306
+ var container = elm.up(Validation.defaultOptions.containerClassName);
307
+ if (container && !container.down('.validation-failed') && this.allowContainerClassName(elm)) {
308
+ if (!Validation.get('IsEmpty').test(elm.value) || !this.isVisible(elm)) {
309
+ container.addClassName('validation-passed');
310
+ } else {
311
+ container.removeClassName('validation-passed');
312
+ }
313
+ container.removeClassName('validation-error');
314
+ }
315
+ }
316
+ return true;
317
+ }
318
+ } catch(e) {
319
+ throw(e)
320
+ }
321
+ },
322
+ isVisible : function(elm) {
323
+ while(elm.tagName != 'BODY') {
324
+ if(!$(elm).visible()) return false;
325
+ elm = elm.parentNode;
326
+ }
327
+ return true;
328
+ },
329
+ getAdvice : function(name, elm) {
330
+ return $('advice-' + name + '-' + Validation.getElmID(elm)) || $('advice-' + Validation.getElmID(elm));
331
+ },
332
+ createAdvice : function(name, elm, useTitle, customError) {
333
+ var v = Validation.get(name);
334
+ var errorMsg = useTitle ? ((elm && elm.title) ? elm.title : v.error) : v.error;
335
+ if (customError) {
336
+ errorMsg = customError;
337
+ }
338
+ try {
339
+ if (Translator){
340
+ errorMsg = Translator.translate(errorMsg);
341
+ }
342
+ }
343
+ catch(e){}
344
+
345
+ advice = '<div class="validation-advice" id="advice-' + name + '-' + Validation.getElmID(elm) +'" style="display:none">' + errorMsg + '</div>'
346
+
347
+
348
+ Validation.insertAdvice(elm, advice);
349
+ advice = Validation.getAdvice(name, elm);
350
+ if($(elm).hasClassName('absolute-advice')) {
351
+ var dimensions = $(elm).getDimensions();
352
+ var originalPosition = Position.cumulativeOffset(elm);
353
+
354
+ advice._adviceTop = (originalPosition[1] + dimensions.height) + 'px';
355
+ advice._adviceLeft = (originalPosition[0]) + 'px';
356
+ advice._adviceWidth = (dimensions.width) + 'px';
357
+ advice._adviceAbsolutize = true;
358
+ }
359
+ return advice;
360
+ },
361
+ getElmID : function(elm) {
362
+ return elm.id ? elm.id : elm.name;
363
+ },
364
+ reset : function(elm) {
365
+ elm = $(elm);
366
+ var cn = $w(elm.className);
367
+ cn.each(function(value) {
368
+ var prop = '__advice'+value.camelize();
369
+ if(elm[prop]) {
370
+ var advice = Validation.getAdvice(value, elm);
371
+ if (advice) {
372
+ advice.hide();
373
+ }
374
+ elm[prop] = '';
375
+ }
376
+ elm.removeClassName('validation-failed');
377
+ elm.removeClassName('validation-passed');
378
+ if (Validation.defaultOptions.addClassNameToContainer && Validation.defaultOptions.containerClassName != '') {
379
+ var container = elm.up(Validation.defaultOptions.containerClassName);
380
+ if (container) {
381
+ container.removeClassName('validation-passed');
382
+ container.removeClassName('validation-error');
383
+ }
384
+ }
385
+ });
386
+ },
387
+ add : function(className, error, test, options) {
388
+ var nv = {};
389
+ nv[className] = new Validator(className, error, test, options);
390
+ Object.extend(Validation.methods, nv);
391
+ },
392
+ addAllThese : function(validators) {
393
+ var nv = {};
394
+ $A(validators).each(function(value) {
395
+ nv[value[0]] = new Validator(value[0], value[1], value[2], (value.length > 3 ? value[3] : {}));
396
+ });
397
+ Object.extend(Validation.methods, nv);
398
+ },
399
+ get : function(name) {
400
+ return Validation.methods[name] ? Validation.methods[name] : Validation.methods['_LikeNoIDIEverSaw_'];
401
+ },
402
+ methods : {
403
+ '_LikeNoIDIEverSaw_' : new Validator('_LikeNoIDIEverSaw_','',{})
404
+ }
405
+ });
406
+
407
+ Validation.add('IsEmpty', '', function(v) {
408
+ return (v == '' || (v == null) || (v.length == 0) || /^\s+$/.test(v)); // || /^\s+$/.test(v));
409
+ });
410
+
411
+ Validation.addAllThese([
412
+ ['validate-select', 'Please select an option.', function(v) {
413
+ return ((v != "none") && (v != null) && (v.length != 0));
414
+ }],
415
+ ['required-entry', 'This is a required field.', function(v) {
416
+ return !Validation.get('IsEmpty').test(v);
417
+ }],
418
+ ['validate-number', 'Please enter a valid number in this field.', function(v) {
419
+ return Validation.get('IsEmpty').test(v) || (!isNaN(parseNumber(v)) && !/^\s+$/.test(parseNumber(v)));
420
+ }],
421
+ ['validate-digits', 'Please use numbers only in this field. please avoid spaces or other characters such as dots or commas.', function(v) {
422
+ return Validation.get('IsEmpty').test(v) || !/[^\d]/.test(v);
423
+ }],
424
+ ['validate-alpha', 'Please use letters only (a-z or A-Z) in this field.', function (v) {
425
+ return Validation.get('IsEmpty').test(v) || /^[a-zA-Z]+$/.test(v)
426
+ }],
427
+ ['validate-code', 'Please use only letters (a-z), numbers (0-9) or underscore(_) in this field, first character should be a letter.', function (v) {
428
+ return Validation.get('IsEmpty').test(v) || /^[a-z]+[a-z0-9_]+$/.test(v)
429
+ }],
430
+ ['validate-alphanum', 'Please use only letters (a-z or A-Z) or numbers (0-9) only in this field. No spaces or other characters are allowed.', function(v) {
431
+ return Validation.get('IsEmpty').test(v) || /^[a-zA-Z0-9]+$/.test(v) /*!/\W/.test(v)*/
432
+ }],
433
+ ['validate-street', 'Please use only letters (a-z or A-Z) or numbers (0-9) or spaces and # only in this field.', function(v) {
434
+ return Validation.get('IsEmpty').test(v) || /^[ \w]{3,}([A-Za-z]\.)?([ \w]*\#\d+)?(\r\n| )[ \w]{3,}/.test(v)
435
+ }],
436
+ ['validate-phoneStrict', 'Please enter a valid phone number. For example (123) 456-7890 or 123-456-7890.', function(v) {
437
+ return Validation.get('IsEmpty').test(v) || /^(\()?\d{3}(\))?(-|\s)?\d{3}(-|\s)\d{4}$/.test(v);
438
+ }],
439
+ ['validate-phoneLax', 'Please enter a valid phone number. For example (123) 456-7890 or 123-456-7890.', function(v) {
440
+ return Validation.get('IsEmpty').test(v) || /^((\d[-. ]?)?((\(\d{3}\))|\d{3}))?[-. ]?\d{3}[-. ]?\d{4}$/.test(v);
441
+ }],
442
+ ['validate-fax', 'Please enter a valid fax number. For example (123) 456-7890 or 123-456-7890.', function(v) {
443
+ return Validation.get('IsEmpty').test(v) || /^(\()?\d{3}(\))?(-|\s)?\d{3}(-|\s)\d{4}$/.test(v);
444
+ }],
445
+ ['validate-date', 'Please enter a valid date.', function(v) {
446
+ var test = new Date(v);
447
+ return Validation.get('IsEmpty').test(v) || !isNaN(test);
448
+ }],
449
+ ['validate-email', 'Please enter a valid email address. For example johndoe@domain.com.', function (v) {
450
+ //return Validation.get('IsEmpty').test(v) || /\w{1,}[@][\w\-]{1,}([.]([\w\-]{1,})){1,3}$/.test(v)
451
+ //return Validation.get('IsEmpty').test(v) || /^[\!\#$%\*/?|\^\{\}`~&\'\+\-=_a-z0-9][\!\#$%\*/?|\^\{\}`~&\'\+\-=_a-z0-9\.]{1,30}[\!\#$%\*/?|\^\{\}`~&\'\+\-=_a-z0-9]@([a-z0-9_-]{1,30}\.){1,5}[a-z]{2,4}$/i.test(v)
452
+ return Validation.get('IsEmpty').test(v) || /^[a-z0-9,!\#\$%&'\*\+\/=\?\^_`\{\|\}~-]+(\.[a-z0-9,!\#\$%&'\*\+\/=\?\^_`\{\|\}~-]+)*@[a-z0-9-]+(\.[a-z0-9-]+)*\.([a-z]{2,})/i.test(v)
453
+ }],
454
+ ['validate-emailSender', 'Please use only visible characters and spaces.', function (v) {
455
+ return Validation.get('IsEmpty').test(v) || /^[\S ]+$/.test(v)
456
+ }],
457
+ ['validate-password', 'Please enter 6 or more characters. Leading or trailing spaces will be ignored.', function(v) {
458
+ var pass=v.strip(); /*strip leading and trailing spaces*/
459
+ return !(pass.length>0 && pass.length < 6);
460
+ }],
461
+ ['validate-admin-password', 'Please enter 7 or more characters. Password should contain both numeric and alphabetic characters.', function(v) {
462
+ var pass=v.strip();
463
+ if (0 == pass.length) {
464
+ return true;
465
+ }
466
+ if (!(/[a-z]/i.test(v)) || !(/[0-9]/.test(v))) {
467
+ return false;
468
+ }
469
+ return !(pass.length < 7);
470
+ }],
471
+ ['validate-cpassword', 'Please make sure your passwords match.', function(v) {
472
+ var conf = $('confirmation') ? $('confirmation') : $$('.validate-cpassword')[0];
473
+ var pass = false;
474
+ if ($('password')) {
475
+ pass = $('password');
476
+ }
477
+ var passwordElements = $$('.validate-password');
478
+ for (var i = 0; i < passwordElements.size(); i++) {
479
+ var passwordElement = passwordElements[i];
480
+ if (passwordElement.up('form').id == conf.up('form').id) {
481
+ pass = passwordElement;
482
+ }
483
+ }
484
+ if ($$('.validate-admin-password').size()) {
485
+ pass = $$('.validate-admin-password')[0];
486
+ }
487
+ return (pass.value == conf.value);
488
+ }],
489
+ ['validate-url', 'Please enter a valid URL. http:// is required', function (v) {
490
+ return Validation.get('IsEmpty').test(v) || /^(http|https|ftp):\/\/(([A-Z0-9][A-Z0-9_-]*)(\.[A-Z0-9][A-Z0-9_-]*)+)(:(\d+))?\/?/i.test(v)
491
+ }],
492
+ ['validate-clean-url', 'Please enter a valid URL. For example http://www.example.com or www.example.com', function (v) {
493
+ return Validation.get('IsEmpty').test(v) || /^(http|https|ftp):\/\/(([A-Z0-9][A-Z0-9_-]*)(\.[A-Z0-9][A-Z0-9_-]*)+.(com|org|net|dk|at|us|tv|info|uk|co.uk|biz|se)$)(:(\d+))?\/?/i.test(v) || /^(www)((\.[A-Z0-9][A-Z0-9_-]*)+.(com|org|net|dk|at|us|tv|info|uk|co.uk|biz|se)$)(:(\d+))?\/?/i.test(v)
494
+ }],
495
+ ['validate-identifier', 'Please enter a valid URL Key. For example "example-page", "example-page.html" or "anotherlevel/example-page"', function (v) {
496
+ return Validation.get('IsEmpty').test(v) || /^[A-Z0-9][A-Z0-9_\/-]+(\.[A-Z0-9_-]+)*$/i.test(v)
497
+ }],
498
+ ['validate-xml-identifier', 'Please enter a valid XML-identifier. For example something_1, block5, id-4', function (v) {
499
+ return Validation.get('IsEmpty').test(v) || /^[A-Z][A-Z0-9_\/-]*$/i.test(v)
500
+ }],
501
+ ['validate-ssn', 'Please enter a valid social security number. For example 123-45-6789.', function(v) {
502
+ return Validation.get('IsEmpty').test(v) || /^\d{3}-?\d{2}-?\d{4}$/.test(v);
503
+ }],
504
+ ['validate-zip', 'Please enter a valid zip code. For example 90602 or 90602-1234.', function(v) {
505
+ return Validation.get('IsEmpty').test(v) || /(^\d{5}$)|(^\d{5}-\d{4}$)/.test(v);
506
+ }],
507
+ ['validate-zip-international', 'Please enter a valid zip code.', function(v) {
508
+ //return Validation.get('IsEmpty').test(v) || /(^[A-z0-9]{2,10}([\s]{0,1}|[\-]{0,1})[A-z0-9]{2,10}$)/.test(v);
509
+ return true;
510
+ }],
511
+ ['validate-date-au', 'Please use this date format: dd/mm/yyyy. For example 17/03/2006 for the 17th of March, 2006.', function(v) {
512
+ if(Validation.get('IsEmpty').test(v)) return true;
513
+ var regex = /^(\d{2})\/(\d{2})\/(\d{4})$/;
514
+ if(!regex.test(v)) return false;
515
+ var d = new Date(v.replace(regex, '$2/$1/$3'));
516
+ return ( parseInt(RegExp.$2, 10) == (1+d.getMonth()) ) &&
517
+ (parseInt(RegExp.$1, 10) == d.getDate()) &&
518
+ (parseInt(RegExp.$3, 10) == d.getFullYear() );
519
+ }],
520
+ ['validate-currency-dollar', 'Please enter a valid $ amount. For example $100.00.', function(v) {
521
+ // [$]1[##][,###]+[.##]
522
+ // [$]1###+[.##]
523
+ // [$]0.##
524
+ // [$].##
525
+ return Validation.get('IsEmpty').test(v) || /^\$?\-?([1-9]{1}[0-9]{0,2}(\,[0-9]{3})*(\.[0-9]{0,2})?|[1-9]{1}\d*(\.[0-9]{0,2})?|0(\.[0-9]{0,2})?|(\.[0-9]{1,2})?)$/.test(v)
526
+ }],
527
+ ['validate-one-required', 'Please select one of the above options.', function (v,elm) {
528
+ var p = elm.parentNode;
529
+ var options = p.getElementsByTagName('INPUT');
530
+ return $A(options).any(function(elm) {
531
+ return $F(elm);
532
+ });
533
+ }],
534
+ ['validate-one-required-by-name', 'Please select one of the options.', function (v,elm) {
535
+ var inputs = $$('input[name="' + elm.name.replace(/([\\"])/g, '\\$1') + '"]');
536
+
537
+ var error = 1;
538
+ for(var i=0;i<inputs.length;i++) {
539
+ if((inputs[i].type == 'checkbox' || inputs[i].type == 'radio') && inputs[i].checked == true) {
540
+ error = 0;
541
+ }
542
+
543
+ if(Validation.isOnChange && (inputs[i].type == 'checkbox' || inputs[i].type == 'radio')) {
544
+ Validation.reset(inputs[i]);
545
+ }
546
+ }
547
+
548
+ if( error == 0 ) {
549
+ return true;
550
+ } else {
551
+ return false;
552
+ }
553
+ }],
554
+ ['validate-not-negative-number', 'Please enter a valid number in this field.', function(v) {
555
+ v = parseNumber(v);
556
+ return (!isNaN(v) && v>=0);
557
+ }],
558
+ ['validate-state', 'Please select State/Province.', function(v) {
559
+ return (v!=0 || v == '');
560
+ }],
561
+
562
+ ['validate-new-password', 'Please enter 6 or more characters. Leading or trailing spaces will be ignored.', function(v) {
563
+ if (!Validation.get('validate-password').test(v)) return false;
564
+ if (Validation.get('IsEmpty').test(v) && v != '') return false;
565
+ return true;
566
+ }],
567
+ ['validate-greater-than-zero', 'Please enter a number greater than 0 in this field.', function(v) {
568
+ if(v.length)
569
+ return parseFloat(v) > 0;
570
+ else
571
+ return true;
572
+ }],
573
+ ['validate-zero-or-greater', 'Please enter a number 0 or greater in this field.', function(v) {
574
+ if(v.length)
575
+ return parseFloat(v) >= 0;
576
+ else
577
+ return true;
578
+ }],
579
+ ['validate-cc-number', 'Please enter a valid credit card number.', function(v, elm) {
580
+ // remove non-numerics
581
+ var ccTypeContainer = $(elm.id.substr(0,elm.id.indexOf('_cc_number')) + '_cc_type');
582
+ if (ccTypeContainer && typeof Validation.creditCartTypes.get(ccTypeContainer.value) != 'undefined'
583
+ && Validation.creditCartTypes.get(ccTypeContainer.value)[2] == false) {
584
+ if (!Validation.get('IsEmpty').test(v) && Validation.get('validate-digits').test(v)) {
585
+ return true;
586
+ } else {
587
+ return false;
588
+ }
589
+ }
590
+ return validateCreditCard(v);
591
+ }],
592
+ ['validate-cc-type', 'Credit card number doesn\'t match credit card type', function(v, elm) {
593
+ // remove credit card number delimiters such as "-" and space
594
+ elm.value = removeDelimiters(elm.value);
595
+ v = removeDelimiters(v);
596
+
597
+ var ccTypeContainer = $(elm.id.substr(0,elm.id.indexOf('_cc_number')) + '_cc_type');
598
+ if (!ccTypeContainer) {
599
+ return true;
600
+ }
601
+ var ccType = ccTypeContainer.value;
602
+
603
+ if (typeof Validation.creditCartTypes.get(ccType) == 'undefined') {
604
+ return false;
605
+ }
606
+
607
+ // Other card type or switch or solo card
608
+ if (Validation.creditCartTypes.get(ccType)[0]==false) {
609
+ return true;
610
+ }
611
+
612
+ // Matched credit card type
613
+ var ccMatchedType = '';
614
+
615
+ Validation.creditCartTypes.each(function (pair) {
616
+ if (pair.value[0] && v.match(pair.value[0])) {
617
+ ccMatchedType = pair.key;
618
+ throw $break;
619
+ }
620
+ });
621
+
622
+ if(ccMatchedType != ccType) {
623
+ return false;
624
+ }
625
+
626
+ if (ccTypeContainer.hasClassName('validation-failed') && Validation.isOnChange) {
627
+ Validation.validate(ccTypeContainer);
628
+ }
629
+
630
+ return true;
631
+ }],
632
+ ['validate-cc-type-select', 'Card type doesn\'t match credit card number', function(v, elm) {
633
+ var ccNumberContainer = $(elm.id.substr(0,elm.id.indexOf('_cc_type')) + '_cc_number');
634
+ if (Validation.isOnChange && Validation.get('IsEmpty').test(ccNumberContainer.value)) {
635
+ return true;
636
+ }
637
+ if (Validation.get('validate-cc-type').test(ccNumberContainer.value, ccNumberContainer)) {
638
+ Validation.validate(ccNumberContainer);
639
+ }
640
+ return Validation.get('validate-cc-type').test(ccNumberContainer.value, ccNumberContainer);
641
+ }],
642
+ ['validate-cc-exp', 'Incorrect credit card expiration date', function(v, elm) {
643
+ var ccExpMonth = v;
644
+ var ccExpYear = $(elm.id.substr(0,elm.id.indexOf('_expiration')) + '_expiration_yr').value;
645
+ var currentTime = new Date();
646
+ var currentMonth = currentTime.getMonth() + 1;
647
+ var currentYear = currentTime.getFullYear();
648
+ if (ccExpMonth < currentMonth && ccExpYear == currentYear) {
649
+ return false;
650
+ }
651
+ return true;
652
+ }],
653
+ ['validate-cc-cvn', 'Please enter a valid credit card verification number.', function(v, elm) {
654
+ var ccTypeContainer = $(elm.id.substr(0,elm.id.indexOf('_cc_cid')) + '_cc_type');
655
+ if (!ccTypeContainer) {
656
+ return true;
657
+ }
658
+ var ccType = ccTypeContainer.value;
659
+
660
+ if (typeof Validation.creditCartTypes.get(ccType) == 'undefined') {
661
+ return false;
662
+ }
663
+
664
+ var re = Validation.creditCartTypes.get(ccType)[1];
665
+
666
+ if (v.match(re)) {
667
+ return true;
668
+ }
669
+
670
+ return false;
671
+ }],
672
+ ['validate-ajax', '', function(v, elm) { return true; }],
673
+ ['validate-data', 'Please use only letters (a-z or A-Z), numbers (0-9) or underscore(_) in this field, first character should be a letter.', function (v) {
674
+ if(v != '' && v) {
675
+ return /^[A-Za-z]+[A-Za-z0-9_]+$/.test(v);
676
+ }
677
+ return true;
678
+ }],
679
+ ['validate-css-length', 'Please input a valid CSS-length. For example 100px or 77pt or 20em or .5ex or 50%', function (v) {
680
+ if (v != '' && v) {
681
+ return /^[0-9\.]+(px|pt|em|ex|%)?$/.test(v) && (!(/\..*\./.test(v))) && !(/\.$/.test(v));
682
+ }
683
+ return true;
684
+ }],
685
+ ['validate-length', 'Maximum length exceeded.', function (v, elm) {
686
+ var re = new RegExp(/^maximum-length-[0-9]+$/);
687
+ var result = true;
688
+ $w(elm.className).each(function(name, index) {
689
+ if (name.match(re) && result) {
690
+ var length = name.split('-')[2];
691
+ result = (v.length <= length);
692
+ }
693
+ });
694
+ return result;
695
+ }],
696
+ ['validate-percents', 'Please enter a number lower than 100', {max:100}]
697
+
698
+ ]);
699
+
700
+ // Credit Card Validation Javascript
701
+ // copyright 12th May 2003, by Stephen Chapman, Felgall Pty Ltd
702
+
703
+ // You have permission to copy and use this javascript provided that
704
+ // the content of the script is not changed in any way.
705
+
706
+ function validateCreditCard(s) {
707
+ // remove non-numerics
708
+ var v = "0123456789";
709
+ var w = "";
710
+ for (i=0; i < s.length; i++) {
711
+ x = s.charAt(i);
712
+ if (v.indexOf(x,0) != -1)
713
+ w += x;
714
+ }
715
+ // validate number
716
+ j = w.length / 2;
717
+ k = Math.floor(j);
718
+ m = Math.ceil(j) - k;
719
+ c = 0;
720
+ for (i=0; i<k; i++) {
721
+ a = w.charAt(i*2+m) * 2;
722
+ c += a > 9 ? Math.floor(a/10 + a%10) : a;
723
+ }
724
+ for (i=0; i<k+m; i++) c += w.charAt(i*2+1-m) * 1;
725
+ return (c%10 == 0);
726
+ }
727
+
728
+ function removeDelimiters (v) {
729
+ v = v.replace(/\s/g, '');
730
+ v = v.replace(/\-/g, '');
731
+ return v;
732
+ }
733
+
734
+ function parseNumber(v)
735
+ {
736
+ if (typeof v != 'string') {
737
+ return parseFloat(v);
738
+ }
739
+
740
+ var isDot = v.indexOf('.');
741
+ var isComa = v.indexOf(',');
742
+
743
+ if (isDot != -1 && isComa != -1) {
744
+ if (isComa > isDot) {
745
+ v = v.replace('.', '').replace(',', '.');
746
+ }
747
+ else {
748
+ v = v.replace(',', '');
749
+ }
750
+ }
751
+ else if (isComa != -1) {
752
+ v = v.replace(',', '.');
753
+ }
754
+
755
+ return parseFloat(v);
756
+ }
757
+
758
+ /**
759
+ * Hash with credit card types wich can be simply extended in payment modules
760
+ * 0 - regexp for card number
761
+ * 1 - regexp for cvn
762
+ * 2 - check or not credit card number trough Luhn algorithm by
763
+ * function validateCreditCard wich you can find above in this file
764
+ */
765
+ Validation.creditCartTypes = $H({
766
+ 'VI': [new RegExp('^4[0-9]{12}([0-9]{3})?$'), new RegExp('^[0-9]{3}$'), true],
767
+ 'MC': [new RegExp('^5[1-5][0-9]{14}$'), new RegExp('^[0-9]{3}$'), true],
768
+ 'AE': [new RegExp('^3[47][0-9]{13}$'), new RegExp('^[0-9]{4}$'), true],
769
+ 'DI': [new RegExp('^6011[0-9]{12}$'), new RegExp('^[0-9]{3}$'), true],
770
+ 'SS': [new RegExp('^((6759[0-9]{12})|(49[013][1356][0-9]{13})|(633[34][0-9]{12})|(633110[0-9]{10})|(564182[0-9]{10}))([0-9]{2,3})?$'), new RegExp('^([0-9]{3}|[0-9]{4})?$'), true],
771
+ 'OT': [false, new RegExp('^([0-9]{3}|[0-9]{4})?$'), false]
772
+ });
773
+
774
+
js/prototype/window.js ADDED
@@ -0,0 +1,1855 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // Copyright (c) 2006 Sébastien Gruhier (http://xilinus.com, http://itseb.com)
2
+ //
3
+ // Permission is hereby granted, free of charge, to any person obtaining
4
+ // a copy of this software and associated documentation files (the
5
+ // "Software"), to deal in the Software without restriction, including
6
+ // without limitation the rights to use, copy, modify, merge, publish,
7
+ // distribute, sublicense, and/or sell copies of the Software, and to
8
+ // permit persons to whom the Software is furnished to do so, subject to
9
+ // the following conditions:
10
+ //
11
+ // The above copyright notice and this permission notice shall be
12
+ // included in all copies or substantial portions of the Software.
13
+ //
14
+ // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21
+ //
22
+ // VERSION 1.3
23
+
24
+ var Window = Class.create();
25
+
26
+ Window.keepMultiModalWindow = false;
27
+ Window.hasEffectLib = (typeof Effect != 'undefined');
28
+ Window.resizeEffectDuration = 0.4;
29
+
30
+ Window.prototype = {
31
+ // Constructor
32
+ // Available parameters : className, blurClassName, title, minWidth, minHeight, maxWidth, maxHeight, width, height, top, left, bottom, right, resizable, zIndex, opacity, recenterAuto, wiredDrag
33
+ // hideEffect, showEffect, showEffectOptions, hideEffectOptions, effectOptions, url, draggable, closable, minimizable, maximizable, parent, onload
34
+ // add all callbacks (if you do not use an observer)
35
+ // onDestroy onStartResize onStartMove onResize onMove onEndResize onEndMove onFocus onBlur onBeforeShow onShow onHide onMinimize onMaximize onClose
36
+
37
+ initialize: function() {
38
+ var id;
39
+ var optionIndex = 0;
40
+ // For backward compatibility like win= new Window("id", {...}) instead of win = new Window({id: "id", ...})
41
+ if (arguments.length > 0) {
42
+ if (typeof arguments[0] == "string" ) {
43
+ id = arguments[0];
44
+ optionIndex = 1;
45
+ }
46
+ else
47
+ id = arguments[0] ? arguments[0].id : null;
48
+ }
49
+
50
+ // Generate unique ID if not specified
51
+ if (!id)
52
+ id = "window_" + new Date().getTime();
53
+
54
+ if ($(id))
55
+ alert("Window " + id + " is already registered in the DOM! Make sure you use setDestroyOnClose() or destroyOnClose: true in the constructor");
56
+
57
+ this.options = Object.extend({
58
+ className: "dialog",
59
+ blurClassName: null,
60
+ minWidth: 100,
61
+ minHeight: 20,
62
+ resizable: true,
63
+ closable: true,
64
+ minimizable: true,
65
+ maximizable: true,
66
+ draggable: true,
67
+ userData: null,
68
+ showEffect: (Window.hasEffectLib ? Effect.Appear : Element.show),
69
+ hideEffect: (Window.hasEffectLib ? Effect.Fade : Element.hide),
70
+ showEffectOptions: {},
71
+ hideEffectOptions: {},
72
+ effectOptions: null,
73
+ parent: document.body,
74
+ title: "&nbsp;",
75
+ url: null,
76
+ onload: Prototype.emptyFunction,
77
+ width: 200,
78
+ height: 300,
79
+ opacity: 1,
80
+ recenterAuto: true,
81
+ wiredDrag: false,
82
+ closeOnEsc: true,
83
+ closeCallback: null,
84
+ destroyOnClose: false,
85
+ gridX: 1,
86
+ gridY: 1
87
+ }, arguments[optionIndex] || {});
88
+ if (this.options.blurClassName)
89
+ this.options.focusClassName = this.options.className;
90
+
91
+ if (typeof this.options.top == "undefined" && typeof this.options.bottom == "undefined")
92
+ this.options.top = this._round(Math.random()*500, this.options.gridY);
93
+ if (typeof this.options.left == "undefined" && typeof this.options.right == "undefined")
94
+ this.options.left = this._round(Math.random()*500, this.options.gridX);
95
+
96
+ if (this.options.effectOptions) {
97
+ Object.extend(this.options.hideEffectOptions, this.options.effectOptions);
98
+ Object.extend(this.options.showEffectOptions, this.options.effectOptions);
99
+ if (this.options.showEffect == Element.Appear)
100
+ this.options.showEffectOptions.to = this.options.opacity;
101
+ }
102
+ if (Window.hasEffectLib) {
103
+ if (this.options.showEffect == Effect.Appear)
104
+ this.options.showEffectOptions.to = this.options.opacity;
105
+
106
+ if (this.options.hideEffect == Effect.Fade)
107
+ this.options.hideEffectOptions.from = this.options.opacity;
108
+ }
109
+ if (this.options.hideEffect == Element.hide)
110
+ this.options.hideEffect = function(){ Element.hide(this.element); if (this.options.destroyOnClose) this.destroy(); }.bind(this)
111
+
112
+ if (this.options.parent != document.body)
113
+ this.options.parent = $(this.options.parent);
114
+
115
+ this.element = this._createWindow(id);
116
+ this.element.win = this;
117
+
118
+ // Bind event listener
119
+ this.eventMouseDown = this._initDrag.bindAsEventListener(this);
120
+ this.eventMouseUp = this._endDrag.bindAsEventListener(this);
121
+ this.eventMouseMove = this._updateDrag.bindAsEventListener(this);
122
+ this.eventOnLoad = this._getWindowBorderSize.bindAsEventListener(this);
123
+ this.eventMouseDownContent = this.toFront.bindAsEventListener(this);
124
+ this.eventResize = this._recenter.bindAsEventListener(this);
125
+ this.eventKeyUp = this._keyUp.bindAsEventListener(this);
126
+
127
+ this.topbar = $(this.element.id + "_top");
128
+ this.bottombar = $(this.element.id + "_bottom");
129
+ this.content = $(this.element.id + "_content");
130
+
131
+ Event.observe(this.topbar, "mousedown", this.eventMouseDown);
132
+ Event.observe(this.bottombar, "mousedown", this.eventMouseDown);
133
+ Event.observe(this.content, "mousedown", this.eventMouseDownContent);
134
+ Event.observe(window, "load", this.eventOnLoad);
135
+ Event.observe(window, "resize", this.eventResize);
136
+ Event.observe(window, "scroll", this.eventResize);
137
+ Event.observe(document, "keyup", this.eventKeyUp);
138
+ Event.observe(this.options.parent, "scroll", this.eventResize);
139
+
140
+ if (this.options.draggable) {
141
+ var that = this;
142
+ [this.topbar, this.topbar.up().previous(), this.topbar.up().next()].each(function(element) {
143
+ element.observe("mousedown", that.eventMouseDown);
144
+ element.addClassName("top_draggable");
145
+ });
146
+ [this.bottombar.up(), this.bottombar.up().previous(), this.bottombar.up().next()].each(function(element) {
147
+ element.observe("mousedown", that.eventMouseDown);
148
+ element.addClassName("bottom_draggable");
149
+ });
150
+
151
+ }
152
+
153
+ if (this.options.resizable) {
154
+ this.sizer = $(this.element.id + "_sizer");
155
+ Event.observe(this.sizer, "mousedown", this.eventMouseDown);
156
+ }
157
+
158
+ this.useLeft = null;
159
+ this.useTop = null;
160
+ if (typeof this.options.left != "undefined") {
161
+ this.element.setStyle({left: parseFloat(this.options.left) + 'px'});
162
+ this.useLeft = true;
163
+ }
164
+ else {
165
+ this.element.setStyle({right: parseFloat(this.options.right) + 'px'});
166
+ this.useLeft = false;
167
+ }
168
+
169
+ if (typeof this.options.top != "undefined") {
170
+ this.element.setStyle({top: parseFloat(this.options.top) + 'px'});
171
+ this.useTop = true;
172
+ }
173
+ else {
174
+ this.element.setStyle({bottom: parseFloat(this.options.bottom) + 'px'});
175
+ this.useTop = false;
176
+ }
177
+
178
+ this.storedLocation = null;
179
+
180
+ this.setOpacity(this.options.opacity);
181
+ if (this.options.zIndex)
182
+ this.setZIndex(this.options.zIndex)
183
+
184
+ if (this.options.destroyOnClose)
185
+ this.setDestroyOnClose(true);
186
+
187
+ this._getWindowBorderSize();
188
+ this.width = this.options.width;
189
+ this.height = this.options.height;
190
+ this.visible = false;
191
+
192
+ this.constraint = false;
193
+ this.constraintPad = {top: 0, left:0, bottom:0, right:0};
194
+
195
+ if (this.width && this.height)
196
+ this.setSize(this.options.width, this.options.height);
197
+ this.setTitle(this.options.title)
198
+ Windows.register(this);
199
+ },
200
+
201
+ // Destructor
202
+ destroy: function() {
203
+ this._notify("onDestroy");
204
+ Event.stopObserving(this.topbar, "mousedown", this.eventMouseDown);
205
+ Event.stopObserving(this.bottombar, "mousedown", this.eventMouseDown);
206
+ Event.stopObserving(this.content, "mousedown", this.eventMouseDownContent);
207
+
208
+ Event.stopObserving(window, "load", this.eventOnLoad);
209
+ Event.stopObserving(window, "resize", this.eventResize);
210
+ Event.stopObserving(window, "scroll", this.eventResize);
211
+
212
+ Event.stopObserving(this.content, "load", this.options.onload);
213
+ Event.stopObserving(document, "keyup", this.eventKeyUp);
214
+
215
+ if (this._oldParent) {
216
+ var content = this.getContent();
217
+ var originalContent = null;
218
+ for(var i = 0; i < content.childNodes.length; i++) {
219
+ originalContent = content.childNodes[i];
220
+ if (originalContent.nodeType == 1)
221
+ break;
222
+ originalContent = null;
223
+ }
224
+ if (originalContent)
225
+ this._oldParent.appendChild(originalContent);
226
+ this._oldParent = null;
227
+ }
228
+
229
+ if (this.sizer)
230
+ Event.stopObserving(this.sizer, "mousedown", this.eventMouseDown);
231
+
232
+ if (this.options.url)
233
+ this.content.src = null
234
+
235
+ if(this.iefix)
236
+ Element.remove(this.iefix);
237
+
238
+ Element.remove(this.element);
239
+ Windows.unregister(this);
240
+ },
241
+
242
+ // Sets close callback, if it sets, it should return true to be able to close the window.
243
+ setCloseCallback: function(callback) {
244
+ this.options.closeCallback = callback;
245
+ },
246
+
247
+ // Gets window content
248
+ getContent: function () {
249
+ return this.content;
250
+ },
251
+
252
+ // Sets the content with an element id
253
+ setContent: function(id, autoresize, autoposition) {
254
+ var element = $(id);
255
+ if (null == element) throw "Unable to find element '" + id + "' in DOM";
256
+ this._oldParent = element.parentNode;
257
+
258
+ var d = null;
259
+ var p = null;
260
+
261
+ if (autoresize)
262
+ d = Element.getDimensions(element);
263
+ if (autoposition)
264
+ p = Position.cumulativeOffset(element);
265
+
266
+ var content = this.getContent();
267
+ // Clear HTML (and even iframe)
268
+ this.setHTMLContent("");
269
+ content = this.getContent();
270
+
271
+ content.appendChild(element);
272
+ element.show();
273
+ if (autoresize)
274
+ this.setSize(d.width, d.height);
275
+ if (autoposition)
276
+ this.setLocation(p[1] - this.heightN, p[0] - this.widthW);
277
+ },
278
+
279
+ setHTMLContent: function(html) {
280
+ // It was an url (iframe), recreate a div content instead of iframe content
281
+ if (this.options.url) {
282
+ this.content.src = null;
283
+ this.options.url = null;
284
+
285
+ var content ="<div id=\"" + this.getId() + "_content\" class=\"" + this.options.className + "_content\"> </div>";
286
+ $(this.getId() +"_table_content").innerHTML = content;
287
+
288
+ this.content = $(this.element.id + "_content");
289
+ }
290
+
291
+ this.getContent().innerHTML = html;
292
+ },
293
+
294
+ setAjaxContent: function(url, options, showCentered, showModal) {
295
+ this.showFunction = showCentered ? "showCenter" : "show";
296
+ this.showModal = showModal || false;
297
+
298
+ options = options || {};
299
+
300
+ // Clear HTML (and even iframe)
301
+ this.setHTMLContent("");
302
+
303
+ this.onComplete = options.onComplete;
304
+ if (! this._onCompleteHandler)
305
+ this._onCompleteHandler = this._setAjaxContent.bind(this);
306
+ options.onComplete = this._onCompleteHandler;
307
+
308
+ new Ajax.Request(url, options);
309
+ options.onComplete = this.onComplete;
310
+ },
311
+
312
+ _setAjaxContent: function(originalRequest) {
313
+ Element.update(this.getContent(), originalRequest.responseText);
314
+ if (this.onComplete)
315
+ this.onComplete(originalRequest);
316
+ this.onComplete = null;
317
+ this[this.showFunction](this.showModal)
318
+ },
319
+
320
+ setURL: function(url) {
321
+ // Not an url content, change div to iframe
322
+ if (this.options.url)
323
+ this.content.src = null;
324
+ this.options.url = url;
325
+ var content= "<iframe frameborder='0' name='" + this.getId() + "_content' id='" + this.getId() + "_content' src='" + url + "' width='" + this.width + "' height='" + this.height + "'> </iframe>";
326
+ $(this.getId() +"_table_content").innerHTML = content;
327
+
328
+ this.content = $(this.element.id + "_content");
329
+ },
330
+
331
+ getURL: function() {
332
+ return this.options.url ? this.options.url : null;
333
+ },
334
+
335
+ refresh: function() {
336
+ if (this.options.url)
337
+ $(this.element.getAttribute('id') + '_content').src = this.options.url;
338
+ },
339
+
340
+ // Stores position/size in a cookie, by default named with window id
341
+ setCookie: function(name, expires, path, domain, secure) {
342
+ name = name || this.element.id;
343
+ this.cookie = [name, expires, path, domain, secure];
344
+
345
+ // Get cookie
346
+ var value = WindowUtilities.getCookie(name)
347
+ // If exists
348
+ if (value) {
349
+ var values = value.split(',');
350
+ var x = values[0].split(':');
351
+ var y = values[1].split(':');
352
+
353
+ var w = parseFloat(values[2]), h = parseFloat(values[3]);
354
+ var mini = values[4];
355
+ var maxi = values[5];
356
+
357
+ this.setSize(w, h);
358
+ if (mini == "true")
359
+ this.doMinimize = true; // Minimize will be done at onload window event
360
+ else if (maxi == "true")
361
+ this.doMaximize = true; // Maximize will be done at onload window event
362
+
363
+ this.useLeft = x[0] == "l";
364
+ this.useTop = y[0] == "t";
365
+
366
+ this.element.setStyle(this.useLeft ? {left: x[1]} : {right: x[1]});
367
+ this.element.setStyle(this.useTop ? {top: y[1]} : {bottom: y[1]});
368
+ }
369
+ },
370
+
371
+ // Gets window ID
372
+ getId: function() {
373
+ return this.element.id;
374
+ },
375
+
376
+ // Detroys itself when closing
377
+ setDestroyOnClose: function() {
378
+ this.options.destroyOnClose = true;
379
+ },
380
+
381
+ setConstraint: function(bool, padding) {
382
+ this.constraint = bool;
383
+ this.constraintPad = Object.extend(this.constraintPad, padding || {});
384
+ // Reset location to apply constraint
385
+ if (this.useTop && this.useLeft)
386
+ this.setLocation(parseFloat(this.element.style.top), parseFloat(this.element.style.left));
387
+ },
388
+
389
+ // initDrag event
390
+
391
+ _initDrag: function(event) {
392
+ // No resize on minimized window
393
+ if (Event.element(event) == this.sizer && this.isMinimized())
394
+ return;
395
+
396
+ // No move on maximzed window
397
+ if (Event.element(event) != this.sizer && this.isMaximized())
398
+ return;
399
+
400
+ if (Prototype.Browser.IE && this.heightN == 0)
401
+ this._getWindowBorderSize();
402
+
403
+ // Get pointer X,Y
404
+ this.pointer = [this._round(Event.pointerX(event), this.options.gridX), this._round(Event.pointerY(event), this.options.gridY)];
405
+ if (this.options.wiredDrag)
406
+ this.currentDrag = this._createWiredElement();
407
+ else
408
+ this.currentDrag = this.element;
409
+
410
+ // Resize
411
+ if (Event.element(event) == this.sizer) {
412
+ this.doResize = true;
413
+ this.widthOrg = this.width;
414
+ this.heightOrg = this.height;
415
+ this.bottomOrg = parseFloat(this.element.getStyle('bottom'));
416
+ this.rightOrg = parseFloat(this.element.getStyle('right'));
417
+ this._notify("onStartResize");
418
+ }
419
+ else {
420
+ this.doResize = false;
421
+
422
+ // Check if click on close button,
423
+ var closeButton = $(this.getId() + '_close');
424
+ if (closeButton && Position.within(closeButton, this.pointer[0], this.pointer[1])) {
425
+ this.currentDrag = null;
426
+ return;
427
+ }
428
+
429
+ this.toFront();
430
+
431
+ if (! this.options.draggable)
432
+ return;
433
+ this._notify("onStartMove");
434
+ }
435
+ // Register global event to capture mouseUp and mouseMove
436
+ Event.observe(document, "mouseup", this.eventMouseUp, false);
437
+ Event.observe(document, "mousemove", this.eventMouseMove, false);
438
+
439
+ // Add an invisible div to keep catching mouse event over iframes
440
+ WindowUtilities.disableScreen('__invisible__', '__invisible__', this.overlayOpacity);
441
+
442
+ // Stop selection while dragging
443
+ document.body.ondrag = function () { return false; };
444
+ document.body.onselectstart = function () { return false; };
445
+
446
+ this.currentDrag.show();
447
+ Event.stop(event);
448
+ },
449
+
450
+ _round: function(val, round) {
451
+ return round == 1 ? val : val = Math.floor(val / round) * round;
452
+ },
453
+
454
+ // updateDrag event
455
+ _updateDrag: function(event) {
456
+ var pointer = [this._round(Event.pointerX(event), this.options.gridX), this._round(Event.pointerY(event), this.options.gridY)];
457
+ var dx = pointer[0] - this.pointer[0];
458
+ var dy = pointer[1] - this.pointer[1];
459
+
460
+ // Resize case, update width/height
461
+ if (this.doResize) {
462
+ var w = this.widthOrg + dx;
463
+ var h = this.heightOrg + dy;
464
+
465
+ dx = this.width - this.widthOrg
466
+ dy = this.height - this.heightOrg
467
+
468
+ // Check if it's a right position, update it to keep upper-left corner at the same position
469
+ if (this.useLeft)
470
+ w = this._updateWidthConstraint(w)
471
+ else
472
+ this.currentDrag.setStyle({right: (this.rightOrg -dx) + 'px'});
473
+ // Check if it's a bottom position, update it to keep upper-left corner at the same position
474
+ if (this.useTop)
475
+ h = this._updateHeightConstraint(h)
476
+ else
477
+ this.currentDrag.setStyle({bottom: (this.bottomOrg -dy) + 'px'});
478
+
479
+ this.setSize(w , h);
480
+ this._notify("onResize");
481
+ }
482
+ // Move case, update top/left
483
+ else {
484
+ this.pointer = pointer;
485
+
486
+ if (this.useLeft) {
487
+ var left = parseFloat(this.currentDrag.getStyle('left')) + dx;
488
+ var newLeft = this._updateLeftConstraint(left);
489
+ // Keep mouse pointer correct
490
+ this.pointer[0] += newLeft-left;
491
+ this.currentDrag.setStyle({left: newLeft + 'px'});
492
+ }
493
+ else
494
+ this.currentDrag.setStyle({right: parseFloat(this.currentDrag.getStyle('right')) - dx + 'px'});
495
+
496
+ if (this.useTop) {
497
+ var top = parseFloat(this.currentDrag.getStyle('top')) + dy;
498
+ var newTop = this._updateTopConstraint(top);
499
+ // Keep mouse pointer correct
500
+ this.pointer[1] += newTop - top;
501
+ this.currentDrag.setStyle({top: newTop + 'px'});
502
+ }
503
+ else
504
+ this.currentDrag.setStyle({bottom: parseFloat(this.currentDrag.getStyle('bottom')) - dy + 'px'});
505
+
506
+ this._notify("onMove");
507
+ }
508
+ if (this.iefix)
509
+ this._fixIEOverlapping();
510
+
511
+ this._removeStoreLocation();
512
+ Event.stop(event);
513
+ },
514
+
515
+ // endDrag callback
516
+ _endDrag: function(event) {
517
+ // Remove temporary div over iframes
518
+ WindowUtilities.enableScreen('__invisible__');
519
+
520
+ if (this.doResize)
521
+ this._notify("onEndResize");
522
+ else
523
+ this._notify("onEndMove");
524
+
525
+ // Release event observing
526
+ Event.stopObserving(document, "mouseup", this.eventMouseUp,false);
527
+ Event.stopObserving(document, "mousemove", this.eventMouseMove, false);
528
+
529
+ Event.stop(event);
530
+
531
+ this._hideWiredElement();
532
+
533
+ // Store new location/size if need be
534
+ this._saveCookie()
535
+
536
+ // Restore selection
537
+ document.body.ondrag = null;
538
+ document.body.onselectstart = null;
539
+ },
540
+
541
+ _updateLeftConstraint: function(left) {
542
+ if (this.constraint && this.useLeft && this.useTop) {
543
+ var width = this.options.parent == document.body ? WindowUtilities.getPageSize().windowWidth : this.options.parent.getDimensions().width;
544
+
545
+ if (left < this.constraintPad.left)
546
+ left = this.constraintPad.left;
547
+ if (left + this.width + this.widthE + this.widthW > width - this.constraintPad.right)
548
+ left = width - this.constraintPad.right - this.width - this.widthE - this.widthW;
549
+ }
550
+ return left;
551
+ },
552
+
553
+ _updateTopConstraint: function(top) {
554
+ if (this.constraint && this.useLeft && this.useTop) {
555
+ var height = this.options.parent == document.body ? WindowUtilities.getPageSize().windowHeight : this.options.parent.getDimensions().height;
556
+
557
+ var h = this.height + this.heightN + this.heightS;
558
+
559
+ if (top < this.constraintPad.top)
560
+ top = this.constraintPad.top;
561
+ if (top + h > height - this.constraintPad.bottom)
562
+ top = height - this.constraintPad.bottom - h;
563
+ }
564
+ return top;
565
+ },
566
+
567
+ _updateWidthConstraint: function(w) {
568
+ if (this.constraint && this.useLeft && this.useTop) {
569
+ var width = this.options.parent == document.body ? WindowUtilities.getPageSize().windowWidth : this.options.parent.getDimensions().width;
570
+ var left = parseFloat(this.element.getStyle("left"));
571
+
572
+ if (left + w + this.widthE + this.widthW > width - this.constraintPad.right)
573
+ w = width - this.constraintPad.right - left - this.widthE - this.widthW;
574
+ }
575
+ return w;
576
+ },
577
+
578
+ _updateHeightConstraint: function(h) {
579
+ if (this.constraint && this.useLeft && this.useTop) {
580
+ var height = this.options.parent == document.body ? WindowUtilities.getPageSize().windowHeight : this.options.parent.getDimensions().height;
581
+ var top = parseFloat(this.element.getStyle("top"));
582
+
583
+ if (top + h + this.heightN + this.heightS > height - this.constraintPad.bottom)
584
+ h = height - this.constraintPad.bottom - top - this.heightN - this.heightS;
585
+ }
586
+ return h;
587
+ },
588
+
589
+
590
+ // Creates HTML window code
591
+ _createWindow: function(id) {
592
+ var className = this.options.className;
593
+ var win = document.createElement("div");
594
+ win.setAttribute('id', id);
595
+ win.className = "dialog";
596
+
597
+ var content;
598
+ if (this.options.url)
599
+ content= "<iframe frameborder=\"0\" name=\"" + id + "_content\" id=\"" + id + "_content\" src=\"" + this.options.url + "\"> </iframe>";
600
+ else
601
+ content ="<div id=\"" + id + "_content\" class=\"" +className + "_content\"> </div>";
602
+
603
+ var closeDiv = this.options.closable ? "<div class='"+ className +"_close' id='"+ id +"_close' onclick='Windows.close(\""+ id +"\", event)'> </div>" : "";
604
+ var minDiv = this.options.minimizable ? "<div class='"+ className + "_minimize' id='"+ id +"_minimize' onclick='Windows.minimize(\""+ id +"\", event)'> </div>" : "";
605
+ var maxDiv = this.options.maximizable ? "<div class='"+ className + "_maximize' id='"+ id +"_maximize' onclick='Windows.maximize(\""+ id +"\", event)'> </div>" : "";
606
+ var seAttributes = this.options.resizable ? "class='" + className + "_sizer' id='" + id + "_sizer'" : "class='" + className + "_se'";
607
+ var blank = "../themes/default/blank.gif";
608
+
609
+ win.innerHTML = closeDiv + minDiv + maxDiv + "\
610
+ <a href='#' id='"+ id +"_focus_anchor'><!-- --></a>\
611
+ <table id='"+ id +"_row1' class=\"top table_window\">\
612
+ <tr>\
613
+ <td class='"+ className +"_nw'></td>\
614
+ <td class='"+ className +"_n'><div id='"+ id +"_top' class='"+ className +"_title title_window'>"+ this.options.title +"</div></td>\
615
+ <td class='"+ className +"_ne'></td>\
616
+ </tr>\
617
+ </table>\
618
+ <table id='"+ id +"_row2' class=\"mid table_window\">\
619
+ <tr>\
620
+ <td class='"+ className +"_w'></td>\
621
+ <td id='"+ id +"_table_content' class='"+ className +"_content' valign='top'>" + content + "</td>\
622
+ <td class='"+ className +"_e'></td>\
623
+ </tr>\
624
+ </table>\
625
+ <table id='"+ id +"_row3' class=\"bot table_window\">\
626
+ <tr>\
627
+ <td class='"+ className +"_sw'></td>\
628
+ <td class='"+ className +"_s'><div id='"+ id +"_bottom' class='status_bar'><span style='float:left; width:1px; height:1px'></span></div></td>\
629
+ <td " + seAttributes + "></td>\
630
+ </tr>\
631
+ </table>\
632
+ ";
633
+ Element.hide(win);
634
+ this.options.parent.insertBefore(win, this.options.parent.firstChild);
635
+ Event.observe($(id + "_content"), "load", this.options.onload);
636
+ return win;
637
+ },
638
+
639
+
640
+ changeClassName: function(newClassName) {
641
+ var className = this.options.className;
642
+ var id = this.getId();
643
+ $A(["_close", "_minimize", "_maximize", "_sizer", "_content"]).each(function(value) { this._toggleClassName($(id + value), className + value, newClassName + value) }.bind(this));
644
+ this._toggleClassName($(id + "_top"), className + "_title", newClassName + "_title");
645
+ $$("#" + id + " td").each(function(td) {td.className = td.className.sub(className,newClassName); });
646
+ this.options.className = newClassName;
647
+ },
648
+
649
+ _toggleClassName: function(element, oldClassName, newClassName) {
650
+ if (element) {
651
+ element.removeClassName(oldClassName);
652
+ element.addClassName(newClassName);
653
+ }
654
+ },
655
+
656
+ // Sets window location
657
+ setLocation: function(top, left) {
658
+ top = this._updateTopConstraint(top);
659
+ left = this._updateLeftConstraint(left);
660
+
661
+ var e = this.currentDrag || this.element;
662
+ e.setStyle({top: top + 'px'});
663
+ e.setStyle({left: left + 'px'});
664
+
665
+ this.useLeft = true;
666
+ this.useTop = true;
667
+ },
668
+
669
+ getLocation: function() {
670
+ var location = {};
671
+ if (this.useTop)
672
+ location = Object.extend(location, {top: this.element.getStyle("top")});
673
+ else
674
+ location = Object.extend(location, {bottom: this.element.getStyle("bottom")});
675
+ if (this.useLeft)
676
+ location = Object.extend(location, {left: this.element.getStyle("left")});
677
+ else
678
+ location = Object.extend(location, {right: this.element.getStyle("right")});
679
+
680
+ return location;
681
+ },
682
+
683
+ // Gets window size
684
+ getSize: function() {
685
+ return {width: this.width, height: this.height};
686
+ },
687
+
688
+ // Sets window size
689
+ setSize: function(width, height, useEffect) {
690
+ width = parseFloat(width);
691
+ height = parseFloat(height);
692
+
693
+ // Check min and max size
694
+ if (!this.minimized && width < this.options.minWidth)
695
+ width = this.options.minWidth;
696
+
697
+ if (!this.minimized && height < this.options.minHeight)
698
+ height = this.options.minHeight;
699
+
700
+ if (this.options. maxHeight && height > this.options. maxHeight)
701
+ height = this.options. maxHeight;
702
+
703
+ if (this.options. maxWidth && width > this.options. maxWidth)
704
+ width = this.options. maxWidth;
705
+
706
+
707
+ if (this.useTop && this.useLeft && Window.hasEffectLib && Effect.ResizeWindow && useEffect) {
708
+ new Effect.ResizeWindow(this, null, null, width, height, {duration: Window.resizeEffectDuration});
709
+ } else {
710
+ this.width = width;
711
+ this.height = height;
712
+ var e = this.currentDrag ? this.currentDrag : this.element;
713
+
714
+ e.setStyle({width: width + this.widthW + this.widthE + "px"})
715
+ e.setStyle({height: height + this.heightN + this.heightS + "px"})
716
+
717
+ // Update content size
718
+ if (!this.currentDrag || this.currentDrag == this.element) {
719
+ var content = $(this.element.id + '_content');
720
+ content.setStyle({height: height + 'px'});
721
+ content.setStyle({width: width + 'px'});
722
+ }
723
+ }
724
+ },
725
+
726
+ updateHeight: function() {
727
+ this.setSize(this.width, this.content.scrollHeight, true);
728
+ },
729
+
730
+ updateWidth: function() {
731
+ this.setSize(this.content.scrollWidth, this.height, true);
732
+ },
733
+
734
+ // Brings window to front
735
+ toFront: function() {
736
+ if (this.element.style.zIndex < Windows.maxZIndex)
737
+ this.setZIndex(Windows.maxZIndex + 1);
738
+ if (this.iefix)
739
+ this._fixIEOverlapping();
740
+ },
741
+
742
+ getBounds: function(insideOnly) {
743
+ if (! this.width || !this.height || !this.visible)
744
+ this.computeBounds();
745
+ var w = this.width;
746
+ var h = this.height;
747
+
748
+ if (!insideOnly) {
749
+ w += this.widthW + this.widthE;
750
+ h += this.heightN + this.heightS;
751
+ }
752
+ var bounds = Object.extend(this.getLocation(), {width: w + "px", height: h + "px"});
753
+ return bounds;
754
+ },
755
+
756
+ computeBounds: function() {
757
+ if (! this.width || !this.height) {
758
+ var size = WindowUtilities._computeSize(this.content.innerHTML, this.content.id, this.width, this.height, 0, this.options.className)
759
+ if (this.height)
760
+ this.width = size + 5
761
+ else
762
+ this.height = size + 5
763
+ }
764
+
765
+ this.setSize(this.width, this.height);
766
+ if (this.centered)
767
+ this._center(this.centerTop, this.centerLeft);
768
+ },
769
+
770
+ // Displays window modal state or not
771
+ show: function(modal) {
772
+ this.visible = true;
773
+ if (modal) {
774
+ // Hack for Safari !!
775
+ if (typeof this.overlayOpacity == "undefined") {
776
+ var that = this;
777
+ setTimeout(function() {that.show(modal)}, 10);
778
+ return;
779
+ }
780
+ Windows.addModalWindow(this);
781
+
782
+ this.modal = true;
783
+ this.setZIndex(Windows.maxZIndex + 1);
784
+ Windows.unsetOverflow(this);
785
+ }
786
+ else
787
+ if (!this.element.style.zIndex)
788
+ this.setZIndex(Windows.maxZIndex + 1);
789
+
790
+ // To restore overflow if need be
791
+ if (this.oldStyle)
792
+ this.getContent().setStyle({overflow: this.oldStyle});
793
+
794
+ this.computeBounds();
795
+
796
+ this._notify("onBeforeShow");
797
+ if (this.options.showEffect != Element.show && this.options.showEffectOptions)
798
+ this.options.showEffect(this.element, this.options.showEffectOptions);
799
+ else
800
+ this.options.showEffect(this.element);
801
+
802
+ this._checkIEOverlapping();
803
+ WindowUtilities.focusedWindow = this
804
+ this._notify("onShow");
805
+ $(this.element.id + '_focus_anchor').focus();
806
+ },
807
+
808
+ // Displays window modal state or not at the center of the page
809
+ showCenter: function(modal, top, left) {
810
+ this.centered = true;
811
+ this.centerTop = top;
812
+ this.centerLeft = left;
813
+
814
+ this.show(modal);
815
+ },
816
+
817
+ isVisible: function() {
818
+ return this.visible;
819
+ },
820
+
821
+ _center: function(top, left) {
822
+ var windowScroll = WindowUtilities.getWindowScroll(this.options.parent);
823
+ var pageSize = WindowUtilities.getPageSize(this.options.parent);
824
+ if (typeof top == "undefined")
825
+ top = (pageSize.windowHeight - (this.height + this.heightN + this.heightS))/2;
826
+ top += windowScroll.top
827
+
828
+ if (typeof left == "undefined")
829
+ left = (pageSize.windowWidth - (this.width + this.widthW + this.widthE))/2;
830
+ left += windowScroll.left
831
+ this.setLocation(top, left);
832
+ this.toFront();
833
+ },
834
+
835
+ _recenter: function(event) {
836
+ if (this.centered) {
837
+ var pageSize = WindowUtilities.getPageSize(this.options.parent);
838
+ var windowScroll = WindowUtilities.getWindowScroll(this.options.parent);
839
+
840
+ // Check for this stupid IE that sends dumb events
841
+ if (this.pageSize && this.pageSize.windowWidth == pageSize.windowWidth && this.pageSize.windowHeight == pageSize.windowHeight &&
842
+ this.windowScroll.left == windowScroll.left && this.windowScroll.top == windowScroll.top)
843
+ return;
844
+ this.pageSize = pageSize;
845
+ this.windowScroll = windowScroll;
846
+ // set height of Overlay to take up whole page and show
847
+ if ($('overlay_modal'))
848
+ $('overlay_modal').setStyle({height: (pageSize.pageHeight + 'px')});
849
+
850
+ if (this.options.recenterAuto)
851
+ this._center(this.centerTop, this.centerLeft);
852
+ }
853
+ },
854
+
855
+ // Hides window
856
+ hide: function() {
857
+ this.visible = false;
858
+ if (this.modal) {
859
+ Windows.removeModalWindow(this);
860
+ Windows.resetOverflow();
861
+ }
862
+ // To avoid bug on scrolling bar
863
+ this.oldStyle = this.getContent().getStyle('overflow') || "auto"
864
+ this.getContent().setStyle({overflow: "hidden"});
865
+
866
+ this.options.hideEffect(this.element, this.options.hideEffectOptions);
867
+
868
+ if(this.iefix)
869
+ this.iefix.hide();
870
+
871
+ if (!this.doNotNotifyHide)
872
+ this._notify("onHide");
873
+ },
874
+
875
+ close: function() {
876
+ // Asks closeCallback if exists
877
+ if (this.visible) {
878
+ if (this.options.closeCallback && ! this.options.closeCallback(this))
879
+ return;
880
+
881
+ if (this.options.destroyOnClose) {
882
+ var destroyFunc = this.destroy.bind(this);
883
+ if (this.options.hideEffectOptions.afterFinish) {
884
+ var func = this.options.hideEffectOptions.afterFinish;
885
+ this.options.hideEffectOptions.afterFinish = function() {func();destroyFunc() }
886
+ }
887
+ else
888
+ this.options.hideEffectOptions.afterFinish = function() {destroyFunc() }
889
+ }
890
+ Windows.updateFocusedWindow();
891
+
892
+ this.doNotNotifyHide = true;
893
+ this.hide();
894
+ this.doNotNotifyHide = false;
895
+ this._notify("onClose");
896
+ }
897
+ },
898
+
899
+ minimize: function() {
900
+ if (this.resizing)
901
+ return;
902
+
903
+ var r2 = $(this.getId() + "_row2");
904
+
905
+ if (!this.minimized) {
906
+ this.minimized = true;
907
+
908
+ var dh = r2.getDimensions().height;
909
+ this.r2Height = dh;
910
+ var h = this.element.getHeight() - dh;
911
+
912
+ if (this.useLeft && this.useTop && Window.hasEffectLib && Effect.ResizeWindow) {
913
+ new Effect.ResizeWindow(this, null, null, null, this.height -dh, {duration: Window.resizeEffectDuration});
914
+ } else {
915
+ this.height -= dh;
916
+ this.element.setStyle({height: h + "px"});
917
+ r2.hide();
918
+ }
919
+
920
+ if (! this.useTop) {
921
+ var bottom = parseFloat(this.element.getStyle('bottom'));
922
+ this.element.setStyle({bottom: (bottom + dh) + 'px'});
923
+ }
924
+ }
925
+ else {
926
+ this.minimized = false;
927
+
928
+ var dh = this.r2Height;
929
+ this.r2Height = null;
930
+ if (this.useLeft && this.useTop && Window.hasEffectLib && Effect.ResizeWindow) {
931
+ new Effect.ResizeWindow(this, null, null, null, this.height + dh, {duration: Window.resizeEffectDuration});
932
+ }
933
+ else {
934
+ var h = this.element.getHeight() + dh;
935
+ this.height += dh;
936
+ this.element.setStyle({height: h + "px"})
937
+ r2.show();
938
+ }
939
+ if (! this.useTop) {
940
+ var bottom = parseFloat(this.element.getStyle('bottom'));
941
+ this.element.setStyle({bottom: (bottom - dh) + 'px'});
942
+ }
943
+ this.toFront();
944
+ }
945
+ this._notify("onMinimize");
946
+
947
+ // Store new location/size if need be
948
+ this._saveCookie()
949
+ },
950
+
951
+ maximize: function() {
952
+ if (this.isMinimized() || this.resizing)
953
+ return;
954
+
955
+ if (Prototype.Browser.IE && this.heightN == 0)
956
+ this._getWindowBorderSize();
957
+
958
+ if (this.storedLocation != null) {
959
+ this._restoreLocation();
960
+ if(this.iefix)
961
+ this.iefix.hide();
962
+ }
963
+ else {
964
+ this._storeLocation();
965
+ Windows.unsetOverflow(this);
966
+
967
+ var windowScroll = WindowUtilities.getWindowScroll(this.options.parent);
968
+ var pageSize = WindowUtilities.getPageSize(this.options.parent);
969
+ var left = windowScroll.left;
970
+ var top = windowScroll.top;
971
+
972
+ if (this.options.parent != document.body) {
973
+ windowScroll = {top:0, left:0, bottom:0, right:0};
974
+ var dim = this.options.parent.getDimensions();
975
+ pageSize.windowWidth = dim.width;
976
+ pageSize.windowHeight = dim.height;
977
+ top = 0;
978
+ left = 0;
979
+ }
980
+
981
+ if (this.constraint) {
982
+ pageSize.windowWidth -= Math.max(0, this.constraintPad.left) + Math.max(0, this.constraintPad.right);
983
+ pageSize.windowHeight -= Math.max(0, this.constraintPad.top) + Math.max(0, this.constraintPad.bottom);
984
+ left += Math.max(0, this.constraintPad.left);
985
+ top += Math.max(0, this.constraintPad.top);
986
+ }
987
+
988
+ var width = pageSize.windowWidth - this.widthW - this.widthE;
989
+ var height= pageSize.windowHeight - this.heightN - this.heightS;
990
+
991
+ if (this.useLeft && this.useTop && Window.hasEffectLib && Effect.ResizeWindow) {
992
+ new Effect.ResizeWindow(this, top, left, width, height, {duration: Window.resizeEffectDuration});
993
+ }
994
+ else {
995
+ this.setSize(width, height);
996
+ this.element.setStyle(this.useLeft ? {left: left} : {right: left});
997
+ this.element.setStyle(this.useTop ? {top: top} : {bottom: top});
998
+ }
999
+
1000
+ this.toFront();
1001
+ if (this.iefix)
1002
+ this._fixIEOverlapping();
1003
+ }
1004
+ this._notify("onMaximize");
1005
+
1006
+ // Store new location/size if need be
1007
+ this._saveCookie()
1008
+ },
1009
+
1010
+ isMinimized: function() {
1011
+ return this.minimized;
1012
+ },
1013
+
1014
+ isMaximized: function() {
1015
+ return (this.storedLocation != null);
1016
+ },
1017
+
1018
+ setOpacity: function(opacity) {
1019
+ if (Element.setOpacity)
1020
+ Element.setOpacity(this.element, opacity);
1021
+ },
1022
+
1023
+ setZIndex: function(zindex) {
1024
+ this.element.setStyle({zIndex: zindex});
1025
+ Windows.updateZindex(zindex, this);
1026
+ },
1027
+
1028
+ setTitle: function(newTitle) {
1029
+ if (!newTitle || newTitle == "")
1030
+ newTitle = "&nbsp;";
1031
+
1032
+ Element.update(this.element.id + '_top', newTitle);
1033
+ },
1034
+
1035
+ getTitle: function() {
1036
+ return $(this.element.id + '_top').innerHTML;
1037
+ },
1038
+
1039
+ setStatusBar: function(element) {
1040
+ var statusBar = $(this.getId() + "_bottom");
1041
+
1042
+ if (typeof(element) == "object") {
1043
+ if (this.bottombar.firstChild)
1044
+ this.bottombar.replaceChild(element, this.bottombar.firstChild);
1045
+ else
1046
+ this.bottombar.appendChild(element);
1047
+ }
1048
+ else
1049
+ this.bottombar.innerHTML = element;
1050
+ },
1051
+
1052
+ _checkIEOverlapping: function() {
1053
+ if(!this.iefix && (navigator.appVersion.indexOf('MSIE')>0) && (navigator.userAgent.indexOf('Opera')<0) && (this.element.getStyle('position')=='absolute')) {
1054
+ new Insertion.After(this.element.id, '<iframe id="' + this.element.id + '_iefix" '+ 'style="display:none;position:absolute;filter:progid:DXImageTransform.Microsoft.Alpha(opacity=0);" ' + 'src="javascript:false;" frameborder="0" scrolling="no"></iframe>');
1055
+ this.iefix = $(this.element.id+'_iefix');
1056
+ }
1057
+ if(this.iefix)
1058
+ setTimeout(this._fixIEOverlapping.bind(this), 50);
1059
+ },
1060
+
1061
+ _fixIEOverlapping: function() {
1062
+ Position.clone(this.element, this.iefix);
1063
+ this.iefix.style.zIndex = this.element.style.zIndex - 1;
1064
+ this.iefix.show();
1065
+ },
1066
+
1067
+ _keyUp: function(event) {
1068
+ if (27 == event.keyCode && this.options.closeOnEsc) {
1069
+ this.close();
1070
+ }
1071
+ },
1072
+
1073
+ _getWindowBorderSize: function(event) {
1074
+ // Hack to get real window border size!!
1075
+ var div = this._createHiddenDiv(this.options.className + "_n")
1076
+ this.heightN = Element.getDimensions(div).height;
1077
+ div.parentNode.removeChild(div)
1078
+
1079
+ var div = this._createHiddenDiv(this.options.className + "_s")
1080
+ this.heightS = Element.getDimensions(div).height;
1081
+ div.parentNode.removeChild(div)
1082
+
1083
+ var div = this._createHiddenDiv(this.options.className + "_e")
1084
+ this.widthE = Element.getDimensions(div).width;
1085
+ div.parentNode.removeChild(div)
1086
+
1087
+ var div = this._createHiddenDiv(this.options.className + "_w")
1088
+ this.widthW = Element.getDimensions(div).width;
1089
+ div.parentNode.removeChild(div);
1090
+
1091
+ var div = document.createElement("div");
1092
+ div.className = "overlay_" + this.options.className ;
1093
+ document.body.appendChild(div);
1094
+ //alert("no timeout:\nopacity: " + div.getStyle("opacity") + "\nwidth: " + document.defaultView.getComputedStyle(div, null).width);
1095
+ var that = this;
1096
+
1097
+ // Workaround for Safari!!
1098
+ setTimeout(function() {that.overlayOpacity = ($(div).getStyle("opacity")); div.parentNode.removeChild(div);}, 10);
1099
+
1100
+ // Workaround for IE!!
1101
+ if (Prototype.Browser.IE) {
1102
+ this.heightS = $(this.getId() +"_row3").getDimensions().height;
1103
+ this.heightN = $(this.getId() +"_row1").getDimensions().height;
1104
+ }
1105
+
1106
+ // Safari size fix
1107
+ if (Prototype.Browser.WebKit && Prototype.Browser.WebKitVersion < 420)
1108
+ this.setSize(this.width, this.height);
1109
+ if (this.doMaximize)
1110
+ this.maximize();
1111
+ if (this.doMinimize)
1112
+ this.minimize();
1113
+ },
1114
+
1115
+ _createHiddenDiv: function(className) {
1116
+ var objBody = document.body;
1117
+ var win = document.createElement("div");
1118
+ win.setAttribute('id', this.element.id+ "_tmp");
1119
+ win.className = className;
1120
+ win.style.display = 'none';
1121
+ win.innerHTML = '';
1122
+ objBody.insertBefore(win, objBody.firstChild);
1123
+ return win;
1124
+ },
1125
+
1126
+ _storeLocation: function() {
1127
+ if (this.storedLocation == null) {
1128
+ this.storedLocation = {useTop: this.useTop, useLeft: this.useLeft,
1129
+ top: this.element.getStyle('top'), bottom: this.element.getStyle('bottom'),
1130
+ left: this.element.getStyle('left'), right: this.element.getStyle('right'),
1131
+ width: this.width, height: this.height };
1132
+ }
1133
+ },
1134
+
1135
+ _restoreLocation: function() {
1136
+ if (this.storedLocation != null) {
1137
+ this.useLeft = this.storedLocation.useLeft;
1138
+ this.useTop = this.storedLocation.useTop;
1139
+
1140
+ if (this.useLeft && this.useTop && Window.hasEffectLib && Effect.ResizeWindow)
1141
+ new Effect.ResizeWindow(this, this.storedLocation.top, this.storedLocation.left, this.storedLocation.width, this.storedLocation.height, {duration: Window.resizeEffectDuration});
1142
+ else {
1143
+ this.element.setStyle(this.useLeft ? {left: this.storedLocation.left} : {right: this.storedLocation.right});
1144
+ this.element.setStyle(this.useTop ? {top: this.storedLocation.top} : {bottom: this.storedLocation.bottom});
1145
+ this.setSize(this.storedLocation.width, this.storedLocation.height);
1146
+ }
1147
+
1148
+ Windows.resetOverflow();
1149
+ this._removeStoreLocation();
1150
+ }
1151
+ },
1152
+
1153
+ _removeStoreLocation: function() {
1154
+ this.storedLocation = null;
1155
+ },
1156
+
1157
+ _saveCookie: function() {
1158
+ if (this.cookie) {
1159
+ var value = "";
1160
+ if (this.useLeft)
1161
+ value += "l:" + (this.storedLocation ? this.storedLocation.left : this.element.getStyle('left'))
1162
+ else
1163
+ value += "r:" + (this.storedLocation ? this.storedLocation.right : this.element.getStyle('right'))
1164
+ if (this.useTop)
1165
+ value += ",t:" + (this.storedLocation ? this.storedLocation.top : this.element.getStyle('top'))
1166
+ else
1167
+ value += ",b:" + (this.storedLocation ? this.storedLocation.bottom :this.element.getStyle('bottom'))
1168
+
1169
+ value += "," + (this.storedLocation ? this.storedLocation.width : this.width);
1170
+ value += "," + (this.storedLocation ? this.storedLocation.height : this.height);
1171
+ value += "," + this.isMinimized();
1172
+ value += "," + this.isMaximized();
1173
+ WindowUtilities.setCookie(value, this.cookie)
1174
+ }
1175
+ },
1176
+
1177
+ _createWiredElement: function() {
1178
+ if (! this.wiredElement) {
1179
+ if (Prototype.Browser.IE)
1180
+ this._getWindowBorderSize();
1181
+ var div = document.createElement("div");
1182
+ div.className = "wired_frame " + this.options.className + "_wired_frame";
1183
+
1184
+ div.style.position = 'absolute';
1185
+ this.options.parent.insertBefore(div, this.options.parent.firstChild);
1186
+ this.wiredElement = $(div);
1187
+ }
1188
+ if (this.useLeft)
1189
+ this.wiredElement.setStyle({left: this.element.getStyle('left')});
1190
+ else
1191
+ this.wiredElement.setStyle({right: this.element.getStyle('right')});
1192
+
1193
+ if (this.useTop)
1194
+ this.wiredElement.setStyle({top: this.element.getStyle('top')});
1195
+ else
1196
+ this.wiredElement.setStyle({bottom: this.element.getStyle('bottom')});
1197
+
1198
+ var dim = this.element.getDimensions();
1199
+ this.wiredElement.setStyle({width: dim.width + "px", height: dim.height +"px"});
1200
+
1201
+ this.wiredElement.setStyle({zIndex: Windows.maxZIndex+30});
1202
+ return this.wiredElement;
1203
+ },
1204
+
1205
+ _hideWiredElement: function() {
1206
+ if (! this.wiredElement || ! this.currentDrag)
1207
+ return;
1208
+ if (this.currentDrag == this.element)
1209
+ this.currentDrag = null;
1210
+ else {
1211
+ if (this.useLeft)
1212
+ this.element.setStyle({left: this.currentDrag.getStyle('left')});
1213
+ else
1214
+ this.element.setStyle({right: this.currentDrag.getStyle('right')});
1215
+
1216
+ if (this.useTop)
1217
+ this.element.setStyle({top: this.currentDrag.getStyle('top')});
1218
+ else
1219
+ this.element.setStyle({bottom: this.currentDrag.getStyle('bottom')});
1220
+
1221
+ this.currentDrag.hide();
1222
+ this.currentDrag = null;
1223
+ if (this.doResize)
1224
+ this.setSize(this.width, this.height);
1225
+ }
1226
+ },
1227
+
1228
+ _notify: function(eventName) {
1229
+ if (this.options[eventName])
1230
+ this.options[eventName](this);
1231
+ else
1232
+ Windows.notify(eventName, this);
1233
+ }
1234
+ };
1235
+
1236
+ // Windows containers, register all page windows
1237
+ var Windows = {
1238
+ windows: [],
1239
+ modalWindows: [],
1240
+ observers: [],
1241
+ focusedWindow: null,
1242
+ maxZIndex: 0,
1243
+ overlayShowEffectOptions: {duration: 0.5},
1244
+ overlayHideEffectOptions: {duration: 0.5},
1245
+
1246
+ addObserver: function(observer) {
1247
+ this.removeObserver(observer);
1248
+ this.observers.push(observer);
1249
+ },
1250
+
1251
+ removeObserver: function(observer) {
1252
+ this.observers = this.observers.reject( function(o) { return o==observer });
1253
+ },
1254
+
1255
+ // onDestroy onStartResize onStartMove onResize onMove onEndResize onEndMove onFocus onBlur onBeforeShow onShow onHide onMinimize onMaximize onClose
1256
+ notify: function(eventName, win) {
1257
+ this.observers.each( function(o) {if(o[eventName]) o[eventName](eventName, win);});
1258
+ },
1259
+
1260
+ // Gets window from its id
1261
+ getWindow: function(id) {
1262
+ return this.windows.detect(function(d) { return d.getId() ==id });
1263
+ },
1264
+
1265
+ // Gets the last focused window
1266
+ getFocusedWindow: function() {
1267
+ return this.focusedWindow;
1268
+ },
1269
+
1270
+ updateFocusedWindow: function() {
1271
+ this.focusedWindow = this.windows.length >=2 ? this.windows[this.windows.length-2] : null;
1272
+ },
1273
+
1274
+ // Registers a new window (called by Windows constructor)
1275
+ register: function(win) {
1276
+ this.windows.push(win);
1277
+ },
1278
+
1279
+ // Add a modal window in the stack
1280
+ addModalWindow: function(win) {
1281
+ // Disable screen if first modal window
1282
+ if (this.modalWindows.length == 0) {
1283
+ WindowUtilities.disableScreen(win.options.className, 'overlay_modal', win.overlayOpacity, win.getId(), win.options.parent);
1284
+ }
1285
+ else {
1286
+ // Move overlay over all windows
1287
+ if (Window.keepMultiModalWindow) {
1288
+ $('overlay_modal').style.zIndex = Windows.maxZIndex + 1;
1289
+ Windows.maxZIndex += 1;
1290
+ WindowUtilities._hideSelect(this.modalWindows.last().getId());
1291
+ }
1292
+ // Hide current modal window
1293
+ else
1294
+ this.modalWindows.last().element.hide();
1295
+ // Fucking IE select issue
1296
+ WindowUtilities._showSelect(win.getId());
1297
+ }
1298
+ this.modalWindows.push(win);
1299
+ },
1300
+
1301
+ removeModalWindow: function(win) {
1302
+ this.modalWindows.pop();
1303
+
1304
+ // No more modal windows
1305
+ if (this.modalWindows.length == 0)
1306
+ WindowUtilities.enableScreen();
1307
+ else {
1308
+ if (Window.keepMultiModalWindow) {
1309
+ this.modalWindows.last().toFront();
1310
+ WindowUtilities._showSelect(this.modalWindows.last().getId());
1311
+ }
1312
+ else
1313
+ this.modalWindows.last().element.show();
1314
+ }
1315
+ },
1316
+
1317
+ // Registers a new window (called by Windows constructor)
1318
+ register: function(win) {
1319
+ this.windows.push(win);
1320
+ },
1321
+
1322
+ // Unregisters a window (called by Windows destructor)
1323
+ unregister: function(win) {
1324
+ this.windows = this.windows.reject(function(d) { return d==win });
1325
+ },
1326
+
1327
+ // Closes all windows
1328
+ closeAll: function() {
1329
+ this.windows.each( function(w) {Windows.close(w.getId())} );
1330
+ },
1331
+
1332
+ closeAllModalWindows: function() {
1333
+ WindowUtilities.enableScreen();
1334
+ this.modalWindows.each( function(win) {if (win) win.close()});
1335
+ },
1336
+
1337
+ // Minimizes a window with its id
1338
+ minimize: function(id, event) {
1339
+ var win = this.getWindow(id)
1340
+ if (win && win.visible)
1341
+ win.minimize();
1342
+ Event.stop(event);
1343
+ },
1344
+
1345
+ // Maximizes a window with its id
1346
+ maximize: function(id, event) {
1347
+ var win = this.getWindow(id)
1348
+ if (win && win.visible)
1349
+ win.maximize();
1350
+ Event.stop(event);
1351
+ },
1352
+
1353
+ // Closes a window with its id
1354
+ close: function(id, event) {
1355
+ var win = this.getWindow(id);
1356
+ if (win)
1357
+ win.close();
1358
+ if (event)
1359
+ Event.stop(event);
1360
+ },
1361
+
1362
+ blur: function(id) {
1363
+ var win = this.getWindow(id);
1364
+ if (!win)
1365
+ return;
1366
+ if (win.options.blurClassName)
1367
+ win.changeClassName(win.options.blurClassName);
1368
+ if (this.focusedWindow == win)
1369
+ this.focusedWindow = null;
1370
+ win._notify("onBlur");
1371
+ },
1372
+
1373
+ focus: function(id) {
1374
+ var win = this.getWindow(id);
1375
+ if (!win)
1376
+ return;
1377
+ if (this.focusedWindow)
1378
+ this.blur(this.focusedWindow.getId())
1379
+
1380
+ if (win.options.focusClassName)
1381
+ win.changeClassName(win.options.focusClassName);
1382
+ this.focusedWindow = win;
1383
+ win._notify("onFocus");
1384
+ },
1385
+
1386
+ unsetOverflow: function(except) {
1387
+ this.windows.each(function(d) { d.oldOverflow = d.getContent().getStyle("overflow") || "auto" ; d.getContent().setStyle({overflow: "hidden"}) });
1388
+ if (except && except.oldOverflow)
1389
+ except.getContent().setStyle({overflow: except.oldOverflow});
1390
+ },
1391
+
1392
+ resetOverflow: function() {
1393
+ this.windows.each(function(d) { if (d.oldOverflow) d.getContent().setStyle({overflow: d.oldOverflow}) });
1394
+ },
1395
+
1396
+ updateZindex: function(zindex, win) {
1397
+ if (zindex > this.maxZIndex) {
1398
+ this.maxZIndex = zindex;
1399
+ if (this.focusedWindow)
1400
+ this.blur(this.focusedWindow.getId())
1401
+ }
1402
+ this.focusedWindow = win;
1403
+ if (this.focusedWindow)
1404
+ this.focus(this.focusedWindow.getId())
1405
+ }
1406
+ };
1407
+
1408
+ var Dialog = {
1409
+ dialogId: null,
1410
+ onCompleteFunc: null,
1411
+ callFunc: null,
1412
+ parameters: null,
1413
+
1414
+ confirm: function(content, parameters) {
1415
+ // Get Ajax return before
1416
+ if (content && typeof content != "string") {
1417
+ Dialog._runAjaxRequest(content, parameters, Dialog.confirm);
1418
+ return
1419
+ }
1420
+ content = content || "";
1421
+
1422
+ parameters = parameters || {};
1423
+ var okLabel = parameters.okLabel ? parameters.okLabel : "Ok";
1424
+ var cancelLabel = parameters.cancelLabel ? parameters.cancelLabel : "Cancel";
1425
+
1426
+ // Backward compatibility
1427
+ parameters = Object.extend(parameters, parameters.windowParameters || {});
1428
+ parameters.windowParameters = parameters.windowParameters || {};
1429
+
1430
+ parameters.className = parameters.className || "alert";
1431
+
1432
+ var okButtonClass = "class ='" + (parameters.buttonClass ? parameters.buttonClass + " " : "") + " ok_button'"
1433
+ var cancelButtonClass = "class ='" + (parameters.buttonClass ? parameters.buttonClass + " " : "") + " cancel_button'"
1434
+ var content = "\
1435
+ <div class='" + parameters.className + "_message'>" + content + "</div>\
1436
+ <div class='" + parameters.className + "_buttons'>\
1437
+ <input type='button' value='" + okLabel + "' onclick='Dialog.okCallback()' " + okButtonClass + "/>\
1438
+ <input type='button' value='" + cancelLabel + "' onclick='Dialog.cancelCallback()' " + cancelButtonClass + "/>\
1439
+ </div>\
1440
+ ";
1441
+ return this._openDialog(content, parameters)
1442
+ },
1443
+
1444
+ alert: function(content, parameters) {
1445
+ // Get Ajax return before
1446
+ if (content && typeof content != "string") {
1447
+ Dialog._runAjaxRequest(content, parameters, Dialog.alert);
1448
+ return
1449
+ }
1450
+ content = content || "";
1451
+
1452
+ parameters = parameters || {};
1453
+ var okLabel = parameters.okLabel ? parameters.okLabel : "Ok";
1454
+
1455
+ // Backward compatibility
1456
+ parameters = Object.extend(parameters, parameters.windowParameters || {});
1457
+ parameters.windowParameters = parameters.windowParameters || {};
1458
+
1459
+ parameters.className = parameters.className || "alert";
1460
+
1461
+ var okButtonClass = "class ='" + (parameters.buttonClass ? parameters.buttonClass + " " : "") + " ok_button'"
1462
+ var content = "\
1463
+ <div class='" + parameters.className + "_message'>" + content + "</div>\
1464
+ <div class='" + parameters.className + "_buttons'>\
1465
+ <input type='button' value='" + okLabel + "' onclick='Dialog.okCallback()' " + okButtonClass + "/>\
1466
+ </div>";
1467
+ return this._openDialog(content, parameters)
1468
+ },
1469
+
1470
+ info: function(content, parameters) {
1471
+ // Get Ajax return before
1472
+ if (content && typeof content != "string") {
1473
+ Dialog._runAjaxRequest(content, parameters, Dialog.info);
1474
+ return
1475
+ }
1476
+ content = content || "";
1477
+
1478
+ // Backward compatibility
1479
+ parameters = parameters || {};
1480
+ parameters = Object.extend(parameters, parameters.windowParameters || {});
1481
+ parameters.windowParameters = parameters.windowParameters || {};
1482
+
1483
+ parameters.className = parameters.className || "alert";
1484
+
1485
+ var content = "<div id='modal_dialog_message' class='" + parameters.className + "_message'>" + content + "</div>";
1486
+ if (parameters.showProgress)
1487
+ content += "<div id='modal_dialog_progress' class='" + parameters.className + "_progress'> </div>";
1488
+
1489
+ parameters.ok = null;
1490
+ parameters.cancel = null;
1491
+
1492
+ return this._openDialog(content, parameters)
1493
+ },
1494
+
1495
+ setInfoMessage: function(message) {
1496
+ $('modal_dialog_message').update(message);
1497
+ },
1498
+
1499
+ closeInfo: function() {
1500
+ Windows.close(this.dialogId);
1501
+ },
1502
+
1503
+ _openDialog: function(content, parameters) {
1504
+ var className = parameters.className;
1505
+
1506
+ if (! parameters.height && ! parameters.width) {
1507
+ parameters.width = WindowUtilities.getPageSize(parameters.options.parent || document.body).pageWidth / 2;
1508
+ }
1509
+ if (parameters.id)
1510
+ this.dialogId = parameters.id;
1511
+ else {
1512
+ var t = new Date();
1513
+ this.dialogId = 'modal_dialog_' + t.getTime();
1514
+ parameters.id = this.dialogId;
1515
+ }
1516
+
1517
+ // compute height or width if need be
1518
+ if (! parameters.height || ! parameters.width) {
1519
+ var size = WindowUtilities._computeSize(content, this.dialogId, parameters.width, parameters.height, 5, className)
1520
+ if (parameters.height)
1521
+ parameters.width = size + 5
1522
+ else
1523
+ parameters.height = size + 5
1524
+ }
1525
+ parameters.effectOptions = parameters.effectOptions ;
1526
+ parameters.resizable = parameters.resizable || false;
1527
+ parameters.minimizable = parameters.minimizable || false;
1528
+ parameters.maximizable = parameters.maximizable || false;
1529
+ parameters.draggable = parameters.draggable || false;
1530
+ parameters.closable = parameters.closable || false;
1531
+
1532
+ var win = new Window(parameters);
1533
+ win.getContent().innerHTML = content;
1534
+
1535
+ win.showCenter(true, parameters.top, parameters.left);
1536
+ win.setDestroyOnClose();
1537
+
1538
+ win.cancelCallback = parameters.onCancel || parameters.cancel;
1539
+ win.okCallback = parameters.onOk || parameters.ok;
1540
+
1541
+ return win;
1542
+ },
1543
+
1544
+ _getAjaxContent: function(originalRequest) {
1545
+ Dialog.callFunc(originalRequest.responseText, Dialog.parameters)
1546
+ },
1547
+
1548
+ _runAjaxRequest: function(message, parameters, callFunc) {
1549
+ if (message.options == null)
1550
+ message.options = {}
1551
+ Dialog.onCompleteFunc = message.options.onComplete;
1552
+ Dialog.parameters = parameters;
1553
+ Dialog.callFunc = callFunc;
1554
+
1555
+ message.options.onComplete = Dialog._getAjaxContent;
1556
+ new Ajax.Request(message.url, message.options);
1557
+ },
1558
+
1559
+ okCallback: function() {
1560
+ var win = Windows.focusedWindow;
1561
+ if (!win.okCallback || win.okCallback(win)) {
1562
+ // Remove onclick on button
1563
+ $$("#" + win.getId()+" input").each(function(element) {element.onclick=null;})
1564
+ win.close();
1565
+ }
1566
+ },
1567
+
1568
+ cancelCallback: function() {
1569
+ var win = Windows.focusedWindow;
1570
+ // Remove onclick on button
1571
+ $$("#" + win.getId()+" input").each(function(element) {element.onclick=null})
1572
+ win.close();
1573
+ if (win.cancelCallback)
1574
+ win.cancelCallback(win);
1575
+ }
1576
+ }
1577
+ /*
1578
+ Based on Lightbox JS: Fullsize Image Overlays
1579
+ by Lokesh Dhakar - http://www.huddletogether.com
1580
+
1581
+ For more information on this script, visit:
1582
+ http://huddletogether.com/projects/lightbox/
1583
+
1584
+ Licensed under the Creative Commons Attribution 2.5 License - http://creativecommons.org/licenses/by/2.5/
1585
+ (basically, do anything you want, just leave my name and link)
1586
+ */
1587
+
1588
+ if (Prototype.Browser.WebKit) {
1589
+ var array = navigator.userAgent.match(new RegExp(/AppleWebKit\/([\d\.\+]*)/));
1590
+ Prototype.Browser.WebKitVersion = parseFloat(array[1]);
1591
+ }
1592
+
1593
+ var WindowUtilities = {
1594
+ // From dragdrop.js
1595
+ getWindowScroll: function(parent) {
1596
+ var T, L, W, H;
1597
+ parent = parent || document.body;
1598
+ if (parent != document.body) {
1599
+ T = parent.scrollTop;
1600
+ L = parent.scrollLeft;
1601
+ W = parent.scrollWidth;
1602
+ H = parent.scrollHeight;
1603
+ }
1604
+ else {
1605
+ var w = window;
1606
+ with (w.document) {
1607
+ if (w.document.documentElement && documentElement.scrollTop) {
1608
+ T = documentElement.scrollTop;
1609
+ L = documentElement.scrollLeft;
1610
+ } else if (w.document.body) {
1611
+ T = body.scrollTop;
1612
+ L = body.scrollLeft;
1613
+ }
1614
+ if (w.innerWidth) {
1615
+ W = w.innerWidth;
1616
+ H = w.innerHeight;
1617
+ } else if (w.document.documentElement && documentElement.clientWidth) {
1618
+ W = documentElement.clientWidth;
1619
+ H = documentElement.clientHeight;
1620
+ } else {
1621
+ W = body.offsetWidth;
1622
+ H = body.offsetHeight
1623
+ }
1624
+ }
1625
+ }
1626
+ return { top: T, left: L, width: W, height: H };
1627
+ },
1628
+ //
1629
+ // getPageSize()
1630
+ // Returns array with page width, height and window width, height
1631
+ // Core code from - quirksmode.org
1632
+ // Edit for Firefox by pHaez
1633
+ //
1634
+ getPageSize: function(parent){
1635
+ parent = parent || document.body;
1636
+ var windowWidth, windowHeight;
1637
+ var pageHeight, pageWidth;
1638
+ if (parent != document.body) {
1639
+ windowWidth = parent.getWidth();
1640
+ windowHeight = parent.getHeight();
1641
+ pageWidth = parent.scrollWidth;
1642
+ pageHeight = parent.scrollHeight;
1643
+ }
1644
+ else {
1645
+ var xScroll, yScroll;
1646
+
1647
+ if (window.innerHeight && window.scrollMaxY) {
1648
+ xScroll = document.body.scrollWidth;
1649
+ yScroll = window.innerHeight + window.scrollMaxY;
1650
+ } else if (document.body.scrollHeight > document.body.offsetHeight){ // all but Explorer Mac
1651
+ xScroll = document.body.scrollWidth;
1652
+ yScroll = document.body.scrollHeight;
1653
+ } else { // Explorer Mac...would also work in Explorer 6 Strict, Mozilla and Safari
1654
+ xScroll = document.body.offsetWidth;
1655
+ yScroll = document.body.offsetHeight;
1656
+ }
1657
+
1658
+
1659
+ if (self.innerHeight) { // all except Explorer
1660
+ windowWidth = self.innerWidth;
1661
+ windowHeight = self.innerHeight;
1662
+ } else if (document.documentElement && document.documentElement.clientHeight) { // Explorer 6 Strict Mode
1663
+ windowWidth = document.documentElement.clientWidth;
1664
+ windowHeight = document.documentElement.clientHeight;
1665
+ } else if (document.body) { // other Explorers
1666
+ windowWidth = document.body.clientWidth;
1667
+ windowHeight = document.body.clientHeight;
1668
+ }
1669
+
1670
+ // for small pages with total height less then height of the viewport
1671
+ if(yScroll < windowHeight){
1672
+ pageHeight = windowHeight;
1673
+ } else {
1674
+ pageHeight = yScroll;
1675
+ }
1676
+
1677
+ // for small pages with total width less then width of the viewport
1678
+ if(xScroll < windowWidth){
1679
+ pageWidth = windowWidth;
1680
+ } else {
1681
+ pageWidth = xScroll;
1682
+ }
1683
+ }
1684
+ return {pageWidth: pageWidth ,pageHeight: pageHeight , windowWidth: windowWidth, windowHeight: windowHeight};
1685
+ },
1686
+
1687
+ disableScreen: function(className, overlayId, overlayOpacity, contentId, parent) {
1688
+ WindowUtilities.initLightbox(overlayId, className, function() {this._disableScreen(className, overlayId, overlayOpacity, contentId)}.bind(this), parent || document.body);
1689
+ },
1690
+
1691
+ _disableScreen: function(className, overlayId, overlayOpacity, contentId) {
1692
+ // prep objects
1693
+ var objOverlay = $(overlayId);
1694
+
1695
+ var pageSize = WindowUtilities.getPageSize(objOverlay.parentNode);
1696
+
1697
+ // Hide select boxes as they will 'peek' through the image in IE, store old value
1698
+ if (contentId && Prototype.Browser.IE) {
1699
+ WindowUtilities._hideSelect();
1700
+ WindowUtilities._showSelect(contentId);
1701
+ }
1702
+
1703
+ // set height of Overlay to take up whole page and show
1704
+ objOverlay.style.height = (pageSize.pageHeight + 'px');
1705
+ objOverlay.style.display = 'none';
1706
+ if (overlayId == "overlay_modal" && Window.hasEffectLib && Windows.overlayShowEffectOptions) {
1707
+ objOverlay.overlayOpacity = overlayOpacity;
1708
+ new Effect.Appear(objOverlay, Object.extend({from: 0, to: overlayOpacity}, Windows.overlayShowEffectOptions));
1709
+ }
1710
+ else
1711
+ objOverlay.style.display = "block";
1712
+ },
1713
+
1714
+ enableScreen: function(id) {
1715
+ id = id || 'overlay_modal';
1716
+ var objOverlay = $(id);
1717
+ if (objOverlay) {
1718
+ // hide lightbox and overlay
1719
+ if (id == "overlay_modal" && Window.hasEffectLib && Windows.overlayHideEffectOptions)
1720
+ new Effect.Fade(objOverlay, Object.extend({from: objOverlay.overlayOpacity, to:0}, Windows.overlayHideEffectOptions));
1721
+ else {
1722
+ objOverlay.style.display = 'none';
1723
+ objOverlay.parentNode.removeChild(objOverlay);
1724
+ }
1725
+
1726
+ // make select boxes visible using old value
1727
+ if (id != "__invisible__")
1728
+ WindowUtilities._showSelect();
1729
+ }
1730
+ },
1731
+
1732
+ _hideSelect: function(id) {
1733
+ if (Prototype.Browser.IE) {
1734
+ id = id == null ? "" : "#" + id + " ";
1735
+ $$(id + 'select').each(function(element) {
1736
+ if (! WindowUtilities.isDefined(element.oldVisibility)) {
1737
+ element.oldVisibility = element.style.visibility ? element.style.visibility : "visible";
1738
+ element.style.visibility = "hidden";
1739
+ }
1740
+ });
1741
+ }
1742
+ },
1743
+
1744
+ _showSelect: function(id) {
1745
+ if (Prototype.Browser.IE) {
1746
+ id = id == null ? "" : "#" + id + " ";
1747
+ $$(id + 'select').each(function(element) {
1748
+ if (WindowUtilities.isDefined(element.oldVisibility)) {
1749
+ // Why?? Ask IE
1750
+ try {
1751
+ element.style.visibility = element.oldVisibility;
1752
+ } catch(e) {
1753
+ element.style.visibility = "visible";
1754
+ }
1755
+ element.oldVisibility = null;
1756
+ }
1757
+ else {
1758
+ if (element.style.visibility)
1759
+ element.style.visibility = "visible";
1760
+ }
1761
+ });
1762
+ }
1763
+ },
1764
+
1765
+ isDefined: function(object) {
1766
+ return typeof(object) != "undefined" && object != null;
1767
+ },
1768
+
1769
+ // initLightbox()
1770
+ // Function runs on window load, going through link tags looking for rel="lightbox".
1771
+ // These links receive onclick events that enable the lightbox display for their targets.
1772
+ // The function also inserts html markup at the top of the page which will be used as a
1773
+ // container for the overlay pattern and the inline image.
1774
+ initLightbox: function(id, className, doneHandler, parent) {
1775
+ // Already done, just update zIndex
1776
+ if ($(id)) {
1777
+ Element.setStyle(id, {zIndex: Windows.maxZIndex + 1});
1778
+ Windows.maxZIndex++;
1779
+ doneHandler();
1780
+ }
1781
+ // create overlay div and hardcode some functional styles (aesthetic styles are in CSS file)
1782
+ else {
1783
+ var objOverlay = document.createElement("div");
1784
+ objOverlay.setAttribute('id', id);
1785
+ objOverlay.className = "overlay_" + className
1786
+ objOverlay.style.display = 'none';
1787
+ objOverlay.style.position = 'absolute';
1788
+ objOverlay.style.top = '0';
1789
+ objOverlay.style.left = '0';
1790
+ objOverlay.style.zIndex = Windows.maxZIndex + 1;
1791
+ Windows.maxZIndex++;
1792
+ objOverlay.style.width = '100%';
1793
+ parent.insertBefore(objOverlay, parent.firstChild);
1794
+ if (Prototype.Browser.WebKit && id == "overlay_modal") {
1795
+ setTimeout(function() {doneHandler()}, 10);
1796
+ }
1797
+ else
1798
+ doneHandler();
1799
+ }
1800
+ },
1801
+
1802
+ setCookie: function(value, parameters) {
1803
+ document.cookie= parameters[0] + "=" + escape(value) +
1804
+ ((parameters[1]) ? "; expires=" + parameters[1].toGMTString() : "") +
1805
+ ((parameters[2]) ? "; path=" + parameters[2] : "") +
1806
+ ((parameters[3]) ? "; domain=" + parameters[3] : "") +
1807
+ ((parameters[4]) ? "; secure" : "");
1808
+ },
1809
+
1810
+ getCookie: function(name) {
1811
+ var dc = document.cookie;
1812
+ var prefix = name + "=";
1813
+ var begin = dc.indexOf("; " + prefix);
1814
+ if (begin == -1) {
1815
+ begin = dc.indexOf(prefix);
1816
+ if (begin != 0) return null;
1817
+ } else {
1818
+ begin += 2;
1819
+ }
1820
+ var end = document.cookie.indexOf(";", begin);
1821
+ if (end == -1) {
1822
+ end = dc.length;
1823
+ }
1824
+ return unescape(dc.substring(begin + prefix.length, end));
1825
+ },
1826
+
1827
+ _computeSize: function(content, id, width, height, margin, className) {
1828
+ var objBody = document.body;
1829
+ var tmpObj = document.createElement("div");
1830
+ tmpObj.setAttribute('id', id);
1831
+ tmpObj.className = className + "_content";
1832
+
1833
+ if (height)
1834
+ tmpObj.style.height = height + "px"
1835
+ else
1836
+ tmpObj.style.width = width + "px"
1837
+
1838
+ tmpObj.style.position = 'absolute';
1839
+ tmpObj.style.top = '0';
1840
+ tmpObj.style.left = '0';
1841
+ tmpObj.style.display = 'none';
1842
+
1843
+ tmpObj.innerHTML = content;
1844
+ objBody.insertBefore(tmpObj, objBody.firstChild);
1845
+
1846
+ var size;
1847
+ if (height)
1848
+ size = $(tmpObj).getDimensions().width + margin;
1849
+ else
1850
+ size = $(tmpObj).getDimensions().height + margin;
1851
+ objBody.removeChild(tmpObj);
1852
+ return size;
1853
+ }
1854
+ }
1855
+
js/prototype/window_effects.js ADDED
@@ -0,0 +1,157 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ Effect.ResizeWindow = Class.create();
2
+ Object.extend(Object.extend(Effect.ResizeWindow.prototype, Effect.Base.prototype), {
3
+ initialize: function(win, top, left, width, height) {
4
+ this.window = win;
5
+ this.window.resizing = true;
6
+
7
+ var size = win.getSize();
8
+ this.initWidth = parseFloat(size.width);
9
+ this.initHeight = parseFloat(size.height);
10
+
11
+ var location = win.getLocation();
12
+ this.initTop = parseFloat(location.top);
13
+ this.initLeft = parseFloat(location.left);
14
+
15
+ this.width = width != null ? parseFloat(width) : this.initWidth;
16
+ this.height = height != null ? parseFloat(height) : this.initHeight;
17
+ this.top = top != null ? parseFloat(top) : this.initTop;
18
+ this.left = left != null ? parseFloat(left) : this.initLeft;
19
+
20
+ this.dx = this.left - this.initLeft;
21
+ this.dy = this.top - this.initTop;
22
+ this.dw = this.width - this.initWidth;
23
+ this.dh = this.height - this.initHeight;
24
+
25
+ this.r2 = $(this.window.getId() + "_row2");
26
+ this.content = $(this.window.getId() + "_content");
27
+
28
+ this.contentOverflow = this.content.getStyle("overflow") || "auto";
29
+ this.content.setStyle({overflow: "hidden"});
30
+
31
+ // Wired mode
32
+ if (this.window.options.wiredDrag) {
33
+ this.window.currentDrag = win._createWiredElement();
34
+ this.window.currentDrag.show();
35
+ this.window.element.hide();
36
+ }
37
+
38
+ this.start(arguments[5]);
39
+ },
40
+
41
+ update: function(position) {
42
+ var width = Math.floor(this.initWidth + this.dw * position);
43
+ var height = Math.floor(this.initHeight + this.dh * position);
44
+ var top = Math.floor(this.initTop + this.dy * position);
45
+ var left = Math.floor(this.initLeft + this.dx * position);
46
+
47
+ if (window.ie) {
48
+ if (Math.floor(height) == 0)
49
+ this.r2.hide();
50
+ else if (Math.floor(height) >1)
51
+ this.r2.show();
52
+ }
53
+ this.r2.setStyle({height: height});
54
+ this.window.setSize(width, height);
55
+ this.window.setLocation(top, left);
56
+ },
57
+
58
+ finish: function(position) {
59
+ // Wired mode
60
+ if (this.window.options.wiredDrag) {
61
+ this.window._hideWiredElement();
62
+ this.window.element.show();
63
+ }
64
+
65
+ this.window.setSize(this.width, this.height);
66
+ this.window.setLocation(this.top, this.left);
67
+ this.r2.setStyle({height: null});
68
+
69
+ this.content.setStyle({overflow: this.contentOverflow});
70
+
71
+ this.window.resizing = false;
72
+ }
73
+ });
74
+
75
+ Effect.ModalSlideDown = function(element) {
76
+ var windowScroll = WindowUtilities.getWindowScroll();
77
+ var height = element.getStyle("height");
78
+ element.setStyle({top: - (parseFloat(height) - windowScroll.top) + "px"});
79
+
80
+ element.show();
81
+ return new Effect.Move(element, Object.extend({ x: 0, y: parseFloat(height) }, arguments[1] || {}));
82
+ };
83
+
84
+
85
+ Effect.ModalSlideUp = function(element) {
86
+ var height = element.getStyle("height");
87
+ return new Effect.Move(element, Object.extend({ x: 0, y: -parseFloat(height) }, arguments[1] || {}));
88
+ };
89
+
90
+ PopupEffect = Class.create();
91
+ PopupEffect.prototype = {
92
+ initialize: function(htmlElement) {
93
+ this.html = $(htmlElement);
94
+ this.options = Object.extend({className: "popup_effect", duration: 0.4}, arguments[1] || {});
95
+
96
+ },
97
+ show: function(element, options) {
98
+ var position = Position.cumulativeOffset(this.html);
99
+ var size = this.html.getDimensions();
100
+ var bounds = element.win.getBounds();
101
+ this.window = element.win;
102
+ // Create a div
103
+ if (!this.div) {
104
+ this.div = document.createElement("div");
105
+ this.div.className = this.options.className;
106
+ this.div.style.height = size.height + "px";
107
+ this.div.style.width = size.width + "px";
108
+ this.div.style.top = position[1] + "px";
109
+ this.div.style.left = position[0] + "px";
110
+ this.div.style.position = "absolute"
111
+ document.body.appendChild(this.div);
112
+ }
113
+ if (this.options.fromOpacity)
114
+ this.div.setStyle({opacity: this.options.fromOpacity})
115
+ this.div.show();
116
+ var style = "top:" + bounds.top + ";left:" +bounds.left + ";width:" + bounds.width +";height:" + bounds.height;
117
+ if (this.options.toOpacity)
118
+ style += ";opacity:" + this.options.toOpacity;
119
+
120
+ new Effect.Morph(this.div ,{style: style, duration: this.options.duration, afterFinish: this._showWindow.bind(this)});
121
+ },
122
+
123
+ hide: function(element, options) {
124
+ var position = Position.cumulativeOffset(this.html);
125
+ var size = this.html.getDimensions();
126
+ this.window.visible = true;
127
+ var bounds = this.window.getBounds();
128
+ this.window.visible = false;
129
+
130
+ this.window.element.hide();
131
+
132
+ this.div.style.height = bounds.height;
133
+ this.div.style.width = bounds.width;
134
+ this.div.style.top = bounds.top;
135
+ this.div.style.left = bounds.left;
136
+
137
+ if (this.options.toOpacity)
138
+ this.div.setStyle({opacity: this.options.toOpacity})
139
+
140
+ this.div.show();
141
+ var style = "top:" + position[1] + "px;left:" + position[0] + "px;width:" + size.width +"px;height:" + size.height + "px";
142
+
143
+ if (this.options.fromOpacity)
144
+ style += ";opacity:" + this.options.fromOpacity;
145
+ new Effect.Morph(this.div ,{style: style, duration: this.options.duration, afterFinish: this._hideDiv.bind(this)});
146
+ },
147
+
148
+ _showWindow: function() {
149
+ this.div.hide();
150
+ this.window.element.show();
151
+ },
152
+
153
+ _hideDiv: function() {
154
+ this.div.hide();
155
+ }
156
+ }
157
+
js/prototype/window_ext.js ADDED
@@ -0,0 +1,115 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // Copyright (c) 2006 Sébastien Gruhier (http://xilinus.com, http://itseb.com)
2
+ // YOU MUST INCLUDE window.js BEFORE
3
+ //
4
+ // Object to store hide/show windows status in a cookie
5
+ // Just add at the end of your HTML file this javascript line: WindowStore.init()
6
+ WindowStore = {
7
+ doSetCookie: false,
8
+ cookieName: "__window_store__",
9
+ expired: null,
10
+
11
+ // Init function with two optional parameters
12
+ // - cookieName (default = __window_store__)
13
+ // - expiration date (default 3 years from now)
14
+ init: function(cookieName, expired) {
15
+ WindowStore.cookieName = cookieName || WindowStore.cookieName
16
+
17
+ if (! expired) {
18
+ var today = new Date();
19
+ today.setYear(today.getYear()+1903);
20
+ WindowStore.expired = today;
21
+ }
22
+ else
23
+ WindowStore.expired = expired;
24
+
25
+ Windows.windows.each(function(win) {
26
+ win.setCookie(win.getId(), WindowStore.expired);
27
+ });
28
+
29
+ // Create observer on show/hide events
30
+ var myObserver = {
31
+ onShow: function(eventName, win) {
32
+ WindowStore._saveCookie();
33
+ },
34
+
35
+ onClose: function(eventName, win) {
36
+ WindowStore._saveCookie();
37
+ },
38
+
39
+ onHide: function(eventName, win) {
40
+ WindowStore._saveCookie();
41
+ }
42
+ }
43
+ Windows.addObserver(myObserver);
44
+
45
+ WindowStore._restoreWindows();
46
+ WindowStore._saveCookie();
47
+ },
48
+
49
+ show: function(win) {
50
+ eval("var cookie = " + WindowUtilities.getCookie(WindowStore.cookieName));
51
+ if (cookie != null) {
52
+ if (cookie[win.getId()])
53
+ win.show();
54
+ }
55
+ else
56
+ win.show();
57
+ },
58
+
59
+ // Function to store windows show/hide status in a cookie
60
+ _saveCookie: function() {
61
+ if (!doSetCookie)
62
+ return;
63
+
64
+ var cookieValue = "{";
65
+ Windows.windows.each(function(win) {
66
+ if (cookieValue != "{")
67
+ cookieValue += ","
68
+ cookieValue += win.getId() + ": " + win.isVisible();
69
+ });
70
+ cookieValue += "}"
71
+
72
+ WindowUtilities.setCookie(cookieValue, [WindowStore.cookieName, WindowStore.expired]);
73
+ },
74
+
75
+ // Function to restore windows show/hide status from a cookie if exists
76
+ _restoreWindows: function() {
77
+ eval("var cookie = " + WindowUtilities.getCookie(WindowStore.cookieName));
78
+ if (cookie != null) {
79
+ doSetCookie = false;
80
+ Windows.windows.each(function(win) {
81
+ if (cookie[win.getId()])
82
+ win.show();
83
+ });
84
+ }
85
+ doSetCookie = true;
86
+ }
87
+ }
88
+
89
+ // Object to set a close key an all windows
90
+ WindowCloseKey = {
91
+ keyCode: Event.KEY_ESC,
92
+
93
+ init: function(keyCode) {
94
+ if (keyCode)
95
+ WindowCloseKey.keyCode = keyCode;
96
+
97
+ Event.observe(document, 'keydown', this._closeCurrentWindow.bindAsEventListener(this));
98
+ },
99
+
100
+ _closeCurrentWindow: function(event) {
101
+ var e = event || window.event
102
+ var characterCode = e.which || e.keyCode;
103
+
104
+ // Check if there is a top window (it means it's an URL content)
105
+ var win = top.Windows.focusedWindow;
106
+ if (characterCode == WindowCloseKey.keyCode && win) {
107
+ if (win.cancelCallback)
108
+ top.Dialog.cancelCallback();
109
+ else if (win.okCallback)
110
+ top.Dialog.okCallback();
111
+ else
112
+ top.Windows.close(top.Windows.focusedWindow.getId());
113
+ }
114
+ }
115
+ }
js/prototype/window_readme.txt ADDED
@@ -0,0 +1,28 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ Official site:
2
+ http://prototype-window.xilinus.com/index.html
3
+
4
+ The license notice below refers to files:
5
+ window.js, window_effects.js, window_ext.js:
6
+
7
+
8
+
9
+
10
+ Copyright (c) 2006 Sébastien Gruhier (http://xilinus.com, http://itseb.com)
11
+
12
+ Permission is hereby granted, free of charge, to any person obtaining
13
+ a copy of this software and associated documentation files (the
14
+ "Software"), to deal in the Software without restriction, including
15
+ without limitation the rights to use, copy, modify, merge, publish,
16
+ distribute, sublicense, and/or sell copies of the Software, and to
17
+ permit persons to whom the Software is furnished to do so, subject to
18
+ the following conditions:
19
+
20
+ The above copyright notice and this permission notice shall be
21
+ included in all copies or substantial portions of the Software.
22
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
23
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
24
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
25
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
26
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
27
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
28
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
js/prototype/windows/MIT-LICENSE ADDED
@@ -0,0 +1,19 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ Copyright (c) 2006 Sébastien Gruhier (http://xilinus.com, http://itseb.com)
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
14
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
15
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
16
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
17
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
18
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
19
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
js/prototype/windows/README ADDED
@@ -0,0 +1,182 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ == Installation/Usage
2
+
3
+ Just copy windows.js in your javascript directory, and default.css + default directory in your stylesheets directory
4
+ See samples/index.html for more details and go on my web page : http://prototype-window.xilinus.com
5
+
6
+ == Change log
7
+ - 04/23/07 V 1.3
8
+ - Added: getTitle
9
+ - Added: blur/focus function on Windows module
10
+ - Added: onBlur event
11
+ - Fixed: WindowCloseKey works with URL content (iframe)
12
+ - Fixed: Modal window with a parent != document.body
13
+ - Updated: prototype 1.5RC3
14
+ - Updated: Dialog handle resizable,minimizable, maximizable, draggable and closable options
15
+ - 02/27/07 V 1.2
16
+ - Added: gridX and gridY constructor's options to snap move and resize
17
+ - Added: Effect on modal overlay (fade/appear) only if effects.js in included.
18
+ You can change effect options (Windows.overlayShowEffectOptions and Windows.overlayHideEffectOptions).
19
+
20
+ - Fixed: Multimodal mode.
21
+ - Fixed: Works on WebKit.
22
+
23
+ - Beta: effects on minimize and maximize. You need to include window_effects.js to have them.
24
+
25
+ - 02/17/07 V 1.1
26
+ - Constructor has been simplified, now you can just do win = new Window(). By default id is automatically generated and can be passed as options
27
+ win = new Window({id: "my_id", width: 100, height: 100})
28
+ Backward compatibility with old constructor win = new Window("my_id", {width: 100, height: 100})
29
+ - Observer event can be passed as window option: win = new Window({onClose: function() {alert('close')}})
30
+ - parent option can be id or element
31
+ - delegate has been removed (not really usefull) and0 setCloseCallback has been addedinstead. (It could be also passed as a constructor's option closeCallback: your_callcabck)
32
+ your_callcabck must return true to be able to close the window
33
+ - add onMove event
34
+ - fix constraint for minimized window
35
+ - destroyOnClose could be passed as constructor's option: win = new Window({destroyOnClose: true})
36
+ - constraint works for maximized windows
37
+ - Dialog ok and cancel parameters has been renamed to onOk and onCancel for coherence (ok and cancel still works)
38
+ - Update to Prototype 1.5 and script.aculo.us 1.7
39
+
40
+ - 01/14/07 V 1.00
41
+ - add changeClassName to change look and feel dynamically.
42
+ - add constraint move. Constraint can be on a div or document.
43
+ - full top and bottom bar are use to move window.
44
+ - fixed computation of window width or height.
45
+ - add setURL/getURL/refresh and setHTMLContent. Content can be change dynamically.
46
+ - add tooltip.js add on. It's an add-on to add dynamically tooltips on a webpage (see samples/tooltips/tooltip.html)
47
+ Thanks to Jonathan Modell of 2moromedia.com.
48
+
49
+ - 12/06/06 V 0.99
50
+ - remove addClass that automatically tries to include default.css
51
+ - add wired move/resize
52
+ - fix recenterAuto
53
+ - add show to WindowStore to be able to open a window the first time, wihtout any cookie (check samples/window_store/html)
54
+
55
+ - 11/06/06 V 0.98
56
+ - new optional behavior for multi-level modal window.
57
+ - Two new add-ons (in window_ext.js file)
58
+ + WindowStore to save open/close window status.
59
+ + WindowCloseKey to handle escape key (or any keys) to close windows/dialogs
60
+
61
+ - 10/26/06 V 0.97
62
+ - add recenterModal to constructor
63
+ - setAjaxContent eval response request
64
+ - modal window multi level
65
+ - fix close/closeAll issues
66
+ - add addCss (auto add default.css)
67
+
68
+ - 09/26/06 V 0.96.3
69
+ - Fixed onClose, no more memory leak and nore issues with sound on IE (even on dialogs)
70
+ - add getLocation
71
+ - Debug select problem on Firefox
72
+ - change mouseup event to onclick event
73
+ - Fixed event propagation on mininize/maximize/close
74
+ - Add frameborder=0
75
+ - Add prototype_window_class_helper.rb by Jorge Díaz (http://xurde.info)
76
+
77
+ - 07/22/06 V 0.96.2
78
+ - Fixed select issue in modal window
79
+
80
+ - 07/15/06 V 0.96.1
81
+ - Bugs fixed
82
+ - Add isVisible()
83
+ - Update debug.js
84
+
85
+ - 07/11/06 V 0.96
86
+ - New events onShow, onHide, onFocus
87
+ - isVisible()
88
+ - Autofit width or height if width or (NOT AND) height is set to null in the constructor
89
+ - updateWidth / updateHeight if you need to update width or height (useful after changing window content if you do not want scrollbars)
90
+ - Add top, left to showCenter(modal, top, left) optional arguments if you need to center only left or top value.
91
+
92
+ - 06/30/06 V 0.95
93
+ - Now you can set windows or dialogs content with an Ajax request!!
94
+ - Fixed IE issue when you destroy window with an url that embeds mp3.
95
+ - Fixed buttonClass issue for Dialog.
96
+ - Update samples
97
+
98
+ - 06/24/06 V 0.90
99
+ - Valid XHTML 1.0 Strict!
100
+ - Fixed minimize function
101
+ - Fixed destroy on window without hide effects
102
+ - No more text selection while dragging
103
+ - Add onMinimize/onMaximize event
104
+
105
+ - 06/19/06 V 0.85.2
106
+ - Remove undeclared vars
107
+ - Set top/left to 0 if not specify
108
+ - Destroy objet after hide effect instead of before effect instead
109
+ - getSize
110
+ - add extended_debug.js (from Jason Pollard)
111
+
112
+ - 06/13/06 V 0.85.1
113
+ - IE bug fixed
114
+
115
+ - 06/12/06 V 0.85
116
+ - Autofit width or height for Dialog
117
+ - Better Move/Resize over
118
+ - Allow select in modal window (even on IE)
119
+ - WARNING, ok callback for Dialog should returns true to close the dialog
120
+ - better window HTML code (no more div inside the td)
121
+ - Add themes
122
+
123
+ - 05/23/06 V 0.80
124
+ - Add setTitle
125
+ - Add setStatusBar
126
+ - Store minimize/maximize in the cookie (Thanks to Ifran)
127
+ - Add onload constructor parameter (Thanks to Ifran)
128
+ - Add button class for dialog (Thanks to Felix Shnir)
129
+
130
+ - 05/09/06 V 0.75
131
+ - Update with Script.aculo.us 1.6.1 and Prototype 1.5.0_rc1
132
+ - Remove PNG for dialog overlay, use opacity as done in lightbox V2
133
+ - Add Windows.focusedWindow and Windows.closeAll
134
+ - Add name to iframe in case of url window
135
+ - Clean up code, use _ for private function (just name convention)
136
+ - Add Dialog.info function, usefull for for submit or notice info (in Rails)
137
+ - Add minimize and maximize buttons
138
+ - Add alert_lite.css without any images
139
+ - Debug
140
+
141
+ - 04/15/06 V 0.70
142
+ - Add autoposition in setContent. The window will at the element location
143
+ - Add draggable/closable parameter if you need to specify is the window is draggable/closable or not
144
+ - Add parent parameter if you need a specific parent instead of body
145
+ - Better resize
146
+ - Add setCookie to store window location/size in a cookie
147
+ - Add parent.html sample
148
+
149
+ - 04/05/06 V 0.65
150
+ - Update to Prototype 1.5.0_pre1, script.aculo.us 1.6.0
151
+ - Add setDestoyOnClose
152
+ - Add Windows Observer with onStartResize(), onEndResize(), onStartMove(), onEndMove(), onClose(), onDestroy() events
153
+ - Add setContent(id, autoresize)
154
+
155
+ - 03/29/06 V 0.6
156
+ - Add Window delegate to manage close action
157
+ - Add modal mode and Dialog class with common panels: alert, confirm
158
+ - Clean HTML code and change caracters to lowercase to be XHTML compliant (thanks to nuxygen and Joseph)
159
+ - Add showEffectOptions, hideEffectOptions, effectOptions to Window constructor (thanks to Jon)
160
+ - Fix checkbox IE bug (big thanks to JCA)
161
+ - Fix other little bugs (thanks to nuxygen, Dennis, and all who sent me emails)
162
+ - Update samples/index.html
163
+ - Add new sample usng frame (samples/inset.html and samples/inframe.html but use only samples/inset.html)
164
+
165
+ - 03/27/06 V 0.51
166
+ - New CSS theme structure
167
+ - Add url: constructor parameter to have a window with an URL content
168
+ - Add bottom/right constructor parameters
169
+ - Update sample files.
170
+
171
+ - 03/24/06 V 0.50 Initial revision
172
+
173
+
174
+ == License
175
+
176
+ it is licensed under the terms of the MIT License, see the included MIT-LICENSE file.
177
+
178
+ == Thanks
179
+ To all of you who sent me bugs, patches and feature requests
180
+
181
+ http://www.ciudadmovil.com.co/q/mod/mapa/conexion.php
182
+ http://www.desyr.net/
js/prototype/windows/themes/alert.css ADDED
@@ -0,0 +1,119 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ .overlay_alert {
2
+ background-color: #85BBEF;
3
+ filter:alpha(opacity=60);
4
+ -moz-opacity: 0.6;
5
+ opacity: 0.6;
6
+ }
7
+
8
+ .alert_nw {
9
+ width: 5px;
10
+ height: 5px;
11
+ background: transparent url(alert/top_left.gif) no-repeat bottom left;
12
+ }
13
+
14
+ .alert_n {
15
+ height: 5px;
16
+ background: transparent url(alert/top.gif) repeat-x bottom left;
17
+ }
18
+
19
+ .alert_ne {
20
+ width: 5px;
21
+ height: 5px;
22
+ background: transparent url(alert/top_right.gif) no-repeat bottom left
23
+ }
24
+
25
+ .alert_e {
26
+ width: 5px;
27
+ background: transparent url(alert/right.gif) repeat-y 0 0;
28
+ }
29
+
30
+ .alert_w {
31
+ width: 5px;
32
+ background: transparent url(alert/left.gif) repeat-y 0 0;
33
+ }
34
+
35
+ .alert_sw {
36
+ width: 5px;
37
+ height: 5px;
38
+ background: transparent url(alert/bottom_left.gif) no-repeat 0 0;
39
+ }
40
+
41
+ .alert_s {
42
+ height: 5px;
43
+ background: transparent url(alert/bottom.gif) repeat-x 0 0;
44
+ }
45
+
46
+ .alert_se, .alert_sizer {
47
+ width: 5px;
48
+ height: 5px;
49
+ background: transparent url(alert/bottom_right.gif) no-repeat 0 0;
50
+ }
51
+
52
+ .alert_close {
53
+ width:0px;
54
+ height:0px;
55
+ display:none;
56
+ }
57
+
58
+ .alert_minimize {
59
+ width:0px;
60
+ height:0px;
61
+ display:none;
62
+ }
63
+
64
+ .alert_maximize {
65
+ width:0px;
66
+ height:0px;
67
+ display:none;
68
+ }
69
+
70
+ .alert_title {
71
+ float:left;
72
+ height:1px;
73
+ width:100%;
74
+ }
75
+
76
+ .alert_content {
77
+ overflow:visible;
78
+ color: #000;
79
+ font-family: Tahoma, Arial, sans-serif;
80
+ font: 12px arial;
81
+ background: #FFF;
82
+ }
83
+
84
+ /* For alert/confirm dialog */
85
+ .alert_window {
86
+ background: #FFF;
87
+ padding:20px;
88
+ margin-left:auto;
89
+ margin-right:auto;
90
+ width:400px;
91
+ }
92
+
93
+ .alert_message {
94
+ font: 12px arial;
95
+ width:100%;
96
+ color:#F00;
97
+ padding-bottom:10px;
98
+ }
99
+
100
+ .alert_buttons {
101
+ text-align:center;
102
+ width:100%;
103
+ }
104
+
105
+ .alert_buttons input {
106
+ width:20%;
107
+ margin:10px;
108
+ }
109
+
110
+ .alert_progress {
111
+ float:left;
112
+ margin:auto;
113
+ text-align:center;
114
+ width:100%;
115
+ height:16px;
116
+ background: #FFF url('alert/progress.gif') no-repeat center center
117
+ }
118
+
119
+
js/prototype/windows/themes/alert/bottom.gif ADDED
Binary file
js/prototype/windows/themes/alert/bottom_left.gif ADDED
Binary file
js/prototype/windows/themes/alert/bottom_right.gif ADDED
Binary file
js/prototype/windows/themes/alert/left.gif ADDED
Binary file
js/prototype/windows/themes/alert/overlay.png ADDED
Binary file
js/prototype/windows/themes/alert/progress.gif ADDED
Binary file
js/prototype/windows/themes/alert/right.gif ADDED
Binary file
js/prototype/windows/themes/alert/top.gif ADDED
Binary file
js/prototype/windows/themes/alert/top_left.gif ADDED
Binary file
js/prototype/windows/themes/alert/top_right.gif ADDED
Binary file
js/prototype/windows/themes/alert_lite.css ADDED
@@ -0,0 +1,88 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ .overlay_alert_lite {
2
+ background-color: #85BBEF;
3
+ filter:alpha(opacity=60);
4
+ -moz-opacity: 0.6;
5
+ opacity: 0.6;
6
+ }
7
+
8
+ .alert_lite_sizer {
9
+ width:0px;
10
+ height:0px;
11
+ display:none;
12
+ }
13
+
14
+ .alert_lite_close {
15
+ width:0px;
16
+ height:0px;
17
+ display:none;
18
+ }
19
+
20
+ .alert_lite_minimize {
21
+ width:0px;
22
+ height:0px;
23
+ display:none;
24
+ }
25
+
26
+ .alert_lite_maximize {
27
+ width:0px;
28
+ height:0px;
29
+ display:none;
30
+ }
31
+
32
+ .alert_lite_title {
33
+ width:0px;
34
+ height:0px;
35
+ display:none;
36
+ }
37
+
38
+ .alert_lite_content {
39
+ overflow:auto;
40
+ color: #000;
41
+ font-family: Tahoma, Arial, sans-serif;
42
+ font-size: 10px;
43
+ background: #FFF;
44
+ }
45
+
46
+
47
+ /* For alert/confirm dialog */
48
+ .alert_lite_window {
49
+ border:1px solid #F00;
50
+ background: #FFF;
51
+ padding:20px;
52
+ margin-left:auto;
53
+ margin-right:auto;
54
+ width:400px;
55
+ }
56
+
57
+ .alert_lite_message {
58
+ font-size:16px;
59
+ text-align:center;
60
+ width:100%;
61
+ color:#F00;
62
+ padding-bottom:10px;
63
+ }
64
+
65
+ .alert_lite_buttons {
66
+ text-align:center;
67
+ width:100%;
68
+ }
69
+
70
+ .alert_lite_buttons input {
71
+ width:20%;
72
+ margin:10px;
73
+ }
74
+
75
+ .alert_lite_progress {
76
+ float:left;
77
+ margin:auto;
78
+ text-align:center;
79
+ width:100%;
80
+ height:16px;
81
+ background: #FFF url('alert/progress.gif') no-repeat center center
82
+ }
83
+
84
+ table.alert_lite_header {
85
+ border:1px solid #F00;
86
+ background:#FFF
87
+ }
88
+
js/prototype/windows/themes/alphacube.css ADDED
@@ -0,0 +1,150 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ .overlay_alphacube {
2
+ background-color: #85BBEF;
3
+ filter:alpha(opacity=60);
4
+ -moz-opacity: 0.6;
5
+ opacity: 0.6;
6
+ }
7
+
8
+ .alphacube_nw {
9
+ background: transparent url(alphacube/left-top.gif) no-repeat 0 0;
10
+ width:10px;
11
+ height:25px;
12
+ }
13
+
14
+ .alphacube_n {
15
+ background: transparent url(alphacube/top-middle.gif) repeat-x 0 0;
16
+ height:25px;
17
+ }
18
+
19
+ .alphacube_ne {
20
+ background: transparent url(alphacube/right-top.gif) no-repeat 0 0;
21
+ width:10px;
22
+ height:25px;
23
+ }
24
+
25
+ .alphacube_w {
26
+ background: transparent url(alphacube/frame-left.gif) repeat-y top left;
27
+ width:7px;
28
+ }
29
+
30
+ .alphacube_e {
31
+ background: transparent url(alphacube/frame-right.gif) repeat-y top right;
32
+ width:7px;
33
+ }
34
+
35
+ .alphacube_sw {
36
+ background: transparent url(alphacube/bottom-left-c.gif) no-repeat 0 0;
37
+ width:7px;
38
+ height:7px;
39
+ }
40
+
41
+ .alphacube_s {
42
+ background: transparent url(alphacube/bottom-middle.gif) repeat-x 0 0;
43
+ height:7px;
44
+ }
45
+
46
+ .alphacube_se, .alphacube_sizer {
47
+ background: transparent url(alphacube/bottom-right-c.gif) no-repeat 0 0;
48
+ width:7px;
49
+ height:7px;
50
+ }
51
+
52
+ .alphacube_sizer {
53
+ cursor:se-resize;
54
+ }
55
+
56
+ .alphacube_close {
57
+ width: 23px;
58
+ height: 23px;
59
+ background: transparent url(alphacube/button-close-focus.gif) no-repeat 0 0;
60
+ position:absolute;
61
+ top:0px;
62
+ right:11px;
63
+ cursor:pointer;
64
+ z-index:1000;
65
+ }
66
+
67
+ .alphacube_minimize {
68
+ width: 23px;
69
+ height: 23px;
70
+ background: transparent url(alphacube/button-min-focus.gif) no-repeat 0 0;
71
+ position:absolute;
72
+ top:0px;
73
+ right:55px;
74
+ cursor:pointer;
75
+ z-index:1000;
76
+ }
77
+
78
+ .alphacube_maximize {
79
+ width: 23px;
80
+ height: 23px;
81
+ background: transparent url(alphacube/button-max-focus.gif) no-repeat 0 0;
82
+ position:absolute;
83
+ top:0px;
84
+ right:33px;
85
+ cursor:pointer;
86
+ z-index:1000;
87
+ }
88
+
89
+ .alphacube_title {
90
+ float:left;
91
+ height:14px;
92
+ font-size:14px;
93
+ text-align:center;
94
+ margin-top:2px;
95
+ width:100%;
96
+ color:#123456;
97
+ }
98
+
99
+ .alphacube_content {
100
+ overflow:auto;
101
+ color: #000;
102
+ font-family: Tahoma, Arial, sans-serif;
103
+ font: 12px arial;
104
+ background:#FDFDFD;
105
+ }
106
+
107
+ /* For alert/confirm dialog */
108
+ .alphacube_window {
109
+ border:1px solid #F00;
110
+ background: #FFF;
111
+ padding:20px;
112
+ margin-left:auto;
113
+ margin-right:auto;
114
+ width:400px;
115
+ }
116
+
117
+ .alphacube_message {
118
+ font: 12px arial;
119
+ text-align:center;
120
+ width:100%;
121
+ padding-bottom:10px;
122
+ }
123
+
124
+ .alphacube_buttons {
125
+ text-align:center;
126
+ width:100%;
127
+ }
128
+
129
+ .alphacube_buttons input {
130
+ width:20%;
131
+ margin:10px;
132
+ }
133
+
134
+ .alphacube_progress {
135
+ float:left;
136
+ margin:auto;
137
+ text-align:center;
138
+ width:100%;
139
+ height:16px;
140
+ background: #FFF url('alert/progress.gif') no-repeat center center
141
+ }
142
+
143
+ .alphacube_wired_frame {
144
+ background: #FFF;
145
+ filter:alpha(opacity=60);
146
+ -moz-opacity: 0.6;
147
+ opacity: 0.6;
148
+ }
149
+
150
+
js/prototype/windows/themes/alphacube/bottom-left-c.gif ADDED
Binary file
js/prototype/windows/themes/alphacube/bottom-middle.gif ADDED
Binary file
js/prototype/windows/themes/alphacube/bottom-right-c.gif ADDED
Binary file
js/prototype/windows/themes/alphacube/button-close-focus.gif ADDED
Binary file
js/prototype/windows/themes/alphacube/button-max-focus.gif ADDED
Binary file
js/prototype/windows/themes/alphacube/button-min-focus.gif ADDED
Binary file
js/prototype/windows/themes/alphacube/frame-left.gif ADDED
Binary file
js/prototype/windows/themes/alphacube/frame-right.gif ADDED
Binary file
js/prototype/windows/themes/alphacube/left-top.gif ADDED
Binary file
js/prototype/windows/themes/alphacube/right-top.gif ADDED
Binary file
js/prototype/windows/themes/alphacube/top-middle.gif ADDED
Binary file
js/prototype/windows/themes/behavior.htc ADDED
@@ -0,0 +1,51 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <public:component>
2
+ <public:attach event="onpropertychange" onevent="propertyChanged()" />
3
+ <script>
4
+
5
+ var supported = /MSIE (5\.5)|[6789]/.test(navigator.userAgent) && navigator.platform == "Win32";
6
+ var realSrc;
7
+ var blankSrc = "blank.gif";
8
+
9
+ if (supported) fixImage();
10
+
11
+ function propertyChanged() {
12
+ if (!supported) return;
13
+
14
+ var pName = event.propertyName;
15
+ if (pName != "src") return;
16
+ // if not set to blank
17
+ if ( ! new RegExp(blankSrc).test(src))
18
+ fixImage();
19
+ };
20
+
21
+ function fixImage() {
22
+ // get src
23
+ var src = element.src;
24
+
25
+ // check for real change
26
+ if (src == realSrc) {
27
+ element.src = blankSrc;
28
+ return;
29
+ }
30
+
31
+ if ( ! new RegExp(blankSrc).test(src)) {
32
+ // backup old src
33
+ realSrc = src;
34
+ }
35
+
36
+ // test for png
37
+ if ( /\.png$/.test( realSrc.toLowerCase() ) ) {
38
+ // set blank image
39
+ element.src = blankSrc;
40
+ // set filter
41
+ element.runtimeStyle.filter = "progid:DXImageTransform.Microsoft.AlphaImageLoader(src='" +
42
+ src + "',sizingMethod='scale')";
43
+ }
44
+ else {
45
+ // remove filter
46
+ element.runtimeStyle.filter = "";
47
+ }
48
+ }
49
+
50
+ </script>
51
+ </public:component>
js/prototype/windows/themes/darkX.css ADDED
@@ -0,0 +1,121 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ .overlay_darkX {
2
+ background-color: #85BBEF;
3
+ filter:alpha(opacity=60);
4
+ -moz-opacity: 0.6;
5
+ opacity: 0.6;
6
+ }
7
+
8
+ .darkX_nw {
9
+ background: transparent url(darkX/titlebar-left-focused.png) no-repeat 0 0;
10
+ width:6px;
11
+ height:21px;
12
+ }
13
+ .darkX_n {
14
+ background: transparent url(darkX/titlebar-mid-focused.png) repeat-x 0 0;
15
+ height:21px;
16
+ }
17
+ .darkX_ne {
18
+ background: transparent url(darkX/titlebar-right-focused.png) no-repeat 0 0;
19
+ width:6px;
20
+ height:21px;
21
+ }
22
+ .darkX_w {
23
+ background: transparent url(darkX/frame-left-focused.png) repeat-y top left;
24
+ width:3px;
25
+ }
26
+
27
+ .darkX_e {
28
+ background: transparent url(darkX/frame-right-focused.png) repeat-y top right;
29
+ width:3px;
30
+ }
31
+
32
+ .darkX_sw {
33
+ background: transparent url(darkX/frame-bottom-left-focused.png) no-repeat 0 0;
34
+ width:5px;
35
+ height:3px;
36
+ }
37
+ .darkX_s {
38
+ background: transparent url(darkX/frame-bottom-mid-focused.png) repeat-x 0 0;
39
+ height:3px;
40
+ }
41
+ .darkX_se, .darkX_sizer {
42
+ background: transparent url(darkX/frame-bottom-right-focused.png) no-repeat 0 0;
43
+ width:5px;
44
+ height:3px;
45
+ }
46
+
47
+ .darkX_sizer {
48
+ cursor:se-resize;
49
+ }
50
+
51
+ .darkX_close {
52
+ width: 21px;
53
+ height: 21px;
54
+ background: transparent url(darkX/button-close-focused.png) no-repeat 0 0;
55
+ position:absolute;
56
+ top:0px;
57
+ right:5px;
58
+ cursor:pointer;
59
+ z-index:1000;
60
+ }
61
+
62
+ .darkX_minimize {
63
+ width: 21px;
64
+ height: 21px;
65
+ background: transparent url(darkX/button-minimize-focused.png) no-repeat 0 0;
66
+ position:absolute;
67
+ top:0px;
68
+ right:26px;
69
+ cursor:pointer;
70
+ z-index:1000;
71
+ }
72
+
73
+ .darkX_maximize {
74
+ width: 21px;
75
+ height: 21px;
76
+ background: transparent url(darkX/button-maximize-focused.png) no-repeat 0 0;
77
+ position:absolute;
78
+ top:0px;
79
+ right:47px;
80
+ cursor:pointer;
81
+ z-index:1000;
82
+ }
83
+
84
+
85
+ .darkX_title {
86
+ float:left;
87
+ height:14px;
88
+ font-size:12px;
89
+ text-align:center;
90
+ margin-top:2px;
91
+ width:100%;
92
+ color:#FFF;
93
+ }
94
+
95
+ .darkX_content {
96
+ overflow:auto;
97
+ color: #E6DF2A;
98
+ font-family: Tahoma, Arial, sans-serif;
99
+ font-size: 14px;
100
+ background:#5E5148;
101
+ }
102
+
103
+
104
+ /* FOR IE */
105
+ * html .darkX_minimize {
106
+ background-color: transparent;
107
+ background-image: none;
108
+ filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src="../themes/darkX/button-minimize-focused.png", sizingMethod="crop");
109
+ }
110
+
111
+ * html .darkX_maximize {
112
+ background-color: transparent;
113
+ background-image: none;
114
+ filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src="../themes/darkX/button-maximize-focused.png", sizingMethod="scale");
115
+ }
116
+
117
+ * html .darkX_close {
118
+ background-color: transparent;
119
+ background-image: none;
120
+ filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src="../themes/darkX/button-close-focused.png", sizingMethod="crop");
121
+ }
js/prototype/windows/themes/darkX/button-close-focused.png ADDED
Binary file
js/prototype/windows/themes/darkX/button-maximize-focused.png ADDED
Binary file
js/prototype/windows/themes/darkX/button-minimize-focused.png ADDED
Binary file
js/prototype/windows/themes/darkX/frame-bottom-left-focused.png ADDED
Binary file
js/prototype/windows/themes/darkX/frame-bottom-mid-focused.png ADDED
Binary file
js/prototype/windows/themes/darkX/frame-bottom-right-focused.png ADDED
Binary file
js/prototype/windows/themes/darkX/frame-left-focused.png ADDED
Binary file
js/prototype/windows/themes/darkX/frame-right-focused.png ADDED
Binary file
js/prototype/windows/themes/darkX/titlebar-left-focused.png ADDED
Binary file
js/prototype/windows/themes/darkX/titlebar-mid-focused.png ADDED
Binary file
js/prototype/windows/themes/darkX/titlebar-right-focused.png ADDED
Binary file
js/prototype/windows/themes/debug.css ADDED
@@ -0,0 +1,25 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ div.inspector div.inspectable {
2
+ padding: 0.25em 0 0.25em 1em;
3
+ background-color: Gray;
4
+ color: white;
5
+ border: outset 2px white;
6
+ cursor: pointer;
7
+ }
8
+
9
+ div.inspector div.child {
10
+ margin: 0 0 0 1em;
11
+ }
12
+
13
+ #debug_window_content { /* DIV container for debug sizing*/
14
+ width:250px;
15
+ height:100px;
16
+ background-color:#000;
17
+ }
18
+
19
+ #debug { /* DIV container for debug contents*/
20
+ padding:3px;
21
+ color:#0f0;
22
+ font-family:monaco, Tahoma, Verdana, Arial, Helvetica, sans-serif;
23
+ font-size:10px;
24
+ }
25
+
js/prototype/windows/themes/default.css ADDED
@@ -0,0 +1,155 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ .overlay_dialog {
2
+ background-color: #666666;
3
+ filter:alpha(opacity=60);
4
+ -moz-opacity: 0.6;
5
+ opacity: 0.6;
6
+ }
7
+
8
+ .overlay___invisible__ {
9
+ background-color: #666666;
10
+ filter:alpha(opacity=0);
11
+ -moz-opacity: 0;
12
+ opacity: 0;
13
+ }
14
+
15
+ .dialog_nw {
16
+ width: 9px;
17
+ height: 23px;
18
+ background: transparent url(default/top_left.gif) no-repeat 0 0;
19
+ }
20
+
21
+ .dialog_n {
22
+ background: transparent url(default/top_mid.gif) repeat-x 0 0;
23
+ height: 23px;
24
+ }
25
+
26
+ .dialog_ne {
27
+ width: 9px;
28
+ height: 23px;
29
+ background: transparent url(default/top_right.gif) no-repeat 0 0;
30
+ }
31
+
32
+ .dialog_e {
33
+ width: 2px;
34
+ background: transparent url(default/center_right.gif) repeat-y 0 0;
35
+ }
36
+
37
+ .dialog_w {
38
+ width: 2px;
39
+ background: transparent url(default/center_left.gif) repeat-y 0 0;
40
+ }
41
+
42
+ .dialog_sw {
43
+ width: 9px;
44
+ height: 19px;
45
+ background: transparent url(default/bottom_left.gif) no-repeat 0 0;
46
+ }
47
+
48
+ .dialog_s {
49
+ background: transparent url(default/bottom_mid.gif) repeat-x 0 0;
50
+ height: 19px;
51
+ }
52
+
53
+ .dialog_se {
54
+ width: 9px;
55
+ height: 19px;
56
+ background: transparent url(default/bottom_right.gif) no-repeat 0 0;
57
+ }
58
+
59
+ .dialog_sizer {
60
+ width: 9px;
61
+ height: 19px;
62
+ background: transparent url(default/sizer.gif) no-repeat 0 0;
63
+ cursor:se-resize;
64
+ }
65
+
66
+ .dialog_close {
67
+ width: 14px;
68
+ height: 14px;
69
+ background: transparent url(default/close.gif) no-repeat 0 0;
70
+ position:absolute;
71
+ top:5px;
72
+ left:8px;
73
+ cursor:pointer;
74
+ z-index:2000;
75
+ }
76
+
77
+ .dialog_minimize {
78
+ width: 14px;
79
+ height: 15px;
80
+ background: transparent url(default/minimize.gif) no-repeat 0 0;
81
+ position:absolute;
82
+ top:5px;
83
+ left:28px;
84
+ cursor:pointer;
85
+ z-index:2000;
86
+ }
87
+
88
+ .dialog_maximize {
89
+ width: 14px;
90
+ height: 15px;
91
+ background: transparent url(default/maximize.gif) no-repeat 0 0;
92
+ position:absolute;
93
+ top:5px;
94
+ left:49px;
95
+ cursor:pointer;
96
+ z-index:2000;
97
+ }
98
+
99
+ .dialog_title {
100
+ float:left;
101
+ height:14px;
102
+ font-family: Tahoma, Arial, sans-serif;
103
+ font-size:12px;
104
+ text-align:center;
105
+ width:100%;
106
+ color:#000;
107
+ }
108
+
109
+ .dialog_content {
110
+ overflow:auto;
111
+ color: #DDD;
112
+ font-family: Tahoma, Arial, sans-serif;
113
+ font-size: 10px;
114
+ background-color:#123;
115
+ }
116
+
117
+ .top_draggable, .bottom_draggable {
118
+ cursor:move;
119
+ }
120
+
121
+ .status_bar {
122
+ font-size:12px;
123
+ }
124
+ .status_bar input{
125
+ font-size:12px;
126
+ }
127
+
128
+ .wired_frame {
129
+ display: block;
130
+ position: absolute;
131
+ border: 1px #000 dashed;
132
+ }
133
+
134
+ /* DO NOT CHANGE THESE VALUES*/
135
+ .dialog {
136
+ display: block;
137
+ position: absolute;
138
+ }
139
+
140
+ .dialog table.table_window {
141
+ border-collapse: collapse;
142
+ border-spacing: 0;
143
+ width: 100%;
144
+ margin: 0px;
145
+ padding:0px;
146
+ }
147
+
148
+ .dialog table.table_window td , .dialog table.table_window th {
149
+ padding: 0;
150
+ }
151
+
152
+ .dialog .title_window {
153
+ -moz-user-select:none;
154
+ }
155
+
js/prototype/windows/themes/default/bottom_left.gif ADDED
Binary file
js/prototype/windows/themes/default/bottom_mid.gif ADDED
Binary file
js/prototype/windows/themes/default/bottom_right.gif ADDED
Binary file
js/prototype/windows/themes/default/bottom_right_resize.gif ADDED
Binary file
js/prototype/windows/themes/default/center_left.gif ADDED
Binary file
js/prototype/windows/themes/default/center_right.gif ADDED
Binary file
js/prototype/windows/themes/default/clear.gif ADDED
Binary file
js/prototype/windows/themes/default/close.gif ADDED
Binary file
js/prototype/windows/themes/default/inspect.gif ADDED
Binary file
js/prototype/windows/themes/default/maximize.gif ADDED
Binary file
js/prototype/windows/themes/default/minimize.gif ADDED
Binary file
js/prototype/windows/themes/default/overlay.png ADDED
Binary file
js/prototype/windows/themes/default/resize.gif ADDED
Binary file
js/prototype/windows/themes/default/sizer.gif ADDED
Binary file
js/prototype/windows/themes/default/top_left.gif ADDED
Binary file
js/prototype/windows/themes/default/top_mid.gif ADDED
Binary file
js/prototype/windows/themes/default/top_right.gif ADDED
Binary file
js/prototype/windows/themes/iefix/blank.gif ADDED
Binary file
js/prototype/windows/themes/iefix/iepngfix.css ADDED
@@ -0,0 +1,3 @@
 
 
 
1
+ /* PNG fix for all themes that uses PNG images on IE */
2
+ td, div { behavior: url(../themes/iefix/iepngfix.htc) }
3
+
js/prototype/windows/themes/iefix/iepngfix.htc ADDED
@@ -0,0 +1,54 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <public:component>
2
+ <public:attach event="onpropertychange" onevent="doFix()" />
3
+
4
+ <script type="text/javascript">
5
+
6
+ // IE5.5+ PNG Alpha Fix v1.0RC4
7
+ // (c) 2004-2005 Angus Turnbull http://www.twinhelix.com
8
+
9
+ // This is licensed under the CC-GNU LGPL, version 2.1 or later.
10
+ // For details, see: http://creativecommons.org/licenses/LGPL/2.1/
11
+
12
+ // Modified/Simplified on 04/23/2007 by Sebastien Gruhier (http://www.xilinus.com)
13
+ // To work only on background and to handle repeat bg
14
+
15
+ // This must be a path to a blank image. That's all the configuration you need.
16
+ if (typeof blankImg == 'undefined') var blankImg = 'blank.gif';
17
+
18
+ var f = 'DXImageTransform.Microsoft.AlphaImageLoader';
19
+
20
+ function filt(s, m)
21
+ {
22
+ if (filters[f])
23
+ {
24
+ filters[f].enabled = s ? true : false;
25
+ if (s) with (filters[f]) { src = s; sizingMethod = m }
26
+ }
27
+ else if (s) style.filter = 'progid:'+f+'(src="'+s+'",sizingMethod="'+m+'")';
28
+ }
29
+
30
+ function doFix()
31
+ {
32
+ // Assume IE7 is OK.
33
+ if (!/MSIE (5\.5|6\.)/.test(navigator.userAgent) ||
34
+ (event && !/(background|src)/.test(event.propertyName))) return;
35
+
36
+ var bgImg = currentStyle.backgroundImage || style.backgroundImage;
37
+ var bgRepeat = currentStyle.backgroundRepeat || style.backgroundRepeat;
38
+ if (bgImg && bgImg != 'none')
39
+ {
40
+ if (bgImg.match(/^url[("']+(.*\.png)[)"']+$/i))
41
+ {
42
+ var s = RegExp.$1;
43
+ if (currentStyle.width == 'auto' && currentStyle.height == 'auto')
44
+ style.width = offsetWidth + 'px';
45
+ style.backgroundImage = 'none';
46
+ filt(s, bgRepeat == "no-repeat" ? 'crop' : 'scale');
47
+ }
48
+ }
49
+ }
50
+
51
+ doFix();
52
+
53
+ </script>
54
+ </public:component>
js/prototype/windows/themes/lighting.css ADDED
@@ -0,0 +1,960 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ .overlay___invisible__ {
2
+ background-color: #666;
3
+ filter:alpha(opacity=0);
4
+ -moz-opacity: 0;
5
+ opacity: 0;
6
+ }
7
+
8
+ .top_draggable, .bottom_draggable {
9
+ cursor:move;
10
+ }
11
+
12
+ .status_bar {
13
+ font-size:12px;
14
+ }
15
+ .status_bar input{
16
+ font-size:12px;
17
+ }
18
+
19
+ .wired_frame {
20
+ display:block;
21
+ position:absolute;
22
+ border:1px #000 dashed;
23
+ }
24
+
25
+
26
+
27
+ .overlay_bluelighting {
28
+ background-color:#FFF;
29
+ filter:alpha(opacity=60);
30
+ -moz-opacity:0.6;
31
+ opacity:0.6;
32
+ }
33
+
34
+ .bluelighting_wired_frame {
35
+ background:#FFF;
36
+ filter:alpha(opacity=60);
37
+ -moz-opacity:0.6;
38
+ opacity:0.6;
39
+ }
40
+
41
+ .bluelighting_nw {
42
+ background:transparent url(lighting/top-left-blue.png) no-repeat 0 0;
43
+ width:9px;
44
+ height:28px;
45
+ }
46
+
47
+ .bluelighting_n {
48
+ background:transparent url(lighting/top-middle-blue.png) repeat-x 0 0;
49
+ height:28px;
50
+ }
51
+
52
+ .bluelighting_ne {
53
+ background:transparent url(lighting/top-right-blue.png) no-repeat 0 0;
54
+ width:15px;
55
+ height:28px;
56
+ }
57
+
58
+ .bluelighting_w {
59
+ background:transparent url(lighting/left-blue.png) repeat-y top left;
60
+ width:9px;
61
+ }
62
+
63
+ .bluelighting_e {
64
+ background:transparent url(lighting/right-blue.png) repeat-y top right;
65
+ width:15px;
66
+ }
67
+
68
+ .bluelighting_sw {
69
+ background:transparent url(lighting/bottom-left-blue.png) no-repeat 0 0;
70
+ width:9px;
71
+ height:15px;
72
+ }
73
+
74
+ .bluelighting_s {
75
+ background:transparent url(lighting/bottom-middle-blue.png) repeat-x 0 0;
76
+ height:15px;
77
+ }
78
+
79
+ .bluelighting_se, .bluelighting_sizer {
80
+ background:transparent url(lighting/bottom-right-blue.png) no-repeat 0 0;
81
+ width:15px;
82
+ height:15px;
83
+ }
84
+
85
+ .bluelighting_sizer {
86
+ cursor:se-resize;
87
+ }
88
+
89
+ .bluelighting_close {
90
+ width:15px;
91
+ height:9px;
92
+ background:transparent url(lighting/button-close-blue.png) no-repeat 0 0;
93
+ position:absolute;
94
+ top:11px;
95
+ right:10px;
96
+ cursor:pointer;
97
+ z-index:1000;
98
+ }
99
+
100
+ .bluelighting_maximize {
101
+ width:15px;
102
+ height:9px;
103
+ background:transparent url(lighting/button-maximize-blue.png) no-repeat 0 0;
104
+ position:absolute;
105
+ top:11px;
106
+ right:25px;
107
+ cursor:pointer;
108
+ z-index:1000;
109
+ }
110
+
111
+ .bluelighting_minimize {
112
+ width:15px;
113
+ height:9px;
114
+ background:transparent url(lighting/button-minimize-blue.png) no-repeat 0 0;
115
+ position:absolute;
116
+ top:11px;
117
+ right:40px;
118
+ cursor:pointer;
119
+ z-index:1000;
120
+ }
121
+
122
+ .bluelighting_title {
123
+ float:left;
124
+ height:14px;
125
+ font-size:14px;
126
+ font-weight:bold;
127
+ font-family:Verdana, Arial, sans-serif;
128
+ text-align:center;
129
+ margin-top:2px;
130
+ width:100%;
131
+ color:#17385B;
132
+ }
133
+
134
+ .bluelighting_content {
135
+ overflow:auto;
136
+ color:#000;
137
+ font-family:Verdana, Arial, sans-serif;
138
+ font-size:12px;
139
+ background:#BFDBFF;
140
+ }
141
+
142
+ /* For alert/confirm dialog */
143
+ .bluelighting_window {
144
+ border:1px solid #F00;
145
+ background:#FFF;
146
+ padding:20px;
147
+ margin-left:auto;
148
+ margin-right:auto;
149
+ width:400px;
150
+ }
151
+
152
+ .bluelighting_message {
153
+ font-size:12px;
154
+ text-align:center;
155
+ width:100%;
156
+ padding-bottom:10px;
157
+ }
158
+
159
+ .bluelighting_buttons {
160
+ text-align:center;
161
+ width:100%;
162
+ }
163
+
164
+ .bluelighting_buttons input {
165
+ border:1px solid #999;
166
+ border-top-color:#CCC;
167
+ border-left-color:#CCC;
168
+ padding:2px;
169
+ background-color:#FFF;
170
+ color:#333;
171
+ background-image:url(lighting/background_buttons.gif);
172
+ background-repeat:repeat-x;
173
+ font-family:Verdana, Arial, sans-serif;
174
+ font-size:10px;
175
+ font-weight:bold;
176
+ text-align:center;
177
+ }
178
+
179
+ .bluelighting_progress {
180
+ float:left;
181
+ margin:auto;
182
+ text-align:center;
183
+ width:100%;
184
+ height:16px;
185
+ background:transparent url('lighting/spinner.gif') no-repeat center center
186
+ }
187
+
188
+ /* FOR IE */
189
+ * html .bluelighting_nw {
190
+ background-color: transparent;
191
+ background-image: none;
192
+ filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src="../themes/lighting/top-left-blue.png", sizingMethod="crop");
193
+ }
194
+
195
+ * html .bluelighting_n {
196
+ background-color: transparent;
197
+ background-image: none;
198
+ filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src="../themes/lighting/top-middle-blue.png", sizingMethod="scale");
199
+ }
200
+
201
+ * html .bluelighting_ne {
202
+ background-color: transparent;
203
+ background-image: none;
204
+ filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src="../themes/lighting/top-right-blue.png", sizingMethod="crop");
205
+ }
206
+
207
+ * html .bluelighting_w {
208
+ background-color: transparent;
209
+ background-image: none;
210
+ filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src="../themes/lighting/left-blue.png", sizingMethod="scale");
211
+ }
212
+
213
+ * html .bluelighting_e {
214
+ background-color: transparent;
215
+ background-image: none;
216
+ filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src="../themes/lighting/right-blue.png", sizingMethod="scale");
217
+ }
218
+
219
+ * html .bluelighting_sw {
220
+ background-color: transparent;
221
+ background-image: none;
222
+ filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src="../themes/lighting/bottom-left-blue.png", sizingMethod="crop");
223
+ }
224
+
225
+ * html .bluelighting_s {
226
+ background-color: transparent;
227
+ background-image: none;
228
+ filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src="../themes/lighting/bottom-middle-blue.png", sizingMethod="scale");
229
+ }
230
+
231
+ * html .bluelighting_se, * html .bluelighting_sizer {
232
+ background-color: transparent;
233
+ background-image: none;
234
+ filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src="../themes/lighting/bottom-right-blue.png", sizingMethod="crop");
235
+ }
236
+
237
+ * html .bluelighting_close {
238
+ background-color: transparent;
239
+ background-image: none;
240
+ filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src="../themes/lighting/button-close-blue.png", sizingMethod="crop");
241
+ }
242
+
243
+ * html .bluelighting_minimize {
244
+ background-color: transparent;
245
+ background-image: none;
246
+ filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src="../themes/lighting/button-minimize-blue.png", sizingMethod="crop");
247
+ }
248
+
249
+ * html .bluelighting_maximize {
250
+ background-color: transparent;
251
+ background-image: none;
252
+ filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src="../themes/lighting/button-maximize-blue.png", sizingMethod="crop");
253
+ }
254
+
255
+ * html .bluelighting_content {
256
+ background:#B8D7FF;
257
+ }
258
+
259
+
260
+
261
+ .overlay_greylighting {
262
+ background-color:#FFF;
263
+ filter:alpha(opacity=60);
264
+ -moz-opacity:0.6;
265
+ opacity:0.6;
266
+ }
267
+
268
+ .greylighting_wired_frame {
269
+ background:#FFF;
270
+ filter:alpha(opacity=60);
271
+ -moz-opacity:0.6;
272
+ opacity:0.6;
273
+ }
274
+
275
+ .greylighting_nw {
276
+ background:transparent url(lighting/top-left-grey.png) no-repeat 0 0;
277
+ width:9px;
278
+ height:28px;
279
+ }
280
+
281
+ .greylighting_n {
282
+ background:transparent url(lighting/top-middle-grey.png) repeat-x 0 0;
283
+ height:28px;
284
+ }
285
+
286
+ .greylighting_ne {
287
+ background:transparent url(lighting/top-right-grey.png) no-repeat 0 0;
288
+ width:15px;
289
+ height:28px;
290
+ }
291
+
292
+ .greylighting_w {
293
+ background:transparent url(lighting/left-grey.png) repeat-y top left;
294
+ width:9px;
295
+ }
296
+
297
+ .greylighting_e {
298
+ background:transparent url(lighting/right-grey.png) repeat-y top right;
299
+ width:15px;
300
+ }
301
+
302
+ .greylighting_sw {
303
+ background:transparent url(lighting/bottom-left-grey.png) no-repeat 0 0;
304
+ width:9px;
305
+ height:15px;
306
+ }
307
+
308
+ .greylighting_s {
309
+ background:transparent url(lighting/bottom-middle-grey.png) repeat-x 0 0;
310
+ height:15px;
311
+ }
312
+
313
+ .greylighting_se, .greylighting_sizer {
314
+ background:transparent url(lighting/bottom-right-grey.png) no-repeat 0 0;
315
+ width:15px;
316
+ height:15px;
317
+ }
318
+
319
+ .greylighting_sizer {
320
+ cursor:se-resize;
321
+ }
322
+
323
+ .greylighting_close {
324
+ width:15px;
325
+ height:9px;
326
+ background:transparent url(lighting/button-close-grey.png) no-repeat 0 0;
327
+ position:absolute;
328
+ top:11px;
329
+ right:10px;
330
+ cursor:pointer;
331
+ z-index:1000;
332
+ }
333
+
334
+ .greylighting_maximize {
335
+ width:15px;
336
+ height:9px;
337
+ background:transparent url(lighting/button-maximize-grey.png) no-repeat 0 0;
338
+ position:absolute;
339
+ top:11px;
340
+ right:25px;
341
+ cursor:pointer;
342
+ z-index:1000;
343
+ }
344
+
345
+ .greylighting_minimize {
346
+ width:15px;
347
+ height:9px;
348
+ background:transparent url(lighting/button-minimize-grey.png) no-repeat 0 0;
349
+ position:absolute;
350
+ top:11px;
351
+ right:40px;
352
+ cursor:pointer;
353
+ z-index:1000;
354
+ }
355
+
356
+ .greylighting_title {
357
+ float:left;
358
+ height:14px;
359
+ font-size:14px;
360
+ font-weight:bold;
361
+ font-family:Verdana, Arial, sans-serif;
362
+ text-align:center;
363
+ margin-top:2px;
364
+ width:100%;
365
+ color:#525252;
366
+ }
367
+
368
+ .greylighting_content {
369
+ overflow:auto;
370
+ color:#000;
371
+ font-family:Verdana, Arial, sans-serif;
372
+ font-size:12px;
373
+ background:#CDCDCD;
374
+ }
375
+
376
+ /* For alert/confirm dialog */
377
+ .greylighting_window {
378
+ border:1px solid #F00;
379
+ background:#FFF;
380
+ padding:20px;
381
+ margin-left:auto;
382
+ margin-right:auto;
383
+ width:400px;
384
+ }
385
+
386
+ .greylighting_message {
387
+ font-size:12px;
388
+ text-align:center;
389
+ width:100%;
390
+ padding-bottom:10px;
391
+ }
392
+
393
+ .greylighting_buttons {
394
+ text-align:center;
395
+ width:100%;
396
+ }
397
+
398
+ .greylighting_buttons input {
399
+ border:1px solid #999;
400
+ border-top-color:#CCC;
401
+ border-left-color:#CCC;
402
+ padding:2px;
403
+ background-color:#FFF;
404
+ color:#333;
405
+ background-image:url(lighting/background_buttons.gif);
406
+ background-repeat:repeat-x;
407
+ font-family:Verdana, Arial, sans-serif;
408
+ font-size:10px;
409
+ font-weight:bold;
410
+ text-align:center;
411
+ }
412
+
413
+ .greylighting_progress {
414
+ float:left;
415
+ margin:auto;
416
+ text-align:center;
417
+ width:100%;
418
+ height:16px;
419
+ background:transparent url('lighting/spinner.gif') no-repeat center center
420
+ }
421
+
422
+ /* FOR IE */
423
+ * html .greylighting_nw {
424
+ background-color: transparent;
425
+ background-image: none;
426
+ filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src="../themes/lighting/top-left-grey.png", sizingMethod="crop");
427
+ }
428
+
429
+ * html .greylighting_n {
430
+ background-color: transparent;
431
+ background-image: none;
432
+ filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src="../themes/lighting/top-middle-grey.png", sizingMethod="scale");
433
+ }
434
+
435
+ * html .greylighting_ne {
436
+ background-color: transparent;
437
+ background-image: none;
438
+ filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src="../themes/lighting/top-right-grey.png", sizingMethod="crop");
439
+ }
440
+
441
+ * html .greylighting_w {
442
+ background-color: transparent;
443
+ background-image: none;
444
+ filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src="../themes/lighting/left-grey.png", sizingMethod="scale");
445
+ }
446
+
447
+ * html .greylighting_e {
448
+ background-color: transparent;
449
+ background-image: none;
450
+ filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src="../themes/lighting/right-grey.png", sizingMethod="scale");
451
+ }
452
+
453
+ * html .greylighting_sw {
454
+ background-color: transparent;
455
+ background-image: none;
456
+ filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src="../themes/lighting/bottom-left-grey.png", sizingMethod="crop");
457
+ }
458
+
459
+ * html .greylighting_s {
460
+ background-color: transparent;
461
+ background-image: none;
462
+ filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src="../themes/lighting/bottom-middle-grey.png", sizingMethod="scale");
463
+ }
464
+
465
+ * html greylighting_se, * html .greylighting_sizer {
466
+ background-color: transparent;
467
+ background-image: none;
468
+ filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src="../themes/lighting/bottom-right-grey.png", sizingMethod="crop");
469
+ }
470
+
471
+ * html .greylighting_close {
472
+ background-color: transparent;
473
+ background-image: none;
474
+ filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src="../themes/lighting/button-close-grey.png", sizingMethod="crop");
475
+ }
476
+
477
+ * html .greylighting_minimize {
478
+ background-color: transparent;
479
+ background-image: none;
480
+ filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src="../themes/lighting/button-minimize-grey.png", sizingMethod="crop");
481
+ }
482
+
483
+ * html .greylighting_maximize {
484
+ background-color: transparent;
485
+ background-image: none;
486
+ filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src="../themes/lighting/button-maximize-grey.png", sizingMethod="crop");
487
+ }
488
+
489
+ * html .greylighting_content {
490
+ background:#C7C7C7;
491
+ }
492
+
493
+
494
+
495
+ .overlay_greenlighting {
496
+ background-color:#FFF;
497
+ filter:alpha(opacity=60);
498
+ -moz-opacity:0.6;
499
+ opacity:0.6;
500
+ }
501
+
502
+ .greenlighting_wired_frame {
503
+ background:#FFF;
504
+ filter:alpha(opacity=60);
505
+ -moz-opacity:0.6;
506
+ opacity:0.6;
507
+ }
508
+
509
+ .greenlighting_nw {
510
+ background:transparent url(lighting/top-left-green.png) no-repeat 0 0;
511
+ width:9px;
512
+ height:28px;
513
+ }
514
+
515
+ .greenlighting_n {
516
+ background:transparent url(lighting/top-middle-green.png) repeat-x 0 0;
517
+ height:28px;
518
+ }
519
+
520
+ .greenlighting_ne {
521
+ background:transparent url(lighting/top-right-green.png) no-repeat 0 0;
522
+ width:15px;
523
+ height:28px;
524
+ }
525
+
526
+ .greenlighting_w {
527
+ background:transparent url(lighting/left-green.png) repeat-y top left;
528
+ width:9px;
529
+ }
530
+
531
+ .greenlighting_e {
532
+ background:transparent url(lighting/right-green.png) repeat-y top right;
533
+ width:15px;
534
+ }
535
+
536
+ .greenlighting_sw {
537
+ background:transparent url(lighting/bottom-left-green.png) no-repeat 0 0;
538
+ width:9px;
539
+ height:15px;
540
+ }
541
+
542
+ .greenlighting_s {
543
+ background:transparent url(lighting/bottom-middle-green.png) repeat-x 0 0;
544
+ height:15px;
545
+ }
546
+
547
+ .greenlighting_se, .greenlighting_sizer {
548
+ background:transparent url(lighting/bottom-right-green.png) no-repeat 0 0;
549
+ width:15px;
550
+ height:15px;
551
+ }
552
+
553
+ .greenlighting_sizer {
554
+ cursor:se-resize;
555
+ }
556
+
557
+ .greenlighting_close {
558
+ width:15px;
559
+ height:9px;
560
+ background:transparent url(lighting/button-close-green.png) no-repeat 0 0;
561
+ position:absolute;
562
+ top:11px;
563
+ right:10px;
564
+ cursor:pointer;
565
+ z-index:1000;
566
+ }
567
+
568
+ .greenlighting_maximize {
569
+ width:15px;
570
+ height:9px;
571
+ background:transparent url(lighting/button-maximize-green.png) no-repeat 0 0;
572
+ position:absolute;
573
+ top:11px;
574
+ right:25px;
575
+ cursor:pointer;
576
+ z-index:1000;
577
+ }
578
+
579
+ .greenlighting_minimize {
580
+ width:15px;
581
+ height:9px;
582
+ background:transparent url(lighting/button-minimize-green.png) no-repeat 0 0;
583
+ position:absolute;
584
+ top:11px;
585
+ right:40px;
586
+ cursor:pointer;
587
+ z-index:1000;
588
+ }
589
+
590
+ .greenlighting_title {
591
+ float:left;
592
+ height:14px;
593
+ font-size:14px;
594
+ font-weight:bold;
595
+ font-family:Verdana, Arial, sans-serif;
596
+ text-align:center;
597
+ margin-top:2px;
598
+ width:100%;
599
+ color:#2A6002;
600
+ }
601
+
602
+ .greenlighting_content {
603
+ overflow:auto;
604
+ color:#000;
605
+ font-family:Verdana, Arial, sans-serif;
606
+ font-size:12px;
607
+ background:#ACFCAF;
608
+ }
609
+
610
+ /* For alert/confirm dialog */
611
+ .greenlighting_window {
612
+ border:1px solid #F00;
613
+ background:#FFF;
614
+ padding:20px;
615
+ margin-left:auto;
616
+ margin-right:auto;
617
+ width:400px;
618
+ }
619
+
620
+ .greenlighting_message {
621
+ font-size:12px;
622
+ text-align:center;
623
+ width:100%;
624
+ padding-bottom:10px;
625
+ }
626
+
627
+ .greenlighting_buttons {
628
+ text-align:center;
629
+ width:100%;
630
+ }
631
+
632
+ .greenlighting_buttons input {
633
+ border:1px solid #999;
634
+ border-top-color:#CCC;
635
+ border-left-color:#CCC;
636
+ padding:2px;
637
+ background-color:#FFF;
638
+ color:#333;
639
+ background-image:url(lighting/background_buttons.gif);
640
+ background-repeat:repeat-x;
641
+ font-family:Verdana, Arial, sans-serif;
642
+ font-size:10px;
643
+ font-weight:bold;
644
+ text-align:center;
645
+ }
646
+
647
+ .greenlighting_progress {
648
+ float:left;
649
+ margin:auto;
650
+ text-align:center;
651
+ width:100%;
652
+ height:16px;
653
+ background:transparent url('lighting/spinner.gif') no-repeat center center
654
+ }
655
+
656
+ /* FOR IE */
657
+ * html .greenlighting_nw {
658
+ background-color: transparent;
659
+ background-image: none;
660
+ filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src="../themes/lighting/top-left-green.png", sizingMethod="crop");
661
+ }
662
+
663
+ * html .greenlighting_n {
664
+ background-color: transparent;
665
+ background-image: none;
666
+ filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src="../themes/lighting/top-middle-green.png", sizingMethod="scale");
667
+ }
668
+
669
+ * html .greenlighting_ne {
670
+ background-color: transparent;
671
+ background-image: none;
672
+ filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src="../themes/lighting/top-right-green.png", sizingMethod="crop");
673
+ }
674
+
675
+ * html .greenlighting_w {
676
+ background-color: transparent;
677
+ background-image: none;
678
+ filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src="../themes/lighting/left-green.png", sizingMethod="scale");
679
+ }
680
+
681
+ * html .greenlighting_e {
682
+ background-color: transparent;
683
+ background-image: none;
684
+ filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src="../themes/lighting/right-green.png", sizingMethod="scale");
685
+ }
686
+
687
+ * html .greenlighting_sw {
688
+ background-color: transparent;
689
+ background-image: none;
690
+ filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src="../themes/lighting/bottom-left-green.png", sizingMethod="crop");
691
+ }
692
+
693
+ * html .greenlighting_s {
694
+ background-color: transparent;
695
+ background-image: none;
696
+ filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src="../themes/lighting/bottom-middle-green.png", sizingMethod="scale");
697
+ }
698
+
699
+ * html greenlighting_se, * html .greenlighting_sizer {
700
+ background-color: transparent;
701
+ background-image: none;
702
+ filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src="../themes/lighting/bottom-right-green.png", sizingMethod="crop");
703
+ }
704
+
705
+ * html .greenlighting_close {
706
+ background-color: transparent;
707
+ background-image: none;
708
+ filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src="../themes/lighting/button-close-green.png", sizingMethod="crop");
709
+ }
710
+
711
+ * html .greenlighting_minimize {
712
+ background-color: transparent;
713
+ background-image: none;
714
+ filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src="../themes/lighting/button-minimize-green.png", sizingMethod="crop");
715
+ }
716
+
717
+ * html .greenlighting_maximize {
718
+ background-color: transparent;
719
+ background-image: none;
720
+ filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src="../themes/lighting/button-maximize-green.png", sizingMethod="crop");
721
+ }
722
+
723
+ * html .greenlighting_content {
724
+ background:#A4FCA7;
725
+ }
726
+
727
+
728
+
729
+ .overlay_darkbluelighting {
730
+ background-color:#FFF;
731
+ filter:alpha(opacity=60);
732
+ -moz-opacity:0.6;
733
+ opacity:0.6;
734
+ }
735
+
736
+ .darkbluelighting_wired_frame {
737
+ background:#FFF;
738
+ filter:alpha(opacity=60);
739
+ -moz-opacity:0.6;
740
+ opacity:0.6;
741
+ }
742
+
743
+ .darkbluelighting_nw {
744
+ background:transparent url(lighting/top-left-darkblue.png) no-repeat 0 0;
745
+ width:9px;
746
+ height:28px;
747
+ }
748
+
749
+ .darkbluelighting_n {
750
+ background:transparent url(lighting/top-middle-darkblue.png) repeat-x 0 0;
751
+ height:28px;
752
+ }
753
+
754
+ .darkbluelighting_ne {
755
+ background:transparent url(lighting/top-right-darkblue.png) no-repeat 0 0;
756
+ width:15px;
757
+ height:28px;
758
+ }
759
+
760
+ .darkbluelighting_w {
761
+ background:transparent url(lighting/left-darkblue.png) repeat-y top left;
762
+ width:9px;
763
+ }
764
+
765
+ .darkbluelighting_e {
766
+ background:transparent url(lighting/right-darkblue.png) repeat-y top right;
767
+ width:15px;
768
+ }
769
+
770
+ .darkbluelighting_sw {
771
+ background:transparent url(lighting/bottom-left-darkblue.png) no-repeat 0 0;
772
+ width:9px;
773
+ height:15px;
774
+ }
775
+
776
+ .darkbluelighting_s {
777
+ background:transparent url(lighting/bottom-middle-darkblue.png) repeat-x 0 0;
778
+ height:15px;
779
+ }
780
+
781
+ .darkbluelighting_se, .darkbluelighting_sizer {
782
+ background:transparent url(lighting/bottom-right-darkblue.png) no-repeat 0 0;
783
+ width:15px;
784
+ height:15px;
785
+ }
786
+
787
+ .darkbluelighting_sizer {
788
+ cursor:se-resize;
789
+ }
790
+
791
+ .darkbluelighting_close {
792
+ width:15px;
793
+ height:9px;
794
+ background:transparent url(lighting/button-close-darkblue.png) no-repeat 0 0;
795
+ position:absolute;
796
+ top:11px;
797
+ right:10px;
798
+ cursor:pointer;
799
+ z-index:1000;
800
+ }
801
+
802
+ .darkbluelighting_maximize {
803
+ width:15px;
804
+ height:9px;
805
+ background:transparent url(lighting/button-maximize-darkblue.png) no-repeat 0 0;
806
+ position:absolute;
807
+ top:11px;
808
+ right:25px;
809
+ cursor:pointer;
810
+ z-index:1000;
811
+ }
812
+
813
+ .darkbluelighting_minimize {
814
+ width:15px;
815
+ height:9px;
816
+ background:transparent url(lighting/button-minimize-darkblue.png) no-repeat 0 0;
817
+ position:absolute;
818
+ top:11px;
819
+ right:40px;
820
+ cursor:pointer;
821
+ z-index:1000;
822
+ }
823
+
824
+ .darkbluelighting_title {
825
+ float:left;
826
+ height:14px;
827
+ font-size:14px;
828
+ font-weight:bold;
829
+ font-family:Verdana, Arial, sans-serif;
830
+ text-align:center;
831
+ margin-top:2px;
832
+ width:100%;
833
+ color:#E4EFFD;
834
+ }
835
+
836
+ .darkbluelighting_content {
837
+ overflow:auto;
838
+ color:#FFF;
839
+ font-family:Verdana, Arial, sans-serif;
840
+ font-size:12px;
841
+ background:#0413C0;
842
+ }
843
+
844
+ /* For alert/confirm dialog */
845
+ .darkbluelighting_window {
846
+ border:1px solid #F00;
847
+ background:#FFF;
848
+ padding:20px;
849
+ margin-left:auto;
850
+ margin-right:auto;
851
+ width:400px;
852
+ }
853
+
854
+ .darkbluelighting_message {
855
+ font-size:12px;
856
+ text-align:center;
857
+ width:100%;
858
+ padding-bottom:10px;
859
+ }
860
+
861
+ .darkbluelighting_buttons {
862
+ text-align:center;
863
+ width:100%;
864
+ }
865
+
866
+ .darkbluelighting_buttons input {
867
+ border:1px solid #999;
868
+ border-top-color:#CCC;
869
+ border-left-color:#CCC;
870
+ padding:2px;
871
+ background-color:#FFF;
872
+ color:#333;
873
+ background-image:url(lighting/background_buttons.gif);
874
+ background-repeat:repeat-x;
875
+ font-family:Verdana, Arial, sans-serif;
876
+ font-size:10px;
877
+ font-weight:bold;
878
+ text-align:center;
879
+ }
880
+
881
+ .darkbluelighting_progress {
882
+ float:left;
883
+ margin:auto;
884
+ text-align:center;
885
+ width:100%;
886
+ height:16px;
887
+ background:transparent url('lighting/spinner.gif') no-repeat center center
888
+ }
889
+
890
+ /* FOR IE */
891
+ * html .darkbluelighting_nw {
892
+ background-color: transparent;
893
+ background-image: none;
894
+ filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src="../themes/lighting/top-left-darkblue.png", sizingMethod="crop");
895
+ }
896
+
897
+ * html .darkbluelighting_n {
898
+ background-color: transparent;
899
+ background-image: none;
900
+ filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src="../themes/lighting/top-middle-darkblue.png", sizingMethod="scale");
901
+ }
902
+
903
+ * html .darkbluelighting_ne {
904
+ background-color: transparent;
905
+ background-image: none;
906
+ filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src="../themes/lighting/top-right-darkblue.png", sizingMethod="crop");
907
+ }
908
+
909
+ * html .darkbluelighting_w {
910
+ background-color: transparent;
911
+ background-image: none;
912
+ filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src="../themes/lighting/left-darkblue.png", sizingMethod="scale");
913
+ }
914
+
915
+ * html .darkbluelighting_e {
916
+ background-color: transparent;
917
+ background-image: none;
918
+ filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src="../themes/lighting/right-darkblue.png", sizingMethod="scale");
919
+ }
920
+
921
+ * html .darkbluelighting_sw {
922
+ background-color: transparent;
923
+ background-image: none;
924
+ filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src="../themes/lighting/bottom-left-darkblue.png", sizingMethod="crop");
925
+ }
926
+
927
+ * html .darkbluelighting_s {
928
+ background-color: transparent;
929
+ background-image: none;
930
+ filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src="../themes/lighting/bottom-middle-darkblue.png", sizingMethod="scale");
931
+ }
932
+
933
+ * html darkbluelighting_se, * html .darkbluelighting_sizer {
934
+ background-color: transparent;
935
+ background-image: none;
936
+ filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src="../themes/lighting/bottom-right-darkblue.png", sizingMethod="crop");
937
+ }
938
+
939
+ * html .darkbluelighting_close {
940
+ background-color: transparent;
941
+ background-image: none;
942
+ filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src="../themes/lighting/button-close-darkblue.png", sizingMethod="crop");
943
+ }
944
+
945
+ * html .darkbluelighting_minimize {
946
+ background-color: transparent;
947
+ background-image: none;
948
+ filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src="../themes/lighting/button-minimize-darkblue.png", sizingMethod="crop");
949
+ }
950
+
951
+ * html .darkbluelighting_maximize {
952
+ background-color: transparent;
953
+ background-image: none;
954
+ filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src="../themes/lighting/button-maximize-darkblue.png", sizingMethod="crop");
955
+ }
956
+
957
+ * html .darkbluelighting_content {
958
+ background:#020EBA;
959
+ }
960
+
js/prototype/windows/themes/lighting/background_buttons.gif ADDED
Binary file
js/prototype/windows/themes/lighting/bottom-left-blue.png ADDED
Binary file
js/prototype/windows/themes/lighting/bottom-left-darkblue.png ADDED
Binary file
js/prototype/windows/themes/lighting/bottom-left-green.png ADDED
Binary file
js/prototype/windows/themes/lighting/bottom-left-grey.png ADDED
Binary file
js/prototype/windows/themes/lighting/bottom-middle-blue.png ADDED
Binary file
js/prototype/windows/themes/lighting/bottom-middle-darkblue.png ADDED
Binary file
js/prototype/windows/themes/lighting/bottom-middle-green.png ADDED
Binary file
js/prototype/windows/themes/lighting/bottom-middle-grey.png ADDED
Binary file
js/prototype/windows/themes/lighting/bottom-right-blue.png ADDED
Binary file
js/prototype/windows/themes/lighting/bottom-right-darkblue.png ADDED
Binary file
js/prototype/windows/themes/lighting/bottom-right-green.png ADDED
Binary file
js/prototype/windows/themes/lighting/bottom-right-grey.png ADDED
Binary file
js/prototype/windows/themes/lighting/button-close-blue.png ADDED
Binary file
js/prototype/windows/themes/lighting/button-close-darkblue.png ADDED
Binary file
js/prototype/windows/themes/lighting/button-close-green.png ADDED
Binary file
js/prototype/windows/themes/lighting/button-close-grey.png ADDED
Binary file
js/prototype/windows/themes/lighting/button-maximize-blue.png ADDED
Binary file
js/prototype/windows/themes/lighting/button-maximize-darkblue.png ADDED
Binary file
js/prototype/windows/themes/lighting/button-maximize-green.png ADDED
Binary file
js/prototype/windows/themes/lighting/button-maximize-grey.png ADDED
Binary file
js/prototype/windows/themes/lighting/button-minimize-blue.png ADDED
Binary file
js/prototype/windows/themes/lighting/button-minimize-darkblue.png ADDED
Binary file
js/prototype/windows/themes/lighting/button-minimize-green.png ADDED
Binary file
js/prototype/windows/themes/lighting/button-minimize-grey.png ADDED
Binary file
js/prototype/windows/themes/lighting/left-blue.png ADDED
Binary file
js/prototype/windows/themes/lighting/left-darkblue.png ADDED
Binary file
js/prototype/windows/themes/lighting/left-green.png ADDED
Binary file
js/prototype/windows/themes/lighting/left-grey.png ADDED
Binary file
js/prototype/windows/themes/lighting/pngbehavior.htc ADDED
@@ -0,0 +1,67 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <public:component>
2
+ <public:attach event="onpropertychange" onevent="doFix()" />
3
+
4
+ <script type="text/javascript">
5
+
6
+ // IE5.5+ PNG Alpha Fix v1.0RC4
7
+ // (c) 2004-2005 Angus Turnbull http://www.twinhelix.com
8
+
9
+ // This is licensed under the CC-GNU LGPL, version 2.1 or later.
10
+ // For details, see: http://creativecommons.org/licenses/LGPL/2.1/
11
+
12
+
13
+ // This must be a path to a blank image. That's all the configuration you need.
14
+ if (typeof blankImg == 'undefined') var blankImg = 'blank.gif';
15
+
16
+
17
+ var f = 'DXImageTransform.Microsoft.AlphaImageLoader';
18
+
19
+ function filt(s, m)
20
+ {
21
+ if (filters[f])
22
+ {
23
+ filters[f].enabled = s ? true : false;
24
+ if (s) with (filters[f]) { src = s; sizingMethod = m }
25
+ }
26
+ else if (s) style.filter = 'progid:'+f+'(src="'+s+'",sizingMethod="'+m+'")';
27
+ }
28
+
29
+ function doFix()
30
+ {
31
+ alert('ok')
32
+
33
+ // Assume IE7 is OK.
34
+ if (!/MSIE (5\.5|6\.)/.test(navigator.userAgent) ||
35
+ (event && !/(background|src)/.test(event.propertyName))) return;
36
+
37
+ var bgImg = currentStyle.backgroundImage || style.backgroundImage;
38
+
39
+ if (tagName == 'IMG')
40
+ {
41
+ if ((/\.png$/i).test(src))
42
+ {
43
+ if (currentStyle.width == 'auto' && currentStyle.height == 'auto')
44
+ style.width = offsetWidth + 'px';
45
+ filt(src, 'scale');
46
+ src = blankImg;
47
+ }
48
+ else if (src.indexOf(blankImg) < 0) filt();
49
+ }
50
+ else if (bgImg && bgImg != 'none')
51
+ {
52
+ if (bgImg.match(/^url[("']+(.*\.png)[)"']+$/i))
53
+ {
54
+ var s = RegExp.$1;
55
+ if (currentStyle.width == 'auto' && currentStyle.height == 'auto')
56
+ style.width = offsetWidth + 'px';
57
+ style.backgroundImage = 'none';
58
+ filt(s, 'crop');
59
+ // IE link fix.
60
+ for (var n = 0; n < childNodes.length; n++)
61
+ if (childNodes[n].style) childNodes[n].style.position = 'relative';
62
+ }
63
+ else filt();
64
+ }
65
+ }
66
+
67
+ doFix();
js/prototype/windows/themes/lighting/right-blue.png ADDED
Binary file
js/prototype/windows/themes/lighting/right-darkblue.png ADDED
Binary file
js/prototype/windows/themes/lighting/right-green.png ADDED
Binary file
js/prototype/windows/themes/lighting/right-grey.png ADDED
Binary file
js/prototype/windows/themes/lighting/spinner.gif ADDED
Binary file
js/prototype/windows/themes/lighting/top-left-blue.png ADDED
Binary file
js/prototype/windows/themes/lighting/top-left-darkblue.png ADDED
Binary file
js/prototype/windows/themes/lighting/top-left-green.png ADDED
Binary file
js/prototype/windows/themes/lighting/top-left-grey.png ADDED
Binary file
js/prototype/windows/themes/lighting/top-middle-blue.png ADDED
Binary file
js/prototype/windows/themes/lighting/top-middle-darkblue.png ADDED
Binary file
js/prototype/windows/themes/lighting/top-middle-green.png ADDED
Binary file
js/prototype/windows/themes/lighting/top-middle-grey.png ADDED
Binary file
js/prototype/windows/themes/lighting/top-right-blue.png ADDED
Binary file
js/prototype/windows/themes/lighting/top-right-darkblue.png ADDED
Binary file
js/prototype/windows/themes/lighting/top-right-green.png ADDED
Binary file
js/prototype/windows/themes/lighting/top-right-grey.png ADDED
Binary file
js/prototype/windows/themes/mac_os_x.css ADDED
@@ -0,0 +1,333 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* Focused windows */
2
+ .overlay_mac_os_x {
3
+ background-color: #85BBEF;
4
+ filter:alpha(opacity=60);
5
+ -moz-opacity: 0.6;
6
+ opacity: 0.6;
7
+ }
8
+
9
+ .mac_os_x_nw {
10
+ background: transparent url(mac_os_x/TL_Main.png) no-repeat 0 0;
11
+ width:24px;
12
+ height:30px;
13
+ }
14
+
15
+ .mac_os_x_n {
16
+ background: transparent url(mac_os_x/T_Main.png) repeat-x 0 0;
17
+ height:30px;
18
+ }
19
+
20
+ .mac_os_x_ne {
21
+ background: transparent url(mac_os_x/TR_Main.png) no-repeat 0 0;
22
+ width:31px;
23
+ height:30px;
24
+ }
25
+
26
+ .mac_os_x_w {
27
+ background: transparent url(mac_os_x/L_Main.png) repeat-y top left;
28
+ width:16px;
29
+ }
30
+
31
+ .mac_os_x_e {
32
+ background: transparent url(mac_os_x/R_Main.png) repeat-y top right;
33
+ width:16px;
34
+ }
35
+
36
+ .mac_os_x_sw {
37
+ background: transparent url(mac_os_x/BL_Main.png) no-repeat 0 0;
38
+ width:31px;
39
+ height:40px;
40
+ }
41
+
42
+ .mac_os_x_s {
43
+ background: transparent url(mac_os_x/B_Main.png) repeat-x 0 0;
44
+ height:40px;
45
+ }
46
+
47
+ .mac_os_x_se, .mac_os_x_sizer {
48
+ background: transparent url(mac_os_x/BR_Main.png) no-repeat 0 0;
49
+ width:31px;
50
+ height:40px;
51
+ }
52
+
53
+ .mac_os_x_sizer {
54
+ cursor:se-resize;
55
+ }
56
+
57
+ .mac_os_x_close {
58
+ width: 19px;
59
+ height: 19px;
60
+ background: transparent url(mac_os_x/close.gif) no-repeat 0 0;
61
+ position:absolute;
62
+ top:12px;
63
+ left:25px;
64
+ cursor:pointer;
65
+ z-index:1000;
66
+ }
67
+
68
+ .mac_os_x_minimize {
69
+ width: 19px;
70
+ height: 19px;
71
+ background: transparent url(mac_os_x/minimize.gif) no-repeat 0 0;
72
+ position:absolute;
73
+ top:12px;
74
+ left:45px;
75
+ cursor:pointer;
76
+ z-index:1000;
77
+ }
78
+
79
+ .mac_os_x_maximize {
80
+ width: 19px;
81
+ height: 19px;
82
+ background: transparent url(mac_os_x/maximize.gif) no-repeat 0 0;
83
+ position:absolute;
84
+ top:12px;
85
+ left:65px;
86
+ cursor:pointer;
87
+ z-index:1000;
88
+ }
89
+
90
+ .mac_os_x_title {
91
+ float:left;
92
+ height:14px;
93
+ font-family: Tahoma, Arial, sans-serif;
94
+ font-size:12px;
95
+ text-align:center;
96
+ margin-top:8px;
97
+ width:100%;
98
+ color:#000;
99
+ }
100
+
101
+ .mac_os_x_content {
102
+ overflow:auto;
103
+ color: #222;
104
+ font-family: Tahoma, Arial, sans-serif;
105
+ font-size: 10px;
106
+ background:#FFF;
107
+ }
108
+ .mac_os_x_s .status_bar {
109
+ padding-bottom:24px;
110
+ }
111
+
112
+ /* FOR IE */
113
+ * html .mac_os_x_nw {
114
+ background-color: transparent;
115
+ background-image: none;
116
+ filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src="../themes/mac_os_x/TL_Main.png", sizingMethod="crop");
117
+ }
118
+
119
+ * html .mac_os_x_n {
120
+ background-color: transparent;
121
+ background-image: none;
122
+ filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src="../themes/mac_os_x/T_Main.png", sizingMethod="scale");
123
+ }
124
+
125
+ * html .mac_os_x_ne {
126
+ background-color: transparent;
127
+ background-image: none;
128
+ filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src="../themes/mac_os_x/TR_Main.png", sizingMethod="crop");
129
+ }
130
+
131
+ * html .mac_os_x_w {
132
+ background-color: transparent;
133
+ background-image: none;
134
+ filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src="../themes/mac_os_x/L_Main.png", sizingMethod="scale");
135
+ }
136
+
137
+ * html .mac_os_x_e {
138
+ background-color: transparent;
139
+ background-image: none;
140
+ filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src="../themes/mac_os_x/R_Main.png", sizingMethod="scale");
141
+ }
142
+
143
+ * html .mac_os_x_sw {
144
+ background-color: transparent;
145
+ background-image: none;
146
+ filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src="../themes/mac_os_x/BL_Main.png", sizingMethod="crop");
147
+ }
148
+
149
+ * html .mac_os_x_s {
150
+ background-color: transparent;
151
+ background-image: none;
152
+ filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src="../themes/mac_os_x/B_Main.png", sizingMethod="scale");
153
+ }
154
+
155
+ * html .mac_os_x_se {
156
+ background-color: transparent;
157
+ background-image: none;
158
+ filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src="../themes/mac_os_x/BR_Main.png", sizingMethod="crop");
159
+ }
160
+
161
+ * html .mac_os_x_sizer {
162
+ background-color: transparent;
163
+ background-image: none;
164
+ filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src="../themes/mac_os_x/BR_Main.png", sizingMethod="crop");
165
+ }
166
+
167
+
168
+ /* Focused windows */
169
+ .overlay_blur_os_x {
170
+ background-color: #85BBEF;
171
+ filter:alpha(opacity=60);
172
+ -moz-opacity: 0.6;
173
+ opacity: 0.6;
174
+ }
175
+
176
+ .blur_os_x_nw {
177
+ background: transparent url(mac_os_x/TL.png) no-repeat 0 0;
178
+ width:24px;
179
+ height:30px;
180
+ }
181
+
182
+ .blur_os_x_n {
183
+ background: transparent url(mac_os_x/T.png) repeat-x 0 0;
184
+ height:30px;
185
+ }
186
+
187
+ .blur_os_x_ne {
188
+ background: transparent url(mac_os_x/TR.png) no-repeat 0 0;
189
+ width:31px;
190
+ height:30px;
191
+ }
192
+
193
+ .blur_os_x_w {
194
+ background: transparent url(mac_os_x/L.png) repeat-y top left;
195
+ width:16px;
196
+ }
197
+
198
+ .blur_os_x_e {
199
+ background: transparent url(mac_os_x/R.png) repeat-y top right;
200
+ width:16px;
201
+ }
202
+
203
+ .blur_os_x_sw {
204
+ background: transparent url(mac_os_x/BL.png) no-repeat 0 0;
205
+ width:31px;
206
+ height:40px;
207
+ }
208
+
209
+ .blur_os_x_s {
210
+ background: transparent url(mac_os_x/B.png) repeat-x 0 0;
211
+ height:40px;
212
+ }
213
+
214
+ .blur_os_x_se, .blur_os_x_sizer {
215
+ background: transparent url(mac_os_x/BR.png) no-repeat 0 0;
216
+ width:31px;
217
+ height:40px;
218
+ }
219
+
220
+ .blur_os_x_sizer {
221
+ cursor:se-resize;
222
+ }
223
+
224
+ .blur_os_x_close {
225
+ width: 19px;
226
+ height: 19px;
227
+ background: transparent url(mac_os_x/close.gif) no-repeat 0 0;
228
+ position:absolute;
229
+ top:12px;
230
+ left:25px;
231
+ cursor:pointer;
232
+ z-index:1000;
233
+ }
234
+
235
+ .blur_os_x_minimize {
236
+ width: 19px;
237
+ height: 19px;
238
+ background: transparent url(mac_os_x/minimize.gif) no-repeat 0 0;
239
+ position:absolute;
240
+ top:12px;
241
+ left:45px;
242
+ cursor:pointer;
243
+ z-index:1000;
244
+ }
245
+
246
+ .blur_os_x_maximize {
247
+ width: 19px;
248
+ height: 19px;
249
+ background: transparent url(mac_os_x/maximize.gif) no-repeat 0 0;
250
+ position:absolute;
251
+ top:12px;
252
+ left:65px;
253
+ cursor:pointer;
254
+ z-index:1000;
255
+ }
256
+
257
+ .blur_os_x_title {
258
+ float:left;
259
+ height:14px;
260
+ font-family: Tahoma, Arial, sans-serif;
261
+ font-size:12px;
262
+ text-align:center;
263
+ margin-top:8px;
264
+ width:100%;
265
+ color:#000;
266
+ }
267
+
268
+ .blur_os_x_content {
269
+ overflow:auto;
270
+ color: #222;
271
+ font-family: Tahoma, Arial, sans-serif;
272
+ font-size: 10px;
273
+ background:#FFF;
274
+ }
275
+ .blur_os_x_s .status_bar {
276
+ padding-bottom:24px;
277
+ }
278
+
279
+ /* FOR IE */
280
+ * html .blur_os_x_nw {
281
+ background-color: transparent;
282
+ background-image: none;
283
+ filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src="../themes/mac_os_x/TL.png", sizingMethod="crop");
284
+ }
285
+
286
+ * html .blur_os_x_n {
287
+ background-color: transparent;
288
+ background-image: none;
289
+ filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src="../themes/mac_os_x/T.png", sizingMethod="scale");
290
+ }
291
+
292
+ * html .blur_os_x_ne {
293
+ background-color: transparent;
294
+ background-image: none;
295
+ filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src="../themes/mac_os_x/TR.png", sizingMethod="crop");
296
+ }
297
+
298
+ * html .blur_os_x_w {
299
+ background-color: transparent;
300
+ background-image: none;
301
+ filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src="../themes/mac_os_x/L.png", sizingMethod="scale");
302
+ }
303
+
304
+ * html .blur_os_x_e {
305
+ background-color: transparent;
306
+ background-image: none;
307
+ filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src="../themes/mac_os_x/R.png", sizingMethod="scale");
308
+ }
309
+
310
+ * html .blur_os_x_sw {
311
+ background-color: transparent;
312
+ background-image: none;
313
+ filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src="../themes/mac_os_x/BL.png", sizingMethod="crop");
314
+ }
315
+
316
+ * html .blur_os_x_s {
317
+ background-color: transparent;
318
+ background-image: none;
319
+ filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src="../themes/mac_os_x/B.png", sizingMethod="scale");
320
+ }
321
+
322
+ * html .blur_os_x_se {
323
+ background-color: transparent;
324
+ background-image: none;
325
+ filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src="../themes/mac_os_x/BR.png", sizingMethod="crop");
326
+ }
327
+
328
+ * html .blur_os_x_sizer {
329
+ background-color: transparent;
330
+ background-image: none;
331
+ filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src="../themes/mac_os_x/BR.png", sizingMethod="crop");
332
+ }
333
+
js/prototype/windows/themes/mac_os_x_dialog.css ADDED
@@ -0,0 +1,160 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ .overlay_mac_os_x_dialog {
2
+ background-color: #FF7224;
3
+ filter:alpha(opacity=60);
4
+ -moz-opacity: 0.6;
5
+ opacity: 0.6;
6
+ }
7
+
8
+ .mac_os_x_dialog_nw {
9
+ background: transparent url(mac_os_x_dialog/L.png) repeat-y top left;
10
+ width:16px;
11
+ height:16px;
12
+ }
13
+
14
+ .mac_os_x_dialog_n {
15
+ background: transparent url(mac_os_x_dialog/bg.gif) repeat 0 0;
16
+ height:18px;
17
+ }
18
+
19
+ .mac_os_x_dialog_ne {
20
+ background: transparent url(mac_os_x_dialog/R.png) repeat-y top left;
21
+ width:16px;
22
+ height:16px;
23
+ }
24
+
25
+ .mac_os_x_dialog_w {
26
+ background: transparent url(mac_os_x_dialog/L.png) repeat-y top left;
27
+ width:16px;
28
+ }
29
+
30
+ .mac_os_x_dialog_e {
31
+ background: transparent url(mac_os_x_dialog/R.png) repeat-y top right;
32
+ width:16px;
33
+ }
34
+
35
+ .mac_os_x_dialog_sw {
36
+ background: transparent url(mac_os_x_dialog/BL.png) no-repeat 0 0;
37
+ width:31px;
38
+ height:40px;
39
+ }
40
+
41
+ .mac_os_x_dialog_s {
42
+ background: transparent url(mac_os_x_dialog/B.png) repeat-x 0 0;
43
+ height:40px;
44
+ }
45
+
46
+ .mac_os_x_dialog_se, .mac_os_x_dialog_sizer {
47
+ background: transparent url(mac_os_x_dialog/BR.png) no-repeat 0 0;
48
+ width:31px;
49
+ height:40px;
50
+ }
51
+
52
+ .mac_os_x_dialog_sizer {
53
+ cursor:se-resize;
54
+ }
55
+
56
+ .mac_os_x_dialog_close {
57
+ width: 19px;
58
+ height: 19px;
59
+ background: transparent url(mac_os_x_dialog/close.gif) no-repeat 0 0;
60
+ position:absolute;
61
+ top:12px;
62
+ left:25px;
63
+ cursor:pointer;
64
+ z-index:1000;
65
+ }
66
+
67
+ .mac_os_x_dialog_minimize {
68
+ width: 19px;
69
+ height: 19px;
70
+ background: transparent url(mac_os_x_dialog/minimize.gif) no-repeat 0 0;
71
+ position:absolute;
72
+ top:12px;
73
+ left:45px;
74
+ cursor:pointer;
75
+ z-index:1000;
76
+ }
77
+
78
+ .mac_os_x_dialog_maximize {
79
+ width: 19px;
80
+ height: 19px;
81
+ background: transparent url(mac_os_x_dialog/maximize.gif) no-repeat 0 0;
82
+ position:absolute;
83
+ top:12px;
84
+ left:65px;
85
+ cursor:pointer;
86
+ z-index:1000;
87
+ }
88
+
89
+ .mac_os_x_dialog_title {
90
+ float:left;
91
+ height:14px;
92
+ font-family: Tahoma, Arial, sans-serif;
93
+ font-size:12px;
94
+ text-align:center;
95
+ margin-top:6px;
96
+ width:100%;
97
+ color:#000;
98
+ }
99
+
100
+ .mac_os_x_dialog_content {
101
+ overflow:auto;
102
+ color: #222;
103
+ font-family: Tahoma, Arial, sans-serif;
104
+ font-size: 10px;
105
+ background: transparent url(mac_os_x_dialog/bg.gif) repeat 0 0;
106
+ }
107
+
108
+ .mac_os_x_dialog_buttons {
109
+ text-align: center;
110
+ }
111
+ /* FOR IE */
112
+ * html .mac_os_x_dialog_nw {
113
+ background-color: transparent;
114
+ background-image: none;
115
+ filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src="../themes/mac_os_x_dialog/L.png", sizingMethod="scale");
116
+ }
117
+
118
+
119
+ * html .mac_os_x_dialog_ne {
120
+ background-color: transparent;
121
+ background-image: none;
122
+ filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src="../themes/mac_os_x_dialog/R.png", sizingMethod="scale");
123
+ }
124
+
125
+ * html .mac_os_x_dialog_w {
126
+ background-color: transparent;
127
+ background-image: none;
128
+ filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src="../themes/mac_os_x_dialog/L.png", sizingMethod="scale");
129
+ }
130
+
131
+ * html .mac_os_x_dialog_e {
132
+ background-color: transparent;
133
+ background-image: none;
134
+ filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src="../themes/mac_os_x_dialog/R.png", sizingMethod="scale");
135
+ }
136
+
137
+ * html .mac_os_x_dialog_sw {
138
+ background-color: transparent;
139
+ background-image: none;
140
+ filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src="../themes/mac_os_x_dialog/BL.png", sizingMethod="crop");
141
+ }
142
+
143
+ * html .mac_os_x_dialog_s {
144
+ background-color: transparent;
145
+ background-image: none;
146
+ filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src="../themes/mac_os_x_dialog/B.png", sizingMethod="scale");
147
+ }
148
+
149
+ * html .mac_os_x_dialog_se {
150
+ background-color: transparent;
151
+ background-image: none;
152
+ filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src="../themes/mac_os_x_dialog/BR.png", sizingMethod="crop");
153
+ }
154
+
155
+ * html .mac_os_x_dialog_sizer {
156
+ background-color: transparent;
157
+ background-image: none;
158
+ filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src="../themes/mac_os_x_dialog/BR.png", sizingMethod="crop");
159
+ }
160
+
js/prototype/windows/themes/magento.css ADDED
@@ -0,0 +1,122 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ .overlay_magento {
2
+ background-color: #000;
3
+ filter:alpha(opacity=60);
4
+ -moz-opacity: 0.6;
5
+ opacity: 0.6;
6
+ }
7
+
8
+ .top.table_window { border-bottom:4px solid #deebf0; background:url(magento/top_bg.gif) repeat-x #7e9fb3; }
9
+ .magento_nw {
10
+ width:6px;
11
+ height:26px;
12
+ }
13
+ .magento_n {
14
+ height:26px;
15
+ }
16
+ .magento_ne {
17
+ width:6px;
18
+ height:26px;
19
+ }
20
+ .magento_w {
21
+ background:#deebf0;
22
+ width:3px;
23
+ }
24
+
25
+ .magento_e {
26
+ background:#deebf0;
27
+ width:3px;
28
+ }
29
+
30
+ .magento_sw {
31
+ background:#deebf0;
32
+ width:5px;
33
+ height:3px;
34
+ }
35
+ .magento_s {
36
+ background:#deebf0;
37
+ height:3px;
38
+ }
39
+ .magento_se, .magento_sizer {
40
+ background:#deebf0;
41
+ width:5px;
42
+ height:3px;
43
+ }
44
+
45
+ .magento_sizer {
46
+ cursor:se-resize;
47
+ }
48
+
49
+ .magento_close {
50
+ width: 15px;
51
+ height: 15px;
52
+ background: transparent url(magento/button-close-focused.png) no-repeat 0 0;
53
+ position:absolute;
54
+ top:5px;
55
+ right:6px;
56
+ cursor:pointer;
57
+ z-index:1000;
58
+ }
59
+
60
+ .magento_minimize {
61
+ width: 21px;
62
+ height: 21px;
63
+ background: transparent url(magento/button-minimize-focused.png) no-repeat 0 0;
64
+ position:absolute;
65
+ top:0px;
66
+ right:26px;
67
+ cursor:pointer;
68
+ z-index:1000;
69
+ }
70
+
71
+ .magento_maximize {
72
+ width: 21px;
73
+ height: 21px;
74
+ background: transparent url(magento/button-maximize-focused.png) no-repeat 0 0;
75
+ position:absolute;
76
+ top:0px;
77
+ right:47px;
78
+ cursor:pointer;
79
+ z-index:1000;
80
+ }
81
+
82
+
83
+ .magento_title {
84
+ float:left;
85
+ height:22px;
86
+ font-size:12px;
87
+ text-align:left;
88
+ margin-top:2px;
89
+ width:100%;
90
+ color:#FFF;
91
+ font-weight:bold;
92
+ }
93
+
94
+ .magento_content {
95
+ overflow:auto;
96
+ font-size: 12px;
97
+ background:#deebf0;
98
+ }
99
+ .magento_content, .magento_content label {
100
+ color: #333;
101
+ font-family:Arial, sans-serif;
102
+ }
103
+
104
+ .magento_buttons { padding-bottom:9px; }
105
+ /* FOR IE */
106
+ * html .magento_minimize {
107
+ background-color: transparent;
108
+ background-image: none;
109
+ filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src="../themes/magento/button-minimize-focused.png", sizingMethod="crop");
110
+ }
111
+
112
+ * html .magento_maximize {
113
+ background-color: transparent;
114
+ background-image: none;
115
+ filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src="../themes/magento/button-maximize-focused.png", sizingMethod="scale");
116
+ }
117
+
118
+ * html .magento_close {
119
+ background-color: transparent;
120
+ background-image: none;
121
+ filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src="../themes/magento/button-close-focused.png", sizingMethod="crop");
122
+ }
js/prototype/windows/themes/magento/button-close-focused.png ADDED
Binary file
js/prototype/windows/themes/magento/top_bg.gif ADDED
Binary file
js/prototype/windows/themes/nuncio.css ADDED
@@ -0,0 +1,164 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ .overlay_nuncio img { border: none; }
2
+
3
+ .overlay_nuncio {
4
+ background-color: #666666;
5
+ }
6
+
7
+ .nuncio_nw {
8
+ width: 12px;
9
+ height: 28px;
10
+ background: url(nuncio/top_left.png) no-repeat;
11
+ }
12
+
13
+ .nuncio_n {
14
+ background: url(nuncio/top_mid.png) repeat-x;
15
+ height: 28px;
16
+ }
17
+
18
+ .nuncio_ne {
19
+ width: 21px;
20
+ height: 28px;
21
+ background: url(nuncio/top_right.png) no-repeat;
22
+ }
23
+
24
+ .nuncio_e {
25
+ width: 21px;
26
+ background: url(nuncio/center_right.png) repeat-y top right;
27
+ }
28
+
29
+ .nuncio_w {
30
+ width: 12px;
31
+ background: url(nuncio/center_left.png) repeat-y top left;
32
+ }
33
+
34
+ .nuncio_sw {
35
+ width: 12px;
36
+ height: 18px;
37
+ background: url(nuncio/bottom_left.png) no-repeat;
38
+ }
39
+
40
+ .nuncio_s {
41
+ background: url(nuncio/bottom_mid.png) repeat-x 0 0;
42
+ height: 18px;
43
+ }
44
+
45
+ .nuncio_se, .nuncio_sizer {
46
+ width: 21px;
47
+ height: 18px;
48
+ background: url(nuncio/bottom_right.png) no-repeat;
49
+ }
50
+
51
+ .nuncio_close {
52
+ width: 14px;
53
+ height: 14px;
54
+ background: url(nuncio/close.png) no-repeat;
55
+ position:absolute;
56
+ top:10px;
57
+ right:22px;
58
+ cursor:pointer;
59
+ z-index:2000;
60
+ }
61
+
62
+ .nuncio_minimize {
63
+ width: 14px;
64
+ height: 15px;
65
+ background: url(nuncio/minimize.png) no-repeat;
66
+ position:absolute;
67
+ top:10px;
68
+ right:40px;
69
+ cursor:pointer;
70
+ z-index:2000;
71
+ }
72
+
73
+ .nuncio_title {
74
+ float:left;
75
+ font-size:11px;
76
+ font-weight: bold;
77
+ font-style: italic;
78
+ color: #fff;
79
+ width: 100%
80
+ }
81
+
82
+ .nuncio_content {
83
+ background: url(nuncio/overlay.png) repeat;
84
+ overflow:auto;
85
+ color: #ddd;
86
+ font-family: Tahoma, Arial, "sans-serif";
87
+ font-size: 10px;
88
+ }
89
+
90
+ .nuncio_sizer {
91
+ cursor:se-resize;
92
+ }
93
+
94
+
95
+ .top_draggable, .bottom_draggable {
96
+ cursor:move
97
+ }
98
+ /* FOR IE */
99
+ * html .nuncio_nw {
100
+ background-color: transparent;
101
+ background-image: none;
102
+ filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src="../themes/nuncio/top_left.png", sizingMethod="crop");
103
+ }
104
+
105
+ * html .nuncio_n {
106
+ background-color: transparent;
107
+ background-image: none;
108
+ filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src="../themes/nuncio/top_mid.png", sizingMethod="scale");
109
+ }
110
+
111
+ * html .nuncio_ne {
112
+ background-color: transparent;
113
+ background-image: none;
114
+ filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src="../themes/nuncio/top_right.png", sizingMethod="crop");
115
+ }
116
+
117
+ * html .nuncio_w {
118
+ background-color: transparent;
119
+ background-image: none;
120
+ filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src="../themes/nuncio/center_left.png", sizingMethod="scale");
121
+ }
122
+
123
+ * html .nuncio_e {
124
+ background-color: transparent;
125
+ background-image: none;
126
+ filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src="../themes/nuncio/center_right.png", sizingMethod="scale");
127
+ }
128
+
129
+ * html .nuncio_sw {
130
+ background-color: transparent;
131
+ background-image: none;
132
+ filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src="../themes/nuncio/bottom_left.png", sizingMethod="crop");
133
+ }
134
+
135
+ * html .nuncio_s {
136
+ background-color: transparent;
137
+ background-image: none;
138
+ filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src="../themes/nuncio/bottom_mid.png", sizingMethod="scale");
139
+ }
140
+
141
+ * html .nuncio_se {
142
+ background-color: transparent;
143
+ background-image: none;
144
+ filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src="../themes/nuncio/bottom_right.png", sizingMethod="crop");
145
+ }
146
+
147
+ * html .nuncio_sizer {
148
+ background-color: transparent;
149
+ background-image: none;
150
+ filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src="../themes/nuncio/bottom_right.png", sizingMethod="crop");
151
+ }
152
+
153
+ * html .nuncio_close {
154
+ background-color: transparent;
155
+ background-image: none;
156
+ filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src="../themes/nuncio/close.png", sizingMethod="crop");
157
+ }
158
+
159
+ * html .nuncio_minimize {
160
+ background-color: transparent;
161
+ background-image: none;
162
+ filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src="../themes/nuncio/minimize.png", sizingMethod="crop");
163
+ }
164
+
js/prototype/windows/themes/nuncio/bottom_left.png ADDED
Binary file
js/prototype/windows/themes/nuncio/bottom_mid.png ADDED
Binary file
js/prototype/windows/themes/nuncio/bottom_right.png ADDED
Binary file
js/prototype/windows/themes/nuncio/center_left.png ADDED
Binary file
js/prototype/windows/themes/nuncio/center_right.png ADDED
Binary file
js/prototype/windows/themes/nuncio/close.png ADDED
Binary file
js/prototype/windows/themes/nuncio/minimize.png ADDED
Binary file
js/prototype/windows/themes/nuncio/overlay.png ADDED
Binary file
js/prototype/windows/themes/nuncio/top_left.png ADDED
Binary file
js/prototype/windows/themes/nuncio/top_mid.png ADDED
Binary file
js/prototype/windows/themes/nuncio/top_right.png ADDED
Binary file
js/prototype/windows/themes/spread.css ADDED
@@ -0,0 +1,108 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ .overlay_spread {
2
+ background-color: #85BBEF;
3
+ filter:alpha(opacity=60);
4
+ -moz-opacity: 0.6;
5
+ opacity: 0.6;
6
+ }
7
+
8
+ .spread_nw {
9
+ background: transparent url(spread/left-top.gif) no-repeat 0 0;
10
+ width:10px;
11
+ height:25px;
12
+ }
13
+
14
+ .spread_n {
15
+ background: transparent url(spread/top-middle.gif) repeat-x 0 0;
16
+ height:25px;
17
+ }
18
+
19
+ .spread_ne {
20
+ background: transparent url(spread/right-top.gif) no-repeat 0 0;
21
+ width:10px;
22
+ height:25px;
23
+ }
24
+
25
+ .spread_w {
26
+ background: transparent url(spread/frame-left.gif) repeat-y top left;
27
+ width:7px;
28
+ }
29
+
30
+ .spread_e {
31
+ background: transparent url(spread/frame-right.gif) repeat-y top right;
32
+ width:7px;
33
+ }
34
+
35
+ .spread_sw {
36
+ background: transparent url(spread/bottom-left-c.gif) no-repeat 0 0;
37
+ width:7px;
38
+ height:7px;
39
+ }
40
+
41
+ .spread_s {
42
+ background: transparent url(spread/bottom-middle.gif) repeat-x 0 0;
43
+ height:7px;
44
+ }
45
+
46
+ .spread_se, .spread_sizer {
47
+ background: transparent url(spread/bottom-right-c.gif) no-repeat 0 0;
48
+ width:7px;
49
+ height:7px;
50
+ }
51
+
52
+ .spread_sizer {
53
+ cursor:se-resize;
54
+ }
55
+
56
+ .spread_close {
57
+ width: 23px;
58
+ height: 23px;
59
+ background: transparent url(spread/button-close-focus.gif) no-repeat 0 0;
60
+ position:absolute;
61
+ top:0px;
62
+ right:11px;
63
+ cursor:pointer;
64
+ z-index:1000;
65
+ }
66
+
67
+ .spread_minimize {
68
+ width: 23px;
69
+ height: 23px;
70
+ background: transparent url(spread/button-min-focus.gif) no-repeat 0 0;
71
+ position:absolute;
72
+ top:0px;
73
+ right:55px;
74
+ cursor:pointer;
75
+ z-index:1000;
76
+ }
77
+
78
+ .spread_maximize {
79
+ width: 23px;
80
+ height: 23px;
81
+ background: transparent url(spread/button-max-focus.gif) no-repeat 0 0;
82
+ position:absolute;
83
+ top:0px;
84
+ right:33px;
85
+ cursor:pointer;
86
+ z-index:1000;
87
+ }
88
+
89
+ .spread_title {
90
+ float:left;
91
+ height:14px;
92
+ font-family: Tahoma, Arial, sans-serif;
93
+ font-size:14px;
94
+ font-weight:bold;
95
+ text-align:left;
96
+ margin-top:2px;
97
+ width:100%;
98
+ color:#E47211;
99
+ }
100
+
101
+ .spread_content {
102
+ overflow:auto;
103
+ color: #222;
104
+ font-family: Tahoma, Arial, sans-serif;
105
+ font-size: 10px;
106
+ background:#A9EA00;
107
+ }
108
+
js/prototype/windows/themes/spread/bottom-left-c.gif ADDED
Binary file
js/prototype/windows/themes/spread/bottom-middle.gif ADDED
Binary file
js/prototype/windows/themes/spread/bottom-right-c.gif ADDED
Binary file
js/prototype/windows/themes/spread/button-close-focus.gif ADDED
Binary file
js/prototype/windows/themes/spread/button-max-focus.gif ADDED
Binary file
js/prototype/windows/themes/spread/button-min-focus.gif ADDED
Binary file
js/prototype/windows/themes/spread/frame-left.gif ADDED
Binary file
js/prototype/windows/themes/spread/frame-right.gif ADDED
Binary file
js/prototype/windows/themes/spread/left-top.gif ADDED
Binary file
js/prototype/windows/themes/spread/right-top.gif ADDED
Binary file
js/prototype/windows/themes/spread/top-middle.gif ADDED
Binary file
js/scriptaculous/builder.js ADDED
@@ -0,0 +1,136 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // script.aculo.us builder.js v1.8.2, Tue Nov 18 18:30:58 +0100 2008
2
+
3
+ // Copyright (c) 2005-2008 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
4
+ //
5
+ // script.aculo.us is freely distributable under the terms of an MIT-style license.
6
+ // For details, see the script.aculo.us web site: http://script.aculo.us/
7
+
8
+ var Builder = {
9
+ NODEMAP: {
10
+ AREA: 'map',
11
+ CAPTION: 'table',
12
+ COL: 'table',
13
+ COLGROUP: 'table',
14
+ LEGEND: 'fieldset',
15
+ OPTGROUP: 'select',
16
+ OPTION: 'select',
17
+ PARAM: 'object',
18
+ TBODY: 'table',
19
+ TD: 'table',
20
+ TFOOT: 'table',
21
+ TH: 'table',
22
+ THEAD: 'table',
23
+ TR: 'table'
24
+ },
25
+ // note: For Firefox < 1.5, OPTION and OPTGROUP tags are currently broken,
26
+ // due to a Firefox bug
27
+ node: function(elementName) {
28
+ elementName = elementName.toUpperCase();
29
+
30
+ // try innerHTML approach
31
+ var parentTag = this.NODEMAP[elementName] || 'div';
32
+ var parentElement = document.createElement(parentTag);
33
+ try { // prevent IE "feature": http://dev.rubyonrails.org/ticket/2707
34
+ parentElement.innerHTML = "<" + elementName + "></" + elementName + ">";
35
+ } catch(e) {}
36
+ var element = parentElement.firstChild || null;
37
+
38
+ // see if browser added wrapping tags
39
+ if(element && (element.tagName.toUpperCase() != elementName))
40
+ element = element.getElementsByTagName(elementName)[0];
41
+
42
+ // fallback to createElement approach
43
+ if(!element) element = document.createElement(elementName);
44
+
45
+ // abort if nothing could be created
46
+ if(!element) return;
47
+
48
+ // attributes (or text)
49
+ if(arguments[1])
50
+ if(this._isStringOrNumber(arguments[1]) ||
51
+ (arguments[1] instanceof Array) ||
52
+ arguments[1].tagName) {
53
+ this._children(element, arguments[1]);
54
+ } else {
55
+ var attrs = this._attributes(arguments[1]);
56
+ if(attrs.length) {
57
+ try { // prevent IE "feature": http://dev.rubyonrails.org/ticket/2707
58
+ parentElement.innerHTML = "<" +elementName + " " +
59
+ attrs + "></" + elementName + ">";
60
+ } catch(e) {}
61
+ element = parentElement.firstChild || null;
62
+ // workaround firefox 1.0.X bug
63
+ if(!element) {
64
+ element = document.createElement(elementName);
65
+ for(attr in arguments[1])
66
+ element[attr == 'class' ? 'className' : attr] = arguments[1][attr];
67
+ }
68
+ if(element.tagName.toUpperCase() != elementName)
69
+ element = parentElement.getElementsByTagName(elementName)[0];
70
+ }
71
+ }
72
+
73
+ // text, or array of children
74
+ if(arguments[2])
75
+ this._children(element, arguments[2]);
76
+
77
+ return $(element);
78
+ },
79
+ _text: function(text) {
80
+ return document.createTextNode(text);
81
+ },
82
+
83
+ ATTR_MAP: {
84
+ 'className': 'class',
85
+ 'htmlFor': 'for'
86
+ },
87
+
88
+ _attributes: function(attributes) {
89
+ var attrs = [];
90
+ for(attribute in attributes)
91
+ attrs.push((attribute in this.ATTR_MAP ? this.ATTR_MAP[attribute] : attribute) +
92
+ '="' + attributes[attribute].toString().escapeHTML().gsub(/"/,'&quot;') + '"');
93
+ return attrs.join(" ");
94
+ },
95
+ _children: function(element, children) {
96
+ if(children.tagName) {
97
+ element.appendChild(children);
98
+ return;
99
+ }
100
+ if(typeof children=='object') { // array can hold nodes and text
101
+ children.flatten().each( function(e) {
102
+ if(typeof e=='object')
103
+ element.appendChild(e);
104
+ else
105
+ if(Builder._isStringOrNumber(e))
106
+ element.appendChild(Builder._text(e));
107
+ });
108
+ } else
109
+ if(Builder._isStringOrNumber(children))
110
+ element.appendChild(Builder._text(children));
111
+ },
112
+ _isStringOrNumber: function(param) {
113
+ return(typeof param=='string' || typeof param=='number');
114
+ },
115
+ build: function(html) {
116
+ var element = this.node('div');
117
+ $(element).update(html.strip());
118
+ return element.down();
119
+ },
120
+ dump: function(scope) {
121
+ if(typeof scope != 'object' && typeof scope != 'function') scope = window; //global scope
122
+
123
+ var tags = ("A ABBR ACRONYM ADDRESS APPLET AREA B BASE BASEFONT BDO BIG BLOCKQUOTE BODY " +
124
+ "BR BUTTON CAPTION CENTER CITE CODE COL COLGROUP DD DEL DFN DIR DIV DL DT EM FIELDSET " +
125
+ "FONT FORM FRAME FRAMESET H1 H2 H3 H4 H5 H6 HEAD HR HTML I IFRAME IMG INPUT INS ISINDEX "+
126
+ "KBD LABEL LEGEND LI LINK MAP MENU META NOFRAMES NOSCRIPT OBJECT OL OPTGROUP OPTION P "+
127
+ "PARAM PRE Q S SAMP SCRIPT SELECT SMALL SPAN STRIKE STRONG STYLE SUB SUP TABLE TBODY TD "+
128
+ "TEXTAREA TFOOT TH THEAD TITLE TR TT U UL VAR").split(/\s+/);
129
+
130
+ tags.each( function(tag){
131
+ scope[tag] = function() {
132
+ return Builder.node.apply(Builder, [tag].concat($A(arguments)));
133
+ };
134
+ });
135
+ }
136
+ };
js/scriptaculous/controls.js ADDED
@@ -0,0 +1,965 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // script.aculo.us controls.js v1.8.2, Tue Nov 18 18:30:58 +0100 2008
2
+
3
+ // Copyright (c) 2005-2008 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
4
+ // (c) 2005-2008 Ivan Krstic (http://blogs.law.harvard.edu/ivan)
5
+ // (c) 2005-2008 Jon Tirsen (http://www.tirsen.com)
6
+ // Contributors:
7
+ // Richard Livsey
8
+ // Rahul Bhargava
9
+ // Rob Wills
10
+ //
11
+ // script.aculo.us is freely distributable under the terms of an MIT-style license.
12
+ // For details, see the script.aculo.us web site: http://script.aculo.us/
13
+
14
+ // Autocompleter.Base handles all the autocompletion functionality
15
+ // that's independent of the data source for autocompletion. This
16
+ // includes drawing the autocompletion menu, observing keyboard
17
+ // and mouse events, and similar.
18
+ //
19
+ // Specific autocompleters need to provide, at the very least,
20
+ // a getUpdatedChoices function that will be invoked every time
21
+ // the text inside the monitored textbox changes. This method
22
+ // should get the text for which to provide autocompletion by
23
+ // invoking this.getToken(), NOT by directly accessing
24
+ // this.element.value. This is to allow incremental tokenized
25
+ // autocompletion. Specific auto-completion logic (AJAX, etc)
26
+ // belongs in getUpdatedChoices.
27
+ //
28
+ // Tokenized incremental autocompletion is enabled automatically
29
+ // when an autocompleter is instantiated with the 'tokens' option
30
+ // in the options parameter, e.g.:
31
+ // new Ajax.Autocompleter('id','upd', '/url/', { tokens: ',' });
32
+ // will incrementally autocomplete with a comma as the token.
33
+ // Additionally, ',' in the above example can be replaced with
34
+ // a token array, e.g. { tokens: [',', '\n'] } which
35
+ // enables autocompletion on multiple tokens. This is most
36
+ // useful when one of the tokens is \n (a newline), as it
37
+ // allows smart autocompletion after linebreaks.
38
+
39
+ if(typeof Effect == 'undefined')
40
+ throw("controls.js requires including script.aculo.us' effects.js library");
41
+
42
+ var Autocompleter = { };
43
+ Autocompleter.Base = Class.create({
44
+ baseInitialize: function(element, update, options) {
45
+ element = $(element);
46
+ this.element = element;
47
+ this.update = $(update);
48
+ this.hasFocus = false;
49
+ this.changed = false;
50
+ this.active = false;
51
+ this.index = 0;
52
+ this.entryCount = 0;
53
+ this.oldElementValue = this.element.value;
54
+
55
+ if(this.setOptions)
56
+ this.setOptions(options);
57
+ else
58
+ this.options = options || { };
59
+
60
+ this.options.paramName = this.options.paramName || this.element.name;
61
+ this.options.tokens = this.options.tokens || [];
62
+ this.options.frequency = this.options.frequency || 0.4;
63
+ this.options.minChars = this.options.minChars || 1;
64
+ this.options.onShow = this.options.onShow ||
65
+ function(element, update){
66
+ if(!update.style.position || update.style.position=='absolute') {
67
+ update.style.position = 'absolute';
68
+ Position.clone(element, update, {
69
+ setHeight: false,
70
+ offsetTop: element.offsetHeight
71
+ });
72
+ }
73
+ Effect.Appear(update,{duration:0.15});
74
+ };
75
+ this.options.onHide = this.options.onHide ||
76
+ function(element, update){ new Effect.Fade(update,{duration:0.15}) };
77
+
78
+ if(typeof(this.options.tokens) == 'string')
79
+ this.options.tokens = new Array(this.options.tokens);
80
+ // Force carriage returns as token delimiters anyway
81
+ if (!this.options.tokens.include('\n'))
82
+ this.options.tokens.push('\n');
83
+
84
+ this.observer = null;
85
+
86
+ this.element.setAttribute('autocomplete','off');
87
+
88
+ Element.hide(this.update);
89
+
90
+ Event.observe(this.element, 'blur', this.onBlur.bindAsEventListener(this));
91
+ Event.observe(this.element, 'keydown', this.onKeyPress.bindAsEventListener(this));
92
+ },
93
+
94
+ show: function() {
95
+ if(Element.getStyle(this.update, 'display')=='none') this.options.onShow(this.element, this.update);
96
+ if(!this.iefix &&
97
+ (Prototype.Browser.IE) &&
98
+ (Element.getStyle(this.update, 'position')=='absolute')) {
99
+ new Insertion.After(this.update,
100
+ '<iframe id="' + this.update.id + '_iefix" '+
101
+ 'style="display:none;position:absolute;filter:progid:DXImageTransform.Microsoft.Alpha(opacity=0);" ' +
102
+ 'src="javascript:false;" frameborder="0" scrolling="no"></iframe>');
103
+ this.iefix = $(this.update.id+'_iefix');
104
+ }
105
+ if(this.iefix) setTimeout(this.fixIEOverlapping.bind(this), 50);
106
+ },
107
+
108
+ fixIEOverlapping: function() {
109
+ Position.clone(this.update, this.iefix, {setTop:(!this.update.style.height)});
110
+ this.iefix.style.zIndex = 1;
111
+ this.update.style.zIndex = 2;
112
+ Element.show(this.iefix);
113
+ },
114
+
115
+ hide: function() {
116
+ this.stopIndicator();
117
+ if(Element.getStyle(this.update, 'display')!='none') this.options.onHide(this.element, this.update);
118
+ if(this.iefix) Element.hide(this.iefix);
119
+ },
120
+
121
+ startIndicator: function() {
122
+ if(this.options.indicator) Element.show(this.options.indicator);
123
+ },
124
+
125
+ stopIndicator: function() {
126
+ if(this.options.indicator) Element.hide(this.options.indicator);
127
+ },
128
+
129
+ onKeyPress: function(event) {
130
+ if(this.active)
131
+ switch(event.keyCode) {
132
+ case Event.KEY_TAB:
133
+ case Event.KEY_RETURN:
134
+ this.selectEntry();
135
+ Event.stop(event);
136
+ case Event.KEY_ESC:
137
+ this.hide();
138
+ this.active = false;
139
+ Event.stop(event);
140
+ return;
141
+ case Event.KEY_LEFT:
142
+ case Event.KEY_RIGHT:
143
+ return;
144
+ case Event.KEY_UP:
145
+ this.markPrevious();
146
+ this.render();
147
+ Event.stop(event);
148
+ return;
149
+ case Event.KEY_DOWN:
150
+ this.markNext();
151
+ this.render();
152
+ Event.stop(event);
153
+ return;
154
+ }
155
+ else
156
+ if(event.keyCode==Event.KEY_TAB || event.keyCode==Event.KEY_RETURN ||
157
+ (Prototype.Browser.WebKit > 0 && event.keyCode == 0)) return;
158
+
159
+ this.changed = true;
160
+ this.hasFocus = true;
161
+
162
+ if(this.observer) clearTimeout(this.observer);
163
+ this.observer =
164
+ setTimeout(this.onObserverEvent.bind(this), this.options.frequency*1000);
165
+ },
166
+
167
+ activate: function() {
168
+ this.changed = false;
169
+ this.hasFocus = true;
170
+ this.getUpdatedChoices();
171
+ },
172
+
173
+ onHover: function(event) {
174
+ var element = Event.findElement(event, 'LI');
175
+ if(this.index != element.autocompleteIndex)
176
+ {
177
+ this.index = element.autocompleteIndex;
178
+ this.render();
179
+ }
180
+ Event.stop(event);
181
+ },
182
+
183
+ onClick: function(event) {
184
+ var element = Event.findElement(event, 'LI');
185
+ this.index = element.autocompleteIndex;
186
+ this.selectEntry();
187
+ this.hide();
188
+ },
189
+
190
+ onBlur: function(event) {
191
+ // needed to make click events working
192
+ setTimeout(this.hide.bind(this), 250);
193
+ this.hasFocus = false;
194
+ this.active = false;
195
+ },
196
+
197
+ render: function() {
198
+ if(this.entryCount > 0) {
199
+ for (var i = 0; i < this.entryCount; i++)
200
+ this.index==i ?
201
+ Element.addClassName(this.getEntry(i),"selected") :
202
+ Element.removeClassName(this.getEntry(i),"selected");
203
+ if(this.hasFocus) {
204
+ this.show();
205
+ this.active = true;
206
+ }
207
+ } else {
208
+ this.active = false;
209
+ this.hide();
210
+ }
211
+ },
212
+
213
+ markPrevious: function() {
214
+ if(this.index > 0) this.index--;
215
+ else this.index = this.entryCount-1;
216
+ //this.getEntry(this.index).scrollIntoView(true); useless
217
+ },
218
+
219
+ markNext: function() {
220
+ if(this.index < this.entryCount-1) this.index++;
221
+ else this.index = 0;
222
+ this.getEntry(this.index).scrollIntoView(false);
223
+ },
224
+
225
+ getEntry: function(index) {
226
+ return this.update.firstChild.childNodes[index];
227
+ },
228
+
229
+ getCurrentEntry: function() {
230
+ return this.getEntry(this.index);
231
+ },
232
+
233
+ selectEntry: function() {
234
+ this.active = false;
235
+ this.updateElement(this.getCurrentEntry());
236
+ },
237
+
238
+ updateElement: function(selectedElement) {
239
+ if (this.options.updateElement) {
240
+ this.options.updateElement(selectedElement);
241
+ return;
242
+ }
243
+ var value = '';
244
+ if (this.options.select) {
245
+ var nodes = $(selectedElement).select('.' + this.options.select) || [];
246
+ if(nodes.length>0) value = Element.collectTextNodes(nodes[0], this.options.select);
247
+ } else
248
+ value = Element.collectTextNodesIgnoreClass(selectedElement, 'informal');
249
+
250
+ var bounds = this.getTokenBounds();
251
+ if (bounds[0] != -1) {
252
+ var newValue = this.element.value.substr(0, bounds[0]);
253
+ var whitespace = this.element.value.substr(bounds[0]).match(/^\s+/);
254
+ if (whitespace)
255
+ newValue += whitespace[0];
256
+ this.element.value = newValue + value + this.element.value.substr(bounds[1]);
257
+ } else {
258
+ this.element.value = value;
259
+ }
260
+ this.oldElementValue = this.element.value;
261
+ this.element.focus();
262
+
263
+ if (this.options.afterUpdateElement)
264
+ this.options.afterUpdateElement(this.element, selectedElement);
265
+ },
266
+
267
+ updateChoices: function(choices) {
268
+ if(!this.changed && this.hasFocus) {
269
+ this.update.innerHTML = choices;
270
+ Element.cleanWhitespace(this.update);
271
+ Element.cleanWhitespace(this.update.down());
272
+
273
+ if(this.update.firstChild && this.update.down().childNodes) {
274
+ this.entryCount =
275
+ this.update.down().childNodes.length;
276
+ for (var i = 0; i < this.entryCount; i++) {
277
+ var entry = this.getEntry(i);
278
+ entry.autocompleteIndex = i;
279
+ this.addObservers(entry);
280
+ }
281
+ } else {
282
+ this.entryCount = 0;
283
+ }
284
+
285
+ this.stopIndicator();
286
+ this.index = 0;
287
+
288
+ if(this.entryCount==1 && this.options.autoSelect) {
289
+ this.selectEntry();
290
+ this.hide();
291
+ } else {
292
+ this.render();
293
+ }
294
+ }
295
+ },
296
+
297
+ addObservers: function(element) {
298
+ Event.observe(element, "mouseover", this.onHover.bindAsEventListener(this));
299
+ Event.observe(element, "click", this.onClick.bindAsEventListener(this));
300
+ },
301
+
302
+ onObserverEvent: function() {
303
+ this.changed = false;
304
+ this.tokenBounds = null;
305
+ if(this.getToken().length>=this.options.minChars) {
306
+ this.getUpdatedChoices();
307
+ } else {
308
+ this.active = false;
309
+ this.hide();
310
+ }
311
+ this.oldElementValue = this.element.value;
312
+ },
313
+
314
+ getToken: function() {
315
+ var bounds = this.getTokenBounds();
316
+ return this.element.value.substring(bounds[0], bounds[1]).strip();
317
+ },
318
+
319
+ getTokenBounds: function() {
320
+ if (null != this.tokenBounds) return this.tokenBounds;
321
+ var value = this.element.value;
322
+ if (value.strip().empty()) return [-1, 0];
323
+ var diff = arguments.callee.getFirstDifferencePos(value, this.oldElementValue);
324
+ var offset = (diff == this.oldElementValue.length ? 1 : 0);
325
+ var prevTokenPos = -1, nextTokenPos = value.length;
326
+ var tp;
327
+ for (var index = 0, l = this.options.tokens.length; index < l; ++index) {
328
+ tp = value.lastIndexOf(this.options.tokens[index], diff + offset - 1);
329
+ if (tp > prevTokenPos) prevTokenPos = tp;
330
+ tp = value.indexOf(this.options.tokens[index], diff + offset);
331
+ if (-1 != tp && tp < nextTokenPos) nextTokenPos = tp;
332
+ }
333
+ return (this.tokenBounds = [prevTokenPos + 1, nextTokenPos]);
334
+ }
335
+ });
336
+
337
+ Autocompleter.Base.prototype.getTokenBounds.getFirstDifferencePos = function(newS, oldS) {
338
+ var boundary = Math.min(newS.length, oldS.length);
339
+ for (var index = 0; index < boundary; ++index)
340
+ if (newS[index] != oldS[index])
341
+ return index;
342
+ return boundary;
343
+ };
344
+
345
+ Ajax.Autocompleter = Class.create(Autocompleter.Base, {
346
+ initialize: function(element, update, url, options) {
347
+ this.baseInitialize(element, update, options);
348
+ this.options.asynchronous = true;
349
+ this.options.onComplete = this.onComplete.bind(this);
350
+ this.options.defaultParams = this.options.parameters || null;
351
+ this.url = url;
352
+ },
353
+
354
+ getUpdatedChoices: function() {
355
+ this.startIndicator();
356
+
357
+ var entry = encodeURIComponent(this.options.paramName) + '=' +
358
+ encodeURIComponent(this.getToken());
359
+
360
+ this.options.parameters = this.options.callback ?
361
+ this.options.callback(this.element, entry) : entry;
362
+
363
+ if(this.options.defaultParams)
364
+ this.options.parameters += '&' + this.options.defaultParams;
365
+
366
+ new Ajax.Request(this.url, this.options);
367
+ },
368
+
369
+ onComplete: function(request) {
370
+ this.updateChoices(request.responseText);
371
+ }
372
+ });
373
+
374
+ // The local array autocompleter. Used when you'd prefer to
375
+ // inject an array of autocompletion options into the page, rather
376
+ // than sending out Ajax queries, which can be quite slow sometimes.
377
+ //
378
+ // The constructor takes four parameters. The first two are, as usual,
379
+ // the id of the monitored textbox, and id of the autocompletion menu.
380
+ // The third is the array you want to autocomplete from, and the fourth
381
+ // is the options block.
382
+ //
383
+ // Extra local autocompletion options:
384
+ // - choices - How many autocompletion choices to offer
385
+ //
386
+ // - partialSearch - If false, the autocompleter will match entered
387
+ // text only at the beginning of strings in the
388
+ // autocomplete array. Defaults to true, which will
389
+ // match text at the beginning of any *word* in the
390
+ // strings in the autocomplete array. If you want to
391
+ // search anywhere in the string, additionally set
392
+ // the option fullSearch to true (default: off).
393
+ //
394
+ // - fullSsearch - Search anywhere in autocomplete array strings.
395
+ //
396
+ // - partialChars - How many characters to enter before triggering
397
+ // a partial match (unlike minChars, which defines
398
+ // how many characters are required to do any match
399
+ // at all). Defaults to 2.
400
+ //
401
+ // - ignoreCase - Whether to ignore case when autocompleting.
402
+ // Defaults to true.
403
+ //
404
+ // It's possible to pass in a custom function as the 'selector'
405
+ // option, if you prefer to write your own autocompletion logic.
406
+ // In that case, the other options above will not apply unless
407
+ // you support them.
408
+
409
+ Autocompleter.Local = Class.create(Autocompleter.Base, {
410
+ initialize: function(element, update, array, options) {
411
+ this.baseInitialize(element, update, options);
412
+ this.options.array = array;
413
+ },
414
+
415
+ getUpdatedChoices: function() {
416
+ this.updateChoices(this.options.selector(this));
417
+ },
418
+
419
+ setOptions: function(options) {
420
+ this.options = Object.extend({
421
+ choices: 10,
422
+ partialSearch: true,
423
+ partialChars: 2,
424
+ ignoreCase: true,
425
+ fullSearch: false,
426
+ selector: function(instance) {
427
+ var ret = []; // Beginning matches
428
+ var partial = []; // Inside matches
429
+ var entry = instance.getToken();
430
+ var count = 0;
431
+
432
+ for (var i = 0; i < instance.options.array.length &&
433
+ ret.length < instance.options.choices ; i++) {
434
+
435
+ var elem = instance.options.array[i];
436
+ var foundPos = instance.options.ignoreCase ?
437
+ elem.toLowerCase().indexOf(entry.toLowerCase()) :
438
+ elem.indexOf(entry);
439
+
440
+ while (foundPos != -1) {
441
+ if (foundPos == 0 && elem.length != entry.length) {
442
+ ret.push("<li><strong>" + elem.substr(0, entry.length) + "</strong>" +
443
+ elem.substr(entry.length) + "</li>");
444
+ break;
445
+ } else if (entry.length >= instance.options.partialChars &&
446
+ instance.options.partialSearch && foundPos != -1) {
447
+ if (instance.options.fullSearch || /\s/.test(elem.substr(foundPos-1,1))) {
448
+ partial.push("<li>" + elem.substr(0, foundPos) + "<strong>" +
449
+ elem.substr(foundPos, entry.length) + "</strong>" + elem.substr(
450
+ foundPos + entry.length) + "</li>");
451
+ break;
452
+ }
453
+ }
454
+
455
+ foundPos = instance.options.ignoreCase ?
456
+ elem.toLowerCase().indexOf(entry.toLowerCase(), foundPos + 1) :
457
+ elem.indexOf(entry, foundPos + 1);
458
+
459
+ }
460
+ }
461
+ if (partial.length)
462
+ ret = ret.concat(partial.slice(0, instance.options.choices - ret.length));
463
+ return "<ul>" + ret.join('') + "</ul>";
464
+ }
465
+ }, options || { });
466
+ }
467
+ });
468
+
469
+ // AJAX in-place editor and collection editor
470
+ // Full rewrite by Christophe Porteneuve <tdd@tddsworld.com> (April 2007).
471
+
472
+ // Use this if you notice weird scrolling problems on some browsers,
473
+ // the DOM might be a bit confused when this gets called so do this
474
+ // waits 1 ms (with setTimeout) until it does the activation
475
+ Field.scrollFreeActivate = function(field) {
476
+ setTimeout(function() {
477
+ Field.activate(field);
478
+ }, 1);
479
+ };
480
+
481
+ Ajax.InPlaceEditor = Class.create({
482
+ initialize: function(element, url, options) {
483
+ this.url = url;
484
+ this.element = element = $(element);
485
+ this.prepareOptions();
486
+ this._controls = { };
487
+ arguments.callee.dealWithDeprecatedOptions(options); // DEPRECATION LAYER!!!
488
+ Object.extend(this.options, options || { });
489
+ if (!this.options.formId && this.element.id) {
490
+ this.options.formId = this.element.id + '-inplaceeditor';
491
+ if ($(this.options.formId))
492
+ this.options.formId = '';
493
+ }
494
+ if (this.options.externalControl)
495
+ this.options.externalControl = $(this.options.externalControl);
496
+ if (!this.options.externalControl)
497
+ this.options.externalControlOnly = false;
498
+ this._originalBackground = this.element.getStyle('background-color') || 'transparent';
499
+ this.element.title = this.options.clickToEditText;
500
+ this._boundCancelHandler = this.handleFormCancellation.bind(this);
501
+ this._boundComplete = (this.options.onComplete || Prototype.emptyFunction).bind(this);
502
+ this._boundFailureHandler = this.handleAJAXFailure.bind(this);
503
+ this._boundSubmitHandler = this.handleFormSubmission.bind(this);
504
+ this._boundWrapperHandler = this.wrapUp.bind(this);
505
+ this.registerListeners();
506
+ },
507
+ checkForEscapeOrReturn: function(e) {
508
+ if (!this._editing || e.ctrlKey || e.altKey || e.shiftKey) return;
509
+ if (Event.KEY_ESC == e.keyCode)
510
+ this.handleFormCancellation(e);
511
+ else if (Event.KEY_RETURN == e.keyCode)
512
+ this.handleFormSubmission(e);
513
+ },
514
+ createControl: function(mode, handler, extraClasses) {
515
+ var control = this.options[mode + 'Control'];
516
+ var text = this.options[mode + 'Text'];
517
+ if ('button' == control) {
518
+ var btn = document.createElement('input');
519
+ btn.type = 'submit';
520
+ btn.value = text;
521
+ btn.className = 'editor_' + mode + '_button';
522
+ if ('cancel' == mode)
523
+ btn.onclick = this._boundCancelHandler;
524
+ this._form.appendChild(btn);
525
+ this._controls[mode] = btn;
526
+ } else if ('link' == control) {
527
+ var link = document.createElement('a');
528
+ link.href = '#';
529
+ link.appendChild(document.createTextNode(text));
530
+ link.onclick = 'cancel' == mode ? this._boundCancelHandler : this._boundSubmitHandler;
531
+ link.className = 'editor_' + mode + '_link';
532
+ if (extraClasses)
533
+ link.className += ' ' + extraClasses;
534
+ this._form.appendChild(link);
535
+ this._controls[mode] = link;
536
+ }
537
+ },
538
+ createEditField: function() {
539
+ var text = (this.options.loadTextURL ? this.options.loadingText : this.getText());
540
+ var fld;
541
+ if (1 >= this.options.rows && !/\r|\n/.test(this.getText())) {
542
+ fld = document.createElement('input');
543
+ fld.type = 'text';
544
+ var size = this.options.size || this.options.cols || 0;
545
+ if (0 < size) fld.size = size;
546
+ } else {
547
+ fld = document.createElement('textarea');
548
+ fld.rows = (1 >= this.options.rows ? this.options.autoRows : this.options.rows);
549
+ fld.cols = this.options.cols || 40;
550
+ }
551
+ fld.name = this.options.paramName;
552
+ fld.value = text; // No HTML breaks conversion anymore
553
+ fld.className = 'editor_field';
554
+ if (this.options.submitOnBlur)
555
+ fld.onblur = this._boundSubmitHandler;
556
+ this._controls.editor = fld;
557
+ if (this.options.loadTextURL)
558
+ this.loadExternalText();
559
+ this._form.appendChild(this._controls.editor);
560
+ },
561
+ createForm: function() {
562
+ var ipe = this;
563
+ function addText(mode, condition) {
564
+ var text = ipe.options['text' + mode + 'Controls'];
565
+ if (!text || condition === false) return;
566
+ ipe._form.appendChild(document.createTextNode(text));
567
+ };
568
+ this._form = $(document.createElement('form'));
569
+ this._form.id = this.options.formId;
570
+ this._form.addClassName(this.options.formClassName);
571
+ this._form.onsubmit = this._boundSubmitHandler;
572
+ this.createEditField();
573
+ if ('textarea' == this._controls.editor.tagName.toLowerCase())
574
+ this._form.appendChild(document.createElement('br'));
575
+ if (this.options.onFormCustomization)
576
+ this.options.onFormCustomization(this, this._form);
577
+ addText('Before', this.options.okControl || this.options.cancelControl);
578
+ this.createControl('ok', this._boundSubmitHandler);
579
+ addText('Between', this.options.okControl && this.options.cancelControl);
580
+ this.createControl('cancel', this._boundCancelHandler, 'editor_cancel');
581
+ addText('After', this.options.okControl || this.options.cancelControl);
582
+ },
583
+ destroy: function() {
584
+ if (this._oldInnerHTML)
585
+ this.element.innerHTML = this._oldInnerHTML;
586
+ this.leaveEditMode();
587
+ this.unregisterListeners();
588
+ },
589
+ enterEditMode: function(e) {
590
+ if (this._saving || this._editing) return;
591
+ this._editing = true;
592
+ this.triggerCallback('onEnterEditMode');
593
+ if (this.options.externalControl)
594
+ this.options.externalControl.hide();
595
+ this.element.hide();
596
+ this.createForm();
597
+ this.element.parentNode.insertBefore(this._form, this.element);
598
+ if (!this.options.loadTextURL)
599
+ this.postProcessEditField();
600
+ if (e) Event.stop(e);
601
+ },
602
+ enterHover: function(e) {
603
+ if (this.options.hoverClassName)
604
+ this.element.addClassName(this.options.hoverClassName);
605
+ if (this._saving) return;
606
+ this.triggerCallback('onEnterHover');
607
+ },
608
+ getText: function() {
609
+ return this.element.innerHTML.unescapeHTML();
610
+ },
611
+ handleAJAXFailure: function(transport) {
612
+ this.triggerCallback('onFailure', transport);
613
+ if (this._oldInnerHTML) {
614
+ this.element.innerHTML = this._oldInnerHTML;
615
+ this._oldInnerHTML = null;
616
+ }
617
+ },
618
+ handleFormCancellation: function(e) {
619
+ this.wrapUp();
620
+ if (e) Event.stop(e);
621
+ },
622
+ handleFormSubmission: function(e) {
623
+ var form = this._form;
624
+ var value = $F(this._controls.editor);
625
+ this.prepareSubmission();
626
+ var params = this.options.callback(form, value) || '';
627
+ if (Object.isString(params))
628
+ params = params.toQueryParams();
629
+ params.editorId = this.element.id;
630
+ if (this.options.htmlResponse) {
631
+ var options = Object.extend({ evalScripts: true }, this.options.ajaxOptions);
632
+ Object.extend(options, {
633
+ parameters: params,
634
+ onComplete: this._boundWrapperHandler,
635
+ onFailure: this._boundFailureHandler
636
+ });
637
+ new Ajax.Updater({ success: this.element }, this.url, options);
638
+ } else {
639
+ var options = Object.extend({ method: 'get' }, this.options.ajaxOptions);
640
+ Object.extend(options, {
641
+ parameters: params,
642
+ onComplete: this._boundWrapperHandler,
643
+ onFailure: this._boundFailureHandler
644
+ });
645
+ new Ajax.Request(this.url, options);
646
+ }
647
+ if (e) Event.stop(e);
648
+ },
649
+ leaveEditMode: function() {
650
+ this.element.removeClassName(this.options.savingClassName);
651
+ this.removeForm();
652
+ this.leaveHover();
653
+ this.element.style.backgroundColor = this._originalBackground;
654
+ this.element.show();
655
+ if (this.options.externalControl)
656
+ this.options.externalControl.show();
657
+ this._saving = false;
658
+ this._editing = false;
659
+ this._oldInnerHTML = null;
660
+ this.triggerCallback('onLeaveEditMode');
661
+ },
662
+ leaveHover: function(e) {
663
+ if (this.options.hoverClassName)
664
+ this.element.removeClassName(this.options.hoverClassName);
665
+ if (this._saving) return;
666
+ this.triggerCallback('onLeaveHover');
667
+ },
668
+ loadExternalText: function() {
669
+ this._form.addClassName(this.options.loadingClassName);
670
+ this._controls.editor.disabled = true;
671
+ var options = Object.extend({ method: 'get' }, this.options.ajaxOptions);
672
+ Object.extend(options, {
673
+ parameters: 'editorId=' + encodeURIComponent(this.element.id),
674
+ onComplete: Prototype.emptyFunction,
675
+ onSuccess: function(transport) {
676
+ this._form.removeClassName(this.options.loadingClassName);
677
+ var text = transport.responseText;
678
+ if (this.options.stripLoadedTextTags)
679
+ text = text.stripTags();
680
+ this._controls.editor.value = text;
681
+ this._controls.editor.disabled = false;
682
+ this.postProcessEditField();
683
+ }.bind(this),
684
+ onFailure: this._boundFailureHandler
685
+ });
686
+ new Ajax.Request(this.options.loadTextURL, options);
687
+ },
688
+ postProcessEditField: function() {
689
+ var fpc = this.options.fieldPostCreation;
690
+ if (fpc)
691
+ $(this._controls.editor)['focus' == fpc ? 'focus' : 'activate']();
692
+ },
693
+ prepareOptions: function() {
694
+ this.options = Object.clone(Ajax.InPlaceEditor.DefaultOptions);
695
+ Object.extend(this.options, Ajax.InPlaceEditor.DefaultCallbacks);
696
+ [this._extraDefaultOptions].flatten().compact().each(function(defs) {
697
+ Object.extend(this.options, defs);
698
+ }.bind(this));
699
+ },
700
+ prepareSubmission: function() {
701
+ this._saving = true;
702
+ this.removeForm();
703
+ this.leaveHover();
704
+ this.showSaving();
705
+ },
706
+ registerListeners: function() {
707
+ this._listeners = { };
708
+ var listener;
709
+ $H(Ajax.InPlaceEditor.Listeners).each(function(pair) {
710
+ listener = this[pair.value].bind(this);
711
+ this._listeners[pair.key] = listener;
712
+ if (!this.options.externalControlOnly)
713
+ this.element.observe(pair.key, listener);
714
+ if (this.options.externalControl)
715
+ this.options.externalControl.observe(pair.key, listener);
716
+ }.bind(this));
717
+ },
718
+ removeForm: function() {
719
+ if (!this._form) return;
720
+ this._form.remove();
721
+ this._form = null;
722
+ this._controls = { };
723
+ },
724
+ showSaving: function() {
725
+ this._oldInnerHTML = this.element.innerHTML;
726
+ this.element.innerHTML = this.options.savingText;
727
+ this.element.addClassName(this.options.savingClassName);
728
+ this.element.style.backgroundColor = this._originalBackground;
729
+ this.element.show();
730
+ },
731
+ triggerCallback: function(cbName, arg) {
732
+ if ('function' == typeof this.options[cbName]) {
733
+ this.options[cbName](this, arg);
734
+ }
735
+ },
736
+ unregisterListeners: function() {
737
+ $H(this._listeners).each(function(pair) {
738
+ if (!this.options.externalControlOnly)
739
+ this.element.stopObserving(pair.key, pair.value);
740
+ if (this.options.externalControl)
741
+ this.options.externalControl.stopObserving(pair.key, pair.value);
742
+ }.bind(this));
743
+ },
744
+ wrapUp: function(transport) {
745
+ this.leaveEditMode();
746
+ // Can't use triggerCallback due to backward compatibility: requires
747
+ // binding + direct element
748
+ this._boundComplete(transport, this.element);
749
+ }
750
+ });
751
+
752
+ Object.extend(Ajax.InPlaceEditor.prototype, {
753
+ dispose: Ajax.InPlaceEditor.prototype.destroy
754
+ });
755
+
756
+ Ajax.InPlaceCollectionEditor = Class.create(Ajax.InPlaceEditor, {
757
+ initialize: function($super, element, url, options) {
758
+ this._extraDefaultOptions = Ajax.InPlaceCollectionEditor.DefaultOptions;
759
+ $super(element, url, options);
760
+ },
761
+
762
+ createEditField: function() {
763
+ var list = document.createElement('select');
764
+ list.name = this.options.paramName;
765
+ list.size = 1;
766
+ this._controls.editor = list;
767
+ this._collection = this.options.collection || [];
768
+ if (this.options.loadCollectionURL)
769
+ this.loadCollection();
770
+ else
771
+ this.checkForExternalText();
772
+ this._form.appendChild(this._controls.editor);
773
+ },
774
+
775
+ loadCollection: function() {
776
+ this._form.addClassName(this.options.loadingClassName);
777
+ this.showLoadingText(this.options.loadingCollectionText);
778
+ var options = Object.extend({ method: 'get' }, this.options.ajaxOptions);
779
+ Object.extend(options, {
780
+ parameters: 'editorId=' + encodeURIComponent(this.element.id),
781
+ onComplete: Prototype.emptyFunction,
782
+ onSuccess: function(transport) {
783
+ var js = transport.responseText.strip();
784
+ if (!/^\[.*\]$/.test(js)) // TODO: improve sanity check
785
+ throw('Server returned an invalid collection representation.');
786
+ this._collection = eval(js);
787
+ this.checkForExternalText();
788
+ }.bind(this),
789
+ onFailure: this.onFailure
790
+ });
791
+ new Ajax.Request(this.options.loadCollectionURL, options);
792
+ },
793
+
794
+ showLoadingText: function(text) {
795
+ this._controls.editor.disabled = true;
796
+ var tempOption = this._controls.editor.firstChild;
797
+ if (!tempOption) {
798
+ tempOption = document.createElement('option');
799
+ tempOption.value = '';
800
+ this._controls.editor.appendChild(tempOption);
801
+ tempOption.selected = true;
802
+ }
803
+ tempOption.update((text || '').stripScripts().stripTags());
804
+ },
805
+
806
+ checkForExternalText: function() {
807
+ this._text = this.getText();
808
+ if (this.options.loadTextURL)
809
+ this.loadExternalText();
810
+ else
811
+ this.buildOptionList();
812
+ },
813
+
814
+ loadExternalText: function() {
815
+ this.showLoadingText(this.options.loadingText);
816
+ var options = Object.extend({ method: 'get' }, this.options.ajaxOptions);
817
+ Object.extend(options, {
818
+ parameters: 'editorId=' + encodeURIComponent(this.element.id),
819
+ onComplete: Prototype.emptyFunction,
820
+ onSuccess: function(transport) {
821
+ this._text = transport.responseText.strip();
822
+ this.buildOptionList();
823
+ }.bind(this),
824
+ onFailure: this.onFailure
825
+ });
826
+ new Ajax.Request(this.options.loadTextURL, options);
827
+ },
828
+
829
+ buildOptionList: function() {
830
+ this._form.removeClassName(this.options.loadingClassName);
831
+ this._collection = this._collection.map(function(entry) {
832
+ return 2 === entry.length ? entry : [entry, entry].flatten();
833
+ });
834
+ var marker = ('value' in this.options) ? this.options.value : this._text;
835
+ var textFound = this._collection.any(function(entry) {
836
+ return entry[0] == marker;
837
+ }.bind(this));
838
+ this._controls.editor.update('');
839
+ var option;
840
+ this._collection.each(function(entry, index) {
841
+ option = document.createElement('option');
842
+ option.value = entry[0];
843
+ option.selected = textFound ? entry[0] == marker : 0 == index;
844
+ option.appendChild(document.createTextNode(entry[1]));
845
+ this._controls.editor.appendChild(option);
846
+ }.bind(this));
847
+ this._controls.editor.disabled = false;
848
+ Field.scrollFreeActivate(this._controls.editor);
849
+ }
850
+ });
851
+
852
+ //**** DEPRECATION LAYER FOR InPlace[Collection]Editor! ****
853
+ //**** This only exists for a while, in order to let ****
854
+ //**** users adapt to the new API. Read up on the new ****
855
+ //**** API and convert your code to it ASAP! ****
856
+
857
+ Ajax.InPlaceEditor.prototype.initialize.dealWithDeprecatedOptions = function(options) {
858
+ if (!options) return;
859
+ function fallback(name, expr) {
860
+ if (name in options || expr === undefined) return;
861
+ options[name] = expr;
862
+ };
863
+ fallback('cancelControl', (options.cancelLink ? 'link' : (options.cancelButton ? 'button' :
864
+ options.cancelLink == options.cancelButton == false ? false : undefined)));
865
+ fallback('okControl', (options.okLink ? 'link' : (options.okButton ? 'button' :
866
+ options.okLink == options.okButton == false ? false : undefined)));
867
+ fallback('highlightColor', options.highlightcolor);
868
+ fallback('highlightEndColor', options.highlightendcolor);
869
+ };
870
+
871
+ Object.extend(Ajax.InPlaceEditor, {
872
+ DefaultOptions: {
873
+ ajaxOptions: { },
874
+ autoRows: 3, // Use when multi-line w/ rows == 1
875
+ cancelControl: 'link', // 'link'|'button'|false
876
+ cancelText: 'cancel',
877
+ clickToEditText: 'Click to edit',
878
+ externalControl: null, // id|elt
879
+ externalControlOnly: false,
880
+ fieldPostCreation: 'activate', // 'activate'|'focus'|false
881
+ formClassName: 'inplaceeditor-form',
882
+ formId: null, // id|elt
883
+ highlightColor: '#ffff99',
884
+ highlightEndColor: '#ffffff',
885
+ hoverClassName: '',
886
+ htmlResponse: true,
887
+ loadingClassName: 'inplaceeditor-loading',
888
+ loadingText: 'Loading...',
889
+ okControl: 'button', // 'link'|'button'|false
890
+ okText: 'ok',
891
+ paramName: 'value',
892
+ rows: 1, // If 1 and multi-line, uses autoRows
893
+ savingClassName: 'inplaceeditor-saving',
894
+ savingText: 'Saving...',
895
+ size: 0,
896
+ stripLoadedTextTags: false,
897
+ submitOnBlur: false,
898
+ textAfterControls: '',
899
+ textBeforeControls: '',
900
+ textBetweenControls: ''
901
+ },
902
+ DefaultCallbacks: {
903
+ callback: function(form) {
904
+ return Form.serialize(form);
905
+ },
906
+ onComplete: function(transport, element) {
907
+ // For backward compatibility, this one is bound to the IPE, and passes
908
+ // the element directly. It was too often customized, so we don't break it.
909
+ new Effect.Highlight(element, {
910
+ startcolor: this.options.highlightColor, keepBackgroundImage: true });
911
+ },
912
+ onEnterEditMode: null,
913
+ onEnterHover: function(ipe) {
914
+ ipe.element.style.backgroundColor = ipe.options.highlightColor;
915
+ if (ipe._effect)
916
+ ipe._effect.cancel();
917
+ },
918
+ onFailure: function(transport, ipe) {
919
+ alert('Error communication with the server: ' + transport.responseText.stripTags());
920
+ },
921
+ onFormCustomization: null, // Takes the IPE and its generated form, after editor, before controls.
922
+ onLeaveEditMode: null,
923
+ onLeaveHover: function(ipe) {
924
+ ipe._effect = new Effect.Highlight(ipe.element, {
925
+ startcolor: ipe.options.highlightColor, endcolor: ipe.options.highlightEndColor,
926
+ restorecolor: ipe._originalBackground, keepBackgroundImage: true
927
+ });
928
+ }
929
+ },
930
+ Listeners: {
931
+ click: 'enterEditMode',
932
+ keydown: 'checkForEscapeOrReturn',
933
+ mouseover: 'enterHover',
934
+ mouseout: 'leaveHover'
935
+ }
936
+ });
937
+
938
+ Ajax.InPlaceCollectionEditor.DefaultOptions = {
939
+ loadingCollectionText: 'Loading options...'
940
+ };
941
+
942
+ // Delayed observer, like Form.Element.Observer,
943
+ // but waits for delay after last key input
944
+ // Ideal for live-search fields
945
+
946
+ Form.Element.DelayedObserver = Class.create({
947
+ initialize: function(element, delay, callback) {
948
+ this.delay = delay || 0.5;
949
+ this.element = $(element);
950
+ this.callback = callback;
951
+ this.timer = null;
952
+ this.lastValue = $F(this.element);
953
+ Event.observe(this.element,'keyup',this.delayedListener.bindAsEventListener(this));
954
+ },
955
+ delayedListener: function(event) {
956
+ if(this.lastValue == $F(this.element)) return;
957
+ if(this.timer) clearTimeout(this.timer);
958
+ this.timer = setTimeout(this.onTimerEvent.bind(this), this.delay * 1000);
959
+ this.lastValue = $F(this.element);
960
+ },
961
+ onTimerEvent: function() {
962
+ this.timer = null;
963
+ this.callback(this.element, $F(this.element));
964
+ }
965
+ });
js/scriptaculous/dragdrop.js ADDED
@@ -0,0 +1,975 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // script.aculo.us dragdrop.js v1.8.2, Tue Nov 18 18:30:58 +0100 2008
2
+
3
+ // Copyright (c) 2005-2008 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
4
+ // (c) 2005-2008 Sammi Williams (http://www.oriontransfer.co.nz, sammi@oriontransfer.co.nz)
5
+ //
6
+ // script.aculo.us is freely distributable under the terms of an MIT-style license.
7
+ // For details, see the script.aculo.us web site: http://script.aculo.us/
8
+
9
+ if(Object.isUndefined(Effect))
10
+ throw("dragdrop.js requires including script.aculo.us' effects.js library");
11
+
12
+ var Droppables = {
13
+ drops: [],
14
+
15
+ remove: function(element) {
16
+ this.drops = this.drops.reject(function(d) { return d.element==$(element) });
17
+ },
18
+
19
+ add: function(element) {
20
+ element = $(element);
21
+ var options = Object.extend({
22
+ greedy: true,
23
+ hoverclass: null,
24
+ tree: false
25
+ }, arguments[1] || { });
26
+
27
+ // cache containers
28
+ if(options.containment) {
29
+ options._containers = [];
30
+ var containment = options.containment;
31
+ if(Object.isArray(containment)) {
32
+ containment.each( function(c) { options._containers.push($(c)) });
33
+ } else {
34
+ options._containers.push($(containment));
35
+ }
36
+ }
37
+
38
+ if(options.accept) options.accept = [options.accept].flatten();
39
+
40
+ Element.makePositioned(element); // fix IE
41
+ options.element = element;
42
+
43
+ this.drops.push(options);
44
+ },
45
+
46
+ findDeepestChild: function(drops) {
47
+ deepest = drops[0];
48
+
49
+ for (i = 1; i < drops.length; ++i)
50
+ if (Element.isParent(drops[i].element, deepest.element))
51
+ deepest = drops[i];
52
+
53
+ return deepest;
54
+ },
55
+
56
+ isContained: function(element, drop) {
57
+ var containmentNode;
58
+ if(drop.tree) {
59
+ containmentNode = element.treeNode;
60
+ } else {
61
+ containmentNode = element.parentNode;
62
+ }
63
+ return drop._containers.detect(function(c) { return containmentNode == c });
64
+ },
65
+
66
+ isAffected: function(point, element, drop) {
67
+ return (
68
+ (drop.element!=element) &&
69
+ ((!drop._containers) ||
70
+ this.isContained(element, drop)) &&
71
+ ((!drop.accept) ||
72
+ (Element.classNames(element).detect(
73
+ function(v) { return drop.accept.include(v) } ) )) &&
74
+ Position.within(drop.element, point[0], point[1]) );
75
+ },
76
+
77
+ deactivate: function(drop) {
78
+ if(drop.hoverclass)
79
+ Element.removeClassName(drop.element, drop.hoverclass);
80
+ this.last_active = null;
81
+ },
82
+
83
+ activate: function(drop) {
84
+ if(drop.hoverclass)
85
+ Element.addClassName(drop.element, drop.hoverclass);
86
+ this.last_active = drop;
87
+ },
88
+
89
+ show: function(point, element) {
90
+ if(!this.drops.length) return;
91
+ var drop, affected = [];
92
+
93
+ this.drops.each( function(drop) {
94
+ if(Droppables.isAffected(point, element, drop))
95
+ affected.push(drop);
96
+ });
97
+
98
+ if(affected.length>0)
99
+ drop = Droppables.findDeepestChild(affected);
100
+
101
+ if(this.last_active && this.last_active != drop) this.deactivate(this.last_active);
102
+ if (drop) {
103
+ Position.within(drop.element, point[0], point[1]);
104
+ if(drop.onHover)
105
+ drop.onHover(element, drop.element, Position.overlap(drop.overlap, drop.element));
106
+
107
+ if (drop != this.last_active) Droppables.activate(drop);
108
+ }
109
+ },
110
+
111
+ fire: function(event, element) {
112
+ if(!this.last_active) return;
113
+ Position.prepare();
114
+
115
+ if (this.isAffected([Event.pointerX(event), Event.pointerY(event)], element, this.last_active))
116
+ if (this.last_active.onDrop) {
117
+ this.last_active.onDrop(element, this.last_active.element, event);
118
+ return true;
119
+ }
120
+ },
121
+
122
+ reset: function() {
123
+ if(this.last_active)
124
+ this.deactivate(this.last_active);
125
+ }
126
+ };
127
+
128
+ var Draggables = {
129
+ drags: [],
130
+ observers: [],
131
+
132
+ register: function(draggable) {
133
+ if(this.drags.length == 0) {
134
+ this.eventMouseUp = this.endDrag.bindAsEventListener(this);
135
+ this.eventMouseMove = this.updateDrag.bindAsEventListener(this);
136
+ this.eventKeypress = this.keyPress.bindAsEventListener(this);
137
+
138
+ Event.observe(document, "mouseup", this.eventMouseUp);
139
+ Event.observe(draggable.element, "mousemove", this.eventMouseMove);
140
+ Event.observe(document, "keypress", this.eventKeypress);
141
+ }
142
+ this.drags.push(draggable);
143
+ },
144
+
145
+ unregister: function(draggable) {
146
+ this.drags = this.drags.reject(function(d) { return d==draggable });
147
+ if(this.drags.length == 0) {
148
+ Event.stopObserving(document, "mouseup", this.eventMouseUp);
149
+ Event.stopObserving(draggable.element, "mousemove", this.eventMouseMove);
150
+ Event.stopObserving(document, "keypress", this.eventKeypress);
151
+ }
152
+ },
153
+
154
+ activate: function(draggable) {
155
+ if(draggable.options.delay) {
156
+ this._timeout = setTimeout(function() {
157
+ Draggables._timeout = null;
158
+ window.focus();
159
+ Draggables.activeDraggable = draggable;
160
+ }.bind(this), draggable.options.delay);
161
+ } else {
162
+ window.focus(); // allows keypress events if window isn't currently focused, fails for Safari
163
+ this.activeDraggable = draggable;
164
+ }
165
+ },
166
+
167
+ deactivate: function() {
168
+ this.activeDraggable = null;
169
+ },
170
+
171
+ updateDrag: function(event) {
172
+ if(!this.activeDraggable) return;
173
+ var pointer = [Event.pointerX(event), Event.pointerY(event)];
174
+ // Mozilla-based browsers fire successive mousemove events with
175
+ // the same coordinates, prevent needless redrawing (moz bug?)
176
+ if(this._lastPointer && (this._lastPointer.inspect() == pointer.inspect())) return;
177
+ this._lastPointer = pointer;
178
+
179
+ this.activeDraggable.updateDrag(event, pointer);
180
+ },
181
+
182
+ endDrag: function(event) {
183
+ if(this._timeout) {
184
+ clearTimeout(this._timeout);
185
+ this._timeout = null;
186
+ }
187
+ if(!this.activeDraggable) return;
188
+ this._lastPointer = null;
189
+ this.activeDraggable.endDrag(event);
190
+ this.activeDraggable = null;
191
+ },
192
+
193
+ keyPress: function(event) {
194
+ if(this.activeDraggable)
195
+ this.activeDraggable.keyPress(event);
196
+ },
197
+
198
+ addObserver: function(observer) {
199
+ this.observers.push(observer);
200
+ this._cacheObserverCallbacks();
201
+ },
202
+
203
+ removeObserver: function(element) { // element instead of observer fixes mem leaks
204
+ this.observers = this.observers.reject( function(o) { return o.element==element });
205
+ this._cacheObserverCallbacks();
206
+ },
207
+
208
+ notify: function(eventName, draggable, event) { // 'onStart', 'onEnd', 'onDrag'
209
+ if(this[eventName+'Count'] > 0)
210
+ this.observers.each( function(o) {
211
+ if(o[eventName]) o[eventName](eventName, draggable, event);
212
+ });
213
+ if(draggable.options[eventName]) draggable.options[eventName](draggable, event);
214
+ },
215
+
216
+ _cacheObserverCallbacks: function() {
217
+ ['onStart','onEnd','onDrag'].each( function(eventName) {
218
+ Draggables[eventName+'Count'] = Draggables.observers.select(
219
+ function(o) { return o[eventName]; }
220
+ ).length;
221
+ });
222
+ }
223
+ };
224
+
225
+ /*--------------------------------------------------------------------------*/
226
+
227
+ var Draggable = Class.create({
228
+ initialize: function(element) {
229
+ var defaults = {
230
+ handle: false,
231
+ reverteffect: function(element, top_offset, left_offset) {
232
+ var dur = Math.sqrt(Math.abs(top_offset^2)+Math.abs(left_offset^2))*0.02;
233
+ new Effect.Move(element, { x: -left_offset, y: -top_offset, duration: dur,
234
+ queue: {scope:'_draggable', position:'end'}
235
+ });
236
+ },
237
+ endeffect: function(element) {
238
+ var toOpacity = Object.isNumber(element._opacity) ? element._opacity : 1.0;
239
+ new Effect.Opacity(element, {duration:0.2, from:0.7, to:toOpacity,
240
+ queue: {scope:'_draggable', position:'end'},
241
+ afterFinish: function(){
242
+ Draggable._dragging[element] = false
243
+ }
244
+ });
245
+ },
246
+ zindex: 1000,
247
+ revert: false,
248
+ quiet: false,
249
+ scroll: false,
250
+ scrollSensitivity: 20,
251
+ scrollSpeed: 15,
252
+ snap: false, // false, or xy or [x,y] or function(x,y){ return [x,y] }
253
+ delay: 0
254
+ };
255
+
256
+ if(!arguments[1] || Object.isUndefined(arguments[1].endeffect))
257
+ Object.extend(defaults, {
258
+ starteffect: function(element) {
259
+ element._opacity = Element.getOpacity(element);
260
+ Draggable._dragging[element] = true;
261
+ new Effect.Opacity(element, {duration:0.2, from:element._opacity, to:0.7});
262
+ }
263
+ });
264
+
265
+ var options = Object.extend(defaults, arguments[1] || { });
266
+
267
+ this.element = $(element);
268
+
269
+ if(options.handle && Object.isString(options.handle))
270
+ this.handle = this.element.down('.'+options.handle, 0);
271
+
272
+ if(!this.handle) this.handle = $(options.handle);
273
+ if(!this.handle) this.handle = this.element;
274
+
275
+ if(options.scroll && !options.scroll.scrollTo && !options.scroll.outerHTML) {
276
+ options.scroll = $(options.scroll);
277
+ this._isScrollChild = Element.childOf(this.element, options.scroll);
278
+ }
279
+
280
+ Element.makePositioned(this.element); // fix IE
281
+
282
+ this.options = options;
283
+ this.dragging = false;
284
+
285
+ this.eventMouseDown = this.initDrag.bindAsEventListener(this);
286
+ Event.observe(this.handle, "mousedown", this.eventMouseDown);
287
+
288
+ Draggables.register(this);
289
+ },
290
+
291
+ destroy: function() {
292
+ Event.stopObserving(this.handle, "mousedown", this.eventMouseDown);
293
+ Draggables.unregister(this);
294
+ },
295
+
296
+ currentDelta: function() {
297
+ return([
298
+ parseInt(Element.getStyle(this.element,'left') || '0'),
299
+ parseInt(Element.getStyle(this.element,'top') || '0')]);
300
+ },
301
+
302
+ initDrag: function(event) {
303
+ if(!Object.isUndefined(Draggable._dragging[this.element]) &&
304
+ Draggable._dragging[this.element]) return;
305
+ if(Event.isLeftClick(event)) {
306
+ // abort on form elements, fixes a Firefox issue
307
+ var src = Event.element(event);
308
+ if((tag_name = src.tagName.toUpperCase()) && (
309
+ tag_name=='INPUT' ||
310
+ tag_name=='SELECT' ||
311
+ tag_name=='OPTION' ||
312
+ tag_name=='BUTTON' ||
313
+ tag_name=='TEXTAREA')) return;
314
+
315
+ var pointer = [Event.pointerX(event), Event.pointerY(event)];
316
+ var pos = Position.cumulativeOffset(this.element);
317
+ this.offset = [0,1].map( function(i) { return (pointer[i] - pos[i]) });
318
+
319
+ Draggables.activate(this);
320
+ Event.stop(event);
321
+ }
322
+ },
323
+
324
+ startDrag: function(event) {
325
+ this.dragging = true;
326
+ if(!this.delta)
327
+ this.delta = this.currentDelta();
328
+
329
+ if(this.options.zindex) {
330
+ this.originalZ = parseInt(Element.getStyle(this.element,'z-index') || 0);
331
+ this.element.style.zIndex = this.options.zindex;
332
+ }
333
+
334
+ if(this.options.ghosting) {
335
+ this._clone = this.element.cloneNode(true);
336
+ this._originallyAbsolute = (this.element.getStyle('position') == 'absolute');
337
+ if (!this._originallyAbsolute)
338
+ Position.absolutize(this.element);
339
+ this.element.parentNode.insertBefore(this._clone, this.element);
340
+ }
341
+
342
+ if(this.options.scroll) {
343
+ if (this.options.scroll == window) {
344
+ var where = this._getWindowScroll(this.options.scroll);
345
+ this.originalScrollLeft = where.left;
346
+ this.originalScrollTop = where.top;
347
+ } else {
348
+ this.originalScrollLeft = this.options.scroll.scrollLeft;
349
+ this.originalScrollTop = this.options.scroll.scrollTop;
350
+ }
351
+ }
352
+
353
+ Draggables.notify('onStart', this, event);
354
+
355
+ if(this.options.starteffect) this.options.starteffect(this.element);
356
+ },
357
+
358
+ updateDrag: function(event, pointer) {
359
+ if(!this.dragging) this.startDrag(event);
360
+
361
+ if(!this.options.quiet){
362
+ Position.prepare();
363
+ Droppables.show(pointer, this.element);
364
+ }
365
+
366
+ Draggables.notify('onDrag', this, event);
367
+
368
+ this.draw(pointer);
369
+ if(this.options.change) this.options.change(this);
370
+
371
+ if(this.options.scroll) {
372
+ this.stopScrolling();
373
+
374
+ var p;
375
+ if (this.options.scroll == window) {
376
+ with(this._getWindowScroll(this.options.scroll)) { p = [ left, top, left+width, top+height ]; }
377
+ } else {
378
+ p = Position.page(this.options.scroll);
379
+ p[0] += this.options.scroll.scrollLeft + Position.deltaX;
380
+ p[1] += this.options.scroll.scrollTop + Position.deltaY;
381
+ p.push(p[0]+this.options.scroll.offsetWidth);
382
+ p.push(p[1]+this.options.scroll.offsetHeight);
383
+ }
384
+ var speed = [0,0];
385
+ if(pointer[0] < (p[0]+this.options.scrollSensitivity)) speed[0] = pointer[0]-(p[0]+this.options.scrollSensitivity);
386
+ if(pointer[1] < (p[1]+this.options.scrollSensitivity)) speed[1] = pointer[1]-(p[1]+this.options.scrollSensitivity);
387
+ if(pointer[0] > (p[2]-this.options.scrollSensitivity)) speed[0] = pointer[0]-(p[2]-this.options.scrollSensitivity);
388
+ if(pointer[1] > (p[3]-this.options.scrollSensitivity)) speed[1] = pointer[1]-(p[3]-this.options.scrollSensitivity);
389
+ this.startScrolling(speed);
390
+ }
391
+
392
+ // fix AppleWebKit rendering
393
+ if(Prototype.Browser.WebKit) window.scrollBy(0,0);
394
+
395
+ Event.stop(event);
396
+ },
397
+
398
+ finishDrag: function(event, success) {
399
+ this.dragging = false;
400
+
401
+ if(this.options.quiet){
402
+ Position.prepare();
403
+ var pointer = [Event.pointerX(event), Event.pointerY(event)];
404
+ Droppables.show(pointer, this.element);
405
+ }
406
+
407
+ if(this.options.ghosting) {
408
+ if (!this._originallyAbsolute)
409
+ Position.relativize(this.element);
410
+ delete this._originallyAbsolute;
411
+ Element.remove(this._clone);
412
+ this._clone = null;
413
+ }
414
+
415
+ var dropped = false;
416
+ if(success) {
417
+ dropped = Droppables.fire(event, this.element);
418
+ if (!dropped) dropped = false;
419
+ }
420
+ if(dropped && this.options.onDropped) this.options.onDropped(this.element);
421
+ Draggables.notify('onEnd', this, event);
422
+
423
+ var revert = this.options.revert;
424
+ if(revert && Object.isFunction(revert)) revert = revert(this.element);
425
+
426
+ var d = this.currentDelta();
427
+ if(revert && this.options.reverteffect) {
428
+ if (dropped == 0 || revert != 'failure')
429
+ this.options.reverteffect(this.element,
430
+ d[1]-this.delta[1], d[0]-this.delta[0]);
431
+ } else {
432
+ this.delta = d;
433
+ }
434
+
435
+ if(this.options.zindex)
436
+ this.element.style.zIndex = this.originalZ;
437
+
438
+ if(this.options.endeffect)
439
+ this.options.endeffect(this.element);
440
+
441
+ Draggables.deactivate(this);
442
+ Droppables.reset();
443
+ },
444
+
445
+ keyPress: function(event) {
446
+ if(event.keyCode!=Event.KEY_ESC) return;
447
+ this.finishDrag(event, false);
448
+ Event.stop(event);
449
+ },
450
+
451
+ endDrag: function(event) {
452
+ if(!this.dragging) return;
453
+ this.stopScrolling();
454
+ this.finishDrag(event, true);
455
+ Event.stop(event);
456
+ },
457
+
458
+ draw: function(point) {
459
+ var pos = Position.cumulativeOffset(this.element);
460
+ if(this.options.ghosting) {
461
+ var r = Position.realOffset(this.element);
462
+ pos[0] += r[0] - Position.deltaX; pos[1] += r[1] - Position.deltaY;
463
+ }
464
+
465
+ var d = this.currentDelta();
466
+ pos[0] -= d[0]; pos[1] -= d[1];
467
+
468
+ if(this.options.scroll && (this.options.scroll != window && this._isScrollChild)) {
469
+ pos[0] -= this.options.scroll.scrollLeft-this.originalScrollLeft;
470
+ pos[1] -= this.options.scroll.scrollTop-this.originalScrollTop;
471
+ }
472
+
473
+ var p = [0,1].map(function(i){
474
+ return (point[i]-pos[i]-this.offset[i])
475
+ }.bind(this));
476
+
477
+ if(this.options.snap) {
478
+ if(Object.isFunction(this.options.snap)) {
479
+ p = this.options.snap(p[0],p[1],this);
480
+ } else {
481
+ if(Object.isArray(this.options.snap)) {
482
+ p = p.map( function(v, i) {
483
+ return (v/this.options.snap[i]).round()*this.options.snap[i] }.bind(this));
484
+ } else {
485
+ p = p.map( function(v) {
486
+ return (v/this.options.snap).round()*this.options.snap }.bind(this));
487
+ }
488
+ }}
489
+
490
+ var style = this.element.style;
491
+ if((!this.options.constraint) || (this.options.constraint=='horizontal'))
492
+ style.left = p[0] + "px";
493
+ if((!this.options.constraint) || (this.options.constraint=='vertical'))
494
+ style.top = p[1] + "px";
495
+
496
+ if(style.visibility=="hidden") style.visibility = ""; // fix gecko rendering
497
+ },
498
+
499
+ stopScrolling: function() {
500
+ if(this.scrollInterval) {
501
+ clearInterval(this.scrollInterval);
502
+ this.scrollInterval = null;
503
+ Draggables._lastScrollPointer = null;
504
+ }
505
+ },
506
+
507
+ startScrolling: function(speed) {
508
+ if(!(speed[0] || speed[1])) return;
509
+ this.scrollSpeed = [speed[0]*this.options.scrollSpeed,speed[1]*this.options.scrollSpeed];
510
+ this.lastScrolled = new Date();
511
+ this.scrollInterval = setInterval(this.scroll.bind(this), 10);
512
+ },
513
+
514
+ scroll: function() {
515
+ var current = new Date();
516
+ var delta = current - this.lastScrolled;
517
+ this.lastScrolled = current;
518
+ if(this.options.scroll == window) {
519
+ with (this._getWindowScroll(this.options.scroll)) {
520
+ if (this.scrollSpeed[0] || this.scrollSpeed[1]) {
521
+ var d = delta / 1000;
522
+ this.options.scroll.scrollTo( left + d*this.scrollSpeed[0], top + d*this.scrollSpeed[1] );
523
+ }
524
+ }
525
+ } else {
526
+ this.options.scroll.scrollLeft += this.scrollSpeed[0] * delta / 1000;
527
+ this.options.scroll.scrollTop += this.scrollSpeed[1] * delta / 1000;
528
+ }
529
+
530
+ Position.prepare();
531
+ Droppables.show(Draggables._lastPointer, this.element);
532
+ Draggables.notify('onDrag', this);
533
+ if (this._isScrollChild) {
534
+ Draggables._lastScrollPointer = Draggables._lastScrollPointer || $A(Draggables._lastPointer);
535
+ Draggables._lastScrollPointer[0] += this.scrollSpeed[0] * delta / 1000;
536
+ Draggables._lastScrollPointer[1] += this.scrollSpeed[1] * delta / 1000;
537
+ if (Draggables._lastScrollPointer[0] < 0)
538
+ Draggables._lastScrollPointer[0] = 0;
539
+ if (Draggables._lastScrollPointer[1] < 0)
540
+ Draggables._lastScrollPointer[1] = 0;
541
+ this.draw(Draggables._lastScrollPointer);
542
+ }
543
+
544
+ if(this.options.change) this.options.change(this);
545
+ },
546
+
547
+ _getWindowScroll: function(w) {
548
+ var T, L, W, H;
549
+ with (w.document) {
550
+ if (w.document.documentElement && documentElement.scrollTop) {
551
+ T = documentElement.scrollTop;
552
+ L = documentElement.scrollLeft;
553
+ } else if (w.document.body) {
554
+ T = body.scrollTop;
555
+ L = body.scrollLeft;
556
+ }
557
+ if (w.innerWidth) {
558
+ W = w.innerWidth;
559
+ H = w.innerHeight;
560
+ } else if (w.document.documentElement && documentElement.clientWidth) {
561
+ W = documentElement.clientWidth;
562
+ H = documentElement.clientHeight;
563
+ } else {
564
+ W = body.offsetWidth;
565
+ H = body.offsetHeight;
566
+ }
567
+ }
568
+ return { top: T, left: L, width: W, height: H };
569
+ }
570
+ });
571
+
572
+ Draggable._dragging = { };
573
+
574
+ /*--------------------------------------------------------------------------*/
575
+
576
+ var SortableObserver = Class.create({
577
+ initialize: function(element, observer) {
578
+ this.element = $(element);
579
+ this.observer = observer;
580
+ this.lastValue = Sortable.serialize(this.element);
581
+ },
582
+
583
+ onStart: function() {
584
+ this.lastValue = Sortable.serialize(this.element);
585
+ },
586
+
587
+ onEnd: function() {
588
+ Sortable.unmark();
589
+ if(this.lastValue != Sortable.serialize(this.element))
590
+ this.observer(this.element)
591
+ }
592
+ });
593
+
594
+ var Sortable = {
595
+ SERIALIZE_RULE: /^[^_\-](?:[A-Za-z0-9\-\_]*)[_](.*)$/,
596
+
597
+ sortables: { },
598
+
599
+ _findRootElement: function(element) {
600
+ while (element.tagName.toUpperCase() != "BODY") {
601
+ if(element.id && Sortable.sortables[element.id]) return element;
602
+ element = element.parentNode;
603
+ }
604
+ },
605
+
606
+ options: function(element) {
607
+ element = Sortable._findRootElement($(element));
608
+ if(!element) return;
609
+ return Sortable.sortables[element.id];
610
+ },
611
+
612
+ destroy: function(element){
613
+ element = $(element);
614
+ var s = Sortable.sortables[element.id];
615
+
616
+ if(s) {
617
+ Draggables.removeObserver(s.element);
618
+ s.droppables.each(function(d){ Droppables.remove(d) });
619
+ s.draggables.invoke('destroy');
620
+
621
+ delete Sortable.sortables[s.element.id];
622
+ }
623
+ },
624
+
625
+ create: function(element) {
626
+ element = $(element);
627
+ var options = Object.extend({
628
+ element: element,
629
+ tag: 'li', // assumes li children, override with tag: 'tagname'
630
+ dropOnEmpty: false,
631
+ tree: false,
632
+ treeTag: 'ul',
633
+ overlap: 'vertical', // one of 'vertical', 'horizontal'
634
+ constraint: 'vertical', // one of 'vertical', 'horizontal', false
635
+ containment: element, // also takes array of elements (or id's); or false
636
+ handle: false, // or a CSS class
637
+ only: false,
638
+ delay: 0,
639
+ hoverclass: null,
640
+ ghosting: false,
641
+ quiet: false,
642
+ scroll: false,
643
+ scrollSensitivity: 20,
644
+ scrollSpeed: 15,
645
+ format: this.SERIALIZE_RULE,
646
+
647
+ // these take arrays of elements or ids and can be
648
+ // used for better initialization performance
649
+ elements: false,
650
+ handles: false,
651
+
652
+ onChange: Prototype.emptyFunction,
653
+ onUpdate: Prototype.emptyFunction
654
+ }, arguments[1] || { });
655
+
656
+ // clear any old sortable with same element
657
+ this.destroy(element);
658
+
659
+ // build options for the draggables
660
+ var options_for_draggable = {
661
+ revert: true,
662
+ quiet: options.quiet,
663
+ scroll: options.scroll,
664
+ scrollSpeed: options.scrollSpeed,
665
+ scrollSensitivity: options.scrollSensitivity,
666
+ delay: options.delay,
667
+ ghosting: options.ghosting,
668
+ constraint: options.constraint,
669
+ handle: options.handle };
670
+
671
+ if(options.starteffect)
672
+ options_for_draggable.starteffect = options.starteffect;
673
+
674
+ if(options.reverteffect)
675
+ options_for_draggable.reverteffect = options.reverteffect;
676
+ else
677
+ if(options.ghosting) options_for_draggable.reverteffect = function(element) {
678
+ element.style.top = 0;
679
+ element.style.left = 0;
680
+ };
681
+
682
+ if(options.endeffect)
683
+ options_for_draggable.endeffect = options.endeffect;
684
+
685
+ if(options.zindex)
686
+ options_for_draggable.zindex = options.zindex;
687
+
688
+ // build options for the droppables
689
+ var options_for_droppable = {
690
+ overlap: options.overlap,
691
+ containment: options.containment,
692
+ tree: options.tree,
693
+ hoverclass: options.hoverclass,
694
+ onHover: Sortable.onHover
695
+ };
696
+
697
+ var options_for_tree = {
698
+ onHover: Sortable.onEmptyHover,
699
+ overlap: options.overlap,
700
+ containment: options.containment,
701
+ hoverclass: options.hoverclass
702
+ };
703
+
704
+ // fix for gecko engine
705
+ Element.cleanWhitespace(element);
706
+
707
+ options.draggables = [];
708
+ options.droppables = [];
709
+
710
+ // drop on empty handling
711
+ if(options.dropOnEmpty || options.tree) {
712
+ Droppables.add(element, options_for_tree);
713
+ options.droppables.push(element);
714
+ }
715
+
716
+ (options.elements || this.findElements(element, options) || []).each( function(e,i) {
717
+ var handle = options.handles ? $(options.handles[i]) :
718
+ (options.handle ? $(e).select('.' + options.handle)[0] : e);
719
+ options.draggables.push(
720
+ new Draggable(e, Object.extend(options_for_draggable, { handle: handle })));
721
+ Droppables.add(e, options_for_droppable);
722
+ if(options.tree) e.treeNode = element;
723
+ options.droppables.push(e);
724
+ });
725
+
726
+ if(options.tree) {
727
+ (Sortable.findTreeElements(element, options) || []).each( function(e) {
728
+ Droppables.add(e, options_for_tree);
729
+ e.treeNode = element;
730
+ options.droppables.push(e);
731
+ });
732
+ }
733
+
734
+ // keep reference
735
+ this.sortables[element.id] = options;
736
+
737
+ // for onupdate
738
+ Draggables.addObserver(new SortableObserver(element, options.onUpdate));
739
+
740
+ },
741
+
742
+ // return all suitable-for-sortable elements in a guaranteed order
743
+ findElements: function(element, options) {
744
+ return Element.findChildren(
745
+ element, options.only, options.tree ? true : false, options.tag);
746
+ },
747
+
748
+ findTreeElements: function(element, options) {
749
+ return Element.findChildren(
750
+ element, options.only, options.tree ? true : false, options.treeTag);
751
+ },
752
+
753
+ onHover: function(element, dropon, overlap) {
754
+ if(Element.isParent(dropon, element)) return;
755
+
756
+ if(overlap > .33 && overlap < .66 && Sortable.options(dropon).tree) {
757
+ return;
758
+ } else if(overlap>0.5) {
759
+ Sortable.mark(dropon, 'before');
760
+ if(dropon.previousSibling != element) {
761
+ var oldParentNode = element.parentNode;
762
+ element.style.visibility = "hidden"; // fix gecko rendering
763
+ dropon.parentNode.insertBefore(element, dropon);
764
+ if(dropon.parentNode!=oldParentNode)
765
+ Sortable.options(oldParentNode).onChange(element);
766
+ Sortable.options(dropon.parentNode).onChange(element);
767
+ }
768
+ } else {
769
+ Sortable.mark(dropon, 'after');
770
+ var nextElement = dropon.nextSibling || null;
771
+ if(nextElement != element) {
772
+ var oldParentNode = element.parentNode;
773
+ element.style.visibility = "hidden"; // fix gecko rendering
774
+ dropon.parentNode.insertBefore(element, nextElement);
775
+ if(dropon.parentNode!=oldParentNode)
776
+ Sortable.options(oldParentNode).onChange(element);
777
+ Sortable.options(dropon.parentNode).onChange(element);
778
+ }
779
+ }
780
+ },
781
+
782
+ onEmptyHover: function(element, dropon, overlap) {
783
+ var oldParentNode = element.parentNode;
784
+ var droponOptions = Sortable.options(dropon);
785
+
786
+ if(!Element.isParent(dropon, element)) {
787
+ var index;
788
+
789
+ var children = Sortable.findElements(dropon, {tag: droponOptions.tag, only: droponOptions.only});
790
+ var child = null;
791
+
792
+ if(children) {
793
+ var offset = Element.offsetSize(dropon, droponOptions.overlap) * (1.0 - overlap);
794
+
795
+ for (index = 0; index < children.length; index += 1) {
796
+ if (offset - Element.offsetSize (children[index], droponOptions.overlap) >= 0) {
797
+ offset -= Element.offsetSize (children[index], droponOptions.overlap);
798
+ } else if (offset - (Element.offsetSize (children[index], droponOptions.overlap) / 2) >= 0) {
799
+ child = index + 1 < children.length ? children[index + 1] : null;
800
+ break;
801
+ } else {
802
+ child = children[index];
803
+ break;
804
+ }
805
+ }
806
+ }
807
+
808
+ dropon.insertBefore(element, child);
809
+
810
+ Sortable.options(oldParentNode).onChange(element);
811
+ droponOptions.onChange(element);
812
+ }
813
+ },
814
+
815
+ unmark: function() {
816
+ if(Sortable._marker) Sortable._marker.hide();
817
+ },
818
+
819
+ mark: function(dropon, position) {
820
+ // mark on ghosting only
821
+ var sortable = Sortable.options(dropon.parentNode);
822
+ if(sortable && !sortable.ghosting) return;
823
+
824
+ if(!Sortable._marker) {
825
+ Sortable._marker =
826
+ ($('dropmarker') || Element.extend(document.createElement('DIV'))).
827
+ hide().addClassName('dropmarker').setStyle({position:'absolute'});
828
+ document.getElementsByTagName("body").item(0).appendChild(Sortable._marker);
829
+ }
830
+ var offsets = Position.cumulativeOffset(dropon);
831
+ Sortable._marker.setStyle({left: offsets[0]+'px', top: offsets[1] + 'px'});
832
+
833
+ if(position=='after')
834
+ if(sortable.overlap == 'horizontal')
835
+ Sortable._marker.setStyle({left: (offsets[0]+dropon.clientWidth) + 'px'});
836
+ else
837
+ Sortable._marker.setStyle({top: (offsets[1]+dropon.clientHeight) + 'px'});
838
+
839
+ Sortable._marker.show();
840
+ },
841
+
842
+ _tree: function(element, options, parent) {
843
+ var children = Sortable.findElements(element, options) || [];
844
+
845
+ for (var i = 0; i < children.length; ++i) {
846
+ var match = children[i].id.match(options.format);
847
+
848
+ if (!match) continue;
849
+
850
+ var child = {
851
+ id: encodeURIComponent(match ? match[1] : null),
852
+ element: element,
853
+ parent: parent,
854
+ children: [],
855
+ position: parent.children.length,
856
+ container: $(children[i]).down(options.treeTag)
857
+ };
858
+
859
+ /* Get the element containing the children and recurse over it */
860
+ if (child.container)
861
+ this._tree(child.container, options, child);
862
+
863
+ parent.children.push (child);
864
+ }
865
+
866
+ return parent;
867
+ },
868
+
869
+ tree: function(element) {
870
+ element = $(element);
871
+ var sortableOptions = this.options(element);
872
+ var options = Object.extend({
873
+ tag: sortableOptions.tag,
874
+ treeTag: sortableOptions.treeTag,
875
+ only: sortableOptions.only,
876
+ name: element.id,
877
+ format: sortableOptions.format
878
+ }, arguments[1] || { });
879
+
880
+ var root = {
881
+ id: null,
882
+ parent: null,
883
+ children: [],
884
+ container: element,
885
+ position: 0
886
+ };
887
+
888
+ return Sortable._tree(element, options, root);
889
+ },
890
+
891
+ /* Construct a [i] index for a particular node */
892
+ _constructIndex: function(node) {
893
+ var index = '';
894
+ do {
895
+ if (node.id) index = '[' + node.position + ']' + index;
896
+ } while ((node = node.parent) != null);
897
+ return index;
898
+ },
899
+
900
+ sequence: function(element) {
901
+ element = $(element);
902
+ var options = Object.extend(this.options(element), arguments[1] || { });
903
+
904
+ return $(this.findElements(element, options) || []).map( function(item) {
905
+ return item.id.match(options.format) ? item.id.match(options.format)[1] : '';
906
+ });
907
+ },
908
+
909
+ setSequence: function(element, new_sequence) {
910
+ element = $(element);
911
+ var options = Object.extend(this.options(element), arguments[2] || { });
912
+
913
+ var nodeMap = { };
914
+ this.findElements(element, options).each( function(n) {
915
+ if (n.id.match(options.format))
916
+ nodeMap[n.id.match(options.format)[1]] = [n, n.parentNode];
917
+ n.parentNode.removeChild(n);
918
+ });
919
+
920
+ new_sequence.each(function(ident) {
921
+ var n = nodeMap[ident];
922
+ if (n) {
923
+ n[1].appendChild(n[0]);
924
+ delete nodeMap[ident];
925
+ }
926
+ });
927
+ },
928
+
929
+ serialize: function(element) {
930
+ element = $(element);
931
+ var options = Object.extend(Sortable.options(element), arguments[1] || { });
932
+ var name = encodeURIComponent(
933
+ (arguments[1] && arguments[1].name) ? arguments[1].name : element.id);
934
+
935
+ if (options.tree) {
936
+ return Sortable.tree(element, arguments[1]).children.map( function (item) {
937
+ return [name + Sortable._constructIndex(item) + "[id]=" +
938
+ encodeURIComponent(item.id)].concat(item.children.map(arguments.callee));
939
+ }).flatten().join('&');
940
+ } else {
941
+ return Sortable.sequence(element, arguments[1]).map( function(item) {
942
+ return name + "[]=" + encodeURIComponent(item);
943
+ }).join('&');
944
+ }
945
+ }
946
+ };
947
+
948
+ // Returns true if child is contained within element
949
+ Element.isParent = function(child, element) {
950
+ if (!child.parentNode || child == element) return false;
951
+ if (child.parentNode == element) return true;
952
+ return Element.isParent(child.parentNode, element);
953
+ };
954
+
955
+ Element.findChildren = function(element, only, recursive, tagName) {
956
+ if(!element.hasChildNodes()) return null;
957
+ tagName = tagName.toUpperCase();
958
+ if(only) only = [only].flatten();
959
+ var elements = [];
960
+ $A(element.childNodes).each( function(e) {
961
+ if(e.tagName && e.tagName.toUpperCase()==tagName &&
962
+ (!only || (Element.classNames(e).detect(function(v) { return only.include(v) }))))
963
+ elements.push(e);
964
+ if(recursive) {
965
+ var grandchildren = Element.findChildren(e, only, recursive, tagName);
966
+ if(grandchildren) elements.push(grandchildren);
967
+ }
968
+ });
969
+
970
+ return (elements.length>0 ? elements.flatten() : []);
971
+ };
972
+
973
+ Element.offsetSize = function (element, type) {
974
+ return element['offset' + ((type=='vertical' || type=='height') ? 'Height' : 'Width')];
975
+ };
js/scriptaculous/effects.js ADDED
@@ -0,0 +1,1130 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // script.aculo.us effects.js v1.8.2, Tue Nov 18 18:30:58 +0100 2008
2
+
3
+ // Copyright (c) 2005-2008 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
4
+ // Contributors:
5
+ // Justin Palmer (http://encytemedia.com/)
6
+ // Mark Pilgrim (http://diveintomark.org/)
7
+ // Martin Bialasinki
8
+ //
9
+ // script.aculo.us is freely distributable under the terms of an MIT-style license.
10
+ // For details, see the script.aculo.us web site: http://script.aculo.us/
11
+
12
+ // converts rgb() and #xxx to #xxxxxx format,
13
+ // returns self (or first argument) if not convertable
14
+ String.prototype.parseColor = function() {
15
+ var color = '#';
16
+ if (this.slice(0,4) == 'rgb(') {
17
+ var cols = this.slice(4,this.length-1).split(',');
18
+ var i=0; do { color += parseInt(cols[i]).toColorPart() } while (++i<3);
19
+ } else {
20
+ if (this.slice(0,1) == '#') {
21
+ if (this.length==4) for(var i=1;i<4;i++) color += (this.charAt(i) + this.charAt(i)).toLowerCase();
22
+ if (this.length==7) color = this.toLowerCase();
23
+ }
24
+ }
25
+ return (color.length==7 ? color : (arguments[0] || this));
26
+ };
27
+
28
+ /*--------------------------------------------------------------------------*/
29
+
30
+ Element.collectTextNodes = function(element) {
31
+ return $A($(element).childNodes).collect( function(node) {
32
+ return (node.nodeType==3 ? node.nodeValue :
33
+ (node.hasChildNodes() ? Element.collectTextNodes(node) : ''));
34
+ }).flatten().join('');
35
+ };
36
+
37
+ Element.collectTextNodesIgnoreClass = function(element, className) {
38
+ return $A($(element).childNodes).collect( function(node) {
39
+ return (node.nodeType==3 ? node.nodeValue :
40
+ ((node.hasChildNodes() && !Element.hasClassName(node,className)) ?
41
+ Element.collectTextNodesIgnoreClass(node, className) : ''));
42
+ }).flatten().join('');
43
+ };
44
+
45
+ Element.setContentZoom = function(element, percent) {
46
+ element = $(element);
47
+ element.setStyle({fontSize: (percent/100) + 'em'});
48
+ if (Prototype.Browser.WebKit) window.scrollBy(0,0);
49
+ return element;
50
+ };
51
+
52
+ Element.getInlineOpacity = function(element){
53
+ return $(element).style.opacity || '';
54
+ };
55
+
56
+ Element.forceRerendering = function(element) {
57
+ try {
58
+ element = $(element);
59
+ var n = document.createTextNode(' ');
60
+ element.appendChild(n);
61
+ element.removeChild(n);
62
+ } catch(e) { }
63
+ };
64
+
65
+ /*--------------------------------------------------------------------------*/
66
+
67
+ var Effect = {
68
+ _elementDoesNotExistError: {
69
+ name: 'ElementDoesNotExistError',
70
+ message: 'The specified DOM element does not exist, but is required for this effect to operate'
71
+ },
72
+ Transitions: {
73
+ linear: Prototype.K,
74
+ sinoidal: function(pos) {
75
+ return (-Math.cos(pos*Math.PI)/2) + .5;
76
+ },
77
+ reverse: function(pos) {
78
+ return 1-pos;
79
+ },
80
+ flicker: function(pos) {
81
+ var pos = ((-Math.cos(pos*Math.PI)/4) + .75) + Math.random()/4;
82
+ return pos > 1 ? 1 : pos;
83
+ },
84
+ wobble: function(pos) {
85
+ return (-Math.cos(pos*Math.PI*(9*pos))/2) + .5;
86
+ },
87
+ pulse: function(pos, pulses) {
88
+ return (-Math.cos((pos*((pulses||5)-.5)*2)*Math.PI)/2) + .5;
89
+ },
90
+ spring: function(pos) {
91
+ return 1 - (Math.cos(pos * 4.5 * Math.PI) * Math.exp(-pos * 6));
92
+ },
93
+ none: function(pos) {
94
+ return 0;
95
+ },
96
+ full: function(pos) {
97
+ return 1;
98
+ }
99
+ },
100
+ DefaultOptions: {
101
+ duration: 1.0, // seconds
102
+ fps: 100, // 100= assume 66fps max.
103
+ sync: false, // true for combining
104
+ from: 0.0,
105
+ to: 1.0,
106
+ delay: 0.0,
107
+ queue: 'parallel'
108
+ },
109
+ tagifyText: function(element) {
110
+ var tagifyStyle = 'position:relative';
111
+ if (Prototype.Browser.IE) tagifyStyle += ';zoom:1';
112
+
113
+ element = $(element);
114
+ $A(element.childNodes).each( function(child) {
115
+ if (child.nodeType==3) {
116
+ child.nodeValue.toArray().each( function(character) {
117
+ element.insertBefore(
118
+ new Element('span', {style: tagifyStyle}).update(
119
+ character == ' ' ? String.fromCharCode(160) : character),
120
+ child);
121
+ });
122
+ Element.remove(child);
123
+ }
124
+ });
125
+ },
126
+ multiple: function(element, effect) {
127
+ var elements;
128
+ if (((typeof element == 'object') ||
129
+ Object.isFunction(element)) &&
130
+ (element.length))
131
+ elements = element;
132
+ else
133
+ elements = $(element).childNodes;
134
+
135
+ var options = Object.extend({
136
+ speed: 0.1,
137
+ delay: 0.0
138
+ }, arguments[2] || { });
139
+ var masterDelay = options.delay;
140
+
141
+ $A(elements).each( function(element, index) {
142
+ new effect(element, Object.extend(options, { delay: index * options.speed + masterDelay }));
143
+ });
144
+ },
145
+ PAIRS: {
146
+ 'slide': ['SlideDown','SlideUp'],
147
+ 'blind': ['BlindDown','BlindUp'],
148
+ 'appear': ['Appear','Fade']
149
+ },
150
+ toggle: function(element, effect) {
151
+ element = $(element);
152
+ effect = (effect || 'appear').toLowerCase();
153
+ var options = Object.extend({
154
+ queue: { position:'end', scope:(element.id || 'global'), limit: 1 }
155
+ }, arguments[2] || { });
156
+ Effect[element.visible() ?
157
+ Effect.PAIRS[effect][1] : Effect.PAIRS[effect][0]](element, options);
158
+ }
159
+ };
160
+
161
+ Effect.DefaultOptions.transition = Effect.Transitions.sinoidal;
162
+
163
+ /* ------------- core effects ------------- */
164
+
165
+ Effect.ScopedQueue = Class.create(Enumerable, {
166
+ initialize: function() {
167
+ this.effects = [];
168
+ this.interval = null;
169
+ },
170
+ _each: function(iterator) {
171
+ this.effects._each(iterator);
172
+ },
173
+ add: function(effect) {
174
+ var timestamp = new Date().getTime();
175
+
176
+ var position = Object.isString(effect.options.queue) ?
177
+ effect.options.queue : effect.options.queue.position;
178
+
179
+ switch(position) {
180
+ case 'front':
181
+ // move unstarted effects after this effect
182
+ this.effects.findAll(function(e){ return e.state=='idle' }).each( function(e) {
183
+ e.startOn += effect.finishOn;
184
+ e.finishOn += effect.finishOn;
185
+ });
186
+ break;
187
+ case 'with-last':
188
+ timestamp = this.effects.pluck('startOn').max() || timestamp;
189
+ break;
190
+ case 'end':
191
+ // start effect after last queued effect has finished
192
+ timestamp = this.effects.pluck('finishOn').max() || timestamp;
193
+ break;
194
+ }
195
+
196
+ effect.startOn += timestamp;
197
+ effect.finishOn += timestamp;
198
+
199
+ if (!effect.options.queue.limit || (this.effects.length < effect.options.queue.limit))
200
+ this.effects.push(effect);
201
+
202
+ if (!this.interval)
203
+ this.interval = setInterval(this.loop.bind(this), 15);
204
+ },
205
+ remove: function(effect) {
206
+ this.effects = this.effects.reject(function(e) { return e==effect });
207
+ if (this.effects.length == 0) {
208
+ clearInterval(this.interval);
209
+ this.interval = null;
210
+ }
211
+ },
212
+ loop: function() {
213
+ var timePos = new Date().getTime();
214
+ for(var i=0, len=this.effects.length;i<len;i++)
215
+ this.effects[i] && this.effects[i].loop(timePos);
216
+ }
217
+ });
218
+
219
+ Effect.Queues = {
220
+ instances: $H(),
221
+ get: function(queueName) {
222
+ if (!Object.isString(queueName)) return queueName;
223
+
224
+ return this.instances.get(queueName) ||
225
+ this.instances.set(queueName, new Effect.ScopedQueue());
226
+ }
227
+ };
228
+ Effect.Queue = Effect.Queues.get('global');
229
+
230
+ Effect.Base = Class.create({
231
+ position: null,
232
+ start: function(options) {
233
+ function codeForEvent(options,eventName){
234
+ return (
235
+ (options[eventName+'Internal'] ? 'this.options.'+eventName+'Internal(this);' : '') +
236
+ (options[eventName] ? 'this.options.'+eventName+'(this);' : '')
237
+ );
238
+ }
239
+ if (options && options.transition === false) options.transition = Effect.Transitions.linear;
240
+ this.options = Object.extend(Object.extend({ },Effect.DefaultOptions), options || { });
241
+ this.currentFrame = 0;
242
+ this.state = 'idle';
243
+ this.startOn = this.options.delay*1000;
244
+ this.finishOn = this.startOn+(this.options.duration*1000);
245
+ this.fromToDelta = this.options.to-this.options.from;
246
+ this.totalTime = this.finishOn-this.startOn;
247
+ this.totalFrames = this.options.fps*this.options.duration;
248
+
249
+ this.render = (function() {
250
+ function dispatch(effect, eventName) {
251
+ if (effect.options[eventName + 'Internal'])
252
+ effect.options[eventName + 'Internal'](effect);
253
+ if (effect.options[eventName])
254
+ effect.options[eventName](effect);
255
+ }
256
+
257
+ return function(pos) {
258
+ if (this.state === "idle") {
259
+ this.state = "running";
260
+ dispatch(this, 'beforeSetup');
261
+ if (this.setup) this.setup();
262
+ dispatch(this, 'afterSetup');
263
+ }
264
+ if (this.state === "running") {
265
+ pos = (this.options.transition(pos) * this.fromToDelta) + this.options.from;
266
+ this.position = pos;
267
+ dispatch(this, 'beforeUpdate');
268
+ if (this.update) this.update(pos);
269
+ dispatch(this, 'afterUpdate');
270
+ }
271
+ };
272
+ })();
273
+
274
+ this.event('beforeStart');
275
+ if (!this.options.sync)
276
+ Effect.Queues.get(Object.isString(this.options.queue) ?
277
+ 'global' : this.options.queue.scope).add(this);
278
+ },
279
+ loop: function(timePos) {
280
+ if (timePos >= this.startOn) {
281
+ if (timePos >= this.finishOn) {
282
+ this.render(1.0);
283
+ this.cancel();
284
+ this.event('beforeFinish');
285
+ if (this.finish) this.finish();
286
+ this.event('afterFinish');
287
+ return;
288
+ }
289
+ var pos = (timePos - this.startOn) / this.totalTime,
290
+ frame = (pos * this.totalFrames).round();
291
+ if (frame > this.currentFrame) {
292
+ this.render(pos);
293
+ this.currentFrame = frame;
294
+ }
295
+ }
296
+ },
297
+ cancel: function() {
298
+ if (!this.options.sync)
299
+ Effect.Queues.get(Object.isString(this.options.queue) ?
300
+ 'global' : this.options.queue.scope).remove(this);
301
+ this.state = 'finished';
302
+ },
303
+ event: function(eventName) {
304
+ if (this.options[eventName + 'Internal']) this.options[eventName + 'Internal'](this);
305
+ if (this.options[eventName]) this.options[eventName](this);
306
+ },
307
+ inspect: function() {
308
+ var data = $H();
309
+ for(property in this)
310
+ if (!Object.isFunction(this[property])) data.set(property, this[property]);
311
+ return '#<Effect:' + data.inspect() + ',options:' + $H(this.options).inspect() + '>';
312
+ }
313
+ });
314
+
315
+ Effect.Parallel = Class.create(Effect.Base, {
316
+ initialize: function(effects) {
317
+ this.effects = effects || [];
318
+ this.start(arguments[1]);
319
+ },
320
+ update: function(position) {
321
+ this.effects.invoke('render', position);
322
+ },
323
+ finish: function(position) {
324
+ this.effects.each( function(effect) {
325
+ effect.render(1.0);
326
+ effect.cancel();
327
+ effect.event('beforeFinish');
328
+ if (effect.finish) effect.finish(position);
329
+ effect.event('afterFinish');
330
+ });
331
+ }
332
+ });
333
+
334
+ Effect.Tween = Class.create(Effect.Base, {
335
+ initialize: function(object, from, to) {
336
+ object = Object.isString(object) ? $(object) : object;
337
+ var args = $A(arguments), method = args.last(),
338
+ options = args.length == 5 ? args[3] : null;
339
+ this.method = Object.isFunction(method) ? method.bind(object) :
340
+ Object.isFunction(object[method]) ? object[method].bind(object) :
341
+ function(value) { object[method] = value };
342
+ this.start(Object.extend({ from: from, to: to }, options || { }));
343
+ },
344
+ update: function(position) {
345
+ this.method(position);
346
+ }
347
+ });
348
+
349
+ Effect.Event = Class.create(Effect.Base, {
350
+ initialize: function() {
351
+ this.start(Object.extend({ duration: 0 }, arguments[0] || { }));
352
+ },
353
+ update: Prototype.emptyFunction
354
+ });
355
+
356
+ Effect.Opacity = Class.create(Effect.Base, {
357
+ initialize: function(element) {
358
+ this.element = $(element);
359
+ if (!this.element) throw(Effect._elementDoesNotExistError);
360
+ // make this work on IE on elements without 'layout'
361
+ if (Prototype.Browser.IE && (!this.element.currentStyle.hasLayout))
362
+ this.element.setStyle({zoom: 1});
363
+ var options = Object.extend({
364
+ from: this.element.getOpacity() || 0.0,
365
+ to: 1.0
366
+ }, arguments[1] || { });
367
+ this.start(options);
368
+ },
369
+ update: function(position) {
370
+ this.element.setOpacity(position);
371
+ }
372
+ });
373
+
374
+ Effect.Move = Class.create(Effect.Base, {
375
+ initialize: function(element) {
376
+ this.element = $(element);
377
+ if (!this.element) throw(Effect._elementDoesNotExistError);
378
+ var options = Object.extend({
379
+ x: 0,
380
+ y: 0,
381
+ mode: 'relative'
382
+ }, arguments[1] || { });
383
+ this.start(options);
384
+ },
385
+ setup: function() {
386
+ this.element.makePositioned();
387
+ this.originalLeft = parseFloat(this.element.getStyle('left') || '0');
388
+ this.originalTop = parseFloat(this.element.getStyle('top') || '0');
389
+ if (this.options.mode == 'absolute') {
390
+ this.options.x = this.options.x - this.originalLeft;
391
+ this.options.y = this.options.y - this.originalTop;
392
+ }
393
+ },
394
+ update: function(position) {
395
+ this.element.setStyle({
396
+ left: (this.options.x * position + this.originalLeft).round() + 'px',
397
+ top: (this.options.y * position + this.originalTop).round() + 'px'
398
+ });
399
+ }
400
+ });
401
+
402
+ // for backwards compatibility
403
+ Effect.MoveBy = function(element, toTop, toLeft) {
404
+ return new Effect.Move(element,
405
+ Object.extend({ x: toLeft, y: toTop }, arguments[3] || { }));
406
+ };
407
+
408
+ Effect.Scale = Class.create(Effect.Base, {
409
+ initialize: function(element, percent) {
410
+ this.element = $(element);
411
+ if (!this.element) throw(Effect._elementDoesNotExistError);
412
+ var options = Object.extend({
413
+ scaleX: true,
414
+ scaleY: true,
415
+ scaleContent: true,
416
+ scaleFromCenter: false,
417
+ scaleMode: 'box', // 'box' or 'contents' or { } with provided values
418
+ scaleFrom: 100.0,
419
+ scaleTo: percent
420
+ }, arguments[2] || { });
421
+ this.start(options);
422
+ },
423
+ setup: function() {
424
+ this.restoreAfterFinish = this.options.restoreAfterFinish || false;
425
+ this.elementPositioning = this.element.getStyle('position');
426
+
427
+ this.originalStyle = { };
428
+ ['top','left','width','height','fontSize'].each( function(k) {
429
+ this.originalStyle[k] = this.element.style[k];
430
+ }.bind(this));
431
+
432
+ this.originalTop = this.element.offsetTop;
433
+ this.originalLeft = this.element.offsetLeft;
434
+
435
+ var fontSize = this.element.getStyle('font-size') || '100%';
436
+ ['em','px','%','pt'].each( function(fontSizeType) {
437
+ if (fontSize.indexOf(fontSizeType)>0) {
438
+ this.fontSize = parseFloat(fontSize);
439
+ this.fontSizeType = fontSizeType;
440
+ }
441
+ }.bind(this));
442
+
443
+ this.factor = (this.options.scaleTo - this.options.scaleFrom)/100;
444
+
445
+ this.dims = null;
446
+ if (this.options.scaleMode=='box')
447
+ this.dims = [this.element.offsetHeight, this.element.offsetWidth];
448
+ if (/^content/.test(this.options.scaleMode))
449
+ this.dims = [this.element.scrollHeight, this.element.scrollWidth];
450
+ if (!this.dims)
451
+ this.dims = [this.options.scaleMode.originalHeight,
452
+ this.options.scaleMode.originalWidth];
453
+ },
454
+ update: function(position) {
455
+ var currentScale = (this.options.scaleFrom/100.0) + (this.factor * position);
456
+ if (this.options.scaleContent && this.fontSize)
457
+ this.element.setStyle({fontSize: this.fontSize * currentScale + this.fontSizeType });
458
+ this.setDimensions(this.dims[0] * currentScale, this.dims[1] * currentScale);
459
+ },
460
+ finish: function(position) {
461
+ if (this.restoreAfterFinish) this.element.setStyle(this.originalStyle);
462
+ },
463
+ setDimensions: function(height, width) {
464
+ var d = { };
465
+ if (this.options.scaleX) d.width = width.round() + 'px';
466
+ if (this.options.scaleY) d.height = height.round() + 'px';
467
+ if (this.options.scaleFromCenter) {
468
+ var topd = (height - this.dims[0])/2;
469
+ var leftd = (width - this.dims[1])/2;
470
+ if (this.elementPositioning == 'absolute') {
471
+ if (this.options.scaleY) d.top = this.originalTop-topd + 'px';
472
+ if (this.options.scaleX) d.left = this.originalLeft-leftd + 'px';
473
+ } else {
474
+ if (this.options.scaleY) d.top = -topd + 'px';
475
+ if (this.options.scaleX) d.left = -leftd + 'px';
476
+ }
477
+ }
478
+ this.element.setStyle(d);
479
+ }
480
+ });
481
+
482
+ Effect.Highlight = Class.create(Effect.Base, {
483
+ initialize: function(element) {
484
+ this.element = $(element);
485
+ if (!this.element) throw(Effect._elementDoesNotExistError);
486
+ var options = Object.extend({ startcolor: '#ffff99' }, arguments[1] || { });
487
+ this.start(options);
488
+ },
489
+ setup: function() {
490
+ // Prevent executing on elements not in the layout flow
491
+ if (this.element.getStyle('display')=='none') { this.cancel(); return; }
492
+ // Disable background image during the effect
493
+ this.oldStyle = { };
494
+ if (!this.options.keepBackgroundImage) {
495
+ this.oldStyle.backgroundImage = this.element.getStyle('background-image');
496
+ this.element.setStyle({backgroundImage: 'none'});
497
+ }
498
+ if (!this.options.endcolor)
499
+ this.options.endcolor = this.element.getStyle('background-color').parseColor('#ffffff');
500
+ if (!this.options.restorecolor)
501
+ this.options.restorecolor = this.element.getStyle('background-color');
502
+ // init color calculations
503
+ this._base = $R(0,2).map(function(i){ return parseInt(this.options.startcolor.slice(i*2+1,i*2+3),16) }.bind(this));
504
+ this._delta = $R(0,2).map(function(i){ return parseInt(this.options.endcolor.slice(i*2+1,i*2+3),16)-this._base[i] }.bind(this));
505
+ },
506
+ update: function(position) {
507
+ this.element.setStyle({backgroundColor: $R(0,2).inject('#',function(m,v,i){
508
+ return m+((this._base[i]+(this._delta[i]*position)).round().toColorPart()); }.bind(this)) });
509
+ },
510
+ finish: function() {
511
+ this.element.setStyle(Object.extend(this.oldStyle, {
512
+ backgroundColor: this.options.restorecolor
513
+ }));
514
+ }
515
+ });
516
+
517
+ Effect.ScrollTo = function(element) {
518
+ var options = arguments[1] || { },
519
+ scrollOffsets = document.viewport.getScrollOffsets(),
520
+ elementOffsets = $(element).cumulativeOffset();
521
+
522
+ if (options.offset) elementOffsets[1] += options.offset;
523
+
524
+ return new Effect.Tween(null,
525
+ scrollOffsets.top,
526
+ elementOffsets[1],
527
+ options,
528
+ function(p){ scrollTo(scrollOffsets.left, p.round()); }
529
+ );
530
+ };
531
+
532
+ /* ------------- combination effects ------------- */
533
+
534
+ Effect.Fade = function(element) {
535
+ element = $(element);
536
+ var oldOpacity = element.getInlineOpacity();
537
+ var options = Object.extend({
538
+ from: element.getOpacity() || 1.0,
539
+ to: 0.0,
540
+ afterFinishInternal: function(effect) {
541
+ if (effect.options.to!=0) return;
542
+ effect.element.hide().setStyle({opacity: oldOpacity});
543
+ }
544
+ }, arguments[1] || { });
545
+ return new Effect.Opacity(element,options);
546
+ };
547
+
548
+ Effect.Appear = function(element) {
549
+ element = $(element);
550
+ var options = Object.extend({
551
+ from: (element.getStyle('display') == 'none' ? 0.0 : element.getOpacity() || 0.0),
552
+ to: 1.0,
553
+ // force Safari to render floated elements properly
554
+ afterFinishInternal: function(effect) {
555
+ effect.element.forceRerendering();
556
+ },
557
+ beforeSetup: function(effect) {
558
+ effect.element.setOpacity(effect.options.from).show();
559
+ }}, arguments[1] || { });
560
+ return new Effect.Opacity(element,options);
561
+ };
562
+
563
+ Effect.Puff = function(element) {
564
+ element = $(element);
565
+ var oldStyle = {
566
+ opacity: element.getInlineOpacity(),
567
+ position: element.getStyle('position'),
568
+ top: element.style.top,
569
+ left: element.style.left,
570
+ width: element.style.width,
571
+ height: element.style.height
572
+ };
573
+ return new Effect.Parallel(
574
+ [ new Effect.Scale(element, 200,
575
+ { sync: true, scaleFromCenter: true, scaleContent: true, restoreAfterFinish: true }),
576
+ new Effect.Opacity(element, { sync: true, to: 0.0 } ) ],
577
+ Object.extend({ duration: 1.0,
578
+ beforeSetupInternal: function(effect) {
579
+ Position.absolutize(effect.effects[0].element);
580
+ },
581
+ afterFinishInternal: function(effect) {
582
+ effect.effects[0].element.hide().setStyle(oldStyle); }
583
+ }, arguments[1] || { })
584
+ );
585
+ };
586
+
587
+ Effect.BlindUp = function(element) {
588
+ element = $(element);
589
+ element.makeClipping();
590
+ return new Effect.Scale(element, 0,
591
+ Object.extend({ scaleContent: false,
592
+ scaleX: false,
593
+ restoreAfterFinish: true,
594
+ afterFinishInternal: function(effect) {
595
+ effect.element.hide().undoClipping();
596
+ }
597
+ }, arguments[1] || { })
598
+ );
599
+ };
600
+
601
+ Effect.BlindDown = function(element) {
602
+ element = $(element);
603
+ var elementDimensions = element.getDimensions();
604
+ return new Effect.Scale(element, 100, Object.extend({
605
+ scaleContent: false,
606
+ scaleX: false,
607
+ scaleFrom: 0,
608
+ scaleMode: {originalHeight: elementDimensions.height, originalWidth: elementDimensions.width},
609
+ restoreAfterFinish: true,
610
+ afterSetup: function(effect) {
611
+ effect.element.makeClipping().setStyle({height: '0px'}).show();
612
+ },
613
+ afterFinishInternal: function(effect) {
614
+ effect.element.undoClipping();
615
+ }
616
+ }, arguments[1] || { }));
617
+ };
618
+
619
+ Effect.SwitchOff = function(element) {
620
+ element = $(element);
621
+ var oldOpacity = element.getInlineOpacity();
622
+ return new Effect.Appear(element, Object.extend({
623
+ duration: 0.4,
624
+ from: 0,
625
+ transition: Effect.Transitions.flicker,
626
+ afterFinishInternal: function(effect) {
627
+ new Effect.Scale(effect.element, 1, {
628
+ duration: 0.3, scaleFromCenter: true,
629
+ scaleX: false, scaleContent: false, restoreAfterFinish: true,
630
+ beforeSetup: function(effect) {
631
+ effect.element.makePositioned().makeClipping();
632
+ },
633
+ afterFinishInternal: function(effect) {
634
+ effect.element.hide().undoClipping().undoPositioned().setStyle({opacity: oldOpacity});
635
+ }
636
+ });
637
+ }
638
+ }, arguments[1] || { }));
639
+ };
640
+
641
+ Effect.DropOut = function(element) {
642
+ element = $(element);
643
+ var oldStyle = {
644
+ top: element.getStyle('top'),
645
+ left: element.getStyle('left'),
646
+ opacity: element.getInlineOpacity() };
647
+ return new Effect.Parallel(
648
+ [ new Effect.Move(element, {x: 0, y: 100, sync: true }),
649
+ new Effect.Opacity(element, { sync: true, to: 0.0 }) ],
650
+ Object.extend(
651
+ { duration: 0.5,
652
+ beforeSetup: function(effect) {
653
+ effect.effects[0].element.makePositioned();
654
+ },
655
+ afterFinishInternal: function(effect) {
656
+ effect.effects[0].element.hide().undoPositioned().setStyle(oldStyle);
657
+ }
658
+ }, arguments[1] || { }));
659
+ };
660
+
661
+ Effect.Shake = function(element) {
662
+ element = $(element);
663
+ var options = Object.extend({
664
+ distance: 20,
665
+ duration: 0.5
666
+ }, arguments[1] || {});
667
+ var distance = parseFloat(options.distance);
668
+ var split = parseFloat(options.duration) / 10.0;
669
+ var oldStyle = {
670
+ top: element.getStyle('top'),
671
+ left: element.getStyle('left') };
672
+ return new Effect.Move(element,
673
+ { x: distance, y: 0, duration: split, afterFinishInternal: function(effect) {
674
+ new Effect.Move(effect.element,
675
+ { x: -distance*2, y: 0, duration: split*2, afterFinishInternal: function(effect) {
676
+ new Effect.Move(effect.element,
677
+ { x: distance*2, y: 0, duration: split*2, afterFinishInternal: function(effect) {
678
+ new Effect.Move(effect.element,
679
+ { x: -distance*2, y: 0, duration: split*2, afterFinishInternal: function(effect) {
680
+ new Effect.Move(effect.element,
681
+ { x: distance*2, y: 0, duration: split*2, afterFinishInternal: function(effect) {
682
+ new Effect.Move(effect.element,
683
+ { x: -distance, y: 0, duration: split, afterFinishInternal: function(effect) {
684
+ effect.element.undoPositioned().setStyle(oldStyle);
685
+ }}); }}); }}); }}); }}); }});
686
+ };
687
+
688
+ Effect.SlideDown = function(element) {
689
+ element = $(element).cleanWhitespace();
690
+ // SlideDown need to have the content of the element wrapped in a container element with fixed height!
691
+ var oldInnerBottom = element.down().getStyle('bottom');
692
+ var elementDimensions = element.getDimensions();
693
+ return new Effect.Scale(element, 100, Object.extend({
694
+ scaleContent: false,
695
+ scaleX: false,
696
+ scaleFrom: window.opera ? 0 : 1,
697
+ scaleMode: {originalHeight: elementDimensions.height, originalWidth: elementDimensions.width},
698
+ restoreAfterFinish: true,
699
+ afterSetup: function(effect) {
700
+ effect.element.makePositioned();
701
+ effect.element.down().makePositioned();
702
+ if (window.opera) effect.element.setStyle({top: ''});
703
+ effect.element.makeClipping().setStyle({height: '0px'}).show();
704
+ },
705
+ afterUpdateInternal: function(effect) {
706
+ effect.element.down().setStyle({bottom:
707
+ (effect.dims[0] - effect.element.clientHeight) + 'px' });
708
+ },
709
+ afterFinishInternal: function(effect) {
710
+ effect.element.undoClipping().undoPositioned();
711
+ effect.element.down().undoPositioned().setStyle({bottom: oldInnerBottom}); }
712
+ }, arguments[1] || { })
713
+ );
714
+ };
715
+
716
+ Effect.SlideUp = function(element) {
717
+ element = $(element).cleanWhitespace();
718
+ var oldInnerBottom = element.down().getStyle('bottom');
719
+ var elementDimensions = element.getDimensions();
720
+ return new Effect.Scale(element, window.opera ? 0 : 1,
721
+ Object.extend({ scaleContent: false,
722
+ scaleX: false,
723
+ scaleMode: 'box',
724
+ scaleFrom: 100,
725
+ scaleMode: {originalHeight: elementDimensions.height, originalWidth: elementDimensions.width},
726
+ restoreAfterFinish: true,
727
+ afterSetup: function(effect) {
728
+ effect.element.makePositioned();
729
+ effect.element.down().makePositioned();
730
+ if (window.opera) effect.element.setStyle({top: ''});
731
+ effect.element.makeClipping().show();
732
+ },
733
+ afterUpdateInternal: function(effect) {
734
+ effect.element.down().setStyle({bottom:
735
+ (effect.dims[0] - effect.element.clientHeight) + 'px' });
736
+ },
737
+ afterFinishInternal: function(effect) {
738
+ effect.element.hide().undoClipping().undoPositioned();
739
+ effect.element.down().undoPositioned().setStyle({bottom: oldInnerBottom});
740
+ }
741
+ }, arguments[1] || { })
742
+ );
743
+ };
744
+
745
+ // Bug in opera makes the TD containing this element expand for a instance after finish
746
+ Effect.Squish = function(element) {
747
+ return new Effect.Scale(element, window.opera ? 1 : 0, {
748
+ restoreAfterFinish: true,
749
+ beforeSetup: function(effect) {
750
+ effect.element.makeClipping();
751
+ },
752
+ afterFinishInternal: function(effect) {
753
+ effect.element.hide().undoClipping();
754
+ }
755
+ });
756
+ };
757
+
758
+ Effect.Grow = function(element) {
759
+ element = $(element);
760
+ var options = Object.extend({
761
+ direction: 'center',
762
+ moveTransition: Effect.Transitions.sinoidal,
763
+ scaleTransition: Effect.Transitions.sinoidal,
764
+ opacityTransition: Effect.Transitions.full
765
+ }, arguments[1] || { });
766
+ var oldStyle = {
767
+ top: element.style.top,
768
+ left: element.style.left,
769
+ height: element.style.height,
770
+ width: element.style.width,
771
+ opacity: element.getInlineOpacity() };
772
+
773
+ var dims = element.getDimensions();
774
+ var initialMoveX, initialMoveY;
775
+ var moveX, moveY;
776
+
777
+ switch (options.direction) {
778
+ case 'top-left':
779
+ initialMoveX = initialMoveY = moveX = moveY = 0;
780
+ break;
781
+ case 'top-right':
782
+ initialMoveX = dims.width;
783
+ initialMoveY = moveY = 0;
784
+ moveX = -dims.width;
785
+ break;
786
+ case 'bottom-left':
787
+ initialMoveX = moveX = 0;
788
+ initialMoveY = dims.height;
789
+ moveY = -dims.height;
790
+ break;
791
+ case 'bottom-right':
792
+ initialMoveX = dims.width;
793
+ initialMoveY = dims.height;
794
+ moveX = -dims.width;
795
+ moveY = -dims.height;
796
+ break;
797
+ case 'center':
798
+ initialMoveX = dims.width / 2;
799
+ initialMoveY = dims.height / 2;
800
+ moveX = -dims.width / 2;
801
+ moveY = -dims.height / 2;
802
+ break;
803
+ }
804
+
805
+ return new Effect.Move(element, {
806
+ x: initialMoveX,
807
+ y: initialMoveY,
808
+ duration: 0.01,
809
+ beforeSetup: function(effect) {
810
+ effect.element.hide().makeClipping().makePositioned();
811
+ },
812
+ afterFinishInternal: function(effect) {
813
+ new Effect.Parallel(
814
+ [ new Effect.Opacity(effect.element, { sync: true, to: 1.0, from: 0.0, transition: options.opacityTransition }),
815
+ new Effect.Move(effect.element, { x: moveX, y: moveY, sync: true, transition: options.moveTransition }),
816
+ new Effect.Scale(effect.element, 100, {
817
+ scaleMode: { originalHeight: dims.height, originalWidth: dims.width },
818
+ sync: true, scaleFrom: window.opera ? 1 : 0, transition: options.scaleTransition, restoreAfterFinish: true})
819
+ ], Object.extend({
820
+ beforeSetup: function(effect) {
821
+ effect.effects[0].element.setStyle({height: '0px'}).show();
822
+ },
823
+ afterFinishInternal: function(effect) {
824
+ effect.effects[0].element.undoClipping().undoPositioned().setStyle(oldStyle);
825
+ }
826
+ }, options)
827
+ );
828
+ }
829
+ });
830
+ };
831
+
832
+ Effect.Shrink = function(element) {
833
+ element = $(element);
834
+ var options = Object.extend({
835
+ direction: 'center',
836
+ moveTransition: Effect.Transitions.sinoidal,
837
+ scaleTransition: Effect.Transitions.sinoidal,
838
+ opacityTransition: Effect.Transitions.none
839
+ }, arguments[1] || { });
840
+ var oldStyle = {
841
+ top: element.style.top,
842
+ left: element.style.left,
843
+ height: element.style.height,
844
+ width: element.style.width,
845
+ opacity: element.getInlineOpacity() };
846
+
847
+ var dims = element.getDimensions();
848
+ var moveX, moveY;
849
+
850
+ switch (options.direction) {
851
+ case 'top-left':
852
+ moveX = moveY = 0;
853
+ break;
854
+ case 'top-right':
855
+ moveX = dims.width;
856
+ moveY = 0;
857
+ break;
858
+ case 'bottom-left':
859
+ moveX = 0;
860
+ moveY = dims.height;
861
+ break;
862
+ case 'bottom-right':
863
+ moveX = dims.width;
864
+ moveY = dims.height;
865
+ break;
866
+ case 'center':
867
+ moveX = dims.width / 2;
868
+ moveY = dims.height / 2;
869
+ break;
870
+ }
871
+
872
+ return new Effect.Parallel(
873
+ [ new Effect.Opacity(element, { sync: true, to: 0.0, from: 1.0, transition: options.opacityTransition }),
874
+ new Effect.Scale(element, window.opera ? 1 : 0, { sync: true, transition: options.scaleTransition, restoreAfterFinish: true}),
875
+ new Effect.Move(element, { x: moveX, y: moveY, sync: true, transition: options.moveTransition })
876
+ ], Object.extend({
877
+ beforeStartInternal: function(effect) {
878
+ effect.effects[0].element.makePositioned().makeClipping();
879
+ },
880
+ afterFinishInternal: function(effect) {
881
+ effect.effects[0].element.hide().undoClipping().undoPositioned().setStyle(oldStyle); }
882
+ }, options)
883
+ );
884
+ };
885
+
886
+ Effect.Pulsate = function(element) {
887
+ element = $(element);
888
+ var options = arguments[1] || { },
889
+ oldOpacity = element.getInlineOpacity(),
890
+ transition = options.transition || Effect.Transitions.linear,
891
+ reverser = function(pos){
892
+ return 1 - transition((-Math.cos((pos*(options.pulses||5)*2)*Math.PI)/2) + .5);
893
+ };
894
+
895
+ return new Effect.Opacity(element,
896
+ Object.extend(Object.extend({ duration: 2.0, from: 0,
897
+ afterFinishInternal: function(effect) { effect.element.setStyle({opacity: oldOpacity}); }
898
+ }, options), {transition: reverser}));
899
+ };
900
+
901
+ Effect.Fold = function(element) {
902
+ element = $(element);
903
+ var oldStyle = {
904
+ top: element.style.top,
905
+ left: element.style.left,
906
+ width: element.style.width,
907
+ height: element.style.height };
908
+ element.makeClipping();
909
+ return new Effect.Scale(element, 5, Object.extend({
910
+ scaleContent: false,
911
+ scaleX: false,
912
+ afterFinishInternal: function(effect) {
913
+ new Effect.Scale(element, 1, {
914
+ scaleContent: false,
915
+ scaleY: false,
916
+ afterFinishInternal: function(effect) {
917
+ effect.element.hide().undoClipping().setStyle(oldStyle);
918
+ } });
919
+ }}, arguments[1] || { }));
920
+ };
921
+
922
+ Effect.Morph = Class.create(Effect.Base, {
923
+ initialize: function(element) {
924
+ this.element = $(element);
925
+ if (!this.element) throw(Effect._elementDoesNotExistError);
926
+ var options = Object.extend({
927
+ style: { }
928
+ }, arguments[1] || { });
929
+
930
+ if (!Object.isString(options.style)) this.style = $H(options.style);
931
+ else {
932
+ if (options.style.include(':'))
933
+ this.style = options.style.parseStyle();
934
+ else {
935
+ this.element.addClassName(options.style);
936
+ this.style = $H(this.element.getStyles());
937
+ this.element.removeClassName(options.style);
938
+ var css = this.element.getStyles();
939
+ this.style = this.style.reject(function(style) {
940
+ return style.value == css[style.key];
941
+ });
942
+ options.afterFinishInternal = function(effect) {
943
+ effect.element.addClassName(effect.options.style);
944
+ effect.transforms.each(function(transform) {
945
+ effect.element.style[transform.style] = '';
946
+ });
947
+ };
948
+ }
949
+ }
950
+ this.start(options);
951
+ },
952
+
953
+ setup: function(){
954
+ function parseColor(color){
955
+ if (!color || ['rgba(0, 0, 0, 0)','transparent'].include(color)) color = '#ffffff';
956
+ color = color.parseColor();
957
+ return $R(0,2).map(function(i){
958
+ return parseInt( color.slice(i*2+1,i*2+3), 16 );
959
+ });
960
+ }
961
+ this.transforms = this.style.map(function(pair){
962
+ var property = pair[0], value = pair[1], unit = null;
963
+
964
+ if (value.parseColor('#zzzzzz') != '#zzzzzz') {
965
+ value = value.parseColor();
966
+ unit = 'color';
967
+ } else if (property == 'opacity') {
968
+ value = parseFloat(value);
969
+ if (Prototype.Browser.IE && (!this.element.currentStyle.hasLayout))
970
+ this.element.setStyle({zoom: 1});
971
+ } else if (Element.CSS_LENGTH.test(value)) {
972
+ var components = value.match(/^([\+\-]?[0-9\.]+)(.*)$/);
973
+ value = parseFloat(components[1]);
974
+ unit = (components.length == 3) ? components[2] : null;
975
+ }
976
+
977
+ var originalValue = this.element.getStyle(property);
978
+ return {
979
+ style: property.camelize(),
980
+ originalValue: unit=='color' ? parseColor(originalValue) : parseFloat(originalValue || 0),
981
+ targetValue: unit=='color' ? parseColor(value) : value,
982
+ unit: unit
983
+ };
984
+ }.bind(this)).reject(function(transform){
985
+ return (
986
+ (transform.originalValue == transform.targetValue) ||
987
+ (
988
+ transform.unit != 'color' &&
989
+ (isNaN(transform.originalValue) || isNaN(transform.targetValue))
990
+ )
991
+ );
992
+ });
993
+ },
994
+ update: function(position) {
995
+ var style = { }, transform, i = this.transforms.length;
996
+ while(i--)
997
+ style[(transform = this.transforms[i]).style] =
998
+ transform.unit=='color' ? '#'+
999
+ (Math.round(transform.originalValue[0]+
1000
+ (transform.targetValue[0]-transform.originalValue[0])*position)).toColorPart() +
1001
+ (Math.round(transform.originalValue[1]+
1002
+ (transform.targetValue[1]-transform.originalValue[1])*position)).toColorPart() +
1003
+ (Math.round(transform.originalValue[2]+
1004
+ (transform.targetValue[2]-transform.originalValue[2])*position)).toColorPart() :
1005
+ (transform.originalValue +
1006
+ (transform.targetValue - transform.originalValue) * position).toFixed(3) +
1007
+ (transform.unit === null ? '' : transform.unit);
1008
+ this.element.setStyle(style, true);
1009
+ }
1010
+ });
1011
+
1012
+ Effect.Transform = Class.create({
1013
+ initialize: function(tracks){
1014
+ this.tracks = [];
1015
+ this.options = arguments[1] || { };
1016
+ this.addTracks(tracks);
1017
+ },
1018
+ addTracks: function(tracks){
1019
+ tracks.each(function(track){
1020
+ track = $H(track);
1021
+ var data = track.values().first();
1022
+ this.tracks.push($H({
1023
+ ids: track.keys().first(),
1024
+ effect: Effect.Morph,
1025
+ options: { style: data }
1026
+ }));
1027
+ }.bind(this));
1028
+ return this;
1029
+ },
1030
+ play: function(){
1031
+ return new Effect.Parallel(
1032
+ this.tracks.map(function(track){
1033
+ var ids = track.get('ids'), effect = track.get('effect'), options = track.get('options');
1034
+ var elements = [$(ids) || $$(ids)].flatten();
1035
+ return elements.map(function(e){ return new effect(e, Object.extend({ sync:true }, options)) });
1036
+ }).flatten(),
1037
+ this.options
1038
+ );
1039
+ }
1040
+ });
1041
+
1042
+ Element.CSS_PROPERTIES = $w(
1043
+ 'backgroundColor backgroundPosition borderBottomColor borderBottomStyle ' +
1044
+ 'borderBottomWidth borderLeftColor borderLeftStyle borderLeftWidth ' +
1045
+ 'borderRightColor borderRightStyle borderRightWidth borderSpacing ' +
1046
+ 'borderTopColor borderTopStyle borderTopWidth bottom clip color ' +
1047
+ 'fontSize fontWeight height left letterSpacing lineHeight ' +
1048
+ 'marginBottom marginLeft marginRight marginTop markerOffset maxHeight '+
1049
+ 'maxWidth minHeight minWidth opacity outlineColor outlineOffset ' +
1050
+ 'outlineWidth paddingBottom paddingLeft paddingRight paddingTop ' +
1051
+ 'right textIndent top width wordSpacing zIndex');
1052
+
1053
+ Element.CSS_LENGTH = /^(([\+\-]?[0-9\.]+)(em|ex|px|in|cm|mm|pt|pc|\%))|0$/;
1054
+
1055
+ String.__parseStyleElement = document.createElement('div');
1056
+ String.prototype.parseStyle = function(){
1057
+ var style, styleRules = $H();
1058
+ if (Prototype.Browser.WebKit)
1059
+ style = new Element('div',{style:this}).style;
1060
+ else {
1061
+ String.__parseStyleElement.innerHTML = '<div style="' + this + '"></div>';
1062
+ style = String.__parseStyleElement.childNodes[0].style;
1063
+ }
1064
+
1065
+ Element.CSS_PROPERTIES.each(function(property){
1066
+ if (style[property]) styleRules.set(property, style[property]);
1067
+ });
1068
+
1069
+ if (Prototype.Browser.IE && this.include('opacity'))
1070
+ styleRules.set('opacity', this.match(/opacity:\s*((?:0|1)?(?:\.\d*)?)/)[1]);
1071
+
1072
+ return styleRules;
1073
+ };
1074
+
1075
+ if (document.defaultView && document.defaultView.getComputedStyle) {
1076
+ Element.getStyles = function(element) {
1077
+ var css = document.defaultView.getComputedStyle($(element), null);
1078
+ return Element.CSS_PROPERTIES.inject({ }, function(styles, property) {
1079
+ styles[property] = css[property];
1080
+ return styles;
1081
+ });
1082
+ };
1083
+ } else {
1084
+ Element.getStyles = function(element) {
1085
+ element = $(element);
1086
+ var css = element.currentStyle, styles;
1087
+ styles = Element.CSS_PROPERTIES.inject({ }, function(results, property) {
1088
+ results[property] = css[property];
1089
+ return results;
1090
+ });
1091
+ if (!styles.opacity) styles.opacity = element.getOpacity();
1092
+ return styles;
1093
+ };
1094
+ }
1095
+
1096
+ Effect.Methods = {
1097
+ morph: function(element, style) {
1098
+ element = $(element);
1099
+ new Effect.Morph(element, Object.extend({ style: style }, arguments[2] || { }));
1100
+ return element;
1101
+ },
1102
+ visualEffect: function(element, effect, options) {
1103
+ element = $(element);
1104
+ var s = effect.dasherize().camelize(), klass = s.charAt(0).toUpperCase() + s.substring(1);
1105
+ new Effect[klass](element, options);
1106
+ return element;
1107
+ },
1108
+ highlight: function(element, options) {
1109
+ element = $(element);
1110
+ new Effect.Highlight(element, options);
1111
+ return element;
1112
+ }
1113
+ };
1114
+
1115
+ $w('fade appear grow shrink fold blindUp blindDown slideUp slideDown '+
1116
+ 'pulsate shake puff squish switchOff dropOut').each(
1117
+ function(effect) {
1118
+ Effect.Methods[effect] = function(element, options){
1119
+ element = $(element);
1120
+ Effect[effect.charAt(0).toUpperCase() + effect.substring(1)](element, options);
1121
+ return element;
1122
+ };
1123
+ }
1124
+ );
1125
+
1126
+ $w('getInlineOpacity forceRerendering setContentZoom collectTextNodes collectTextNodesIgnoreClass getStyles').each(
1127
+ function(f) { Effect.Methods[f] = Element[f]; }
1128
+ );
1129
+
1130
+ Element.addMethods(Effect.Methods);
js/scriptaculous/scriptaculous.js ADDED
@@ -0,0 +1,60 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // script.aculo.us scriptaculous.js v1.8.2, Tue Nov 18 18:30:58 +0100 2008
2
+
3
+ // Copyright (c) 2005-2008 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
4
+ //
5
+ // Permission is hereby granted, free of charge, to any person obtaining
6
+ // a copy of this software and associated documentation files (the
7
+ // "Software"), to deal in the Software without restriction, including
8
+ // without limitation the rights to use, copy, modify, merge, publish,
9
+ // distribute, sublicense, and/or sell copies of the Software, and to
10
+ // permit persons to whom the Software is furnished to do so, subject to
11
+ // the following conditions:
12
+ //
13
+ // The above copyright notice and this permission notice shall be
14
+ // included in all copies or substantial portions of the Software.
15
+ //
16
+ // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23
+ //
24
+ // For details, see the script.aculo.us web site: http://script.aculo.us/
25
+
26
+ var Scriptaculous = {
27
+ Version: '1.8.2',
28
+ require: function(libraryName) {
29
+ // inserting via DOM fails in Safari 2.0, so brute force approach
30
+ document.write('<script type="text/javascript" src="'+libraryName+'"><\/script>');
31
+ },
32
+ REQUIRED_PROTOTYPE: '1.6.0.3',
33
+ load: function() {
34
+ function convertVersionString(versionString) {
35
+ var v = versionString.replace(/_.*|\./g, '');
36
+ v = parseInt(v + '0'.times(4-v.length));
37
+ return versionString.indexOf('_') > -1 ? v-1 : v;
38
+ }
39
+
40
+ if((typeof Prototype=='undefined') ||
41
+ (typeof Element == 'undefined') ||
42
+ (typeof Element.Methods=='undefined') ||
43
+ (convertVersionString(Prototype.Version) <
44
+ convertVersionString(Scriptaculous.REQUIRED_PROTOTYPE)))
45
+ throw("script.aculo.us requires the Prototype JavaScript framework >= " +
46
+ Scriptaculous.REQUIRED_PROTOTYPE);
47
+
48
+ var js = /scriptaculous\.js(\?.*)?$/;
49
+ $$('head script[src]').findAll(function(s) {
50
+ return s.src.match(js);
51
+ }).each(function(s) {
52
+ var path = s.src.replace(js, ''),
53
+ includes = s.src.match(/\?.*load=([a-z,]*)/);
54
+ (includes ? includes[1] : 'builder,effects,dragdrop,controls,slider,sound').split(',').each(
55
+ function(include) { Scriptaculous.require(path+include+'.js') });
56
+ });
57
+ }
58
+ };
59
+
60
+ Scriptaculous.load();
js/scriptaculous/slider.js ADDED
@@ -0,0 +1,277 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // script.aculo.us slider.js v1.8.2, Tue Nov 18 18:30:58 +0100 2008
2
+
3
+ // Copyright (c) 2005-2008 Marty Haught, Thomas Fuchs
4
+ //
5
+ // script.aculo.us is freely distributable under the terms of an MIT-style license.
6
+ // For details, see the script.aculo.us web site: http://script.aculo.us/
7
+
8
+ if (!Control) var Control = { };
9
+
10
+ // options:
11
+ // axis: 'vertical', or 'horizontal' (default)
12
+ //
13
+ // callbacks:
14
+ // onChange(value)
15
+ // onSlide(value)
16
+ Control.Slider = Class.create({
17
+ initialize: function(handle, track, options) {
18
+ var slider = this;
19
+
20
+ if (Object.isArray(handle)) {
21
+ this.handles = handle.collect( function(e) { return $(e) });
22
+ } else {
23
+ this.handles = [$(handle)];
24
+ }
25
+
26
+ this.track = $(track);
27
+ this.options = options || { };
28
+
29
+ this.axis = this.options.axis || 'horizontal';
30
+ this.increment = this.options.increment || 1;
31
+ this.step = parseInt(this.options.step || '1');
32
+ this.range = this.options.range || $R(0,1);
33
+
34
+ this.value = 0; // assure backwards compat
35
+ this.values = this.handles.map( function() { return 0 });
36
+ this.spans = this.options.spans ? this.options.spans.map(function(s){ return $(s) }) : false;
37
+ this.options.startSpan = $(this.options.startSpan || null);
38
+ this.options.endSpan = $(this.options.endSpan || null);
39
+
40
+ this.restricted = this.options.restricted || false;
41
+
42
+ this.maximum = this.options.maximum || this.range.end;
43
+ this.minimum = this.options.minimum || this.range.start;
44
+
45
+ // Will be used to align the handle onto the track, if necessary
46
+ this.alignX = parseInt(this.options.alignX || '0');
47
+ this.alignY = parseInt(this.options.alignY || '0');
48
+
49
+ this.trackLength = this.maximumOffset() - this.minimumOffset();
50
+
51
+ this.handleLength = this.isVertical() ?
52
+ (this.handles[0].offsetHeight != 0 ?
53
+ this.handles[0].offsetHeight : this.handles[0].style.height.replace(/px$/,"")) :
54
+ (this.handles[0].offsetWidth != 0 ? this.handles[0].offsetWidth :
55
+ this.handles[0].style.width.replace(/px$/,""));
56
+
57
+ this.active = false;
58
+ this.dragging = false;
59
+ this.disabled = false;
60
+
61
+ if (this.options.disabled) this.setDisabled();
62
+
63
+ // Allowed values array
64
+ this.allowedValues = this.options.values ? this.options.values.sortBy(Prototype.K) : false;
65
+ if (this.allowedValues) {
66
+ this.minimum = this.allowedValues.min();
67
+ this.maximum = this.allowedValues.max();
68
+ }
69
+
70
+ this.eventMouseDown = this.startDrag.bindAsEventListener(this);
71
+ this.eventMouseUp = this.endDrag.bindAsEventListener(this);
72
+ this.eventMouseMove = this.update.bindAsEventListener(this);
73
+
74
+ // Initialize handles in reverse (make sure first handle is active)
75
+ this.handles.each( function(h,i) {
76
+ i = slider.handles.length-1-i;
77
+ slider.setValue(parseFloat(
78
+ (Object.isArray(slider.options.sliderValue) ?
79
+ slider.options.sliderValue[i] : slider.options.sliderValue) ||
80
+ slider.range.start), i);
81
+ h.makePositioned().observe("mousedown", slider.eventMouseDown);
82
+ });
83
+
84
+ this.track.observe("mousedown", this.eventMouseDown);
85
+ document.observe("mouseup", this.eventMouseUp);
86
+ $(this.track.parentNode.parentNode).observe("mousemove", this.eventMouseMove);
87
+
88
+
89
+ this.initialized = true;
90
+ },
91
+ dispose: function() {
92
+ var slider = this;
93
+ Event.stopObserving(this.track, "mousedown", this.eventMouseDown);
94
+ Event.stopObserving(document, "mouseup", this.eventMouseUp);
95
+ Event.stopObserving(this.track.parentNode.parentNode, "mousemove", this.eventMouseMove);
96
+ this.handles.each( function(h) {
97
+ Event.stopObserving(h, "mousedown", slider.eventMouseDown);
98
+ });
99
+ },
100
+ setDisabled: function(){
101
+ this.disabled = true;
102
+ this.track.parentNode.className = this.track.parentNode.className + ' disabled';
103
+ },
104
+ setEnabled: function(){
105
+ this.disabled = false;
106
+ },
107
+ getNearestValue: function(value){
108
+ if (this.allowedValues){
109
+ if (value >= this.allowedValues.max()) return(this.allowedValues.max());
110
+ if (value <= this.allowedValues.min()) return(this.allowedValues.min());
111
+
112
+ var offset = Math.abs(this.allowedValues[0] - value);
113
+ var newValue = this.allowedValues[0];
114
+ this.allowedValues.each( function(v) {
115
+ var currentOffset = Math.abs(v - value);
116
+ if (currentOffset <= offset){
117
+ newValue = v;
118
+ offset = currentOffset;
119
+ }
120
+ });
121
+ return newValue;
122
+ }
123
+ if (value > this.range.end) return this.range.end;
124
+ if (value < this.range.start) return this.range.start;
125
+ return value;
126
+ },
127
+ setValue: function(sliderValue, handleIdx){
128
+ if (!this.active) {
129
+ this.activeHandleIdx = handleIdx || 0;
130
+ this.activeHandle = this.handles[this.activeHandleIdx];
131
+ this.updateStyles();
132
+ }
133
+ handleIdx = handleIdx || this.activeHandleIdx || 0;
134
+ if (this.initialized && this.restricted) {
135
+ if ((handleIdx>0) && (sliderValue<this.values[handleIdx-1]))
136
+ sliderValue = this.values[handleIdx-1];
137
+ if ((handleIdx < (this.handles.length-1)) && (sliderValue>this.values[handleIdx+1]))
138
+ sliderValue = this.values[handleIdx+1];
139
+ }
140
+ sliderValue = this.getNearestValue(sliderValue);
141
+ this.values[handleIdx] = sliderValue;
142
+ this.value = this.values[0]; // assure backwards compat
143
+
144
+ this.handles[handleIdx].style[this.isVertical() ? 'top' : 'left'] =
145
+ this.translateToPx(sliderValue);
146
+
147
+ this.drawSpans();
148
+ if (!this.dragging || !this.event) this.updateFinished();
149
+ },
150
+ setValueBy: function(delta, handleIdx) {
151
+ this.setValue(this.values[handleIdx || this.activeHandleIdx || 0] + delta,
152
+ handleIdx || this.activeHandleIdx || 0);
153
+ },
154
+ translateToPx: function(value) {
155
+ return Math.round(
156
+ ((this.trackLength-this.handleLength)/(this.range.end-this.range.start)) *
157
+ (value - this.range.start)) + "px";
158
+ },
159
+ translateToValue: function(offset) {
160
+ return ((offset/(this.trackLength-this.handleLength) *
161
+ (this.range.end-this.range.start)) + this.range.start);
162
+ },
163
+ getRange: function(range) {
164
+ var v = this.values.sortBy(Prototype.K);
165
+ range = range || 0;
166
+ return $R(v[range],v[range+1]);
167
+ },
168
+ minimumOffset: function(){
169
+ return(this.isVertical() ? this.alignY : this.alignX);
170
+ },
171
+ maximumOffset: function(){
172
+ return(this.isVertical() ?
173
+ (this.track.offsetHeight != 0 ? this.track.offsetHeight :
174
+ this.track.style.height.replace(/px$/,"")) - this.alignY :
175
+ (this.track.offsetWidth != 0 ? this.track.offsetWidth :
176
+ this.track.style.width.replace(/px$/,"")) - this.alignX);
177
+ },
178
+ isVertical: function(){
179
+ return (this.axis == 'vertical');
180
+ },
181
+ drawSpans: function() {
182
+ var slider = this;
183
+ if (this.spans)
184
+ $R(0, this.spans.length-1).each(function(r) { slider.setSpan(slider.spans[r], slider.getRange(r)) });
185
+ if (this.options.startSpan)
186
+ this.setSpan(this.options.startSpan,
187
+ $R(0, this.values.length>1 ? this.getRange(0).min() : this.value ));
188
+ if (this.options.endSpan)
189
+ this.setSpan(this.options.endSpan,
190
+ $R(this.values.length>1 ? this.getRange(this.spans.length-1).max() : this.value, this.maximum));
191
+ },
192
+ setSpan: function(span, range) {
193
+ if (this.isVertical()) {
194
+ span.style.top = this.translateToPx(range.start);
195
+ span.style.height = this.translateToPx(range.end - range.start + this.range.start);
196
+ } else {
197
+ span.style.left = this.translateToPx(range.start);
198
+ span.style.width = this.translateToPx(range.end - range.start + this.range.start);
199
+ }
200
+ },
201
+ updateStyles: function() {
202
+ this.handles.each( function(h){ Element.removeClassName(h, 'selected') });
203
+ Element.addClassName(this.activeHandle, 'selected');
204
+ },
205
+ startDrag: function(event) {
206
+ if (Event.isLeftClick(event)) {
207
+ if (!this.disabled){
208
+ this.active = true;
209
+
210
+ var handle = Event.element(event);
211
+ var pointer = [Event.pointerX(event), Event.pointerY(event)];
212
+ var track = handle;
213
+ if (track==this.track) {
214
+ var offsets = Position.cumulativeOffset(this.track);
215
+ this.event = event;
216
+ this.setValue(this.translateToValue(
217
+ (this.isVertical() ? pointer[1]-offsets[1] : pointer[0]-offsets[0])-(this.handleLength/2)
218
+ ));
219
+ var offsets = Position.cumulativeOffset(this.activeHandle);
220
+ this.offsetX = (pointer[0] - offsets[0]);
221
+ this.offsetY = (pointer[1] - offsets[1]);
222
+ } else {
223
+ // find the handle (prevents issues with Safari)
224
+ while((this.handles.indexOf(handle) == -1) && handle.parentNode)
225
+ handle = handle.parentNode;
226
+
227
+ if (this.handles.indexOf(handle)!=-1) {
228
+ this.activeHandle = handle;
229
+ this.activeHandleIdx = this.handles.indexOf(this.activeHandle);
230
+ this.updateStyles();
231
+
232
+ var offsets = Position.cumulativeOffset(this.activeHandle);
233
+ this.offsetX = (pointer[0] - offsets[0]);
234
+ this.offsetY = (pointer[1] - offsets[1]);
235
+ }
236
+ }
237
+ }
238
+ Event.stop(event);
239
+ }
240
+ },
241
+ update: function(event) {
242
+ if (this.active) {
243
+ if (!this.dragging) this.dragging = true;
244
+ this.draw(event);
245
+ if (Prototype.Browser.WebKit) window.scrollBy(0,0);
246
+ Event.stop(event);
247
+ }
248
+ },
249
+ draw: function(event) {
250
+ var pointer = [Event.pointerX(event), Event.pointerY(event)];
251
+ var offsets = Position.cumulativeOffset(this.track);
252
+ pointer[0] -= this.offsetX + offsets[0];
253
+ pointer[1] -= this.offsetY + offsets[1];
254
+ this.event = event;
255
+ this.setValue(this.translateToValue( this.isVertical() ? pointer[1] : pointer[0] ));
256
+ if (this.initialized && this.options.onSlide)
257
+ this.options.onSlide(this.values.length>1 ? this.values : this.value, this);
258
+ },
259
+ endDrag: function(event) {
260
+ if (this.active && this.dragging) {
261
+ this.finishDrag(event, true);
262
+ Event.stop(event);
263
+ }
264
+ this.active = false;
265
+ this.dragging = false;
266
+ },
267
+ finishDrag: function(event, success) {
268
+ this.active = false;
269
+ this.dragging = false;
270
+ this.updateFinished();
271
+ },
272
+ updateFinished: function() {
273
+ if (this.initialized && this.options.onChange)
274
+ this.options.onChange(this.values.length>1 ? this.values : this.value, this);
275
+ this.event = null;
276
+ }
277
+ });
js/scriptaculous/sound.js ADDED
@@ -0,0 +1,55 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // script.aculo.us sound.js v1.8.2, Tue Nov 18 18:30:58 +0100 2008
2
+
3
+ // Copyright (c) 2005-2008 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
4
+ //
5
+ // Based on code created by Jules Gravinese (http://www.webveteran.com/)
6
+ //
7
+ // script.aculo.us is freely distributable under the terms of an MIT-style license.
8
+ // For details, see the script.aculo.us web site: http://script.aculo.us/
9
+
10
+ Sound = {
11
+ tracks: {},
12
+ _enabled: true,
13
+ template:
14
+ new Template('<embed style="height:0" id="sound_#{track}_#{id}" src="#{url}" loop="false" autostart="true" hidden="true"/>'),
15
+ enable: function(){
16
+ Sound._enabled = true;
17
+ },
18
+ disable: function(){
19
+ Sound._enabled = false;
20
+ },
21
+ play: function(url){
22
+ if(!Sound._enabled) return;
23
+ var options = Object.extend({
24
+ track: 'global', url: url, replace: false
25
+ }, arguments[1] || {});
26
+
27
+ if(options.replace && this.tracks[options.track]) {
28
+ $R(0, this.tracks[options.track].id).each(function(id){
29
+ var sound = $('sound_'+options.track+'_'+id);
30
+ sound.Stop && sound.Stop();
31
+ sound.remove();
32
+ });
33
+ this.tracks[options.track] = null;
34
+ }
35
+
36
+ if(!this.tracks[options.track])
37
+ this.tracks[options.track] = { id: 0 };
38
+ else
39
+ this.tracks[options.track].id++;
40
+
41
+ options.id = this.tracks[options.track].id;
42
+ $$('body')[0].insert(
43
+ Prototype.Browser.IE ? new Element('bgsound',{
44
+ id: 'sound_'+options.track+'_'+options.id,
45
+ src: options.url, loop: 1, autostart: true
46
+ }) : Sound.template.evaluate(options));
47
+ }
48
+ };
49
+
50
+ if(Prototype.Browser.Gecko && navigator.userAgent.indexOf("Win") > 0){
51
+ if(navigator.plugins && $A(navigator.plugins).detect(function(p){ return p.name.indexOf('QuickTime') != -1 }))
52
+ Sound.template = new Template('<object id="sound_#{track}_#{id}" width="0" height="0" type="audio/mpeg" data="#{url}"/>');
53
+ else
54
+ Sound.play = function(){};
55
+ }
js/scriptaculous/unittest.js ADDED
@@ -0,0 +1,568 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // script.aculo.us unittest.js v1.8.2, Tue Nov 18 18:30:58 +0100 2008
2
+
3
+ // Copyright (c) 2005-2008 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
4
+ // (c) 2005-2008 Jon Tirsen (http://www.tirsen.com)
5
+ // (c) 2005-2008 Michael Schuerig (http://www.schuerig.de/michael/)
6
+ //
7
+ // script.aculo.us is freely distributable under the terms of an MIT-style license.
8
+ // For details, see the script.aculo.us web site: http://script.aculo.us/
9
+
10
+ // experimental, Firefox-only
11
+ Event.simulateMouse = function(element, eventName) {
12
+ var options = Object.extend({
13
+ pointerX: 0,
14
+ pointerY: 0,
15
+ buttons: 0,
16
+ ctrlKey: false,
17
+ altKey: false,
18
+ shiftKey: false,
19
+ metaKey: false
20
+ }, arguments[2] || {});
21
+ var oEvent = document.createEvent("MouseEvents");
22
+ oEvent.initMouseEvent(eventName, true, true, document.defaultView,
23
+ options.buttons, options.pointerX, options.pointerY, options.pointerX, options.pointerY,
24
+ options.ctrlKey, options.altKey, options.shiftKey, options.metaKey, 0, $(element));
25
+
26
+ if(this.mark) Element.remove(this.mark);
27
+ this.mark = document.createElement('div');
28
+ this.mark.appendChild(document.createTextNode(" "));
29
+ document.body.appendChild(this.mark);
30
+ this.mark.style.position = 'absolute';
31
+ this.mark.style.top = options.pointerY + "px";
32
+ this.mark.style.left = options.pointerX + "px";
33
+ this.mark.style.width = "5px";
34
+ this.mark.style.height = "5px;";
35
+ this.mark.style.borderTop = "1px solid red;";
36
+ this.mark.style.borderLeft = "1px solid red;";
37
+
38
+ if(this.step)
39
+ alert('['+new Date().getTime().toString()+'] '+eventName+'/'+Test.Unit.inspect(options));
40
+
41
+ $(element).dispatchEvent(oEvent);
42
+ };
43
+
44
+ // Note: Due to a fix in Firefox 1.0.5/6 that probably fixed "too much", this doesn't work in 1.0.6 or DP2.
45
+ // You need to downgrade to 1.0.4 for now to get this working
46
+ // See https://bugzilla.mozilla.org/show_bug.cgi?id=289940 for the fix that fixed too much
47
+ Event.simulateKey = function(element, eventName) {
48
+ var options = Object.extend({
49
+ ctrlKey: false,
50
+ altKey: false,
51
+ shiftKey: false,
52
+ metaKey: false,
53
+ keyCode: 0,
54
+ charCode: 0
55
+ }, arguments[2] || {});
56
+
57
+ var oEvent = document.createEvent("KeyEvents");
58
+ oEvent.initKeyEvent(eventName, true, true, window,
59
+ options.ctrlKey, options.altKey, options.shiftKey, options.metaKey,
60
+ options.keyCode, options.charCode );
61
+ $(element).dispatchEvent(oEvent);
62
+ };
63
+
64
+ Event.simulateKeys = function(element, command) {
65
+ for(var i=0; i<command.length; i++) {
66
+ Event.simulateKey(element,'keypress',{charCode:command.charCodeAt(i)});
67
+ }
68
+ };
69
+
70
+ var Test = {};
71
+ Test.Unit = {};
72
+
73
+ // security exception workaround
74
+ Test.Unit.inspect = Object.inspect;
75
+
76
+ Test.Unit.Logger = Class.create();
77
+ Test.Unit.Logger.prototype = {
78
+ initialize: function(log) {
79
+ this.log = $(log);
80
+ if (this.log) {
81
+ this._createLogTable();
82
+ }
83
+ },
84
+ start: function(testName) {
85
+ if (!this.log) return;
86
+ this.testName = testName;
87
+ this.lastLogLine = document.createElement('tr');
88
+ this.statusCell = document.createElement('td');
89
+ this.nameCell = document.createElement('td');
90
+ this.nameCell.className = "nameCell";
91
+ this.nameCell.appendChild(document.createTextNode(testName));
92
+ this.messageCell = document.createElement('td');
93
+ this.lastLogLine.appendChild(this.statusCell);
94
+ this.lastLogLine.appendChild(this.nameCell);
95
+ this.lastLogLine.appendChild(this.messageCell);
96
+ this.loglines.appendChild(this.lastLogLine);
97
+ },
98
+ finish: function(status, summary) {
99
+ if (!this.log) return;
100
+ this.lastLogLine.className = status;
101
+ this.statusCell.innerHTML = status;
102
+ this.messageCell.innerHTML = this._toHTML(summary);
103
+ this.addLinksToResults();
104
+ },
105
+ message: function(message) {
106
+ if (!this.log) return;
107
+ this.messageCell.innerHTML = this._toHTML(message);
108
+ },
109
+ summary: function(summary) {
110
+ if (!this.log) return;
111
+ this.logsummary.innerHTML = this._toHTML(summary);
112
+ },
113
+ _createLogTable: function() {
114
+ this.log.innerHTML =
115
+ '<div id="logsummary"></div>' +
116
+ '<table id="logtable">' +
117
+ '<thead><tr><th>Status</th><th>Test</th><th>Message</th></tr></thead>' +
118
+ '<tbody id="loglines"></tbody>' +
119
+ '</table>';
120
+ this.logsummary = $('logsummary');
121
+ this.loglines = $('loglines');
122
+ },
123
+ _toHTML: function(txt) {
124
+ return txt.escapeHTML().replace(/\n/g,"<br/>");
125
+ },
126
+ addLinksToResults: function(){
127
+ $$("tr.failed .nameCell").each( function(td){ // todo: limit to children of this.log
128
+ td.title = "Run only this test";
129
+ Event.observe(td, 'click', function(){ window.location.search = "?tests=" + td.innerHTML;});
130
+ });
131
+ $$("tr.passed .nameCell").each( function(td){ // todo: limit to children of this.log
132
+ td.title = "Run all tests";
133
+ Event.observe(td, 'click', function(){ window.location.search = "";});
134
+ });
135
+ }
136
+ };
137
+
138
+ Test.Unit.Runner = Class.create();
139
+ Test.Unit.Runner.prototype = {
140
+ initialize: function(testcases) {
141
+ this.options = Object.extend({
142
+ testLog: 'testlog'
143
+ }, arguments[1] || {});
144
+ this.options.resultsURL = this.parseResultsURLQueryParameter();
145
+ this.options.tests = this.parseTestsQueryParameter();
146
+ if (this.options.testLog) {
147
+ this.options.testLog = $(this.options.testLog) || null;
148
+ }
149
+ if(this.options.tests) {
150
+ this.tests = [];
151
+ for(var i = 0; i < this.options.tests.length; i++) {
152
+ if(/^test/.test(this.options.tests[i])) {
153
+ this.tests.push(new Test.Unit.Testcase(this.options.tests[i], testcases[this.options.tests[i]], testcases["setup"], testcases["teardown"]));
154
+ }
155
+ }
156
+ } else {
157
+ if (this.options.test) {
158
+ this.tests = [new Test.Unit.Testcase(this.options.test, testcases[this.options.test], testcases["setup"], testcases["teardown"])];
159
+ } else {
160
+ this.tests = [];
161
+ for(var testcase in testcases) {
162
+ if(/^test/.test(testcase)) {
163
+ this.tests.push(
164
+ new Test.Unit.Testcase(
165
+ this.options.context ? ' -> ' + this.options.titles[testcase] : testcase,
166
+ testcases[testcase], testcases["setup"], testcases["teardown"]
167
+ ));
168
+ }
169
+ }
170
+ }
171
+ }
172
+ this.currentTest = 0;
173
+ this.logger = new Test.Unit.Logger(this.options.testLog);
174
+ setTimeout(this.runTests.bind(this), 1000);
175
+ },
176
+ parseResultsURLQueryParameter: function() {
177
+ return window.location.search.parseQuery()["resultsURL"];
178
+ },
179
+ parseTestsQueryParameter: function(){
180
+ if (window.location.search.parseQuery()["tests"]){
181
+ return window.location.search.parseQuery()["tests"].split(',');
182
+ };
183
+ },
184
+ // Returns:
185
+ // "ERROR" if there was an error,
186
+ // "FAILURE" if there was a failure, or
187
+ // "SUCCESS" if there was neither
188
+ getResult: function() {
189
+ var hasFailure = false;
190
+ for(var i=0;i<this.tests.length;i++) {
191
+ if (this.tests[i].errors > 0) {
192
+ return "ERROR";
193
+ }
194
+ if (this.tests[i].failures > 0) {
195
+ hasFailure = true;
196
+ }
197
+ }
198
+ if (hasFailure) {
199
+ return "FAILURE";
200
+ } else {
201
+ return "SUCCESS";
202
+ }
203
+ },
204
+ postResults: function() {
205
+ if (this.options.resultsURL) {
206
+ new Ajax.Request(this.options.resultsURL,
207
+ { method: 'get', parameters: 'result=' + this.getResult(), asynchronous: false });
208
+ }
209
+ },
210
+ runTests: function() {
211
+ var test = this.tests[this.currentTest];
212
+ if (!test) {
213
+ // finished!
214
+ this.postResults();
215
+ this.logger.summary(this.summary());
216
+ return;
217
+ }
218
+ if(!test.isWaiting) {
219
+ this.logger.start(test.name);
220
+ }
221
+ test.run();
222
+ if(test.isWaiting) {
223
+ this.logger.message("Waiting for " + test.timeToWait + "ms");
224
+ setTimeout(this.runTests.bind(this), test.timeToWait || 1000);
225
+ } else {
226
+ this.logger.finish(test.status(), test.summary());
227
+ this.currentTest++;
228
+ // tail recursive, hopefully the browser will skip the stackframe
229
+ this.runTests();
230
+ }
231
+ },
232
+ summary: function() {
233
+ var assertions = 0;
234
+ var failures = 0;
235
+ var errors = 0;
236
+ var messages = [];
237
+ for(var i=0;i<this.tests.length;i++) {
238
+ assertions += this.tests[i].assertions;
239
+ failures += this.tests[i].failures;
240
+ errors += this.tests[i].errors;
241
+ }
242
+ return (
243
+ (this.options.context ? this.options.context + ': ': '') +
244
+ this.tests.length + " tests, " +
245
+ assertions + " assertions, " +
246
+ failures + " failures, " +
247
+ errors + " errors");
248
+ }
249
+ };
250
+
251
+ Test.Unit.Assertions = Class.create();
252
+ Test.Unit.Assertions.prototype = {
253
+ initialize: function() {
254
+ this.assertions = 0;
255
+ this.failures = 0;
256
+ this.errors = 0;
257
+ this.messages = [];
258
+ },
259
+ summary: function() {
260
+ return (
261
+ this.assertions + " assertions, " +
262
+ this.failures + " failures, " +
263
+ this.errors + " errors" + "\n" +
264
+ this.messages.join("\n"));
265
+ },
266
+ pass: function() {
267
+ this.assertions++;
268
+ },
269
+ fail: function(message) {
270
+ this.failures++;
271
+ this.messages.push("Failure: " + message);
272
+ },
273
+ info: function(message) {
274
+ this.messages.push("Info: " + message);
275
+ },
276
+ error: function(error) {
277
+ this.errors++;
278
+ this.messages.push(error.name + ": "+ error.message + "(" + Test.Unit.inspect(error) +")");
279
+ },
280
+ status: function() {
281
+ if (this.failures > 0) return 'failed';
282
+ if (this.errors > 0) return 'error';
283
+ return 'passed';
284
+ },
285
+ assert: function(expression) {
286
+ var message = arguments[1] || 'assert: got "' + Test.Unit.inspect(expression) + '"';
287
+ try { expression ? this.pass() :
288
+ this.fail(message); }
289
+ catch(e) { this.error(e); }
290
+ },
291
+ assertEqual: function(expected, actual) {
292
+ var message = arguments[2] || "assertEqual";
293
+ try { (expected == actual) ? this.pass() :
294
+ this.fail(message + ': expected "' + Test.Unit.inspect(expected) +
295
+ '", actual "' + Test.Unit.inspect(actual) + '"'); }
296
+ catch(e) { this.error(e); }
297
+ },
298
+ assertInspect: function(expected, actual) {
299
+ var message = arguments[2] || "assertInspect";
300
+ try { (expected == actual.inspect()) ? this.pass() :
301
+ this.fail(message + ': expected "' + Test.Unit.inspect(expected) +
302
+ '", actual "' + Test.Unit.inspect(actual) + '"'); }
303
+ catch(e) { this.error(e); }
304
+ },
305
+ assertEnumEqual: function(expected, actual) {
306
+ var message = arguments[2] || "assertEnumEqual";
307
+ try { $A(expected).length == $A(actual).length &&
308
+ expected.zip(actual).all(function(pair) { return pair[0] == pair[1] }) ?
309
+ this.pass() : this.fail(message + ': expected ' + Test.Unit.inspect(expected) +
310
+ ', actual ' + Test.Unit.inspect(actual)); }
311
+ catch(e) { this.error(e); }
312
+ },
313
+ assertNotEqual: function(expected, actual) {
314
+ var message = arguments[2] || "assertNotEqual";
315
+ try { (expected != actual) ? this.pass() :
316
+ this.fail(message + ': got "' + Test.Unit.inspect(actual) + '"'); }
317
+ catch(e) { this.error(e); }
318
+ },
319
+ assertIdentical: function(expected, actual) {
320
+ var message = arguments[2] || "assertIdentical";
321
+ try { (expected === actual) ? this.pass() :
322
+ this.fail(message + ': expected "' + Test.Unit.inspect(expected) +
323
+ '", actual "' + Test.Unit.inspect(actual) + '"'); }
324
+ catch(e) { this.error(e); }
325
+ },
326
+ assertNotIdentical: function(expected, actual) {
327
+ var message = arguments[2] || "assertNotIdentical";
328
+ try { !(expected === actual) ? this.pass() :
329
+ this.fail(message + ': expected "' + Test.Unit.inspect(expected) +
330
+ '", actual "' + Test.Unit.inspect(actual) + '"'); }
331
+ catch(e) { this.error(e); }
332
+ },
333
+ assertNull: function(obj) {
334
+ var message = arguments[1] || 'assertNull';
335
+ try { (obj==null) ? this.pass() :
336
+ this.fail(message + ': got "' + Test.Unit.inspect(obj) + '"'); }
337
+ catch(e) { this.error(e); }
338
+ },
339
+ assertMatch: function(expected, actual) {
340
+ var message = arguments[2] || 'assertMatch';
341
+ var regex = new RegExp(expected);
342
+ try { (regex.exec(actual)) ? this.pass() :
343
+ this.fail(message + ' : regex: "' + Test.Unit.inspect(expected) + ' did not match: ' + Test.Unit.inspect(actual) + '"'); }
344
+ catch(e) { this.error(e); }
345
+ },
346
+ assertHidden: function(element) {
347
+ var message = arguments[1] || 'assertHidden';
348
+ this.assertEqual("none", element.style.display, message);
349
+ },
350
+ assertNotNull: function(object) {
351
+ var message = arguments[1] || 'assertNotNull';
352
+ this.assert(object != null, message);
353
+ },
354
+ assertType: function(expected, actual) {
355
+ var message = arguments[2] || 'assertType';
356
+ try {
357
+ (actual.constructor == expected) ? this.pass() :
358
+ this.fail(message + ': expected "' + Test.Unit.inspect(expected) +
359
+ '", actual "' + (actual.constructor) + '"'); }
360
+ catch(e) { this.error(e); }
361
+ },
362
+ assertNotOfType: function(expected, actual) {
363
+ var message = arguments[2] || 'assertNotOfType';
364
+ try {
365
+ (actual.constructor != expected) ? this.pass() :
366
+ this.fail(message + ': expected "' + Test.Unit.inspect(expected) +
367
+ '", actual "' + (actual.constructor) + '"'); }
368
+ catch(e) { this.error(e); }
369
+ },
370
+ assertInstanceOf: function(expected, actual) {
371
+ var message = arguments[2] || 'assertInstanceOf';
372
+ try {
373
+ (actual instanceof expected) ? this.pass() :
374
+ this.fail(message + ": object was not an instance of the expected type"); }
375
+ catch(e) { this.error(e); }
376
+ },
377
+ assertNotInstanceOf: function(expected, actual) {
378
+ var message = arguments[2] || 'assertNotInstanceOf';
379
+ try {
380
+ !(actual instanceof expected) ? this.pass() :
381
+ this.fail(message + ": object was an instance of the not expected type"); }
382
+ catch(e) { this.error(e); }
383
+ },
384
+ assertRespondsTo: function(method, obj) {
385
+ var message = arguments[2] || 'assertRespondsTo';
386
+ try {
387
+ (obj[method] && typeof obj[method] == 'function') ? this.pass() :
388
+ this.fail(message + ": object doesn't respond to [" + method + "]"); }
389
+ catch(e) { this.error(e); }
390
+ },
391
+ assertReturnsTrue: function(method, obj) {
392
+ var message = arguments[2] || 'assertReturnsTrue';
393
+ try {
394
+ var m = obj[method];
395
+ if(!m) m = obj['is'+method.charAt(0).toUpperCase()+method.slice(1)];
396
+ m() ? this.pass() :
397
+ this.fail(message + ": method returned false"); }
398
+ catch(e) { this.error(e); }
399
+ },
400
+ assertReturnsFalse: function(method, obj) {
401
+ var message = arguments[2] || 'assertReturnsFalse';
402
+ try {
403
+ var m = obj[method];
404
+ if(!m) m = obj['is'+method.charAt(0).toUpperCase()+method.slice(1)];
405
+ !m() ? this.pass() :
406
+ this.fail(message + ": method returned true"); }
407
+ catch(e) { this.error(e); }
408
+ },
409
+ assertRaise: function(exceptionName, method) {
410
+ var message = arguments[2] || 'assertRaise';
411
+ try {
412
+ method();
413
+ this.fail(message + ": exception expected but none was raised"); }
414
+ catch(e) {
415
+ ((exceptionName == null) || (e.name==exceptionName)) ? this.pass() : this.error(e);
416
+ }
417
+ },
418
+ assertElementsMatch: function() {
419
+ var expressions = $A(arguments), elements = $A(expressions.shift());
420
+ if (elements.length != expressions.length) {
421
+ this.fail('assertElementsMatch: size mismatch: ' + elements.length + ' elements, ' + expressions.length + ' expressions');
422
+ return false;
423
+ }
424
+ elements.zip(expressions).all(function(pair, index) {
425
+ var element = $(pair.first()), expression = pair.last();
426
+ if (element.match(expression)) return true;
427
+ this.fail('assertElementsMatch: (in index ' + index + ') expected ' + expression.inspect() + ' but got ' + element.inspect());
428
+ }.bind(this)) && this.pass();
429
+ },
430
+ assertElementMatches: function(element, expression) {
431
+ this.assertElementsMatch([element], expression);
432
+ },
433
+ benchmark: function(operation, iterations) {
434
+ var startAt = new Date();
435
+ (iterations || 1).times(operation);
436
+ var timeTaken = ((new Date())-startAt);
437
+ this.info((arguments[2] || 'Operation') + ' finished ' +
438
+ iterations + ' iterations in ' + (timeTaken/1000)+'s' );
439
+ return timeTaken;
440
+ },
441
+ _isVisible: function(element) {
442
+ element = $(element);
443
+ if(!element.parentNode) return true;
444
+ this.assertNotNull(element);
445
+ if(element.style && Element.getStyle(element, 'display') == 'none')
446
+ return false;
447
+
448
+ return this._isVisible(element.parentNode);
449
+ },
450
+ assertNotVisible: function(element) {
451
+ this.assert(!this._isVisible(element), Test.Unit.inspect(element) + " was not hidden and didn't have a hidden parent either. " + ("" || arguments[1]));
452
+ },
453
+ assertVisible: function(element) {
454
+ this.assert(this._isVisible(element), Test.Unit.inspect(element) + " was not visible. " + ("" || arguments[1]));
455
+ },
456
+ benchmark: function(operation, iterations) {
457
+ var startAt = new Date();
458
+ (iterations || 1).times(operation);
459
+ var timeTaken = ((new Date())-startAt);
460
+ this.info((arguments[2] || 'Operation') + ' finished ' +
461
+ iterations + ' iterations in ' + (timeTaken/1000)+'s' );
462
+ return timeTaken;
463
+ }
464
+ };
465
+
466
+ Test.Unit.Testcase = Class.create();
467
+ Object.extend(Object.extend(Test.Unit.Testcase.prototype, Test.Unit.Assertions.prototype), {
468
+ initialize: function(name, test, setup, teardown) {
469
+ Test.Unit.Assertions.prototype.initialize.bind(this)();
470
+ this.name = name;
471
+
472
+ if(typeof test == 'string') {
473
+ test = test.gsub(/(\.should[^\(]+\()/,'#{0}this,');
474
+ test = test.gsub(/(\.should[^\(]+)\(this,\)/,'#{1}(this)');
475
+ this.test = function() {
476
+ eval('with(this){'+test+'}');
477
+ }
478
+ } else {
479
+ this.test = test || function() {};
480
+ }
481
+
482
+ this.setup = setup || function() {};
483
+ this.teardown = teardown || function() {};
484
+ this.isWaiting = false;
485
+ this.timeToWait = 1000;
486
+ },
487
+ wait: function(time, nextPart) {
488
+ this.isWaiting = true;
489
+ this.test = nextPart;
490
+ this.timeToWait = time;
491
+ },
492
+ run: function() {
493
+ try {
494
+ try {
495
+ if (!this.isWaiting) this.setup.bind(this)();
496
+ this.isWaiting = false;
497
+ this.test.bind(this)();
498
+ } finally {
499
+ if(!this.isWaiting) {
500
+ this.teardown.bind(this)();
501
+ }
502
+ }
503
+ }
504
+ catch(e) { this.error(e); }
505
+ }
506
+ });
507
+
508
+ // *EXPERIMENTAL* BDD-style testing to please non-technical folk
509
+ // This draws many ideas from RSpec http://rspec.rubyforge.org/
510
+
511
+ Test.setupBDDExtensionMethods = function(){
512
+ var METHODMAP = {
513
+ shouldEqual: 'assertEqual',
514
+ shouldNotEqual: 'assertNotEqual',
515
+ shouldEqualEnum: 'assertEnumEqual',
516
+ shouldBeA: 'assertType',
517
+ shouldNotBeA: 'assertNotOfType',
518
+ shouldBeAn: 'assertType',
519
+ shouldNotBeAn: 'assertNotOfType',
520
+ shouldBeNull: 'assertNull',
521
+ shouldNotBeNull: 'assertNotNull',
522
+
523
+ shouldBe: 'assertReturnsTrue',
524
+ shouldNotBe: 'assertReturnsFalse',
525
+ shouldRespondTo: 'assertRespondsTo'
526
+ };
527
+ var makeAssertion = function(assertion, args, object) {
528
+ this[assertion].apply(this,(args || []).concat([object]));
529
+ };
530
+
531
+ Test.BDDMethods = {};
532
+ $H(METHODMAP).each(function(pair) {
533
+ Test.BDDMethods[pair.key] = function() {
534
+ var args = $A(arguments);
535
+ var scope = args.shift();
536
+ makeAssertion.apply(scope, [pair.value, args, this]); };
537
+ });
538
+
539
+ [Array.prototype, String.prototype, Number.prototype, Boolean.prototype].each(
540
+ function(p){ Object.extend(p, Test.BDDMethods) }
541
+ );
542
+ };
543
+
544
+ Test.context = function(name, spec, log){
545
+ Test.setupBDDExtensionMethods();
546
+
547
+ var compiledSpec = {};
548
+ var titles = {};
549
+ for(specName in spec) {
550
+ switch(specName){
551
+ case "setup":
552
+ case "teardown":
553
+ compiledSpec[specName] = spec[specName];
554
+ break;
555
+ default:
556
+ var testName = 'test'+specName.gsub(/\s+/,'-').camelize();
557
+ var body = spec[specName].toString().split('\n').slice(1);
558
+ if(/^\{/.test(body[0])) body = body.slice(1);
559
+ body.pop();
560
+ body = body.map(function(statement){
561
+ return statement.strip()
562
+ });
563
+ compiledSpec[testName] = body.join('\n');
564
+ titles[testName] = specName;
565
+ }
566
+ }
567
+ new Test.Unit.Runner(compiledSpec, { titles: titles, testLog: log || 'testlog', context: name });
568
+ };
package.xml ADDED
@@ -0,0 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <?xml version="1.0"?>
2
+ <package>
3
+ <name>Lib_Js_Prototype</name>
4
+ <version>1.6.0.3.0</version>
5
+ <stability>stable</stability>
6
+ <license>Mixed</license>
7
+ <channel>community</channel>
8
+ <extends/>
9
+ <summary>Prototype and Scriptaculous Javascript Libraries for Magento</summary>
10
+ <description>Prototype and Scriptaculous Javascript Libraries for Magento</description>
11
+ <notes>1.6.0.3.0</notes>
12
+ <authors><author><name>Magento Core Team</name><user>auto-converted</user><email>core@magentocommerce.com</email></author></authors>
13
+ <date>2010-02-12</date>
14
+ <time>22:54:30</time>
15
+ <contents><target name="mageweb"><dir name="js"><dir name="prototype"><dir name="windows"><dir name="themes"><dir name="alert"><file name="bottom.gif" hash="e859e3bc00c4f10360fa81a659aa673f"/><file name="bottom_left.gif" hash="53585b1a0351d599e76a85ccc26f7980"/><file name="bottom_right.gif" hash="8170abe3fec71fd17612869a2f036cd6"/><file name="left.gif" hash="4f235c4e6afb0d386d220638c49e4545"/><file name="overlay.png" hash="f4ddcee6f819975bc9c5643b570de6dc"/><file name="progress.gif" hash="86b1ac6d1c485d54efa3a53643e91ceb"/><file name="right.gif" hash="838ade41815529e7a63f99c93b3a01f7"/><file name="top.gif" hash="8702ca9b81c19f6220ce81c4ea215878"/><file name="top_left.gif" hash="a8c097bcb67bddf640c2bd9161b79476"/><file name="top_right.gif" hash="05ef4e1a417a5a2c81fc816406a4842a"/></dir><dir name="alphacube"><file name="bottom-left-c.gif" hash="434cdfc5298f33efb108264cf3370e1c"/><file name="bottom-middle.gif" hash="3f882dd32d57a29a785f448bbba5ed26"/><file name="bottom-right-c.gif" hash="4c37ad7b94fc901a1cfaf54a1742d5fd"/><file name="button-close-focus.gif" hash="99c44a6df2733b58083af7a4d9522116"/><file name="button-max-focus.gif" hash="408cd33fa89269b8395bf10afe69d456"/><file name="button-min-focus.gif" hash="ae06210658bad8bcc88dea377c4dc908"/><file name="frame-left.gif" hash="1bb1207b43425d214d4dc0da108f5449"/><file name="frame-right.gif" hash="8b9c36079881aa15c27a137666c56a38"/><file name="left-top.gif" hash="1ea936a090b4dfe8160fcb3a90ddb145"/><file name="right-top.gif" hash="e1b641feab640cb4207fa52160715e32"/><file name="top-middle.gif" hash="7f94c1018d023832c7c9e1fa468a9555"/></dir><dir name="darkX"><file name="button-close-focused.png" hash="5090b529a86a79679e0a26ccb0e1b0c6"/><file name="button-maximize-focused.png" hash="0f84bfcc9626d2cb1826291268b29f20"/><file name="button-minimize-focused.png" hash="630cd8cdd7124d412c6253e5c7cfc32a"/><file name="frame-bottom-left-focused.png" hash="8a34a3be2f349315dfd287ec15148332"/><file name="frame-bottom-mid-focused.png" hash="f1dbacdb64a19e00a485d426126f26db"/><file name="frame-bottom-right-focused.png" hash="17acb7874856dc68c3c017238d42054a"/><file name="frame-left-focused.png" hash="f30ab13888b2e48d0637991164a8f748"/><file name="frame-right-focused.png" hash="1115115c62507971b2f5eed3c2c5c2d0"/><file name="titlebar-left-focused.png" hash="491130dedbdbb3b2682f37424347b14c"/><file name="titlebar-mid-focused.png" hash="ae46975fc8a5e5a9f73f810d0c88809a"/><file name="titlebar-right-focused.png" hash="9560eb10dee94985f3ebe935833e2ae4"/></dir><dir name="default"><file name="bottom_left.gif" hash="fb99ffa815a8648f95f42698fe5dfaa1"/><file name="bottom_mid.gif" hash="49b9ca7025562ea7f070a9111282364b"/><file name="bottom_right.gif" hash="e46768f632765cd86c5fe5d0166dcf2c"/><file name="bottom_right_resize.gif" hash="1b35a4ec3b734dfe37e31ba87bcc7d99"/><file name="center_left.gif" hash="bd567580b4ee16a7a2734057cfbbe219"/><file name="center_right.gif" hash="eef184d5d89d1710313581a2ccf408e8"/><file name="clear.gif" hash="7af1206eeb0e7834a75e69d70676060d"/><file name="close.gif" hash="8a08f243c37a8e25a88d4ac135b2f07d"/><file name="inspect.gif" hash="aa2a0961067aad5c54b8634919af863b"/><file name="maximize.gif" hash="e73cd71c4979ebeadeb9e27d40a9e8fb"/><file name="minimize.gif" hash="2d2f4b1bd0506f342425f80ab76c49a3"/><file name="overlay.png" hash="536d40e87cda0c7ae7b11f1721aa52d0"/><file name="resize.gif" hash="320f534b5d444b39701e0b679529e779"/><file name="sizer.gif" hash="1b35a4ec3b734dfe37e31ba87bcc7d99"/><file name="top_left.gif" hash="9c5e5920bfc189a45cc618099af93aa8"/><file name="top_mid.gif" hash="a12ff2b944025ad2d127d033dae5e9e1"/><file name="top_right.gif" hash="0cf1ec5b93f8ac8fcce0e2f72cf7f45e"/></dir><dir name="iefix"><file name="blank.gif" hash="56398e76be6355ad5999b262208a17c9"/><file name="iepngfix.css" hash="da3154c9a817850376f73a7976bfcb13"/><file name="iepngfix.htc" hash="b50c4e352a64254c5ceb6c63bcd0b176"/></dir><dir name="lighting"><file name="background_buttons.gif" hash="e66e67aaaf08a7b24f3cd1ba22584b42"/><file name="bottom-left-blue.png" hash="7c9e91d421945141315fc105d464a99f"/><file name="bottom-left-darkblue.png" hash="e88c2380acf403ee28597c6045988cc6"/><file name="bottom-left-green.png" hash="ee25ce8a12229b009fbfd91f7ba51e26"/><file name="bottom-left-grey.png" hash="5fdb3eae397ac7279aa5a7fdaad3dcc2"/><file name="bottom-middle-blue.png" hash="e93cc9d31d88f45c047a98a66be04354"/><file name="bottom-middle-darkblue.png" hash="763c88c424e0900e675042d3f0958bd4"/><file name="bottom-middle-green.png" hash="77e0a22afd2c55a83b5c7fa98a12ef25"/><file name="bottom-middle-grey.png" hash="3a2ebdeff74e2ff63c4471575568dd01"/><file name="bottom-right-blue.png" hash="0bc11a61047e8716451a283ebff897e5"/><file name="bottom-right-darkblue.png" hash="88e33ea702a304ae237edd57bc8447d6"/><file name="bottom-right-green.png" hash="7bce162df013eba43a659ae6e780ae4b"/><file name="bottom-right-grey.png" hash="86eb476492d911aac5688c9747fe7a1d"/><file name="button-close-blue.png" hash="42ae1a35caf8a9a275d6e748c27769fb"/><file name="button-close-darkblue.png" hash="50dbcd898dc519c1e6ac0d3a478978cd"/><file name="button-close-green.png" hash="b4273572fa91cba909a0a3e15b994d19"/><file name="button-close-grey.png" hash="124964b634ba67f2bb6dd08cf8cafd5a"/><file name="button-maximize-blue.png" hash="85b79237d85b09c205e09166dd8f4af0"/><file name="button-maximize-darkblue.png" hash="108d10619214e3365820aa4ab008aed5"/><file name="button-maximize-green.png" hash="90f5527705e4fd81997564e81c6ac2a3"/><file name="button-maximize-grey.png" hash="c46a8c014bd14be167f4c6a2f2dd52ed"/><file name="button-minimize-blue.png" hash="1fd738b99877a4dfa5656491cc3d8e6b"/><file name="button-minimize-darkblue.png" hash="b6d9da1cdf51ab54682fa75a6df2c40d"/><file name="button-minimize-green.png" hash="9e7d26298a0a49ffee3fbab6ea838e01"/><file name="button-minimize-grey.png" hash="0432701c2425cb3a5143d8a04bda0d87"/><file name="left-blue.png" hash="0a6acf0a863c04845a93b681769527cd"/><file name="left-darkblue.png" hash="44cdce8a75de4425d7eb7763092cc38d"/><file name="left-green.png" hash="d83116c49d62dc46bff0b7b4200b4ecf"/><file name="left-grey.png" hash="f3486d3293ae98b5edb8889c4b4082ef"/><file name="pngbehavior.htc" hash="b94c44e30423fd18a8b82bda5a139db3"/><file name="right-blue.png" hash="2c9b6b80d4a6b190b8e38a1c101e828c"/><file name="right-darkblue.png" hash="9b3267c5d36bb3f4588167cc3e78e569"/><file name="right-green.png" hash="4436968c2adbe6ed7c475c225631bc7c"/><file name="right-grey.png" hash="36b3de47bcbbd6b53e2f6e06843ee6e8"/><file name="spinner.gif" hash="c7b3cbb3ec8249a7121b722cdd76b870"/><file name="top-left-blue.png" hash="a5cb9eaa82f67df223d6784a52b26f1f"/><file name="top-left-darkblue.png" hash="e4a3af23d2cae7909331eb1995963c82"/><file name="top-left-green.png" hash="eb4cb604177c342998023d3dcd3aa5b0"/><file name="top-left-grey.png" hash="9f6f39abc4ae9539a0f54567a4a5d4f8"/><file name="top-middle-blue.png" hash="6d01df8637385bbe592b8df369294c8d"/><file name="top-middle-darkblue.png" hash="2c91ea6462e72a29cd07300d4102b88a"/><file name="top-middle-green.png" hash="e0f56311091bfb370fc6783fc7e71068"/><file name="top-middle-grey.png" hash="8c02881b730d602589fe9ed4bcaeb689"/><file name="top-right-blue.png" hash="4afefb06dc63c864211724a6348f25ad"/><file name="top-right-darkblue.png" hash="d8a9031987f648f170af67023179618d"/><file name="top-right-green.png" hash="b38813f9200440051273bdd622f5e545"/><file name="top-right-grey.png" hash="d7f7332ddf8686fb9810e4170767bf52"/></dir><dir name="magento"><file name="button-close-focused.png" hash="5771d6d66a73a93c6027b1cafa9f8626"/><file name="top_bg.gif" hash="fdce7a29552bc72446f895df68ed10d0"/></dir><dir name="nuncio"><file name="bottom_left.png" hash="d9be5c7b432a342c6da5ef9b10148267"/><file name="bottom_mid.png" hash="facee2e7ee7c572a8f412750b0ce5387"/><file name="bottom_right.png" hash="6f3c124a066a11ff225897112de8e9d7"/><file name="center_left.png" hash="a11bee83f99addccc0d5eff3d2e82b8f"/><file name="center_right.png" hash="bf6b023ad1751d5f60f9820eea72ac28"/><file name="close.png" hash="46744062a7b54416c8767f8e0ccf1c41"/><file name="minimize.png" hash="bc911a3e90fc0640e0899856759a5e01"/><file name="overlay.png" hash="5ccd88855e923eb8a1bd9da1dec9d7fe"/><file name="top_left.png" hash="d3105aacc2c69954df11af953875a12e"/><file name="top_mid.png" hash="cb679a8c77e9b7485b5f0eca547eb103"/><file name="top_right.png" hash="e65d6fc6bf53891c487e414db16f1038"/></dir><dir name="spread"><file name="bottom-left-c.gif" hash="84641d08576f68a11f717103365dfb83"/><file name="bottom-middle.gif" hash="20ab265c67355c5b72cdcdc8739af555"/><file name="bottom-right-c.gif" hash="cb27b72623e997badc599e76024a6e44"/><file name="button-close-focus.gif" hash="99c44a6df2733b58083af7a4d9522116"/><file name="button-max-focus.gif" hash="408cd33fa89269b8395bf10afe69d456"/><file name="button-min-focus.gif" hash="ae06210658bad8bcc88dea377c4dc908"/><file name="frame-left.gif" hash="63dc99b0c4ba0518688f7eca1f1628ca"/><file name="frame-right.gif" hash="a03585eec830f37898c7041d557dafc5"/><file name="left-top.gif" hash="7c78b8b59976d19191acf940cbfc04fb"/><file name="right-top.gif" hash="597530287fe1dc491278f855749f7e01"/><file name="top-middle.gif" hash="fa6fd6b90945c47f8d1718d9139d0a75"/></dir><file name="alert.css" hash="27df86baae5a6fa2e3556bdf1b85ccc6"/><file name="alert_lite.css" hash="fbeaff8f185cd3b302f1a8db5efa0110"/><file name="alphacube.css" hash="27c968911eaef53df158c55083ef0c84"/><file name="behavior.htc" hash="5588dff36ad5595f8353730e853044e5"/><file name="darkX.css" hash="16a964cfe57a2c979ad3d97831673b79"/><file name="debug.css" hash="63ee9aa7b7d80e0bb5e311407746ccd3"/><file name="default.css" hash="16014098f441d12d06c088135e2fde28"/><file name="lighting.css" hash="d13de730c8ee7ef04167d361bdf8eebd"/><file name="mac_os_x.css" hash="65204ef34c1eeff0be29c53b0614076a"/><file name="mac_os_x_dialog.css" hash="0b7cd9d6a9e8f940f50bc4a080f54b1b"/><file name="magento.css" hash="26845e1d1a5a0bb13a38371ba7078351"/><file name="nuncio.css" hash="e30e31b94d96b0b27c80ad6d943d7010"/><file name="spread.css" hash="a804413d7f1f9550c134477f6f9219ee"/></dir><file name="MIT-LICENSE" hash="a839f717f1675b571481268a4e4a4ee2"/><file name="README" hash="75b8b2e714cbcb48337540a451655967"/></dir><file name="debug.js" hash="d5990eabf728ade1f34496737455c8ff"/><file name="deprecation.js" hash="4dfe41a2d0ef43c8fe7726bd2b80b18d"/><file name="effects.js" hash="91e1b7d8c6043dff4eadbe054a90e3a7"/><file name="extended_debug.js" hash="cc706bc76bb1c5a2610fc296cd85e053"/><file name="prototype.js" hash="d23187d61f796d39487acbe34af031bc"/><file name="tooltip.js" hash="8509b04b1594b7e6382d7cfdf4ee1236"/><file name="tooltip_manager.js" hash="6b9759cbad296fda3c18d7669d6b5af0"/><file name="validation.js" hash="504b8f2e9b1402ef14991abc45c35de8"/><file name="window.js" hash="90c94ca69a6acf7ee4fb0c4e00916a71"/><file name="window_effects.js" hash="3c0b47a0f3cd41753a3992d01c118c3d"/><file name="window_ext.js" hash="5ab45fe5f734927890c95b9d5547f47f"/><file name="window_readme.txt" hash="97306d2a8c4be2ec65f66d2ec233289c"/></dir><dir name="scriptaculous"><file name="builder.js" hash="1174f6fc34ca5d54ba10b0c719386e7c"/><file name="controls.js" hash="8c414e1787c0ac9f10b16b252361c8b2"/><file name="dragdrop.js" hash="c824212f4d19277be0fd11a87a9cd0fd"/><file name="effects.js" hash="d795089f95a22306cca9b337c439c65a"/><file name="scriptaculous.js" hash="d59eba4e0b14b672208b0862ae1c2196"/><file name="slider.js" hash="6043f96a71d2685fecd02e2ab99e84d9"/><file name="sound.js" hash="0f0fab23fa2cb1bc7717fd2bdf45402e"/><file name="unittest.js" hash="99969698b22272f77bdf4c64586862b3"/></dir></dir></target></contents>
16
+ <compatible/>
17
+ <dependencies><required><package><name>Mage_Pear_Helpers</name><channel>community</channel><min>1.0.18800</min><max></max></package></required></dependencies>
18
+ </package>